rdtarga.c
上传用户:wuyixingx
上传日期:2007-01-08
资源大小:745k
文件大小:15k
源码类别:

图形图象

开发平台:

C/C++

  1. /*
  2.  * rdtarga.c
  3.  *
  4.  * Copyright (C) 1991-1996, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to read input images in Targa format.
  9.  *
  10.  * These routines may need modification for non-Unix environments or
  11.  * specialized applications.  As they stand, they assume input from
  12.  * an ordinary stdio stream.  They further assume that reading begins
  13.  * at the start of the file; start_input may need work if the
  14.  * user interface has already read some data (e.g., to determine that
  15.  * the file is indeed Targa format).
  16.  *
  17.  * Based on code contributed by Lee Daniel Crocker.
  18.  */
  19. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  20. #ifdef TARGA_SUPPORTED
  21. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  22. #ifdef HAVE_UNSIGNED_CHAR
  23. typedef unsigned char U_CHAR;
  24. #define UCH(x) ((int) (x))
  25. #else /* !HAVE_UNSIGNED_CHAR */
  26. #ifdef CHAR_IS_UNSIGNED
  27. typedef char U_CHAR;
  28. #define UCH(x) ((int) (x))
  29. #else
  30. typedef char U_CHAR;
  31. #define UCH(x) ((int) (x) & 0xFF)
  32. #endif
  33. #endif /* HAVE_UNSIGNED_CHAR */
  34. #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
  35. /* Private version of data source object */
  36. typedef struct _tga_source_struct * tga_source_ptr;
  37. typedef struct _tga_source_struct {
  38.   struct cjpeg_source_struct pub; /* public fields */
  39.   j_compress_ptr cinfo; /* back link saves passing separate parm */
  40.   JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
  41.   jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
  42.   JDIMENSION current_row; /* Current logical row number to read */
  43.   /* Pointer to routine to extract next Targa pixel from input file */
  44.   JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
  45.   /* Result of read_pixel is delivered here: */
  46.   U_CHAR tga_pixel[4];
  47.   int pixel_size; /* Bytes per Targa pixel (1 to 4) */
  48.   /* State info for reading RLE-coded pixels; both counts must be init to 0 */
  49.   int block_count; /* # of pixels remaining in RLE block */
  50.   int dup_pixel_count; /* # of times to duplicate previous pixel */
  51.   /* This saves the correct pixel-row-expansion method for preload_image */
  52.   JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
  53.        cjpeg_source_ptr sinfo));
  54. } tga_source_struct;
  55. /* For expanding 5-bit pixel values to 8-bit with best rounding */
  56. static const UINT8 c5to8bits[32] = {
  57.     0,   8,  16,  25,  33,  41,  49,  58,
  58.    66,  74,  82,  90,  99, 107, 115, 123,
  59.   132, 140, 148, 156, 165, 173, 181, 189,
  60.   197, 206, 214, 222, 230, 239, 247, 255
  61. };
  62. LOCAL(int)
  63. read_byte (tga_source_ptr sinfo)
  64. /* Read next byte from Targa file */
  65. {
  66.   register FILE *infile = sinfo->pub.input_file;
  67.   register int c;
  68.   if ((c = getc(infile)) == EOF)
  69.     ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
  70.   return c;
  71. }
  72. LOCAL(void)
  73. read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
  74. /* Read the colormap from a Targa file */
  75. {
  76.   int i;
  77.   /* Presently only handles 24-bit BGR format */
  78.   if (mapentrysize != 24)
  79.     ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
  80.   for (i = 0; i < cmaplen; i++) {
  81.     sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
  82.     sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
  83.     sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
  84.   }
  85. }
  86. /*
  87.  * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
  88.  */
  89. METHODDEF(void)
  90. read_non_rle_pixel (tga_source_ptr sinfo)
  91. /* Read one Targa pixel from the input file; no RLE expansion */
  92. {
  93.   register FILE *infile = sinfo->pub.input_file;
  94.   register int i;
  95.   for (i = 0; i < sinfo->pixel_size; i++) {
  96.     sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
  97.   }
  98. }
  99. METHODDEF(void)
  100. read_rle_pixel (tga_source_ptr sinfo)
  101. /* Read one Targa pixel from the input file, expanding RLE data as needed */
  102. {
  103.   register FILE *infile = sinfo->pub.input_file;
  104.   register int i;
  105.   /* Duplicate previously read pixel? */
  106.   if (sinfo->dup_pixel_count > 0) {
  107.     sinfo->dup_pixel_count--;
  108.     return;
  109.   }
  110.   /* Time to read RLE block header? */
  111.   if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
  112.     i = read_byte(sinfo);
  113.     if (i & 0x80) { /* Start of duplicate-pixel block? */
  114.       sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
  115.       sinfo->block_count = 0; /* then read new block header */
  116.     } else {
  117.       sinfo->block_count = i & 0x7F; /* number of pixels after this one */
  118.     }
  119.   }
  120.   /* Read next pixel */
  121.   for (i = 0; i < sinfo->pixel_size; i++) {
  122.     sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
  123.   }
  124. }
  125. /*
  126.  * Read one row of pixels.
  127.  *
  128.  * We provide several different versions depending on input file format.
  129.  */
  130. METHODDEF(JDIMENSION)
  131. get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  132. /* This version is for reading 8-bit grayscale pixels */
  133. {
  134.   tga_source_ptr source = (tga_source_ptr) sinfo;
  135.   register JSAMPROW ptr;
  136.   register JDIMENSION col;
  137.   
  138.   ptr = source->pub.buffer[0];
  139.   for (col = cinfo->image_width; col > 0; col--) {
  140.     (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  141.     *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
  142.   }
  143.   return 1;
  144. }
  145. METHODDEF(JDIMENSION)
  146. get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  147. /* This version is for reading 8-bit colormap indexes */
  148. {
  149.   tga_source_ptr source = (tga_source_ptr) sinfo;
  150.   register int t;
  151.   register JSAMPROW ptr;
  152.   register JDIMENSION col;
  153.   register JSAMPARRAY colormap = source->colormap;
  154.   ptr = source->pub.buffer[0];
  155.   for (col = cinfo->image_width; col > 0; col--) {
  156.     (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  157.     t = UCH(source->tga_pixel[0]);
  158.     *ptr++ = colormap[0][t];
  159.     *ptr++ = colormap[1][t];
  160.     *ptr++ = colormap[2][t];
  161.   }
  162.   return 1;
  163. }
  164. METHODDEF(JDIMENSION)
  165. get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  166. /* This version is for reading 16-bit pixels */
  167. {
  168.   tga_source_ptr source = (tga_source_ptr) sinfo;
  169.   register int t;
  170.   register JSAMPROW ptr;
  171.   register JDIMENSION col;
  172.   
  173.   ptr = source->pub.buffer[0];
  174.   for (col = cinfo->image_width; col > 0; col--) {
  175.     (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  176.     t = UCH(source->tga_pixel[0]);
  177.     t += UCH(source->tga_pixel[1]) << 8;
  178.     /* We expand 5 bit data to 8 bit sample width.
  179.      * The format of the 16-bit (LSB first) input word is
  180.      *     xRRRRRGGGGGBBBBB
  181.      */
  182.     ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
  183.     t >>= 5;
  184.     ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
  185.     t >>= 5;
  186.     ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
  187.     ptr += 3;
  188.   }
  189.   return 1;
  190. }
  191. METHODDEF(JDIMENSION)
  192. get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  193. /* This version is for reading 24-bit pixels */
  194. {
  195.   tga_source_ptr source = (tga_source_ptr) sinfo;
  196.   register JSAMPROW ptr;
  197.   register JDIMENSION col;
  198.   
  199.   ptr = source->pub.buffer[0];
  200.   for (col = cinfo->image_width; col > 0; col--) {
  201.     (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  202.     *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
  203.     *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
  204.     *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
  205.   }
  206.   return 1;
  207. }
  208. /*
  209.  * Targa also defines a 32-bit pixel format with order B,G,R,A.
  210.  * We presently ignore the attribute byte, so the code for reading
  211.  * these pixels is identical to the 24-bit routine above.
  212.  * This works because the actual pixel length is only known to read_pixel.
  213.  */
  214. #define get_32bit_row  get_24bit_row
  215. /*
  216.  * This method is for re-reading the input data in standard top-down
  217.  * row order.  The entire image has already been read into whole_image
  218.  * with proper conversion of pixel format, but it's in a funny row order.
  219.  */
  220. METHODDEF(JDIMENSION)
  221. get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  222. {
  223.   tga_source_ptr source = (tga_source_ptr) sinfo;
  224.   JDIMENSION source_row;
  225.   /* Compute row of source that maps to current_row of normal order */
  226.   /* For now, assume image is bottom-up and not interlaced. */
  227.   /* NEEDS WORK to support interlaced images! */
  228.   source_row = cinfo->image_height - source->current_row - 1;
  229.   /* Fetch that row from virtual array */
  230.   source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  231.     ((j_common_ptr) cinfo, source->whole_image,
  232.      source_row, (JDIMENSION) 1, FALSE);
  233.   source->current_row++;
  234.   return 1;
  235. }
  236. /*
  237.  * This method loads the image into whole_image during the first call on
  238.  * get_pixel_rows.  The get_pixel_rows pointer is then adjusted to call
  239.  * get_memory_row on subsequent calls.
  240.  */
  241. METHODDEF(JDIMENSION)
  242. preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  243. {
  244.   tga_source_ptr source = (tga_source_ptr) sinfo;
  245.   JDIMENSION row;
  246.   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  247.   /* Read the data into a virtual array in input-file row order. */
  248.   for (row = 0; row < cinfo->image_height; row++) {
  249.     if (progress != NULL) {
  250.       progress->pub.pass_counter = (long) row;
  251.       progress->pub.pass_limit = (long) cinfo->image_height;
  252.       (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  253.     }
  254.     source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  255.       ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
  256.     (*source->get_pixel_rows) (cinfo, sinfo);
  257.   }
  258.   if (progress != NULL)
  259.     progress->completed_extra_passes++;
  260.   /* Set up to read from the virtual array in unscrambled order */
  261.   source->pub.get_pixel_rows = get_memory_row;
  262.   source->current_row = 0;
  263.   /* And read the first row */
  264.   return get_memory_row(cinfo, sinfo);
  265. }
  266. /*
  267.  * Read the file header; return image size and component count.
  268.  */
  269. METHODDEF(void)
  270. start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  271. {
  272.   tga_source_ptr source = (tga_source_ptr) sinfo;
  273.   U_CHAR targaheader[18];
  274.   int idlen, cmaptype, subtype, flags, interlace_type, components;
  275.   unsigned int width, height, maplen;
  276.   boolean is_bottom_up;
  277. #define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + 
  278.  (((unsigned int) UCH(targaheader[offset+1])) << 8))
  279.   if (! ReadOK(source->pub.input_file, targaheader, 18))
  280.     ERREXIT(cinfo, JERR_INPUT_EOF);
  281.   /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  282.   if (targaheader[16] == 15)
  283.     targaheader[16] = 16;
  284.   idlen = UCH(targaheader[0]);
  285.   cmaptype = UCH(targaheader[1]);
  286.   subtype = UCH(targaheader[2]);
  287.   maplen = GET_2B(5);
  288.   width = GET_2B(12);
  289.   height = GET_2B(14);
  290.   source->pixel_size = UCH(targaheader[16]) >> 3;
  291.   flags = UCH(targaheader[17]); /* Image Descriptor byte */
  292.   is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
  293.   interlace_type = flags >> 6; /* bits 6/7 are interlace code */
  294.   if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
  295.       source->pixel_size < 1 || source->pixel_size > 4 ||
  296.       (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
  297.       interlace_type != 0) /* currently don't allow interlaced image */
  298.     ERREXIT(cinfo, JERR_TGA_BADPARMS);
  299.   
  300.   if (subtype > 8) {
  301.     /* It's an RLE-coded file */
  302.     source->read_pixel = read_rle_pixel;
  303.     source->block_count = source->dup_pixel_count = 0;
  304.     subtype -= 8;
  305.   } else {
  306.     /* Non-RLE file */
  307.     source->read_pixel = read_non_rle_pixel;
  308.   }
  309.   /* Now should have subtype 1, 2, or 3 */
  310.   components = 3; /* until proven different */
  311.   cinfo->in_color_space = JCS_RGB;
  312.   switch (subtype) {
  313.   case 1: /* Colormapped image */
  314.     if (source->pixel_size == 1 && cmaptype == 1)
  315.       source->get_pixel_rows = get_8bit_row;
  316.     else
  317.       ERREXIT(cinfo, JERR_TGA_BADPARMS);
  318.     TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
  319.     break;
  320.   case 2: /* RGB image */
  321.     switch (source->pixel_size) {
  322.     case 2:
  323.       source->get_pixel_rows = get_16bit_row;
  324.       break;
  325.     case 3:
  326.       source->get_pixel_rows = get_24bit_row;
  327.       break;
  328.     case 4:
  329.       source->get_pixel_rows = get_32bit_row;
  330.       break;
  331.     default:
  332.       ERREXIT(cinfo, JERR_TGA_BADPARMS);
  333.       break;
  334.     }
  335.     TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
  336.     break;
  337.   case 3: /* Grayscale image */
  338.     components = 1;
  339.     cinfo->in_color_space = JCS_GRAYSCALE;
  340.     if (source->pixel_size == 1)
  341.       source->get_pixel_rows = get_8bit_gray_row;
  342.     else
  343.       ERREXIT(cinfo, JERR_TGA_BADPARMS);
  344.     TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
  345.     break;
  346.   default:
  347.     ERREXIT(cinfo, JERR_TGA_BADPARMS);
  348.     break;
  349.   }
  350.   if (is_bottom_up) {
  351.     /* Create a virtual array to buffer the upside-down image. */
  352.     source->whole_image = (*cinfo->mem->request_virt_sarray)
  353.       ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
  354.        (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
  355.     if (cinfo->progress != NULL) {
  356.       cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  357.       progress->total_extra_passes++; /* count file input as separate pass */
  358.     }
  359.     /* source->pub.buffer will point to the virtual array. */
  360.     source->pub.buffer_height = 1; /* in case anyone looks at it */
  361.     source->pub.get_pixel_rows = preload_image;
  362.   } else {
  363.     /* Don't need a virtual array, but do need a one-row input buffer. */
  364.     source->whole_image = NULL;
  365.     source->pub.buffer = (*cinfo->mem->alloc_sarray)
  366.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  367.        (JDIMENSION) width * components, (JDIMENSION) 1);
  368.     source->pub.buffer_height = 1;
  369.     source->pub.get_pixel_rows = source->get_pixel_rows;
  370.   }
  371.   
  372.   while (idlen--) /* Throw away ID field */
  373.     (void) read_byte(source);
  374.   if (maplen > 0) {
  375.     if (maplen > 256 || GET_2B(3) != 0)
  376.       ERREXIT(cinfo, JERR_TGA_BADCMAP);
  377.     /* Allocate space to store the colormap */
  378.     source->colormap = (*cinfo->mem->alloc_sarray)
  379.       ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
  380.     /* and read it from the file */
  381.     read_colormap(source, (int) maplen, UCH(targaheader[7]));
  382.   } else {
  383.     if (cmaptype) /* but you promised a cmap! */
  384.       ERREXIT(cinfo, JERR_TGA_BADPARMS);
  385.     source->colormap = NULL;
  386.   }
  387.   cinfo->input_components = components;
  388.   cinfo->data_precision = 8;
  389.   cinfo->image_width = width;
  390.   cinfo->image_height = height;
  391. }
  392. /*
  393.  * Finish up at the end of the file.
  394.  */
  395. METHODDEF(void)
  396. finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  397. {
  398.   /* no work */
  399. }
  400. /*
  401.  * The module selection routine for Targa format input.
  402.  */
  403. GLOBAL(cjpeg_source_ptr)
  404. jinit_read_targa (j_compress_ptr cinfo)
  405. {
  406.   tga_source_ptr source;
  407.   /* Create module interface object */
  408.   source = (tga_source_ptr)
  409.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  410.   SIZEOF(tga_source_struct));
  411.   source->cinfo = cinfo; /* make back link for subroutines */
  412.   /* Fill in method ptrs, except get_pixel_rows which start_input sets */
  413.   source->pub.start_input = start_input_tga;
  414.   source->pub.finish_input = finish_input_tga;
  415.   return (cjpeg_source_ptr) source;
  416. }
  417. #endif /* TARGA_SUPPORTED */