Implement reading 16 and 32-bit color-mapped TGA images
Currently only 24-bit color-mapped images can be read. Closes #18966. Co-authored-by: Muster128 <Muster128@trac.wxwidgets.org>
This commit is contained in:
@@ -192,6 +192,22 @@ void Palette_GetRGB(const unsigned char *palette, unsigned int paletteCount,
|
|||||||
*blue = palette[(paletteCount * 2) + index];
|
*blue = palette[(paletteCount * 2) + index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Palette_GetRGBA(const unsigned char *palette, unsigned int paletteCount,
|
||||||
|
unsigned int index,
|
||||||
|
unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char* alpha)
|
||||||
|
{
|
||||||
|
if (index >= paletteCount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*red = palette[index];
|
||||||
|
*green = palette[(paletteCount * 1) + index];
|
||||||
|
*blue = palette[(paletteCount * 2) + index];
|
||||||
|
*alpha = palette[(paletteCount * 3) + index];
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void Palette_SetRGB(unsigned char *palette, unsigned int paletteCount,
|
void Palette_SetRGB(unsigned char *palette, unsigned int paletteCount,
|
||||||
unsigned int index,
|
unsigned int index,
|
||||||
@@ -202,6 +218,17 @@ void Palette_SetRGB(unsigned char *palette, unsigned int paletteCount,
|
|||||||
palette[(paletteCount * 2) + index] = blue;
|
palette[(paletteCount * 2) + index] = blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Palette_SetRGBA(unsigned char *palette, unsigned int paletteCount,
|
||||||
|
unsigned int index,
|
||||||
|
unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
|
||||||
|
{
|
||||||
|
palette[index] = red;
|
||||||
|
palette[(paletteCount * 1) + index] = green;
|
||||||
|
palette[(paletteCount * 2) + index] = blue;
|
||||||
|
palette[(paletteCount * 3) + index] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int ReadTGA(wxImage* image, wxInputStream& stream)
|
int ReadTGA(wxImage* image, wxInputStream& stream)
|
||||||
{
|
{
|
||||||
@@ -214,6 +241,8 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
short imageType = hdr[HDR_IMAGETYPE];
|
short imageType = hdr[HDR_IMAGETYPE];
|
||||||
unsigned int paletteLength = hdr[HDR_PALETTELENGTH]
|
unsigned int paletteLength = hdr[HDR_PALETTELENGTH]
|
||||||
+ 256 * hdr[HDR_PALETTELENGTH + 1];
|
+ 256 * hdr[HDR_PALETTELENGTH + 1];
|
||||||
|
unsigned int paletteStart = hdr[HDR_PALETTESTART]
|
||||||
|
+ 256 * hdr[HDR_PALETTESTART + 1];
|
||||||
int width = (hdr[HDR_WIDTH] + 256 * hdr[HDR_WIDTH + 1]) -
|
int width = (hdr[HDR_WIDTH] + 256 * hdr[HDR_WIDTH + 1]) -
|
||||||
(hdr[HDR_XORIGIN] + 256 * hdr[HDR_XORIGIN + 1]);
|
(hdr[HDR_XORIGIN] + 256 * hdr[HDR_XORIGIN + 1]);
|
||||||
int height = (hdr[HDR_HEIGHT] + 256 * hdr[HDR_HEIGHT + 1]) -
|
int height = (hdr[HDR_HEIGHT] + 256 * hdr[HDR_HEIGHT + 1]) -
|
||||||
@@ -241,8 +270,15 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
|
|
||||||
unsigned char *dst = image->GetData();
|
unsigned char *dst = image->GetData();
|
||||||
|
|
||||||
|
short palettebpp = hdr[HDR_PALETTEBITS];
|
||||||
|
if (colorType == wxTGA_MAPPED && !(palettebpp == 15 || palettebpp == 16 || palettebpp == 24 || palettebpp == 32))
|
||||||
|
{
|
||||||
|
return wxTGA_INVFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* alpha = NULL;
|
unsigned char* alpha = NULL;
|
||||||
if (bpp == 16 || bpp == 32)
|
if ((colorType != wxTGA_MAPPED && (bpp == 16 || bpp == 32)) ||
|
||||||
|
(colorType == wxTGA_MAPPED && (palettebpp == 16 || palettebpp == 32)))
|
||||||
{
|
{
|
||||||
image->SetAlpha();
|
image->SetAlpha();
|
||||||
|
|
||||||
@@ -253,22 +289,54 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
if (stream.SeekI(offset, wxFromStart) == wxInvalidOffset)
|
if (stream.SeekI(offset, wxFromStart) == wxInvalidOffset)
|
||||||
return wxTGA_INVFORMAT;
|
return wxTGA_INVFORMAT;
|
||||||
|
|
||||||
|
|
||||||
wxScopedArray<unsigned char> palette;
|
wxScopedArray<unsigned char> palette;
|
||||||
// Load a palette if we have one.
|
// Load a palette if we have one.
|
||||||
if (colorType == wxTGA_MAPPED)
|
if (colorType == wxTGA_MAPPED)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
wxScopedArray<unsigned char> paletteTmp(paletteLength*3);
|
int palEntrySize = (palettebpp == 15 || palettebpp == 24) ? 3 : 4;
|
||||||
|
wxScopedArray<unsigned char> paletteTmp(paletteLength*palEntrySize);
|
||||||
palette.swap(paletteTmp);
|
palette.swap(paletteTmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char buf[3];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < paletteLength; i++)
|
for (unsigned int i = 0; i < paletteLength; i++)
|
||||||
{
|
{
|
||||||
stream.Read(buf, 3);
|
unsigned char buf[4];
|
||||||
|
stream.Read(buf, (palettebpp == 15) ? 2 : palettebpp/8);
|
||||||
|
|
||||||
Palette_SetRGB(palette.get(), paletteLength, i, buf[2], buf[1], buf[0]);
|
switch(palettebpp)
|
||||||
|
{
|
||||||
|
case 15:
|
||||||
|
{
|
||||||
|
unsigned char r = (buf[1] & 0x7C) << 1;
|
||||||
|
r |= r >> 5;
|
||||||
|
unsigned char g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xE0) >> 2);
|
||||||
|
g |= g >> 5;
|
||||||
|
unsigned char b = (buf[0] & 0x1F) << 3;
|
||||||
|
b |= b >> 5;
|
||||||
|
Palette_SetRGB(palette.get(), paletteLength, paletteStart+i, r, g, b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
{
|
||||||
|
unsigned char a = (buf[1] & 0x80) ? 0 : 255;
|
||||||
|
unsigned char r = (buf[1] & 0x7C) << 1;
|
||||||
|
r |= r >> 5;
|
||||||
|
unsigned char g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xE0) >> 2);
|
||||||
|
g |= g >> 5;
|
||||||
|
unsigned char b = (buf[0] & 0x1F) << 3;
|
||||||
|
b |= b >> 5;
|
||||||
|
Palette_SetRGBA(palette.get(), paletteLength, paletteStart+i, r, g, b, a);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
Palette_SetRGB(palette.get(), paletteLength, paletteStart+i, buf[2], buf[1], buf[0]);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
Palette_SetRGBA(palette.get(), paletteLength, paletteStart+i, buf[2], buf[1], buf[0], buf[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_PALETTE
|
#if wxUSE_PALETTE
|
||||||
@@ -313,12 +381,24 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
{
|
{
|
||||||
for (unsigned long index = 0; index < imageSize; index += pixelSize)
|
for (unsigned long index = 0; index < imageSize; index += pixelSize)
|
||||||
{
|
{
|
||||||
Palette_GetRGB(palette.get(), paletteLength,
|
if ( alpha )
|
||||||
imageData[index], &r, &g, &b);
|
{
|
||||||
|
unsigned char a;
|
||||||
*(dst++) = r;
|
Palette_GetRGBA(palette.get(), paletteLength,
|
||||||
*(dst++) = g;
|
imageData[index], &r, &g, &b, &a);
|
||||||
*(dst++) = b;
|
*dst++ = r;
|
||||||
|
*dst++ = g;
|
||||||
|
*dst++ = b;
|
||||||
|
*alpha++ = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Palette_GetRGB(palette.get(), paletteLength,
|
||||||
|
imageData[index], &r, &g, &b);
|
||||||
|
*dst++ = r;
|
||||||
|
*dst++ = g;
|
||||||
|
*dst++ = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -508,12 +588,24 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
{
|
{
|
||||||
for (unsigned long index = 0; index < imageSize; index += pixelSize)
|
for (unsigned long index = 0; index < imageSize; index += pixelSize)
|
||||||
{
|
{
|
||||||
Palette_GetRGB(palette.get(), paletteLength,
|
if ( alpha )
|
||||||
imageData[index], &r, &g, &b);
|
{
|
||||||
|
unsigned char a;
|
||||||
*(dst++) = r;
|
Palette_GetRGBA(palette.get(), paletteLength,
|
||||||
*(dst++) = g;
|
imageData[index], &r, &g, &b, &a);
|
||||||
*(dst++) = b;
|
*dst++ = r;
|
||||||
|
*dst++ = g;
|
||||||
|
*dst++ = b;
|
||||||
|
*alpha++ = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Palette_GetRGB(palette.get(), paletteLength,
|
||||||
|
imageData[index], &r, &g, &b);
|
||||||
|
*dst++ = r;
|
||||||
|
*dst++ = g;
|
||||||
|
*dst++ = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user