mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-04 05:50:15 +00:00
Fix several issues decoding TGA files
This commit is contained in:
parent
9a75d01efe
commit
9e7e2767c8
@ -59,12 +59,10 @@ FileFormat* CreateTgaFormat()
|
|||||||
return new TgaFormat;
|
return new TgaFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rle_tga_read:
|
static void rle_tga_read8(FILE* f, uint8_t* address, int w, int type)
|
||||||
* Helper for reading 256 color RLE data from TGA files.
|
|
||||||
*/
|
|
||||||
static void rle_tga_read(unsigned char *address, int w, int type, FILE *f)
|
|
||||||
{
|
{
|
||||||
unsigned char value;
|
uint8_t* end = address + (w * (type == 1 ? 1: 2));
|
||||||
|
uint8_t value;
|
||||||
int count, g;
|
int count, g;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
@ -75,11 +73,14 @@ static void rle_tga_read(unsigned char *address, int w, int type, FILE *f)
|
|||||||
c += count;
|
c += count;
|
||||||
value = fgetc(f);
|
value = fgetc(f);
|
||||||
while (count--) {
|
while (count--) {
|
||||||
if (type == 1)
|
if (type == 1) {
|
||||||
*(address++) = value;
|
if (address+1 < end)
|
||||||
|
*(address++) = value;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
*((uint16_t*)address) = value;
|
if (address+2 < end)
|
||||||
address += sizeof(uint16_t);
|
*((uint16_t*)address) = graya(value, 255);
|
||||||
|
address += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,24 +88,25 @@ static void rle_tga_read(unsigned char *address, int w, int type, FILE *f)
|
|||||||
count++;
|
count++;
|
||||||
c += count;
|
c += count;
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
fread(address, 1, count, f);
|
if (address+count < end)
|
||||||
|
fread(address, 1, count, f);
|
||||||
address += count;
|
address += count;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (g=0; g<count; g++) {
|
for (g=0; g<count; g++) {
|
||||||
*((uint16_t*)address) = fgetc(f);
|
int c = fgetc(f);
|
||||||
address += sizeof(uint16_t);
|
if (address+2 < end)
|
||||||
|
*((uint16_t*)address) = graya(c, 255);
|
||||||
|
address += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (c < w);
|
} while (c < w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rle_tga_read32:
|
static void rle_tga_read32(FILE* f, uint32_t* address, int w, bool withAlpha)
|
||||||
* Helper for reading 32 bit RLE data from TGA files.
|
|
||||||
*/
|
|
||||||
static void rle_tga_read32(uint32_t* address, int w, FILE *f)
|
|
||||||
{
|
{
|
||||||
|
uint32_t* end = address + w;
|
||||||
unsigned char value[4];
|
unsigned char value[4];
|
||||||
int count;
|
int count;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
@ -115,25 +117,28 @@ static void rle_tga_read32(uint32_t* address, int w, FILE *f)
|
|||||||
count = (count & 0x7F) + 1;
|
count = (count & 0x7F) + 1;
|
||||||
c += count;
|
c += count;
|
||||||
fread(value, 1, 4, f);
|
fread(value, 1, 4, f);
|
||||||
while (count--)
|
while (count--) {
|
||||||
*(address++) = rgba(value[2], value[1], value[0], value[3]);
|
if (address+1 < end)
|
||||||
|
*(address++) = rgba(value[2], value[1], value[0],
|
||||||
|
withAlpha ? value[3]: 255);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
count++;
|
count++;
|
||||||
c += count;
|
c += count;
|
||||||
while (count--) {
|
while (count--) {
|
||||||
fread(value, 1, 4, f);
|
fread(value, 1, 4, f);
|
||||||
*(address++) = rgba(value[2], value[1], value[0], value[3]);
|
if (address+1 < end)
|
||||||
|
*(address++) = rgba(value[2], value[1], value[0],
|
||||||
|
withAlpha ? value[3]: 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (c < w);
|
} while (c < w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rle_tga_read24:
|
static void rle_tga_read24(FILE* f, uint32_t* address, int w)
|
||||||
* Helper for reading 24 bit RLE data from TGA files.
|
|
||||||
*/
|
|
||||||
static void rle_tga_read24(uint32_t* address, int w, FILE *f)
|
|
||||||
{
|
{
|
||||||
|
uint32_t* end = address + w;
|
||||||
unsigned char value[4];
|
unsigned char value[4];
|
||||||
int count;
|
int count;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
@ -144,25 +149,26 @@ static void rle_tga_read24(uint32_t* address, int w, FILE *f)
|
|||||||
count = (count & 0x7F) + 1;
|
count = (count & 0x7F) + 1;
|
||||||
c += count;
|
c += count;
|
||||||
fread(value, 1, 3, f);
|
fread(value, 1, 3, f);
|
||||||
while (count--)
|
while (count--) {
|
||||||
*(address++) = rgba(value[2], value[1], value[0], 255);
|
if (address+1 < end)
|
||||||
|
*(address++) = rgba(value[2], value[1], value[0], 255);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
count++;
|
count++;
|
||||||
c += count;
|
c += count;
|
||||||
while (count--) {
|
while (count--) {
|
||||||
fread(value, 1, 3, f);
|
fread(value, 1, 3, f);
|
||||||
*(address++) = rgba(value[2], value[1], value[0], 255);
|
if (address+1 < end)
|
||||||
|
*(address++) = rgba(value[2], value[1], value[0], 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (c < w);
|
} while (c < w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rle_tga_read16:
|
|
||||||
* Helper for reading 16 bit RLE data from TGA files.
|
|
||||||
*/
|
|
||||||
static void rle_tga_read16(uint32_t* address, int w, FILE *f)
|
static void rle_tga_read16(uint32_t* address, int w, FILE *f)
|
||||||
{
|
{
|
||||||
|
uint32_t* end = address + w;
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
uint32_t color;
|
uint32_t color;
|
||||||
int count;
|
int count;
|
||||||
@ -174,22 +180,26 @@ static void rle_tga_read16(uint32_t* address, int w, FILE *f)
|
|||||||
count = (count & 0x7F) + 1;
|
count = (count & 0x7F) + 1;
|
||||||
c += count;
|
c += count;
|
||||||
value = fgetw(f);
|
value = fgetw(f);
|
||||||
color = rgba(scale_5bits_to_8bits(((value >> 10) & 0x1F)),
|
color = rgba(scale_5bits_to_8bits((value >> 10) & 0x1F),
|
||||||
scale_5bits_to_8bits(((value >> 5) & 0x1F)),
|
scale_5bits_to_8bits((value >> 5) & 0x1F),
|
||||||
scale_5bits_to_8bits((value & 0x1F)), 255);
|
scale_5bits_to_8bits(value & 0x1F), 255);
|
||||||
|
|
||||||
while (count--)
|
while (count--) {
|
||||||
*(address++) = color;
|
if (address+1 < end)
|
||||||
|
*(address++) = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
count++;
|
count++;
|
||||||
c += count;
|
c += count;
|
||||||
while (count--) {
|
while (count--) {
|
||||||
value = fgetw(f);
|
value = fgetw(f);
|
||||||
color = rgba(scale_5bits_to_8bits(((value >> 10) & 0x1F)),
|
color = rgba(scale_5bits_to_8bits((value >> 10) & 0x1F),
|
||||||
scale_5bits_to_8bits(((value >> 5) & 0x1F)),
|
scale_5bits_to_8bits((value >> 5) & 0x1F),
|
||||||
scale_5bits_to_8bits((value & 0x1F)), 255);
|
scale_5bits_to_8bits(value & 0x1F), 255);
|
||||||
*(address++) = color;
|
|
||||||
|
if (address+1 < end)
|
||||||
|
*(address++) = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (c < w);
|
} while (c < w);
|
||||||
@ -232,9 +242,9 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
c = fgetw(f);
|
c = fgetw(f);
|
||||||
image_palette[i][0] = (c & 0x1F) << 3;
|
image_palette[i][0] = scale_5bits_to_8bits(c & 0x1F);
|
||||||
image_palette[i][1] = ((c >> 5) & 0x1F) << 3;
|
image_palette[i][1] = scale_5bits_to_8bits((c >> 5) & 0x1F);
|
||||||
image_palette[i][2] = ((c >> 10) & 0x1F) << 3;
|
image_palette[i][2] = scale_5bits_to_8bits((c >> 10) & 0x1F);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
@ -265,6 +275,7 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
image_type &= 7;
|
image_type &= 7;
|
||||||
|
|
||||||
PixelFormat pixelFormat;
|
PixelFormat pixelFormat;
|
||||||
|
bool withAlpha = false;
|
||||||
|
|
||||||
switch (image_type) {
|
switch (image_type) {
|
||||||
|
|
||||||
@ -291,7 +302,8 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
(bpp != 24) && (bpp != 32))) {
|
(bpp != 24) && (bpp != 32))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((descriptor_bits & 0xf) == 8)
|
withAlpha = ((descriptor_bits & 0xf) == 8);
|
||||||
|
if (withAlpha)
|
||||||
fop->sequenceSetHasAlpha(true);
|
fop->sequenceSetHasAlpha(true);
|
||||||
pixelFormat = IMAGE_RGB;
|
pixelFormat = IMAGE_RGB;
|
||||||
break;
|
break;
|
||||||
@ -325,7 +337,7 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
if (compressed)
|
if (compressed)
|
||||||
rle_tga_read(image->getPixelAddress(0, yc), image_width, image_type, f);
|
rle_tga_read8(f, image->getPixelAddress(0, yc), image_width, image_type);
|
||||||
else if (image_type == 1)
|
else if (image_type == 1)
|
||||||
fread(image->getPixelAddress(0, yc), 1, image_width, f);
|
fread(image->getPixelAddress(0, yc), 1, image_width, f);
|
||||||
else {
|
else {
|
||||||
@ -337,18 +349,21 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
case 2:
|
case 2:
|
||||||
if (bpp == 32) {
|
if (bpp == 32) {
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
rle_tga_read32((uint32_t*)image->getPixelAddress(0, yc), image_width, f);
|
rle_tga_read32(f, (uint32_t*)image->getPixelAddress(0, yc), image_width,
|
||||||
|
withAlpha);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (x=0; x<image_width; x++) {
|
for (x=0; x<image_width; x++) {
|
||||||
fread(rgb, 1, 4, f);
|
fread(rgb, 1, 4, f);
|
||||||
put_pixel_fast<RgbTraits>(image, x, yc, rgba(rgb[2], rgb[1], rgb[0], rgb[3]));
|
put_pixel_fast<RgbTraits>(image, x, yc,
|
||||||
|
rgba(rgb[2], rgb[1], rgb[0],
|
||||||
|
withAlpha ? rgb[3]: 255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bpp == 24) {
|
else if (bpp == 24) {
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
rle_tga_read24((uint32_t*)image->getPixelAddress(0, yc), image_width, f);
|
rle_tga_read24(f, (uint32_t*)image->getPixelAddress(0, yc), image_width);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (x=0; x<image_width; x++) {
|
for (x=0; x<image_width; x++) {
|
||||||
@ -364,9 +379,10 @@ bool TgaFormat::onLoad(FileOp* fop)
|
|||||||
else {
|
else {
|
||||||
for (x=0; x<image_width; x++) {
|
for (x=0; x<image_width; x++) {
|
||||||
c = fgetw(f);
|
c = fgetw(f);
|
||||||
put_pixel_fast<RgbTraits>(image, x, yc, rgba(((c >> 10) & 0x1F),
|
put_pixel_fast<RgbTraits>(
|
||||||
((c >> 5) & 0x1F),
|
image, x, yc, rgba(scale_5bits_to_8bits((c >> 10) & 0x1F),
|
||||||
(c & 0x1F), 255));
|
scale_5bits_to_8bits((c >> 5) & 0x1F),
|
||||||
|
scale_5bits_to_8bits(c & 0x1F), 255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,7 +435,8 @@ bool TgaFormat::onSave(FileOp* fop)
|
|||||||
fputc(depth, f); /* bits per pixel */
|
fputc(depth, f); /* bits per pixel */
|
||||||
|
|
||||||
/* descriptor (bottom to top, 8-bit alpha) */
|
/* descriptor (bottom to top, 8-bit alpha) */
|
||||||
fputc(image->pixelFormat() == IMAGE_RGB && !fop->document()->sprite()->isOpaque()? 8: 0, f);
|
fputc(image->pixelFormat() == IMAGE_RGB &&
|
||||||
|
!fop->document()->sprite()->isOpaque() ? 8: 0, f);
|
||||||
|
|
||||||
if (need_pal) {
|
if (need_pal) {
|
||||||
for (y=0; y<256; y++) {
|
for (y=0; y<256; y++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user