+ }
+}
+
+
+
+/*
+=item color_pack
+
+Packs a colour into an array of bytes, for 2 byte type the first byte
+will be GGGBBBBB, and the second will be ARRRRRGG. "A" represents an
+attribute bit. The 3 byte entry contains 1 byte each of blue, green,
+and red. The 4 byte entry contains 1 byte each of blue, green, red,
+and attribute.
+
+ buf - destination buffer
+ bitspp - bits per pixel
+ val - color to pack
+
+=cut
+*/
+
+static
+void
+color_pack(unsigned char *buf, int bitspp, i_color *val) {
+ switch (bitspp) {
+ case 8:
+ buf[0] = val->gray.gray_color;
+ break;
+ case 16:
+ buf[0] = (val->rgba.b >> 3);
+ buf[0] |= (val->rgba.g & 0x38) << 2;
+ buf[1] = (val->rgba.r & 0xf8)>> 1;
+ buf[1] |= (val->rgba.g >> 6);
+ buf[1] |= val->rgba.a > 0x7f ? 0 : 0x80;
+ break;
+ case 15:
+ buf[0] = (val->rgba.b >> 3);
+ buf[0] |= (val->rgba.g & 0x38) << 2;
+ buf[1] = (val->rgba.r & 0xf8)>> 1;
+ buf[1] |= (val->rgba.g >> 6);
+ break;
+ case 24:
+ buf[0] = val->rgb.b;
+ buf[1] = val->rgb.g;
+ buf[2] = val->rgb.r;
+ break;
+ case 32:
+ buf[0] = val->rgba.b;
+ buf[1] = val->rgba.g;
+ buf[2] = val->rgba.r;
+ buf[3] = val->rgba.a;
+ break;
+ }
+}
+
+
+/*
+=item find_repeat
+
+Helper function for rle compressor to find the next triple repeat of the
+same pixel value in buffer.
+
+ buf - buffer
+ length - number of pixel values in buffer
+ bytepp - number of bytes in a pixel value
+
+=cut
+*/
+
+static
+int
+find_repeat(unsigned char *buf, int length, int bytepp) {
+ int i = 0;
+
+ while(i<length-1) {
+ if(memcmp(buf+i*bytepp, buf+(i+1)*bytepp, bytepp) == 0) {
+ if (i == length-2) return -1;
+ if (memcmp(buf+(i+1)*bytepp, buf+(i+2)*bytepp,bytepp) == 0)
+ return i;
+ else i++;
+ }
+ i++;
+ }
+ return -1;
+}
+
+
+/*
+=item find_span
+
+Helper function for rle compressor to find the length of a span where
+the same pixel value is in the buffer.
+
+ buf - buffer
+ length - number of pixel values in buffer
+ bytepp - number of bytes in a pixel value
+
+=cut
+*/
+
+static
+int
+find_span(unsigned char *buf, int length, int bytepp) {
+ int i = 0;
+ while(i<length) {
+ if(memcmp(buf, buf+(i*bytepp), bytepp) != 0) return i;
+ i++;
+ }
+ return length;
+}
+
+
+/*
+=item tga_header_unpack(header, headbuf)
+
+Unpacks the header structure into from buffer and stores
+in the header structure.
+
+ header - header structure
+ headbuf - buffer to unpack from
+
+=cut
+*/
+
+static
+void
+tga_header_unpack(tga_header *header, unsigned char headbuf[18]) {
+ header->idlength = headbuf[0];
+ header->colourmaptype = headbuf[1];
+ header->datatypecode = headbuf[2];
+ header->colourmaporigin = (headbuf[4] << 8) + headbuf[3];
+ header->colourmaplength = (headbuf[6] << 8) + headbuf[5];
+ header->colourmapdepth = headbuf[7];
+ header->x_origin = (headbuf[9] << 8) + headbuf[8];
+ header->y_origin = (headbuf[11] << 8) + headbuf[10];
+ header->width = (headbuf[13] << 8) + headbuf[12];
+ header->height = (headbuf[15] << 8) + headbuf[14];
+ header->bitsperpixel = headbuf[16];
+ header->imagedescriptor = headbuf[17];
+}
+
+
+/* this function should never produce diagnostics to stdout, maybe to the logfile */
+int
+tga_header_verify(unsigned char headbuf[18]) {
+ tga_header header;
+ tga_header_unpack(&header, headbuf);
+ switch (header.datatypecode) {
+ default:
+ /*printf("bad typecode!\n");*/
+ return 0;
+ case 1: /* Uncompressed, color-mapped images */
+ case 3: /* Uncompressed, grayscale images */
+ case 9: /* Compressed, color-mapped images */
+ case 11: /* Compressed, grayscale images */
+ if (header.bitsperpixel != 8)
+ return 0;
+ break;
+ case 0:
+ case 2: /* Uncompressed, rgb images */
+ case 10: /* Compressed, rgb images */
+ if (header.bitsperpixel != 15 && header.bitsperpixel != 16
+ && header.bitsperpixel != 24 && header.bitsperpixel != 32)
+ return 0;
+ break;
+ }
+
+ switch (header.colourmaptype) {
+ default:
+ /*printf("bad colourmaptype!\n");*/
+ return 0;
+ case 1:
+ if (header.datatypecode != 1 && header.datatypecode != 9)
+ return 0; /* only get a color map on a color mapped image */
+ case 0:
+ break;
+ }
+
+ switch (header.colourmapdepth) {