summaryrefslogtreecommitdiff
path: root/Build/source/utils/sam2p/input-tga.ci
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-07-09 22:44:40 +0000
committerKarl Berry <karl@freefriends.org>2006-07-09 22:44:40 +0000
commit6684474324a04b457fe7019684c42eb68c4fea4b (patch)
tree63f0520f448252eb06342d5e0ea8e700c4976136 /Build/source/utils/sam2p/input-tga.ci
parentbb92d19047f4437f2d13091072ec63a5641dc43c (diff)
new graphics utility sam2p
git-svn-id: svn://tug.org/texlive/trunk@1792 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/sam2p/input-tga.ci')
-rw-r--r--Build/source/utils/sam2p/input-tga.ci604
1 files changed, 604 insertions, 0 deletions
diff --git a/Build/source/utils/sam2p/input-tga.ci b/Build/source/utils/sam2p/input-tga.ci
new file mode 100644
index 00000000000..9f8b72dcf0a
--- /dev/null
+++ b/Build/source/utils/sam2p/input-tga.ci
@@ -0,0 +1,604 @@
+/* This code is ripped from Autotrace-0.29. Small modifications by pts. */
+
+/* input-tga.ci reads tga files */
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* #include <unistd.h> */
+
+#include "at_bitmap.h"
+/* #include "message.h" */
+/* #include "xstd.h" */
+/* #include "input-tga.h" */ /* BUGFIX by pts: bmp -> tga */
+
+/* TODO:
+ - Handle loading images that aren't 8 bits per channel.
+*/
+
+/* Round up a division to the nearest integer. */
+#define ROUNDUP_DIVIDE(n,d) (((n) + (d - 1)) / (d))
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define INDEXED 1
+#define INDEXEDA 2
+#define GRAY 3
+#define TGA_RGB 5
+#define INDEXED_IMAGE 1
+#define INDEXEDA_IMAGE 2
+#define GRAY_IMAGE 3
+#define GRAYA_IMAGE 4
+#define TGA_RGB_IMAGE 5
+#define TGA_RGBA_IMAGE 6
+
+typedef struct _TgaSaveVals
+{
+ int rle;
+} TgaSaveVals;
+
+typedef struct _TgaSaveInterface
+{
+ int run;
+} TgaSaveInterface;
+
+struct tga_header
+{
+ unsigned char idLength;
+ unsigned char colorMapType;
+
+ /* The image type. */
+#define TGA_TYPE_MAPPED 1
+#define TGA_TYPE_COLOR 2
+#define TGA_TYPE_GRAY 3
+#define TGA_TYPE_MAPPED_RLE 9
+#define TGA_TYPE_COLOR_RLE 10
+#define TGA_TYPE_GRAY_RLE 11
+ unsigned char imageType;
+
+ /* 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;
+
+ /* Image Specification. */
+ unsigned char xOriginLo, xOriginHi;
+ unsigned char yOriginLo, yOriginHi;
+
+ unsigned char widthLo, widthHi;
+ unsigned char heightLo, heightHi;
+
+ unsigned char bpp;
+
+ /* Image descriptor.
+ 3-0: attribute bpp
+ 4: left-to-right ordering
+ 5: top-to-bottom ordering
+ 7-6: zero
+ */
+#define TGA_DESC_ABITS 0x0f
+#define TGA_DESC_HORIZONTAL 0x10
+#define TGA_DESC_VERTICAL 0x20
+ unsigned char descriptor;
+};
+
+#if 0
+static struct
+{
+ unsigned int extensionAreaOffset;
+ unsigned int developerDirectoryOffset;
+#define TGA_SIGNATURE "TRUEVISION-XFILE"
+ char signature[16];
+ char dot;
+ char null;
+} tga_footer;
+#endif
+
+
+static bitmap_type ReadImage (FILE *fp,
+ struct tga_header *hdr);
+#if PTS_SAM2P /**** pts ****/
+bitmap_type tga_load_image (FILE* filename)
+#else
+bitmap_type tga_load_image (at_string filename)
+#endif
+{
+ FILE *fp;
+ struct tga_header hdr;
+
+ bitmap_type image;
+
+ image.bitmap = NULL;
+
+ #if PTS_SAM2P /**** pts ****/
+ fp=filename;
+ #else
+ fp = fopen (filename, "rb");
+ if (!fp)
+ FATAL1 ("TGA: can't open \"%s\"\n", filename);
+ #endif
+
+ memset(&hdr, '\0', sizeof(hdr));
+
+#if 0
+ /* Check the footer. */
+ if (fseek (fp, 0L - (sizeof (tga_footer)), SEEK_END)
+ || fread (&tga_footer, sizeof (tga_footer), 1, fp) != 1)
+#if PTS_SAM2P
+ FATALP("TGA: Cannot read footer");
+#else
+ FATAL1 ("TGA: Cannot read footer from \"%s\"\n", filename);
+#endif
+ /* Check the signature. */
+ if (fseek (fp, 0, SEEK_SET) ||
+#else
+ if (0 ||
+#endif
+ fread (&hdr, sizeof (hdr), 1, fp) != 1)
+#if PTS_SAM2P
+ FATALP("TGA: Cannot read header");
+#else
+ FATAL1 ("TGA: Cannot read header from \"%s\"\n", filename);
+#endif
+
+ /* Skip the image ID field. */
+ {
+#if 0
+ if (hdr.idLength && fseek (fp, hdr.idLength, SEEK_CUR))
+#else
+ char buf[256];
+ if (hdr.idLength!=fread(buf, 1, hdr.idLength, fp))
+#endif
+#if PTS_SAM2P
+ FATALP("TGA: Cannot skip ID field");
+#else
+ FATAL1 ("TGA: Cannot skip ID field in \"%s\"\n", filename);
+#endif
+ }
+
+ image = ReadImage (fp, &hdr);
+ /* fclose (fp); */
+ return image;
+}
+
+
+static int
+std_fread (unsigned char *buf,
+ int datasize,
+ int nelems,
+ FILE *fp)
+{
+
+ return fread (buf, datasize, nelems, fp);
+}
+
+#define RLE_PACKETSIZE 0x80
+
+/* Decode a bufferful of file. */
+static int
+rle_fread (unsigned char *buf,
+ int datasize,
+ int nelems,
+ FILE *fp)
+{
+ static unsigned char *statebuf = 0;
+ static int statelen = 0;
+ static int laststate = 0;
+
+ int j, k;
+ int buflen, count, bytes;
+ unsigned char *p;
+
+ /* Scale the buffer length. */
+ buflen = nelems * datasize;
+
+ j = 0;
+ while (j < buflen)
+ {
+ if (laststate < statelen)
+ {
+ /* Copy bytes from our previously decoded buffer. */
+ bytes = MIN (buflen - j, statelen - laststate);
+ memcpy (buf + j, statebuf + laststate, bytes);
+ j += bytes;
+ laststate += bytes;
+
+ /* 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;
+ }
+
+return nelems;
+}
+
+static bitmap_type
+ReadImage (FILE *fp,
+ struct tga_header *hdr)
+{
+ bitmap_type image;
+ unsigned char *buffer;
+ unsigned char *alphas;
+
+ int width, height, bpp, abpp, pbpp, nalphas;
+ int j, k;
+ int pelbytes, wbytes, bsize, npels, pels;
+ int rle, badread;
+ int itype=0, dtype;
+ unsigned char *cmap = NULL;
+ int (*myfread)(unsigned char *, int, int, FILE *);
+
+ /* Find out whether the image is horizontally or vertically reversed. */
+ char horzrev = (char) (hdr->descriptor & TGA_DESC_HORIZONTAL);
+ char vertrev = (char) (!(hdr->descriptor & TGA_DESC_VERTICAL));
+
+ image.bitmap = NULL;
+
+ /* Reassemble the multi-byte values correctly, regardless of
+ host endianness. */
+ width = (hdr->widthHi << 8) | hdr->widthLo;
+ height = (hdr->heightHi << 8) | hdr->heightLo;
+
+ bpp = hdr->bpp;
+ abpp = hdr->descriptor & TGA_DESC_ABITS;
+
+ if (hdr->imageType == TGA_TYPE_COLOR ||
+ hdr->imageType == TGA_TYPE_COLOR_RLE)
+ pbpp = MIN (bpp / 3, 8) * 3;
+ else if (abpp < bpp)
+ pbpp = bpp - abpp;
+ else
+ pbpp = bpp;
+
+ 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");
+
+ if (abpp)
+ dtype = INDEXEDA_IMAGE;
+ else
+ dtype = INDEXED_IMAGE;
+ break;
+
+ case TGA_TYPE_GRAY_RLE:
+ rle = 1;
+ case TGA_TYPE_GRAY:
+ itype = GRAY;
+
+ if (abpp)
+ dtype = GRAYA_IMAGE;
+ else
+ dtype = GRAY_IMAGE;
+ break;
+
+ case TGA_TYPE_COLOR_RLE:
+ rle = 1;
+ case TGA_TYPE_COLOR:
+ itype = TGA_RGB;
+
+ if (abpp)
+ dtype = TGA_RGBA_IMAGE;
+ else
+ dtype = TGA_RGB_IMAGE;
+ 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;
+
+ index = (hdr->colorMapIndexHi << 8) | hdr->colorMapIndexLo;
+ length = (hdr->colorMapLengthHi << 8) | hdr->colorMapLengthLo;
+
+ if (length == 0)
+ FATALP1 ("TGA: invalid color map length ", length);
+
+ pelbytes = ROUNDUP_DIVIDE (hdr->colorMapSize, 8);
+ colors = length + index;
+ cmap = (unsigned char *) malloc (colors * pelbytes);
+
+ /* Zero the entries up to the beginning of the map. */
+ memset (cmap, 0, index * pelbytes);
+
+ /* Read in the rest of the colormap. */
+ if (fread (cmap + (index * pelbytes), pelbytes, length, fp) != length)
+ FATALP1 ("TGA: error reading colormap; ftell == ", ftell (fp));
+
+ /* If we have an alpha channel, then create a mapping to the alpha
+ values. */
+ if (pelbytes > 3)
+ alphas = (unsigned char *) malloc (colors);
+
+ k = 0;
+ for (j = 0; j < colors * pelbytes; j += pelbytes)
+ {
+ /* Swap from BGR to TGA_RGB. */
+ unsigned char tmp = cmap[j];
+ cmap[k ++] = cmap[j + 2];
+ cmap[k ++] = cmap[j + 1];
+ cmap[k ++] = tmp;
+
+ /* Take the alpha values out of the colormap. */
+ if (alphas)
+ alphas[nalphas ++] = cmap[j + 3];
+ }
+
+ /* If the last color was transparent, then omit it from the
+ mapping. */
+ if (nalphas && alphas[nalphas - 1] == 0)
+ colors --;
+
+ /* Now pretend as if we only have 8 bpp. */
+ abpp = 0;
+ pbpp = 8;
+ pelbytes = 1;
+ }
+ else
+ pelbytes = 3;
+
+ image.bitmap = (unsigned char *) malloc (width * height * 3 * sizeof(unsigned char));
+ BITMAP_WIDTH (image) = (unsigned short) width;
+ BITMAP_HEIGHT (image) = (unsigned short) height;
+ BITMAP_PLANES (image) = (unsigned short) 3;
+
+ /* Calculate TGA bytes per pixel. */
+ bpp = ROUNDUP_DIVIDE (pbpp + abpp, 8);
+
+ /* 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;
+
+ temp2 = temp = image.bitmap;
+ image.bitmap = temp3 = (unsigned char *) malloc (width * height * 3 * sizeof (unsigned char));
+
+ for (ypos = 0; ypos < height; ypos++)
+ {
+ for (xpos = 0; xpos < width; xpos++)
+ {
+ index = *temp2++;
+ *temp3++ = cmap[3*index+0];
+ *temp3++ = cmap[3*index+1];
+ *temp3++ = cmap[3*index+2];
+ }
+ }
+ free (temp);
+ free (cmap);
+ }
+
+ if (alphas)
+ free (alphas);
+
+ return image;
+} /* read_image */