/* Color Map Specification. */
/* We need to separately specify high and low bytes to avoid endianness
and alignment problems. */
unsigned char colorMapIndexLo, colorMapIndexHi;
unsigned char colorMapLengthLo, colorMapLengthHi;
unsigned char colorMapSize;
/* If we used up all of our state bytes, then reset them. */
if (laststate >= statelen)
{
laststate = 0;
statelen = 0;
}
/* If we filled the buffer, then exit the loop. */
if (j >= buflen)
break;
}
/* Decode the next packet. */
count = fgetc (fp);
if (count == EOF)
{
return j / datasize;
}
/* Scale the byte length to the size of the data. */
bytes = ((count & ~RLE_PACKETSIZE) + 1) * datasize;
if (j + bytes <= buflen)
{
/* We can copy directly into the image buffer. */
p = buf + j;
}
else {
/* Allocate the state buffer if we haven't already. */
if (!statebuf)
statebuf = (unsigned char *) malloc (RLE_PACKETSIZE * datasize);
p = statebuf;
}
if (count & RLE_PACKETSIZE)
{
/* Fill the buffer with the next value. */
if (fread (p, datasize, 1, fp) != 1)
{
return j / datasize;
}
/* Optimized case for single-byte encoded data. */
if (datasize == 1)
memset (p + 1, *p, bytes - 1);
else
for (k = datasize; k < bytes; k += datasize)
memcpy (p + k, p, datasize);
}
else
{
/* Read in the buffer. */
if (fread (p, bytes, 1, fp) != 1)
{
return j / datasize;
}
}
/* We may need to copy bytes from the state buffer. */
if (p == statebuf)
statelen = bytes;
else
j += bytes;
}
if (abpp + pbpp > bpp)
{
WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is greater than ",bpp," total bits per pixel");
/* Assume that alpha bits were set incorrectly. */
abpp = bpp - pbpp;
WARNINGP1 ("TGA: reducing to * bit alpha: ", abpp);
}
else if (abpp + pbpp < bpp)
{
WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is less than ",bpp," total bits per pixel");
/* Again, assume that alpha bits were set incorrectly. */
abpp = bpp - pbpp;
WARNINGP1 ("TGA: increasing to * bit alpha: ", abpp);
}
rle = 0;
switch (hdr->imageType)
{
case TGA_TYPE_MAPPED_RLE:
rle = 1;
case TGA_TYPE_MAPPED:
itype = INDEXED;
/* Find the size of palette elements. */
pbpp = MIN (hdr->colorMapSize / 3, 8) * 3;
if (pbpp < hdr->colorMapSize)
abpp = hdr->colorMapSize - pbpp;
else
abpp = 0;
if (bpp != 8)
/* We can only cope with 8-bit indices. */
FATALP ("TGA: index sizes other than 8 bits are unimplemented");
break;
case TGA_TYPE_GRAY_RLE:
rle = 1;
case TGA_TYPE_GRAY:
itype = GRAY;
break;
case TGA_TYPE_COLOR_RLE:
rle = 1;
case TGA_TYPE_COLOR:
itype = TGA_RGB;
break;
default:
FATALP1 ("TGA: unrecognized image type ", (unsigned)hdr->imageType);
}
if ((abpp && abpp != 8) ||
((itype == TGA_RGB || itype == INDEXED) && pbpp != 24) ||
(itype == GRAY && pbpp != 8))
/* FIXME: We haven't implemented bit-packed fields yet. */
FATALP ("TGA: channel sizes other than 8 bits are unimplemented");
/* Check that we have a color map only when we need it. */
if (itype == INDEXED)
{
if (hdr->colorMapType != 1)
FATALP1 ("TGA: indexed image has invalid color map type ",
(unsigned)hdr->colorMapType);
}
else if (hdr->colorMapType != 0)
FATALP1 ("TGA: non-indexed image has invalid color map type ",
(unsigned)hdr->colorMapType);
alphas = 0;
nalphas = 0;
if (hdr->colorMapType == 1)
{
/* We need to read in the colormap. */
int index, colors;
unsigned int length;
/* Maybe we need to reverse the data. */
buffer = NULL;
if (horzrev || vertrev)
buffer = (unsigned char *) malloc (width * height * pelbytes * sizeof (unsigned char));
if (rle)
myfread = rle_fread;
else
myfread = std_fread;
wbytes = width * pelbytes;
badread = 0;
npels = width * height;
bsize = wbytes * height;
/* Suck in the data one height at a time. */
if (badread)
pels = 0;
else
pels = (*myfread) (image.bitmap, bpp, npels, fp);
if (pels != npels)
{
if (!badread)
{
/* Probably premature end of file. */
WARNINGP1 ("TGA: error reading; ftell == ", ftell (fp));
badread = 1;
}
/* Fill the rest of this tile with zeros. */
memset (image.bitmap + (pels * bpp), 0, ((npels - pels) * bpp));
}
/* If we have indexed alphas, then set them. */
if (nalphas)
{
/* Start at the end of the buffer, and work backwards. */
k = (npels - 1) * bpp;
for (j = bsize - pelbytes; j >= 0; j -= pelbytes)
{
/* Find the alpha for this index. */
image.bitmap[j + 1] = alphas[image.bitmap[k]];
image.bitmap[j] = image.bitmap[k --];
}
}
if (itype == GRAY)
for (j = bsize/3 - 1; j >= 0; j -= 1)
{
/* Find the alpha for this index. */
image.bitmap[3*j] = image.bitmap[j];
image.bitmap[3*j+1] = image.bitmap[j];
image.bitmap[3*j+2] = image.bitmap[j];
}
if (pelbytes >= 3)
{
/* Rearrange the colors from BGR to TGA_RGB. */
for (j = 0; j < bsize; j += pelbytes)
{
unsigned char tmp = image.bitmap[j];
image.bitmap[j] = image.bitmap[j + 2];
image.bitmap[j + 2] = tmp;
}
}
if (horzrev || vertrev)
{
unsigned char *tmp;
if (vertrev)
{
/* We need to mirror only vertically. */
for (j = 0; j < bsize; j += wbytes)
memcpy (buffer + j,
image.bitmap + bsize - (j + wbytes), wbytes);
}
else if (horzrev)
{
/* We need to mirror only horizontally. */
for (j = 0; j < bsize; j += wbytes)
for (k = 0; k < wbytes; k += pelbytes)
memcpy (buffer + k + j,
image.bitmap + (j + wbytes) - (k + pelbytes), pelbytes);
}
else
{
/* Completely reverse the pixels in the buffer. */
for (j = 0; j < bsize; j += pelbytes)
memcpy (buffer + j,
image.bitmap + bsize - (j + pelbytes), pelbytes);
}
/* Swap the buffers because we modified them. */
tmp = buffer;
buffer = image.bitmap;
image.bitmap = tmp;
}
if (fgetc (fp) != EOF)
WARNINGP ("TGA: too much input data, ignoring extra...");
free (buffer);
if (hdr->colorMapType == 1)
{
unsigned char *temp, *temp2, *temp3;
unsigned char index;
int xpos, ypos;