home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / common / lbmlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-09  |  16.3 KB  |  803 lines

  1. // lbmlib.c
  2.  
  3. #include "cmdlib.h"
  4. #include "lbmlib.h"
  5.  
  6.  
  7.  
  8. /*
  9. ============================================================================
  10.  
  11.                         LBM STUFF
  12.  
  13. ============================================================================
  14. */
  15.  
  16.  
  17. typedef unsigned char    UBYTE;
  18. //conflicts with windows typedef short            WORD;
  19. typedef unsigned short    UWORD;
  20. typedef long            LONG;
  21.  
  22. typedef enum
  23. {
  24.     ms_none,
  25.     ms_mask,
  26.     ms_transcolor,
  27.     ms_lasso
  28. } mask_t;
  29.  
  30. typedef enum
  31. {
  32.     cm_none,
  33.     cm_rle1
  34. } compress_t;
  35.  
  36. typedef struct
  37. {
  38.     UWORD        w,h;
  39.     short        x,y;
  40.     UBYTE        nPlanes;
  41.     UBYTE        masking;
  42.     UBYTE        compression;
  43.     UBYTE        pad1;
  44.     UWORD        transparentColor;
  45.     UBYTE        xAspect,yAspect;
  46.     short        pageWidth,pageHeight;
  47. } bmhd_t;
  48.  
  49. extern    bmhd_t    bmhd;                        // will be in native byte order
  50.  
  51.  
  52.  
  53. #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
  54. #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
  55. #define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
  56. #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
  57. #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
  58. #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
  59.  
  60.  
  61. bmhd_t  bmhd;
  62.  
  63. int    Align (int l)
  64. {
  65.     if (l&1)
  66.         return l+1;
  67.     return l;
  68. }
  69.  
  70.  
  71.  
  72. /*
  73. ================
  74. LBMRLEdecompress
  75.  
  76. Source must be evenly aligned!
  77. ================
  78. */
  79. byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
  80. {
  81.     int     count;
  82.     byte    b,rept;
  83.  
  84.     count = 0;
  85.  
  86.     do
  87.     {
  88.         rept = *source++;
  89.  
  90.         if (rept > 0x80)
  91.         {
  92.             rept = (rept^0xff)+2;
  93.             b = *source++;
  94.             memset(unpacked,b,rept);
  95.             unpacked += rept;
  96.         }
  97.         else if (rept < 0x80)
  98.         {
  99.             rept++;
  100.             memcpy(unpacked,source,rept);
  101.             unpacked += rept;
  102.             source += rept;
  103.         }
  104.         else
  105.             rept = 0;               // rept of 0x80 is NOP
  106.  
  107.         count += rept;
  108.  
  109.     } while (count<bpwidth);
  110.  
  111.     if (count>bpwidth)
  112.         Error ("Decompression exceeded width!\n");
  113.  
  114.  
  115.     return source;
  116. }
  117.  
  118.  
  119. /*
  120. =================
  121. LoadLBM
  122. =================
  123. */
  124. void LoadLBM (char *filename, byte **picture, byte **palette)
  125. {
  126.     byte    *LBMbuffer, *picbuffer, *cmapbuffer;
  127.     int             y;
  128.     byte    *LBM_P, *LBMEND_P;
  129.     byte    *pic_p;
  130.     byte    *body_p;
  131.  
  132.     int    formtype,formlength;
  133.     int    chunktype,chunklength;
  134.  
  135. // qiet compiler warnings
  136.     picbuffer = NULL;
  137.     cmapbuffer = NULL;
  138.  
  139. //
  140. // load the LBM
  141. //
  142.     LoadFile (filename, (void **)&LBMbuffer);
  143.  
  144. //
  145. // parse the LBM header
  146. //
  147.     LBM_P = LBMbuffer;
  148.     if ( *(int *)LBMbuffer != LittleLong(FORMID) )
  149.        Error ("No FORM ID at start of file!\n");
  150.  
  151.     LBM_P += 4;
  152.     formlength = BigLong( *(int *)LBM_P );
  153.     LBM_P += 4;
  154.     LBMEND_P = LBM_P + Align(formlength);
  155.  
  156.     formtype = LittleLong(*(int *)LBM_P);
  157.  
  158.     if (formtype != ILBMID && formtype != PBMID)
  159.         Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
  160.         ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
  161.  
  162.     LBM_P += 4;
  163.  
  164. //
  165. // parse chunks
  166. //
  167.  
  168.     while (LBM_P < LBMEND_P)
  169.     {
  170.         chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
  171.         LBM_P += 4;
  172.         chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
  173.         LBM_P += 4;
  174.  
  175.         switch ( chunktype )
  176.         {
  177.         case BMHDID:
  178.             memcpy (&bmhd,LBM_P,sizeof(bmhd));
  179.             bmhd.w = BigShort(bmhd.w);
  180.             bmhd.h = BigShort(bmhd.h);
  181.             bmhd.x = BigShort(bmhd.x);
  182.             bmhd.y = BigShort(bmhd.y);
  183.             bmhd.pageWidth = BigShort(bmhd.pageWidth);
  184.             bmhd.pageHeight = BigShort(bmhd.pageHeight);
  185.             break;
  186.  
  187.         case CMAPID:
  188.             cmapbuffer = malloc (768);
  189.             memset (cmapbuffer, 0, 768);
  190.             memcpy (cmapbuffer, LBM_P, chunklength);
  191.             break;
  192.  
  193.         case BODYID:
  194.             body_p = LBM_P;
  195.  
  196.             pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
  197.             if (formtype == PBMID)
  198.             {
  199.             //
  200.             // unpack PBM
  201.             //
  202.                 for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
  203.                 {
  204.                     if (bmhd.compression == cm_rle1)
  205.                         body_p = LBMRLEDecompress ((byte *)body_p
  206.                         , pic_p , bmhd.w);
  207.                     else if (bmhd.compression == cm_none)
  208.                     {
  209.                         memcpy (pic_p,body_p,bmhd.w);
  210.                         body_p += Align(bmhd.w);
  211.                     }
  212.                 }
  213.  
  214.             }
  215.             else
  216.             {
  217.             //
  218.             // unpack ILBM
  219.             //
  220.                 Error ("%s is an interlaced LBM, not packed", filename);
  221.             }
  222.             break;
  223.         }
  224.  
  225.         LBM_P += Align(chunklength);
  226.     }
  227.  
  228.     free (LBMbuffer);
  229.  
  230.     *picture = picbuffer;
  231.  
  232.     if (palette)
  233.         *palette = cmapbuffer;
  234. }
  235.  
  236.  
  237. /*
  238. ============================================================================
  239.  
  240.                             WRITE LBM
  241.  
  242. ============================================================================
  243. */
  244.  
  245. /*
  246. ==============
  247. WriteLBMfile
  248. ==============
  249. */
  250. void WriteLBMfile (char *filename, byte *data,
  251.                    int width, int height, byte *palette)
  252. {
  253.     byte    *lbm, *lbmptr;
  254.     int    *formlength, *bmhdlength, *cmaplength, *bodylength;
  255.     int    length;
  256.     bmhd_t  basebmhd;
  257.  
  258.     lbm = lbmptr = malloc (width*height+1000);
  259.  
  260. //
  261. // start FORM
  262. //
  263.     *lbmptr++ = 'F';
  264.     *lbmptr++ = 'O';
  265.     *lbmptr++ = 'R';
  266.     *lbmptr++ = 'M';
  267.  
  268.     formlength = (int*)lbmptr;
  269.     lbmptr+=4;                      // leave space for length
  270.  
  271.     *lbmptr++ = 'P';
  272.     *lbmptr++ = 'B';
  273.     *lbmptr++ = 'M';
  274.     *lbmptr++ = ' ';
  275.  
  276. //
  277. // write BMHD
  278. //
  279.     *lbmptr++ = 'B';
  280.     *lbmptr++ = 'M';
  281.     *lbmptr++ = 'H';
  282.     *lbmptr++ = 'D';
  283.  
  284.     bmhdlength = (int *)lbmptr;
  285.     lbmptr+=4;                      // leave space for length
  286.  
  287.     memset (&basebmhd,0,sizeof(basebmhd));
  288.     basebmhd.w = BigShort((short)width);
  289.     basebmhd.h = BigShort((short)height);
  290.     basebmhd.nPlanes = BigShort(8);
  291.     basebmhd.xAspect = BigShort(5);
  292.     basebmhd.yAspect = BigShort(6);
  293.     basebmhd.pageWidth = BigShort((short)width);
  294.     basebmhd.pageHeight = BigShort((short)height);
  295.  
  296.     memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
  297.     lbmptr += sizeof(basebmhd);
  298.  
  299.     length = lbmptr-(byte *)bmhdlength-4;
  300.     *bmhdlength = BigLong(length);
  301.     if (length&1)
  302.         *lbmptr++ = 0;          // pad chunk to even offset
  303.  
  304. //
  305. // write CMAP
  306. //
  307.     *lbmptr++ = 'C';
  308.     *lbmptr++ = 'M';
  309.     *lbmptr++ = 'A';
  310.     *lbmptr++ = 'P';
  311.  
  312.     cmaplength = (int *)lbmptr;
  313.     lbmptr+=4;                      // leave space for length
  314.  
  315.     memcpy (lbmptr,palette,768);
  316.     lbmptr += 768;
  317.  
  318.     length = lbmptr-(byte *)cmaplength-4;
  319.     *cmaplength = BigLong(length);
  320.     if (length&1)
  321.         *lbmptr++ = 0;          // pad chunk to even offset
  322.  
  323. //
  324. // write BODY
  325. //
  326.     *lbmptr++ = 'B';
  327.     *lbmptr++ = 'O';
  328.     *lbmptr++ = 'D';
  329.     *lbmptr++ = 'Y';
  330.  
  331.     bodylength = (int *)lbmptr;
  332.     lbmptr+=4;                      // leave space for length
  333.  
  334.     memcpy (lbmptr,data,width*height);
  335.     lbmptr += width*height;
  336.  
  337.     length = lbmptr-(byte *)bodylength-4;
  338.     *bodylength = BigLong(length);
  339.     if (length&1)
  340.         *lbmptr++ = 0;          // pad chunk to even offset
  341.  
  342. //
  343. // done
  344. //
  345.     length = lbmptr-(byte *)formlength-4;
  346.     *formlength = BigLong(length);
  347.     if (length&1)
  348.         *lbmptr++ = 0;          // pad chunk to even offset
  349.  
  350. //
  351. // write output file
  352. //
  353.     SaveFile (filename, lbm, lbmptr-lbm);
  354.     free (lbm);
  355. }
  356.  
  357.  
  358. /*
  359. ============================================================================
  360.  
  361. LOAD PCX
  362.  
  363. ============================================================================
  364. */
  365.  
  366. typedef struct
  367. {
  368.     char    manufacturer;
  369.     char    version;
  370.     char    encoding;
  371.     char    bits_per_pixel;
  372.     unsigned short    xmin,ymin,xmax,ymax;
  373.     unsigned short    hres,vres;
  374.     unsigned char    palette[48];
  375.     char    reserved;
  376.     char    color_planes;
  377.     unsigned short    bytes_per_line;
  378.     unsigned short    palette_type;
  379.     char    filler[58];
  380.     unsigned char    data;            // unbounded
  381. } pcx_t;
  382.  
  383.  
  384. /*
  385. ==============
  386. LoadPCX
  387. ==============
  388. */
  389. void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
  390. {
  391.     byte    *raw;
  392.     pcx_t    *pcx;
  393.     int        x, y;
  394.     int        len;
  395.     int        dataByte, runLength;
  396.     byte    *out, *pix;
  397.  
  398.     //
  399.     // load the file
  400.     //
  401.     len = LoadFile (filename, (void **)&raw);
  402.  
  403.     //
  404.     // parse the PCX file
  405.     //
  406.     pcx = (pcx_t *)raw;
  407.     raw = &pcx->data;
  408.  
  409.     pcx->xmin = LittleShort(pcx->xmin);
  410.     pcx->ymin = LittleShort(pcx->ymin);
  411.     pcx->xmax = LittleShort(pcx->xmax);
  412.     pcx->ymax = LittleShort(pcx->ymax);
  413.     pcx->hres = LittleShort(pcx->hres);
  414.     pcx->vres = LittleShort(pcx->vres);
  415.     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
  416.     pcx->palette_type = LittleShort(pcx->palette_type);
  417.  
  418.     if (pcx->manufacturer != 0x0a
  419.         || pcx->version != 5
  420.         || pcx->encoding != 1
  421.         || pcx->bits_per_pixel != 8
  422.         || pcx->xmax >= 640
  423.         || pcx->ymax >= 480)
  424.         Error ("Bad pcx file %s", filename);
  425.     
  426.     if (palette)
  427.     {
  428.         *palette = malloc(768);
  429.         memcpy (*palette, (byte *)pcx + len - 768, 768);
  430.     }
  431.  
  432.     if (width)
  433.         *width = pcx->xmax+1;
  434.     if (height)
  435.         *height = pcx->ymax+1;
  436.  
  437.     if (!pic)
  438.         return;
  439.  
  440.     out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
  441.     if (!out)
  442.         Error ("Skin_Cache: couldn't allocate");
  443.  
  444.     *pic = out;
  445.  
  446.     pix = out;
  447.  
  448.     for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
  449.     {
  450.         for (x=0 ; x<=pcx->xmax ; )
  451.         {
  452.             dataByte = *raw++;
  453.  
  454.             if((dataByte & 0xC0) == 0xC0)
  455.             {
  456.                 runLength = dataByte & 0x3F;
  457.                 dataByte = *raw++;
  458.             }
  459.             else
  460.                 runLength = 1;
  461.  
  462.             while(runLength-- > 0)
  463.                 pix[x++] = dataByte;
  464.         }
  465.  
  466.     }
  467.  
  468.     if ( raw - (byte *)pcx > len)
  469.         Error ("PCX file %s was malformed", filename);
  470.  
  471.     free (pcx);
  472. }
  473.  
  474. /* 
  475. ============== 
  476. WritePCXfile 
  477. ============== 
  478. */ 
  479. void WritePCXfile (char *filename, byte *data, 
  480.                    int width, int height, byte *palette) 
  481. {
  482.     int        i, j, length;
  483.     pcx_t    *pcx;
  484.     byte        *pack;
  485.       
  486.     pcx = malloc (width*height*2+1000);
  487.     memset (pcx, 0, sizeof(*pcx));
  488.  
  489.     pcx->manufacturer = 0x0a;    // PCX id
  490.     pcx->version = 5;            // 256 color
  491.      pcx->encoding = 1;        // uncompressed
  492.     pcx->bits_per_pixel = 8;        // 256 color
  493.     pcx->xmin = 0;
  494.     pcx->ymin = 0;
  495.     pcx->xmax = LittleShort((short)(width-1));
  496.     pcx->ymax = LittleShort((short)(height-1));
  497.     pcx->hres = LittleShort((short)width);
  498.     pcx->vres = LittleShort((short)height);
  499.     pcx->color_planes = 1;        // chunky image
  500.     pcx->bytes_per_line = LittleShort((short)width);
  501.     pcx->palette_type = LittleShort(2);        // not a grey scale
  502.  
  503.     // pack the image
  504.     pack = &pcx->data;
  505.     
  506.     for (i=0 ; i<height ; i++)
  507.     {
  508.         for (j=0 ; j<width ; j++)
  509.         {
  510.             if ( (*data & 0xc0) != 0xc0)
  511.                 *pack++ = *data++;
  512.             else
  513.             {
  514.                 *pack++ = 0xc1;
  515.                 *pack++ = *data++;
  516.             }
  517.         }
  518.     }
  519.             
  520.     // write the palette
  521.     *pack++ = 0x0c;    // palette ID byte
  522.     for (i=0 ; i<768 ; i++)
  523.         *pack++ = *palette++;
  524.         
  525. // write output file 
  526.     length = pack - (byte *)pcx;
  527.     SaveFile (filename, pcx, length);
  528.  
  529.     free (pcx);
  530.  
  531.  
  532. /*
  533. ============================================================================
  534.  
  535. LOAD IMAGE
  536.  
  537. ============================================================================
  538. */
  539.  
  540. /*
  541. ==============
  542. Load256Image
  543.  
  544. Will load either an lbm or pcx, depending on extension.
  545. Any of the return pointers can be NULL if you don't want them.
  546. ==============
  547. */
  548. void Load256Image (char *name, byte **pixels, byte **palette,
  549.                    int *width, int *height)
  550. {
  551.     char    ext[128];
  552.  
  553.     ExtractFileExtension (name, ext);
  554.     if (!Q_strcasecmp (ext, "lbm"))
  555.     {
  556.         LoadLBM (name, pixels, palette);
  557.         if (width)
  558.             *width = bmhd.w;
  559.         if (height)
  560.             *height = bmhd.h;
  561.     }
  562.     else if (!Q_strcasecmp (ext, "pcx"))
  563.     {
  564.         LoadPCX (name, pixels, palette, width, height);
  565.     }
  566.     else
  567.         Error ("%s doesn't have a known image extension", name);
  568. }
  569.  
  570.  
  571. /*
  572. ==============
  573. Save256Image
  574.  
  575. Will save either an lbm or pcx, depending on extension.
  576. ==============
  577. */
  578. void Save256Image (char *name, byte *pixels, byte *palette,
  579.                    int width, int height)
  580. {
  581.     char    ext[128];
  582.  
  583.     ExtractFileExtension (name, ext);
  584.     if (!Q_strcasecmp (ext, "lbm"))
  585.     {
  586.         WriteLBMfile (name, pixels, width, height, palette);
  587.     }
  588.     else if (!Q_strcasecmp (ext, "pcx"))
  589.     {
  590.         WritePCXfile (name, pixels, width, height, palette);
  591.     }
  592.     else
  593.         Error ("%s doesn't have a known image extension", name);
  594. }
  595.  
  596.  
  597.  
  598.  
  599. /*
  600. ============================================================================
  601.  
  602. TARGA IMAGE
  603.  
  604. ============================================================================
  605. */
  606.  
  607. typedef struct _TargaHeader {
  608.     unsigned char     id_length, colormap_type, image_type;
  609.     unsigned short    colormap_index, colormap_length;
  610.     unsigned char    colormap_size;
  611.     unsigned short    x_origin, y_origin, width, height;
  612.     unsigned char    pixel_size, attributes;
  613. } TargaHeader;
  614.  
  615. int fgetLittleShort (FILE *f)
  616. {
  617.     byte    b1, b2;
  618.  
  619.     b1 = fgetc(f);
  620.     b2 = fgetc(f);
  621.  
  622.     return (short)(b1 + b2*256);
  623. }
  624.  
  625. int fgetLittleLong (FILE *f)
  626. {
  627.     byte    b1, b2, b3, b4;
  628.  
  629.     b1 = fgetc(f);
  630.     b2 = fgetc(f);
  631.     b3 = fgetc(f);
  632.     b4 = fgetc(f);
  633.  
  634.     return b1 + (b2<<8) + (b3<<16) + (b4<<24);
  635. }
  636.  
  637.  
  638. /*
  639. =============
  640. LoadTGA
  641. =============
  642. */
  643. void LoadTGA (char *name, byte **pixels, int *width, int *height)
  644. {
  645.     int                columns, rows, numPixels;
  646.     byte            *pixbuf;
  647.     int                row, column;
  648.     FILE            *fin;
  649.     byte            *targa_rgba;
  650.     TargaHeader        targa_header;
  651.  
  652.     fin = fopen (name, "rb");
  653.     if (!fin)
  654.         Error ("Couldn't read %s", name);
  655.  
  656.     targa_header.id_length = fgetc(fin);
  657.     targa_header.colormap_type = fgetc(fin);
  658.     targa_header.image_type = fgetc(fin);
  659.     
  660.     targa_header.colormap_index = fgetLittleShort(fin);
  661.     targa_header.colormap_length = fgetLittleShort(fin);
  662.     targa_header.colormap_size = fgetc(fin);
  663.     targa_header.x_origin = fgetLittleShort(fin);
  664.     targa_header.y_origin = fgetLittleShort(fin);
  665.     targa_header.width = fgetLittleShort(fin);
  666.     targa_header.height = fgetLittleShort(fin);
  667.     targa_header.pixel_size = fgetc(fin);
  668.     targa_header.attributes = fgetc(fin);
  669.  
  670.     if (targa_header.image_type!=2 
  671.         && targa_header.image_type!=10) 
  672.         Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
  673.  
  674.     if (targa_header.colormap_type !=0 
  675.         || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
  676.         Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
  677.  
  678.     columns = targa_header.width;
  679.     rows = targa_header.height;
  680.     numPixels = columns * rows;
  681.  
  682.     if (width)
  683.         *width = columns;
  684.     if (height)
  685.         *height = rows;
  686.     targa_rgba = malloc(numPixels*4);
  687.     *pixels = targa_rgba;
  688.  
  689.     if (targa_header.id_length != 0)
  690.         fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
  691.     
  692.     if (targa_header.image_type==2) {  // Uncompressed, RGB images
  693.         for(row=rows-1; row>=0; row--) {
  694.             pixbuf = targa_rgba + row*columns*4;
  695.             for(column=0; column<columns; column++) {
  696.                 unsigned char red,green,blue,alphabyte;
  697.                 switch (targa_header.pixel_size) {
  698.                     case 24:
  699.                             
  700.                             blue = getc(fin);
  701.                             green = getc(fin);
  702.                             red = getc(fin);
  703.                             *pixbuf++ = red;
  704.                             *pixbuf++ = green;
  705.                             *pixbuf++ = blue;
  706.                             *pixbuf++ = 255;
  707.                             break;
  708.                     case 32:
  709.                             blue = getc(fin);
  710.                             green = getc(fin);
  711.                             red = getc(fin);
  712.                             alphabyte = getc(fin);
  713.                             *pixbuf++ = red;
  714.                             *pixbuf++ = green;
  715.                             *pixbuf++ = blue;
  716.                             *pixbuf++ = alphabyte;
  717.                             break;
  718.                 }
  719.             }
  720.         }
  721.     }
  722.     else if (targa_header.image_type==10) {   // Runlength encoded RGB images
  723.         unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
  724.         for(row=rows-1; row>=0; row--) {
  725.             pixbuf = targa_rgba + row*columns*4;
  726.             for(column=0; column<columns; ) {
  727.                 packetHeader=getc(fin);
  728.                 packetSize = 1 + (packetHeader & 0x7f);
  729.                 if (packetHeader & 0x80) {        // run-length packet
  730.                     switch (targa_header.pixel_size) {
  731.                         case 24:
  732.                                 blue = getc(fin);
  733.                                 green = getc(fin);
  734.                                 red = getc(fin);
  735.                                 alphabyte = 255;
  736.                                 break;
  737.                         case 32:
  738.                                 blue = getc(fin);
  739.                                 green = getc(fin);
  740.                                 red = getc(fin);
  741.                                 alphabyte = getc(fin);
  742.                                 break;
  743.                     }
  744.     
  745.                     for(j=0;j<packetSize;j++) {
  746.                         *pixbuf++=red;
  747.                         *pixbuf++=green;
  748.                         *pixbuf++=blue;
  749.                         *pixbuf++=alphabyte;
  750.                         column++;
  751.                         if (column==columns) { // run spans across rows
  752.                             column=0;
  753.                             if (row>0)
  754.                                 row--;
  755.                             else
  756.                                 goto breakOut;
  757.                             pixbuf = targa_rgba + row*columns*4;
  758.                         }
  759.                     }
  760.                 }
  761.                 else {                            // non run-length packet
  762.                     for(j=0;j<packetSize;j++) {
  763.                         switch (targa_header.pixel_size) {
  764.                             case 24:
  765.                                     blue = getc(fin);
  766.                                     green = getc(fin);
  767.                                     red = getc(fin);
  768.                                     *pixbuf++ = red;
  769.                                     *pixbuf++ = green;
  770.                                     *pixbuf++ = blue;
  771.                                     *pixbuf++ = 255;
  772.                                     break;
  773.                             case 32:
  774.                                     blue = getc(fin);
  775.                                     green = getc(fin);
  776.                                     red = getc(fin);
  777.                                     alphabyte = getc(fin);
  778.                                     *pixbuf++ = red;
  779.                                     *pixbuf++ = green;
  780.                                     *pixbuf++ = blue;
  781.                                     *pixbuf++ = alphabyte;
  782.                                     break;
  783.                         }
  784.                         column++;
  785.                         if (column==columns) { // pixel packet run spans across rows
  786.                             column=0;
  787.                             if (row>0)
  788.                                 row--;
  789.                             else
  790.                                 goto breakOut;
  791.                             pixbuf = targa_rgba + row*columns*4;
  792.                         }                        
  793.                     }
  794.                 }
  795.             }
  796.             breakOut:;
  797.         }
  798.     }
  799.     
  800.     fclose(fin);
  801. }
  802.