home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmtga.c < prev    next >
C/C++ Source or Header  |  1993-08-27  |  14KB  |  560 lines

  1. /*
  2.  
  3. GBMTGA.C  Truevision Targa/Vista support
  4.  
  5. Reads any uncompressed type as 8 bit or 24 bit.
  6. Writes out only as 8 bit or 24 bit.
  7. Output options: 16,24,32, ydown,yup (default: 24 yup)
  8.  
  9. */
  10.  
  11. /*...sincludes:0:*/
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <memory.h>
  18. #include <malloc.h>
  19. #ifdef AIX
  20. #include <unistd.h>
  21. #else
  22. #include <io.h>
  23. #endif
  24. #include <fcntl.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include "standard.h"
  28. #include "gbm.h"
  29.  
  30. /*...vgbm\46\h:0:*/
  31. /*...e*/
  32.  
  33. /*...suseful:0:*/
  34. #define    low_byte(w)    ((byte)  ((w)&0x00ff)    )
  35. #define    high_byte(w)    ((byte) (((w)&0xff00)>>8))
  36. #define    make_word(a,b)    (((word)a) + (((word)b) << 8))
  37. /*...e*/
  38. /*...ssame:0:*/
  39. static BOOLEAN same(char *s1, char *s2, int n)
  40.     {
  41.     for ( ; n--; s1++, s2++ )
  42.         if ( tolower(*s1) != tolower(*s2) )
  43.             return ( FALSE );
  44.     return ( TRUE );
  45.     }
  46. /*...e*/
  47. /*...sfind_word:0:*/
  48. static char *find_word(char *str, char *substr)
  49.     {
  50.     char    buf [100+1], *s;
  51.     int    len = strlen(substr);
  52.  
  53.     for ( s  = strtok(strcpy(buf, str), " \t,");
  54.           s != NULL;
  55.           s  = strtok(NULL, " \t,") )
  56.         if ( same(s, substr, len) && s [len] == '\0' )
  57.             return ( str + (s - buf) );
  58.     return ( NULL );
  59.     }
  60. /*...e*/
  61.  
  62. static GBMFT tga_gbmft =
  63.     {
  64.     "Targa",
  65.     "Truevision Targa/Vista bitmap",
  66.     "TGA VST AFI",
  67.     GBM_FT_R8|GBM_FT_R24|
  68.     GBM_FT_W8|GBM_FT_W24,
  69.     };
  70.  
  71. #define    GBM_ERR_TGA_BAD_BPP    ((GBM_ERR) 400)
  72. #define    GBM_ERR_TGA_BAD_TYPE    ((GBM_ERR) 401)
  73. #define    GBM_ERR_TGA_BAD_PAL    ((GBM_ERR) 402)
  74.  
  75. /*...starga file header definition:0:*/
  76. /*
  77.  
  78. A Targa file is a header, followed by an identification string, followed by
  79. a color map, followed by the data for the image. Both the identification
  80. string and the color-map can be of zero length.
  81.  
  82. */
  83.  
  84. #define    TGA_NO_IMAGE    0        /* No image data included in file    */
  85. #define    TGA_UNCOMP_CM    1        /* Uncompressed, Color-Mapped (VDA/D */
  86.                     /* and Targa M-8 images)             */
  87. #define    TGA_UNCOMP_RGB    2        /* Uncompressed, RGB images (eg: ICB */
  88.                     /* Targa 16, 24 and 32)              */
  89. #define    TGA_UNCOMP_BW    3        /* Uncompressed, B/W images (eg:     */
  90.                     /* Targa 8 and Targa M-8 images)     */
  91. #define    TGA_RL_CM    9        /* Run-length, Color-Mapped (VDA/D   */
  92.                     /* and Targa M-8 images)             */
  93. #define    TGA_RL_RGB    10        /* Run-length, RGB images (eg: ICB   */
  94.                     /* Targa 16, 24 and 32)              */
  95. #define    TGA_RL_BW    11        /* Run-length, B/W images (eg: Targa */
  96.                     /* 8 and Targa M-8)                  */
  97. #define    TGA_COMP_CM    32        /* Compressed Color-Mapped (VDA/D)   */
  98.                     /* data using Huffman, Delta, and    */
  99.                     /* run length encoding               */
  100. #define    TGA_COMP_CM_4    33        /* Compressed Color-Mapped (VDA/D)   */
  101.                     /* data using Huffman, Delta, and    */
  102.                     /* run length encoding in 4 passes   */
  103.  
  104. #define    IDB_ATTRIBUTES    0x0f        /* How many attrib bits per pixel    */
  105.                     /* ie: 1 for T16, 8 for T32          */
  106. #define    IDB_ORIGIN    0x20        /* Origin in top left corner bit     */
  107.                     /* else its in bottom left corner    */
  108. #define    IDB_INTERLEAVE    0xc0        /* Interleave bits as defined below  */
  109. #define    IDB_NON_INT    0x00        /* Non-Interlaced                    */
  110. #define    IDB_2_WAY    0x40        /* 2 way (even/odd) interleaving     */
  111. #define    IDB_4_WAY    0x80        /* 4 way interleaving (eg: AT&T PC)  */
  112.  
  113. typedef struct
  114.     {
  115.     byte    n_chars_in_id;        /* Length of identification text     */
  116.     byte    color_map_present;    /* 0 means no, 1 yes                 */
  117.     byte    image_type;        /* Type of image file, one of TGA_   */
  118.     byte    color_map_start_low;    /* These 5 bytes are only valid if   */
  119.     byte    color_map_start_high;    /* color_map_present is 1. They      */
  120.     byte    color_map_length_low;    /* Specify the size of the color map */
  121.     byte    color_map_length_high;    /* and where it starts from          */
  122.     byte    color_map_entry_bits;    /* Bits per color map entry          */
  123.                     /* Typically 15, 16, 24 or 32        */
  124.     byte    x_origin_low;
  125.     byte    x_origin_high;
  126.     byte    y_origin_low;
  127.     byte    y_origin_high;
  128.     byte    width_low;
  129.     byte    width_high;
  130.     byte    height_low;
  131.     byte    height_high;
  132.     byte    bpp;            /* Typically 16, 24 or 32            */
  133.     byte    image_descriptor;    /* Split into IDB_ bits              */
  134.     } TGA_HEADER;
  135.  
  136. #define    SIZEOF_TGA_HEADER    18
  137. /*...e*/
  138. /*...sconverters:0:*/
  139. /*...st24_t32:0:*/
  140. static void t24_t32(byte *dest, byte *src, int n)
  141.     {
  142.     while ( n-- )
  143.         {
  144.         *dest++ = *src++;
  145.         *dest++ = *src++;
  146.         *dest++ = *src++;
  147.         dest++;
  148.         }
  149.     }
  150. /*...e*/
  151. /*...st32_t24:0:*/
  152. static void t32_t24(byte *dest, byte *src, int n)
  153.     {
  154.     while ( n-- )
  155.         {
  156.         *dest++ = *src++;
  157.         *dest++ = *src++;
  158.         *dest++ = *src++;
  159.         src++;
  160.         }
  161.     }
  162. /*...e*/
  163. /*...st24_t16:0:*/
  164. static void t24_t16(byte *dest, byte *src, int n)
  165.     {
  166.     while ( n-- )
  167.         {
  168.         word    b = (word) (*src++ & 0xf8);
  169.         word    g = (word) (*src++ & 0xf8);
  170.         word    r = (word) (*src++ & 0xf8);
  171.         word    w;
  172.  
  173.         w = ((r << 7) | (g << 2) | (b >> 3));
  174.  
  175.         *dest++ = (byte)  w;
  176.         *dest++ = (byte) (w >> 8);
  177.         }
  178.     }
  179. /*...e*/
  180. /*...st16_t24:0:*/
  181. static void t16_t24(byte *dest, byte *src, int n)
  182.     {
  183.     while ( n-- )
  184.         {
  185.         word    l = *src++;
  186.         word    h = *src++;
  187.         word    w = l + (h << 8);
  188.  
  189.         *dest++ = (byte) ((w & 0x001f) << 3);
  190.         *dest++ = (byte) ((w & 0x03e0) >> 2);
  191.         *dest++ = (byte) ((w & 0x7c00) >> 7);
  192.         }
  193.     }
  194. /*...e*/
  195. /*...e*/
  196.  
  197. /*...stga_qft:0:*/
  198. GBM_ERR tga_qft(GBMFT *gbmft)
  199.     {
  200.     *gbmft = tga_gbmft;
  201.     return ( GBM_ERR_OK );
  202.     }
  203. /*...e*/
  204. /*...stga_rhdr:0:*/
  205. GBM_ERR tga_rhdr(char *fn, int fd, GBM *gbm, char *opt)
  206.     {
  207.     TGA_HEADER tga_header;
  208.     int    w, h, bpp;
  209.  
  210.     fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
  211.  
  212.     lseek(fd, 0L, SEEK_SET);
  213.     read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
  214.  
  215.     bpp = tga_header.bpp;
  216.  
  217.     if ( tga_header.image_type != TGA_UNCOMP_CM  &&
  218.          tga_header.image_type != TGA_UNCOMP_RGB )
  219.         return ( GBM_ERR_TGA_BAD_TYPE );
  220.  
  221.     if ( !( (bpp ==  8 && tga_header.image_type == TGA_UNCOMP_CM ) ||
  222.         (bpp == 16 && tga_header.image_type == TGA_UNCOMP_RGB) ||
  223.         (bpp == 24 && tga_header.image_type == TGA_UNCOMP_RGB) ||
  224.         (bpp == 32 && tga_header.image_type == TGA_UNCOMP_RGB) ) )
  225.         return ( GBM_ERR_TGA_BAD_BPP );
  226.  
  227.     if ( bpp == 8 && tga_header.color_map_entry_bits != 24 )
  228.         return ( GBM_ERR_TGA_BAD_PAL );
  229.  
  230.     w = make_word(tga_header.width_low , tga_header.width_high );
  231.     h = make_word(tga_header.height_low, tga_header.height_high);
  232.  
  233.     if ( w <= 0 || h <= 0 )
  234.         return ( GBM_ERR_BAD_SIZE );
  235.  
  236.     gbm -> w   = w;
  237.     gbm -> h   = h;
  238.     gbm -> bpp = ( bpp == 8 ) ? 8 : 24;
  239.  
  240.     return ( GBM_ERR_OK );
  241.     }
  242. /*...e*/
  243. /*...stga_rpal:0:*/
  244. GBM_ERR tga_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
  245.     {
  246.     if ( gbm -> bpp == 8 )
  247.         {
  248.         TGA_HEADER tga_header;
  249.         int    color_map_start, color_map_length, i;
  250.  
  251.         lseek(fd, 0L, SEEK_SET);
  252.         read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
  253.         lseek(fd, (long) tga_header.n_chars_in_id, SEEK_CUR);    /* Skip ID string */
  254.  
  255.         color_map_start  = make_word(tga_header.color_map_start_low, tga_header.color_map_start_high);
  256.         color_map_length = make_word(tga_header.color_map_length_low, tga_header.color_map_length_high);
  257.  
  258.         memset(gbmrgb, 0, 0x100 * sizeof(GBMRGB));
  259.         for ( i = color_map_start; i < color_map_start + color_map_length; i++ )
  260.             {
  261.             byte    b [3];
  262.  
  263.             read(fd, (char *) b, 3);
  264.             gbmrgb [i].b = b [0];
  265.             gbmrgb [i].g = b [1];
  266.             gbmrgb [i].r = b [2];
  267.             }
  268.         }
  269.  
  270.     return ( GBM_ERR_OK );
  271.     }
  272. /*...e*/
  273. /*...stga_rdata:0:*/
  274. GBM_ERR tga_rdata(int fd, GBM *gbm, byte *data)
  275.     {
  276.     TGA_HEADER tga_header;
  277.     BOOLEAN top_left_origin;
  278.     byte    *linebuf, *p;
  279.     int    i, stride;
  280.  
  281.     lseek(fd, 0L, SEEK_SET);
  282.     read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
  283.     lseek(fd, (long) tga_header.n_chars_in_id, SEEK_CUR);    /* Skip ID string */
  284.  
  285.     top_left_origin = ((tga_header.image_descriptor & IDB_ORIGIN) != 0);
  286.  
  287.     if ( tga_header.color_map_present )
  288.         {
  289.         int    color_map_length;
  290.         int    bpp_pal = tga_header.color_map_entry_bits;
  291.             /* Valid values are 32, 24, 16 and sometimes 15 */
  292.  
  293.         if ( bpp_pal == 15 ) bpp_pal = 16;
  294.  
  295.         color_map_length = make_word(tga_header.color_map_length_low, tga_header.color_map_length_high);
  296.         lseek(fd, (long) ((color_map_length * bpp_pal) / 8L), SEEK_CUR);
  297.         }
  298.  
  299.     switch ( tga_header.bpp )
  300.         {
  301. /*...s8:16:*/
  302. case 8:
  303.     stride = ((gbm -> w + 3) & ~3);
  304.     p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
  305.     for ( i = 0; i < gbm -> h; i++ )
  306.         {
  307.         read(fd, p, gbm -> w);
  308.         if ( top_left_origin )
  309.             p -= stride;
  310.         else
  311.             p += stride;
  312.         }
  313.     break;
  314. /*...e*/
  315. /*...s16:16:*/
  316. case 16:
  317.     if ( (linebuf = malloc(gbm -> w * 2)) == NULL )
  318.         return ( GBM_ERR_MEM );
  319.  
  320.     stride = ((gbm -> w * 3 + 3) & ~3);
  321.     p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
  322.     for ( i = 0; i < gbm -> h; i++ )
  323.         {
  324.         read(fd, linebuf, gbm -> w * 2);
  325.         t16_t24(p, linebuf, gbm -> w);
  326.         if ( top_left_origin )
  327.             p -= stride;
  328.         else
  329.             p += stride;
  330.         }
  331.  
  332.     free(linebuf);
  333.  
  334.     break;
  335. /*...e*/
  336. /*...s24:16:*/
  337. case 24:
  338.     stride = ((gbm -> w * 3 + 3) & ~3);
  339.     p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
  340.     for ( i = 0; i < gbm -> h; i++ )
  341.         {
  342.         read(fd, p, gbm -> w * 3);
  343.         if ( top_left_origin )
  344.             p -= stride;
  345.         else
  346.             p += stride;
  347.         }
  348.     break;
  349. /*...e*/
  350. /*...s32:16:*/
  351. case 32:
  352.     if ( (linebuf = malloc(gbm -> w * 4)) == NULL )
  353.         return ( GBM_ERR_MEM );
  354.  
  355.     stride = ((gbm -> w * 3 + 3) & ~3);
  356.     p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
  357.     for ( i = 0; i < gbm -> h; i++ )
  358.         {
  359.         read(fd, linebuf, gbm -> w * 4);
  360.         t32_t24(p, linebuf, gbm -> w);
  361.         if ( top_left_origin )
  362.             p -= stride;
  363.         else
  364.             p += stride;
  365.         }
  366.  
  367.     free(linebuf);
  368.  
  369.     break;
  370. /*...e*/
  371.         }
  372.  
  373.     return ( GBM_ERR_OK );
  374.     }
  375. /*...e*/
  376. /*...stga_w:0:*/
  377. #define    SW3(a,b,c)    ((a)*4+(b)*2+(c))
  378.  
  379. GBM_ERR tga_w(char *fn, int fd, GBM *gbm, GBMRGB *gbmrgb, byte *data, char *opt)
  380.     {
  381.     TGA_HEADER tga_header;
  382.     int    i, stride;
  383.     byte    *p;
  384.     int    obpp;
  385.     BOOLEAN o16   = ( find_word(opt, "16"   ) != NULL );
  386.     BOOLEAN o24   = ( find_word(opt, "24"   ) != NULL );
  387.     BOOLEAN o32   = ( find_word(opt, "32"   ) != NULL );
  388.     BOOLEAN yup   = ( find_word(opt, "yup"  ) != NULL );
  389.     BOOLEAN ydown = ( find_word(opt, "ydown") != NULL );
  390.  
  391.     fn=fn; /* Suppress 'unref arg' compiler warning */
  392.  
  393.     if ( gbm -> bpp == 24 )
  394.         switch ( SW3(o16,o24,o32) )
  395.             {
  396.             case SW3(1,0,0):    obpp = 16;    break;
  397.             case SW3(0,0,0):
  398.             case SW3(0,1,0):    obpp = 24;    break;
  399.             case SW3(0,0,1):    obpp = 32;    break;
  400.             default:        return ( GBM_ERR_BAD_OPTION );
  401.             }
  402.     else
  403.         {
  404.         if ( o16 || o24 || o32 )
  405.             return ( GBM_ERR_BAD_OPTION );
  406.         obpp = 8;
  407.         }
  408.  
  409.     if ( yup && ydown )
  410.         return ( GBM_ERR_BAD_OPTION );
  411.  
  412.     tga_header.n_chars_in_id         = 0;
  413.     tga_header.image_type            = ( obpp == 8 ) ? TGA_UNCOMP_CM : TGA_UNCOMP_RGB;
  414.     tga_header.color_map_present     = (byte) ( gbm -> bpp == 8 );
  415.     tga_header.x_origin_low          = low_byte(0);
  416.     tga_header.x_origin_high         = high_byte(0);
  417.     tga_header.y_origin_low          = low_byte(0);
  418.     tga_header.y_origin_high         = high_byte(0);
  419.     tga_header.color_map_start_low   = low_byte(0);
  420.     tga_header.color_map_start_high  = high_byte(0);
  421.     tga_header.color_map_length_low  = low_byte(0x100);
  422.     tga_header.color_map_length_high = high_byte(0x100);
  423.     tga_header.color_map_entry_bits  = 24;
  424.     tga_header.width_low             = low_byte(gbm -> w);
  425.     tga_header.width_high            = high_byte(gbm -> w);
  426.     tga_header.height_low            = low_byte(gbm -> h);
  427.     tga_header.height_high           = high_byte(gbm -> h);
  428.     tga_header.bpp                   = (byte) obpp;
  429.     tga_header.image_descriptor      = IDB_NON_INT;
  430.  
  431.     if ( ydown )
  432.         tga_header.image_descriptor |= IDB_ORIGIN;
  433.  
  434.     write(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
  435.  
  436.     switch ( obpp )
  437.         {
  438. /*...s8:16:*/
  439. case 8:
  440.     for ( i = 0; i < 0x100; i++ )
  441.         {
  442.         byte    b [3];
  443.  
  444.         b [0] = gbmrgb [i].b;
  445.         b [1] = gbmrgb [i].g;
  446.         b [2] = gbmrgb [i].r;
  447.         write(fd, b, 3);
  448.         }
  449.  
  450.     stride = ((gbm -> w + 3) & ~3);
  451.     p = data;
  452.  
  453.     if ( ydown )
  454.         {
  455.         data += ((gbm -> h - 1) * stride);
  456.         stride = -stride;
  457.         }
  458.  
  459.     for ( i = 0; i < gbm -> h; i++ )
  460.         {
  461.         write(fd, p, gbm -> w);
  462.         p += stride;
  463.         }
  464.     break;
  465. /*...e*/
  466. /*...s16:16:*/
  467. case 16:
  468.     {
  469.     byte    *linebuf;
  470.  
  471.     if ( (linebuf = malloc(gbm -> w * 2)) == NULL )
  472.         return ( GBM_ERR_MEM );
  473.  
  474.     stride = ((gbm -> w * 3 + 3) & ~3);
  475.     p = data;
  476.  
  477.     if ( ydown )
  478.         {
  479.         data += ((gbm -> h - 1) * stride);
  480.         stride = -stride;
  481.         }
  482.  
  483.     for ( i = 0; i < gbm -> h; i++ )
  484.         {
  485.         t24_t16(linebuf, p, gbm -> w);
  486.         write(fd, linebuf, gbm -> w * 2);
  487.         p += stride;
  488.         }
  489.  
  490.     free(linebuf);
  491.     }
  492.     break;
  493. /*...e*/
  494. /*...s24:16:*/
  495. case 24:
  496.     stride = ((gbm -> w * 3 + 3) & ~3);
  497.     p = data;
  498.  
  499.     if ( ydown )
  500.         {
  501.         data += ((gbm -> h - 1) * stride);
  502.         stride = -stride;
  503.         }
  504.  
  505.     for ( i = 0; i < gbm -> h; i++ )
  506.         {
  507.         write(fd, p, gbm -> w * 3);
  508.         p += stride;
  509.         }
  510.     break;
  511. /*...e*/
  512. /*...s32:16:*/
  513. case 32:
  514.     {
  515.     byte    *linebuf;
  516.  
  517.     if ( (linebuf = malloc(gbm -> w * 4)) == NULL )
  518.         return ( GBM_ERR_MEM );
  519.  
  520.     stride = ((gbm -> w * 3 + 3) & ~3);
  521.     p = data;
  522.  
  523.     if ( ydown )
  524.         {
  525.         data += ((gbm -> h - 1) * stride);
  526.         stride = -stride;
  527.         }
  528.  
  529.     for ( i = 0; i < gbm -> h; i++ )
  530.         {
  531.         t24_t32(linebuf, p, gbm -> w);
  532.         write(fd, linebuf, gbm -> w * 4);
  533.         p += stride;
  534.         }
  535.  
  536.     free(linebuf);
  537.     }
  538.     break;
  539. /*...e*/
  540.         }
  541.  
  542.     return ( GBM_ERR_OK );
  543.     }
  544. /*...e*/
  545. /*...stga_err:0:*/
  546. char *tga_err(GBM_ERR rc)
  547.     {
  548.     switch ( (int) rc )
  549.         {
  550.         case GBM_ERR_TGA_BAD_BPP:
  551.             return ( "bits per pixel not 8, 16, 24 or 32" );
  552.         case GBM_ERR_TGA_BAD_TYPE:
  553.             return ( "unsupported compression type for bits per pixel" );
  554.         case GBM_ERR_TGA_BAD_PAL:
  555.             return ( "color map entry size not 24 bits per pixel" );
  556.         }
  557.     return ( NULL );
  558.     }
  559. /*...e*/
  560.