mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Fix problems loading/saving .png files with non-zero transparent index.
This commit is contained in:
parent
c3e38daff2
commit
5ff9450536
@ -553,10 +553,8 @@ void fop_operate(FileOp *fop)
|
||||
|
||||
// For each frame in the sprite.
|
||||
for (int frame=0; frame < sprite->getTotalFrames(); ++frame) {
|
||||
// Draw the "frame" in "fop->seq.image"
|
||||
sprite->setCurrentFrame(frame);
|
||||
|
||||
// Draw all the sprite in this frame in the image.
|
||||
image_clear(fop->seq.image, 0);
|
||||
sprite->render(fop->seq.image, 0, 0);
|
||||
|
||||
// Setup the palette.
|
||||
|
@ -195,7 +195,8 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
}
|
||||
|
||||
// Transparent palette entries
|
||||
std::vector<bool> trans_entries(256, false);
|
||||
std::vector<uint8_t> pal_alphas(256, 255);
|
||||
int mask_entry = -1;
|
||||
|
||||
// Read the palette
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
|
||||
@ -212,21 +213,30 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
fop_sequence_set_color(fop, c, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Read transparent entries
|
||||
// Read alpha values for palette entries
|
||||
png_bytep trans = NULL; // Transparent palette entries
|
||||
int num_trans = 0;
|
||||
|
||||
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
|
||||
|
||||
for (int i = 0; i < num_trans; ++i) {
|
||||
int j = trans[i];
|
||||
if (j >= 0 && j < (int)trans_entries.size()) {
|
||||
trans_entries[j] = true;
|
||||
pal_alphas[i] = trans[i];
|
||||
|
||||
if (pal_alphas[i] < 128) {
|
||||
fop->seq.has_alpha = true; // Is a transparent sprite
|
||||
|
||||
if (mask_entry < 0)
|
||||
mask_entry = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the transparent color to the first transparent entry found
|
||||
if (mask_entry >= 0)
|
||||
fop->document->getSprite()->setTransparentColor(mask_entry);
|
||||
}
|
||||
|
||||
mask_entry = fop->document->getSprite()->getTransparentColor();
|
||||
|
||||
/* Allocate the memory to hold the image using the fields of info_ptr. */
|
||||
|
||||
/* The easiest way to read the image: */
|
||||
@ -295,10 +305,8 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
|
||||
// All transparent values are converted to entry 0.
|
||||
// TODO Add support for multiple transparent palette entries in Indexed sprites.
|
||||
if (!trans_entries.empty() && trans_entries[c]) {
|
||||
*(dst_address++) = 0;
|
||||
if (pal_alphas[c] < 128) {
|
||||
*(dst_address++) = mask_entry;
|
||||
}
|
||||
else {
|
||||
*(dst_address++) = c;
|
||||
@ -412,10 +420,8 @@ bool PngFormat::onSave(FileOp* fop)
|
||||
#error PNG_MAX_PALETTE_LENGTH should be 256
|
||||
#endif
|
||||
|
||||
/* set the palette if there is one. REQUIRED for indexed-color images */
|
||||
palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
|
||||
* png_sizeof(png_color));
|
||||
/* ... set palette colors ... */
|
||||
// Save the color palette.
|
||||
palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
|
||||
for (c = 0; c < PNG_MAX_PALETTE_LENGTH; c++) {
|
||||
fop_sequence_get_color(fop, c, &r, &g, &b);
|
||||
palette[c].red = r;
|
||||
@ -425,13 +431,18 @@ bool PngFormat::onSave(FileOp* fop)
|
||||
|
||||
png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
|
||||
|
||||
// Index 0 will be the transparent color in the PNG file (only if
|
||||
// the sprite does not have a background layer).
|
||||
// If the sprite does not have a background layer, we include the
|
||||
// alpha information of palette entries to indicate which is the
|
||||
// transparent color.
|
||||
if (fop->document->getSprite()->getBackgroundLayer() == NULL) {
|
||||
png_bytep trans = (png_bytep)png_malloc(png_ptr, 1);
|
||||
trans[0] = 0; // Entry 0 is transparent
|
||||
int mask_entry = fop->document->getSprite()->getTransparentColor();
|
||||
int num_trans = mask_entry+1;
|
||||
png_bytep trans = (png_bytep)png_malloc(png_ptr, num_trans);
|
||||
|
||||
png_set_tRNS(png_ptr, info_ptr, trans, 1, NULL);
|
||||
for (c = 0; c < num_trans; ++c)
|
||||
trans[c] = (c == mask_entry ? 0: 255);
|
||||
|
||||
png_set_tRNS(png_ptr, info_ptr, trans, num_trans, NULL);
|
||||
png_free(png_ptr, trans);
|
||||
}
|
||||
}
|
||||
|
@ -403,7 +403,9 @@ void Sprite::remapImages(int frame_from, int frame_to, const std::vector<uint8_t
|
||||
|
||||
void Sprite::render(Image* image, int x, int y) const
|
||||
{
|
||||
image_rectfill(image, x, y, x+m_width-1, y+m_height-1, 0);
|
||||
image_rectfill(image, x, y, x+m_width-1, y+m_height-1,
|
||||
(m_imgtype == IMAGE_INDEXED ? getTransparentColor(): 0));
|
||||
|
||||
layer_render(getFolder(), image, x, y, getCurrentFrame());
|
||||
}
|
||||
|
||||
@ -413,8 +415,8 @@ int Sprite::getPixel(int x, int y) const
|
||||
|
||||
if ((x >= 0) && (y >= 0) && (x < m_width) && (y < m_height)) {
|
||||
Image* image = image_new(m_imgtype, 1, 1);
|
||||
image_clear(image, 0);
|
||||
this->render(image, -x, -y);
|
||||
image_clear(image, (m_imgtype == IMAGE_INDEXED ? getTransparentColor(): 0));
|
||||
render(image, -x, -y);
|
||||
color = image_getpixel(image, 0, 0);
|
||||
image_free(image);
|
||||
}
|
||||
|
@ -127,9 +127,10 @@ public:
|
||||
|
||||
void remapImages(int frame_from, int frame_to, const std::vector<uint8_t>& mapping);
|
||||
|
||||
////////////////////////////////////////
|
||||
// Drawing
|
||||
|
||||
// Draws the sprite in the given image at the given position. Before
|
||||
// drawing the sprite, this function clears (with the sprite's
|
||||
// background color) the rectangle area that will occupy the drawn
|
||||
// sprite.
|
||||
void render(Image* image, int x, int y) const;
|
||||
|
||||
// Gets a pixel from the sprite in the specified position. If in the
|
||||
|
@ -215,8 +215,6 @@ void UndoTransaction::autocropSprite(int bgcolor)
|
||||
|
||||
for (int frame=0; frame<m_sprite->getTotalFrames(); ++frame) {
|
||||
m_sprite->setCurrentFrame(frame);
|
||||
|
||||
image_clear(image, 0);
|
||||
m_sprite->render(image, 0, 0);
|
||||
|
||||
// TODO configurable (what color pixel to use as "refpixel",
|
||||
|
@ -795,7 +795,6 @@ static void monitor_thumbnail_generation(void *_data)
|
||||
|
||||
// Render the 'sprite' in one plain 'image'
|
||||
image = image_new(sprite->getImgType(), sprite->getWidth(), sprite->getHeight());
|
||||
image_clear(image, 0);
|
||||
sprite->render(image, 0, 0);
|
||||
|
||||
// Calculate the thumbnail size
|
||||
|
Loading…
x
Reference in New Issue
Block a user