mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-03 21:46:20 +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);
|
*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)
|
Image* fop_sequence_image(FileOp* fop, PixelFormat pixelFormat, int w, int h)
|
||||||
{
|
{
|
||||||
Sprite* sprite;
|
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_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_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_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);
|
Image* fop_sequence_image(FileOp* fi, PixelFormat pixelFormat, int w, int h);
|
||||||
|
|
||||||
void fop_error(FileOp* fop, const char *error, ...);
|
void fop_error(FileOp* fop, const char *error, ...);
|
||||||
|
@ -39,7 +39,8 @@ class PngFormat : public FileFormat {
|
|||||||
FILE_SUPPORT_GRAY |
|
FILE_SUPPORT_GRAY |
|
||||||
FILE_SUPPORT_GRAYA |
|
FILE_SUPPORT_GRAYA |
|
||||||
FILE_SUPPORT_INDEXED |
|
FILE_SUPPORT_INDEXED |
|
||||||
FILE_SUPPORT_SEQUENCES;
|
FILE_SUPPORT_SEQUENCES |
|
||||||
|
FILE_SUPPORT_PALETTE_WITH_ALPHA;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onLoad(FileOp* fop) override;
|
bool onLoad(FileOp* fop) override;
|
||||||
@ -184,10 +185,6 @@ bool PngFormat::onLoad(FileOp* fop)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transparent palette entries
|
|
||||||
std::vector<uint8_t> pal_alphas(256, 255);
|
|
||||||
int mask_entry = -1;
|
|
||||||
|
|
||||||
// Read the palette
|
// Read the palette
|
||||||
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE &&
|
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE &&
|
||||||
png_get_PLTE(png_ptr, info_ptr, &palette, &num_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
|
// Read alpha values for palette entries
|
||||||
png_bytep trans = NULL; // Transparent palette entries
|
png_bytep trans = NULL; // Transparent palette entries
|
||||||
int num_trans = 0;
|
int num_trans = 0;
|
||||||
|
int mask_entry = -1;
|
||||||
|
|
||||||
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
|
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
|
||||||
|
|
||||||
for (int i = 0; i < num_trans; ++i) {
|
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
|
fop->seq.has_alpha = true; // Is a transparent sprite
|
||||||
|
if (trans[i] == 0) {
|
||||||
if (mask_entry < 0)
|
if (mask_entry < 0)
|
||||||
mask_entry = i;
|
mask_entry = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,8 +224,6 @@ bool PngFormat::onLoad(FileOp* fop)
|
|||||||
fop->document->sprite()->setTransparentColor(mask_entry);
|
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. */
|
/* Allocate the memory to hold the image using the fields of info_ptr. */
|
||||||
|
|
||||||
/* The easiest way to read the image: */
|
/* 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) {
|
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
|
||||||
uint8_t* src_address = row_pointer;
|
uint8_t* src_address = row_pointer;
|
||||||
uint8_t* dst_address = (uint8_t*)image->getPixelAddress(0, y);
|
uint8_t* dst_address = (uint8_t*)image->getPixelAddress(0, y);
|
||||||
unsigned int x, c;
|
unsigned int x;
|
||||||
|
|
||||||
for (x=0; x<width; x++) {
|
for (x=0; x<width; x++)
|
||||||
c = *(src_address++);
|
*(dst_address++) = *(src_address++);
|
||||||
|
|
||||||
if (pal_alphas[c] < 128) {
|
|
||||||
*(dst_address++) = mask_entry;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*(dst_address++) = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fop_progress(fop,
|
fop_progress(fop,
|
||||||
@ -415,20 +404,24 @@ bool PngFormat::onSave(FileOp* fop)
|
|||||||
png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
|
png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
|
||||||
|
|
||||||
// If the sprite does not have a (visible) background layer, we
|
// If the sprite does not have a (visible) background layer, we
|
||||||
// include the alpha information of palette entries to indicate
|
// put alpha=0 to the transparent color.
|
||||||
// which is the transparent color.
|
int mask_entry = -1;
|
||||||
if (fop->document->sprite()->backgroundLayer() == NULL ||
|
if (fop->document->sprite()->backgroundLayer() == NULL ||
|
||||||
!fop->document->sprite()->backgroundLayer()->isVisible()) {
|
!fop->document->sprite()->backgroundLayer()->isVisible()) {
|
||||||
int mask_entry = fop->document->sprite()->transparentColor();
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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. */
|
/* Write the file header information. */
|
||||||
|
Loading…
Reference in New Issue
Block a user