mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-11 18:41:05 +00:00
Add support for 8-bit png files with alpha channel
This commit is contained in:
parent
6796e9f9be
commit
8f62baedb3
@ -776,6 +776,25 @@ void fop_sequence_get_color(FileOp *fop, int index, int *r, int *g, int *b)
|
||||
*b = rgba_getb(c);
|
||||
}
|
||||
|
||||
void fop_sequence_set_alpha(FileOp* fop, int index, int a)
|
||||
{
|
||||
int c = fop->seq.palette->getEntry(index);
|
||||
int r = rgba_getr(c);
|
||||
int g = rgba_getg(c);
|
||||
int b = rgba_getb(c);
|
||||
|
||||
fop->seq.palette->setEntry(index, rgba(r, g, b, a));
|
||||
}
|
||||
|
||||
void fop_sequence_get_alpha(FileOp* fop, int index, int* a)
|
||||
{
|
||||
ASSERT(index >= 0);
|
||||
if (index >= 0 && index < fop->seq.palette->size())
|
||||
*a = rgba_geta(fop->seq.palette->getEntry(index));
|
||||
else
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
Image* fop_sequence_image(FileOp* fop, PixelFormat pixelFormat, int w, int h)
|
||||
{
|
||||
Sprite* sprite;
|
||||
|
@ -135,6 +135,8 @@ namespace app {
|
||||
void fop_sequence_set_format_options(FileOp* fop, const base::SharedPtr<FormatOptions>& format_options);
|
||||
void fop_sequence_set_color(FileOp* fop, int index, int r, int g, int b);
|
||||
void fop_sequence_get_color(FileOp* fop, int index, int *r, int *g, int *b);
|
||||
void fop_sequence_set_alpha(FileOp* fop, int index, int a);
|
||||
void fop_sequence_get_alpha(FileOp* fop, int index, int* a);
|
||||
Image* fop_sequence_image(FileOp* fi, PixelFormat pixelFormat, int w, int h);
|
||||
|
||||
void fop_error(FileOp* fop, const char *error, ...);
|
||||
|
@ -39,7 +39,8 @@ class PngFormat : public FileFormat {
|
||||
FILE_SUPPORT_GRAY |
|
||||
FILE_SUPPORT_GRAYA |
|
||||
FILE_SUPPORT_INDEXED |
|
||||
FILE_SUPPORT_SEQUENCES;
|
||||
FILE_SUPPORT_SEQUENCES |
|
||||
FILE_SUPPORT_PALETTE_WITH_ALPHA;
|
||||
}
|
||||
|
||||
bool onLoad(FileOp* fop) override;
|
||||
@ -184,10 +185,6 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transparent palette entries
|
||||
std::vector<uint8_t> pal_alphas(256, 255);
|
||||
int mask_entry = -1;
|
||||
|
||||
// Read the palette
|
||||
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE &&
|
||||
png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
|
||||
@ -206,17 +203,19 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
// Read alpha values for palette entries
|
||||
png_bytep trans = NULL; // Transparent palette entries
|
||||
int num_trans = 0;
|
||||
int mask_entry = -1;
|
||||
|
||||
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
|
||||
|
||||
for (int i = 0; i < num_trans; ++i) {
|
||||
pal_alphas[i] = trans[i];
|
||||
fop_sequence_set_alpha(fop, i, trans[i]);
|
||||
|
||||
if (pal_alphas[i] < 128) {
|
||||
if (trans[i] < 255) {
|
||||
fop->seq.has_alpha = true; // Is a transparent sprite
|
||||
|
||||
if (mask_entry < 0)
|
||||
mask_entry = i;
|
||||
if (trans[i] == 0) {
|
||||
if (mask_entry < 0)
|
||||
mask_entry = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,8 +224,6 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
fop->document->sprite()->setTransparentColor(mask_entry);
|
||||
}
|
||||
|
||||
mask_entry = fop->document->sprite()->transparentColor();
|
||||
|
||||
/* Allocate the memory to hold the image using the fields of info_ptr. */
|
||||
|
||||
/* The easiest way to read the image: */
|
||||
@ -290,18 +287,10 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
|
||||
uint8_t* src_address = row_pointer;
|
||||
uint8_t* dst_address = (uint8_t*)image->getPixelAddress(0, y);
|
||||
unsigned int x, c;
|
||||
unsigned int x;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
|
||||
if (pal_alphas[c] < 128) {
|
||||
*(dst_address++) = mask_entry;
|
||||
}
|
||||
else {
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
||||
for (x=0; x<width; x++)
|
||||
*(dst_address++) = *(src_address++);
|
||||
}
|
||||
|
||||
fop_progress(fop,
|
||||
@ -415,20 +404,24 @@ bool PngFormat::onSave(FileOp* fop)
|
||||
png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
|
||||
|
||||
// If the sprite does not have a (visible) background layer, we
|
||||
// include the alpha information of palette entries to indicate
|
||||
// which is the transparent color.
|
||||
// put alpha=0 to the transparent color.
|
||||
int mask_entry = -1;
|
||||
if (fop->document->sprite()->backgroundLayer() == NULL ||
|
||||
!fop->document->sprite()->backgroundLayer()->isVisible()) {
|
||||
int mask_entry = fop->document->sprite()->transparentColor();
|
||||
int num_trans = mask_entry+1;
|
||||
png_bytep trans = (png_bytep)png_malloc(png_ptr, num_trans);
|
||||
|
||||
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);
|
||||
mask_entry = fop->document->sprite()->transparentColor();
|
||||
}
|
||||
|
||||
int num_trans = PNG_MAX_PALETTE_LENGTH;
|
||||
png_bytep trans = (png_bytep)png_malloc(png_ptr, num_trans);
|
||||
|
||||
for (c=0; c<num_trans; ++c) {
|
||||
int alpha = 255;
|
||||
fop_sequence_get_alpha(fop, c, &alpha);
|
||||
trans[c] = (c == mask_entry ? 0: alpha);
|
||||
}
|
||||
|
||||
png_set_tRNS(png_ptr, info_ptr, trans, num_trans, NULL);
|
||||
png_free(png_ptr, trans);
|
||||
}
|
||||
|
||||
/* Write the file header information. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user