home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR2 / DVPG30FS.ZIP / JRDTARGA.C < prev    next >
C/C++ Source or Header  |  1993-12-03  |  13KB  |  436 lines

  1. /*
  2.  *  modified by Eric P
  3.  *
  4.  *  needs to be fixed for bottom up images - pointers to buffer will not work
  5.  *
  6.  
  7.  * jrdtarga.c
  8.  *
  9.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  10.  * This file is part of the Independent JPEG Group's software.
  11.  * For conditions of distribution and use, see the accompanying README file.
  12.  *
  13.  * This file contains routines to read input images in Targa format.
  14.  *
  15.  * These routines may need modification for non-Unix environments or
  16.  * specialized applications.  As they stand, they assume input from
  17.  * an ordinary stdio stream.  They further assume that reading begins
  18.  * at the start of the file; input_init may need work if the
  19.  * user interface has already read some data (e.g., to determine that
  20.  * the file is indeed Targa format).
  21.  *
  22.  * These routines are invoked via the methods get_input_row
  23.  * and input_init/term.
  24.  *
  25.  * Based on code contributed by Lee Daniel Crocker.
  26.  */
  27.  
  28. /*#include "jinclude.h"*/
  29. #include "extern.h"
  30.  
  31. #ifdef TARGA_SUPPORTED
  32.  
  33. short input_components;
  34. COLOR_SPACE in_color_space;
  35.  
  36. /* moved out by Eric P for speed -> shared with jrdgif.c */
  37. extern FILE * infile;
  38.  
  39. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  40.  
  41. #ifdef HAVE_UNSIGNED_CHAR
  42. typedef unsigned char U_CHAR;
  43. #define UCH(x)    ((int) (x))
  44. #else /* !HAVE_UNSIGNED_CHAR */
  45. #ifdef CHAR_IS_UNSIGNED
  46. typedef char U_CHAR;
  47. #define UCH(x)    ((int) (x))
  48. #else
  49. typedef char U_CHAR;
  50. #define UCH(x)    ((int) (x) & 0xFF)
  51. #endif
  52. #endif /* HAVE_UNSIGNED_CHAR */
  53.  
  54.  
  55. #define    ReadOK(file,buffer,len)    (JFREAD(file,buffer,len) == ((size_t) (len)))
  56.  
  57. JSAMPARRAY colormap;    /* Targa colormap (converted to my format) */
  58.  
  59. int row_index;        /* index counter to force gr_row for bottom up images */
  60.  
  61. /*static long current_row;    /* Current logical row number to read */
  62.  
  63. /* Pointer to routine to extract next Targa pixel from input file */
  64. static void (*read_pixel) PP((decompress_info_ptr cinfo));
  65.  
  66. /* Result of read_pixel is delivered here: */
  67. static U_CHAR tga_pixel[4];
  68.  
  69. static int pixel_size;        /* Bytes per Targa pixel (1 to 4) */
  70.  
  71. /* State info for reading RLE-coded pixels; both counts must be init to 0 */
  72. static int block_count;        /* # of pixels remaining in RLE block */
  73. static int dup_pixel_count;    /* # of times to duplicate previous pixel */
  74.  
  75. /* This saves the correct pixel-row-expansion method for preload_image */
  76. static void (*get_pixel_row) PP((decompress_info_ptr cinfo,
  77.                  JSAMPIMAGE pixel_row));
  78.  
  79.  
  80. /* For expanding 5-bit pixel values to 8-bit with best rounding */
  81.  
  82. static const UINT8 c5to8bits[32] = {
  83.     0,   8,  16,  24,  32,  41,  49,  57,
  84.     65,  74,  82,  90,  98, 106, 115, 123,
  85.   131, 139, 148, 156, 164, 172, 180, 189,
  86.   197, 205, 213, 222, 230, 238, 246, 255
  87. };
  88.  
  89.  
  90.  
  91. LOCAL int
  92. read_byte (decompress_info_ptr cinfo)
  93. /* Read next byte from Targa file */
  94. {
  95. /*  register FILE *infile = cinfo->input_file;*/
  96.   register int c;
  97.  
  98.   if ((c = getc(infile)) == EOF)
  99.      ERREXIT(cinfo->emethods, "Premature EOF in Targa file");
  100.   return c;
  101. }
  102.  
  103.  
  104. LOCAL void
  105. read_colormap (decompress_info_ptr cinfo, int cmaplen, int mapentrysize)
  106. /* Read the colormap from a Targa file */
  107. {
  108.   int i;
  109.  
  110.   /* Presently only handles 24-bit BGR format */
  111.   if (mapentrysize != 24)
  112.      ERREXIT(cinfo->emethods, "Unsupported Targa colormap format");
  113.  
  114.   for (i = 0; i < cmaplen; i++) {
  115.      colormap[2][i] = (JSAMPLE) read_byte(cinfo);
  116.      colormap[1][i] = (JSAMPLE) read_byte(cinfo);
  117.      colormap[0][i] = (JSAMPLE) read_byte(cinfo);
  118.   }
  119.  
  120.   cinfo->color_map_present = TRUE;
  121.   cinfo->colormap = colormap;
  122. }
  123.  
  124.  
  125. /*
  126.  * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
  127.  */
  128.  
  129. LOCAL void
  130. read_non_rle_pixel (decompress_info_ptr cinfo)
  131. /* Read one Targa pixel from the input file; no RLE expansion */
  132. {
  133. /*  register FILE * infile = cinfo->input_file;*/
  134.   register int i;
  135.  
  136.   for (i = 0; i < pixel_size; i++) {
  137.      tga_pixel[i] = (U_CHAR) getc(infile);
  138.   }
  139. }
  140.  
  141.  
  142. LOCAL void
  143. read_rle_pixel (decompress_info_ptr cinfo)
  144. /* Read one Targa pixel from the input file, expanding RLE data as needed */
  145. {
  146. /*  register FILE * infile = cinfo->input_file;*/
  147.   register int i;
  148.  
  149.   /* Duplicate previously read pixel? */
  150.   if (dup_pixel_count > 0) {
  151.      dup_pixel_count--;
  152.      return;
  153.   }
  154.  
  155.   /* Time to read RLE block header? */
  156.   if (--block_count < 0) {    /* decrement pixels remaining in block */
  157.      i = read_byte(cinfo);
  158.      if (i & 0x80) {        /* Start of duplicate-pixel block? */
  159.       dup_pixel_count = i & 0x7F; /* number of duplications after this one */
  160.       block_count = 0;        /* then read new block header */
  161.      } else {
  162.       block_count = i & 0x7F;    /* number of pixels after this one */
  163.     }
  164.   }
  165.  
  166.   /* Read next pixel */
  167.   for (i = 0; i < pixel_size; i++) {
  168.     tga_pixel[i] = (U_CHAR) getc(infile);
  169.   }
  170. }
  171.  
  172.  
  173. /*
  174.  * Read one row of pixels.
  175.  *
  176.  * We provide several different versions depending on input file format.
  177.  */
  178.  
  179.  
  180. METHODDEF void
  181. get_8bit_gray_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  182. /* This version is for reading 8-bit grayscale pixels */
  183. {
  184.   register JSAMPROW ptr0;
  185.   register long col;
  186.  
  187.   ptr0 = pixel_row[0][0];
  188.   for (col = cinfo->image_width; col > 0; col--) {
  189.      (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  190.      *ptr0++ = (JSAMPLE) UCH(tga_pixel[0]);
  191.   }
  192. }
  193.  
  194. METHODDEF void
  195. get_8bit_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  196. /* This version is for reading 8-bit colormap indexes */
  197. {
  198.   register int t, col;
  199.   register JSAMPROW ptr0;
  200.  
  201.   ptr0 = pixel_row[0][0];
  202.   for (col = cinfo->image_width; col > 0; col--) {
  203.      (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  204.      *ptr0++ = UCH(tga_pixel[0]);
  205.   }
  206. }
  207.  
  208. METHODDEF void
  209. get_16bit_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  210. /* This version is for reading 16-bit pixels */
  211. {
  212.   register int t;
  213.   register JSAMPROW ptr0, ptr1, ptr2;
  214.   register int col;
  215.  
  216.   ptr0 = pixel_row[0][0];
  217.   ptr1 = pixel_row[1][0];
  218.   ptr2 = pixel_row[2][0];
  219.   for (col = cinfo->image_width; col > 0; col--) {
  220.      (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  221.      t = UCH(tga_pixel[0]);
  222.      t += UCH(tga_pixel[1]) << 8;
  223.      /* We expand 5 bit data to 8 bit sample width.
  224.       * The format of the 16-bit (LSB first) input word is
  225.       *     xRRRRRGGGGGBBBBB
  226.       */
  227.      *ptr2++ = (JSAMPLE) c5to8bits[t & 0x1F];
  228.      t >>= 5;
  229.      *ptr1++ = (JSAMPLE) c5to8bits[t & 0x1F];
  230.      t >>= 5;
  231.      *ptr0++ = (JSAMPLE) c5to8bits[t & 0x1F];
  232.   }
  233. }
  234.  
  235. METHODDEF void
  236. get_24bit_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  237. /* This version is for reading 24-bit pixels */
  238. {
  239.   register JSAMPROW ptr0, ptr1, ptr2;
  240.   register int col;
  241.  
  242.   ptr0 = pixel_row[0][0];
  243.   ptr1 = pixel_row[1][0];
  244.   ptr2 = pixel_row[2][0];
  245.   for (col = cinfo->image_width; col > 0; col--) {
  246.      (*read_pixel) (cinfo);    /* Load next pixel into tga_pixel */
  247.      *ptr0++ = (JSAMPLE) UCH(tga_pixel[2]); /* convert BGR to RGB order */
  248.      *ptr1++ = (JSAMPLE) UCH(tga_pixel[1]);
  249.      *ptr2++ = (JSAMPLE) UCH(tga_pixel[0]);
  250.   }
  251. }
  252.  
  253. /*
  254.  * Targa also defines a 32-bit pixel format with order B,G,R,A.
  255.  * We presently ignore the attribute byte, so the code for reading
  256.  * these pixels is identical to the 24-bit routine above.
  257.  * This works because the actual pixel length is only known to read_pixel.
  258.  */
  259.  
  260. #define get_32bit_row  get_24bit_row
  261.  
  262.  
  263. /*
  264.  * This method is for reading the input data in a bottom up order
  265.  *
  266.  *  this is done by forcing the viewer to the bottom of the screen
  267.  *  this means that panning will be up-side down!
  268.  *
  269.  *  interlaced order is not supported and will look like junk
  270.  */
  271.  
  272. METHODDEF void
  273. get_bottom_up_row (decompress_info_ptr cinfo, JSAMPIMAGE pixel_row)
  274. {
  275. gr_row = row_index--;
  276.  
  277. (*get_pixel_row) (cinfo, pixel_row);
  278. }
  279.  
  280.  
  281.  
  282.  
  283. /*
  284.  * Read the file header; return image size and component count.
  285.  */
  286.  
  287. METHODDEF void
  288. input_init (decompress_info_ptr cinfo)
  289. {
  290.   U_CHAR targaheader[18];
  291.   int idlen, cmaptype, subtype, flags, interlace_type, components;
  292.   UINT16 width, height, maplen;
  293.   boolean is_bottom_up;
  294.  
  295. #define GET_2B(offset)    ((unsigned int) UCH(targaheader[offset]) + \
  296.              (((unsigned int) UCH(targaheader[offset+1])) << 8))
  297.  
  298.   if (! ReadOK(cinfo->input_file, targaheader, 18))
  299.     ERREXIT(cinfo->emethods, "Unexpected end of file");
  300.  
  301.   /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  302.   if (targaheader[16] == 15)
  303.     targaheader[16] = 16;
  304.  
  305.   idlen = UCH(targaheader[0]);
  306.   cmaptype = UCH(targaheader[1]);
  307.   subtype = UCH(targaheader[2]);
  308.   maplen = GET_2B(5);
  309.   width = GET_2B(12);
  310.   height = GET_2B(14);
  311.   pixel_size = UCH(targaheader[16]) >> 3;
  312.   flags = UCH(targaheader[17]);    /* Image Descriptor byte */
  313.  
  314.   is_bottom_up = ((flags & 0x20) == 0);    /* bit 5 set => top-down */
  315.   interlace_type = flags >> 6;    /* bits 6/7 are interlace code */
  316.  
  317.   if (cmaptype > 1 ||        /* cmaptype must be 0 or 1 */
  318.       pixel_size < 1 || pixel_size > 4 ||
  319.       (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
  320.       interlace_type != 0)    /* currently don't allow interlaced image */
  321.      ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  322.   
  323.   if (subtype > 8) {
  324.     /* It's an RLE-coded file */
  325.     read_pixel = read_rle_pixel;
  326.     block_count = dup_pixel_count = 0;
  327.      subtype -= 8;
  328.   } else {
  329.     /* Non-RLE file */
  330.      read_pixel = read_non_rle_pixel;
  331.   }
  332.  
  333.   /* Now should have subtype 1, 2, or 3 */
  334.   components = 3;        /* until proven different */
  335.   in_color_space = CS_RGB;
  336.  
  337.   switch (subtype) {
  338.   case 1:            /* colormapped image */
  339.      if (pixel_size == 1 && cmaptype == 1)
  340.         get_pixel_row = get_8bit_row;
  341.      else
  342.         ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  343.      TRACEMS2(cinfo->emethods, 1, "%ux%u colormapped Targa image",
  344.           width, height);
  345.      break;
  346.   case 2:            /* RGB image */
  347.      switch (pixel_size) {
  348.      case 2:
  349.         get_pixel_row = get_16bit_row;
  350.         break;
  351.      case 3:
  352.         get_pixel_row = get_24bit_row;
  353.         break;
  354.      case 4:
  355.         get_pixel_row = get_32bit_row;
  356.         break;
  357.      default:
  358.         ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  359.         break;
  360.      }
  361.      TRACEMS2(cinfo->emethods, 1, "%ux%u RGB Targa image",
  362.           width, height);
  363.      break;
  364.   case 3:            /* Grayscale image */
  365.      components = 1;
  366.      in_color_space = CS_GRAYSCALE;
  367.      if (pixel_size == 1)
  368.         get_pixel_row = get_8bit_gray_row;
  369.      else
  370.         ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  371.      TRACEMS2(cinfo->emethods, 1, "%ux%u grayscale Targa image",
  372.           width, height);
  373.      break;
  374.   default:
  375.      ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  376.      break;
  377.   }
  378.  
  379.   if (is_bottom_up) {
  380.      row_ordering = UPSIDE_DOWN;
  381.      gr_row = height;        /* force viewer to start at the bottom of the screen */
  382.      row_index = height;    /* local variable used to force the graphic row index */
  383.      cinfo->methods->get_input_row = get_bottom_up_row;
  384. /*     cinfo->total_passes++;    /* count file reading as separate pass */
  385.   } else {
  386.      cinfo->methods->get_input_row = get_pixel_row;
  387.   }
  388.  
  389.   while (idlen--)        /* Throw away ID field */
  390.      (void) read_byte(cinfo);
  391.  
  392.   if (maplen > 0) {
  393.      if (maplen > 256 || GET_2B(3) != 0)
  394.         ERREXIT(cinfo->emethods, "Colormap too large");
  395.      /* Allocate space to store the colormap */
  396.      colormap = (*cinfo->emethods->alloc_small_sarray)
  397.             ((long) maplen, 3L);
  398.      /* and read it from the file */
  399.      read_colormap(cinfo, (int) maplen, UCH(targaheader[7]));
  400.   } else {
  401.      if (cmaptype)        /* but you promised a cmap! */
  402.         ERREXIT(cinfo->emethods, "Invalid or unsupported Targa file");
  403.      colormap = NULL;
  404.   }
  405.  
  406.   input_components = components;
  407.   cinfo->num_components = components;
  408.   cinfo->image_width = width;
  409.   cinfo->image_height = height;
  410.   cinfo->data_precision = 8;    /* always, even if 12-bit JSAMPLEs */
  411. }
  412.  
  413.  
  414.  
  415. /*
  416.  * The method selection routine for Targa format input.
  417.  * Note that this must be called by the user interface before calling
  418.  * jpeg_compress.  If multiple input formats are supported, the
  419.  * user interface is responsible for discovering the file format and
  420.  * calling the appropriate method selection routine.
  421.  */
  422.  
  423. GLOBAL void
  424. j_sel_r_targa (decompress_info_ptr cinfo)
  425. {
  426.     cinfo->out_color_space = CS_RGB;        /* needed default?? ie default is color */
  427.  
  428. cinfo->methods->read_file_header = input_init;
  429.   /* cinfo->methods->get_input_row is set by input_init */
  430.  
  431. infile = cinfo->input_file;
  432. }
  433.  
  434.  
  435. #endif /* TARGA_SUPPORTED */
  436.