kusano 7d535a
/*
kusano 7d535a
 * rdtarga.c
kusano 7d535a
 *
kusano 7d535a
 * Copyright (C) 1991-1996, Thomas G. Lane.
kusano 7d535a
 * This file is part of the Independent JPEG Group's software.
kusano 7d535a
 * For conditions of distribution and use, see the accompanying README file.
kusano 7d535a
 *
kusano 7d535a
 * This file contains routines to read input images in Targa format.
kusano 7d535a
 *
kusano 7d535a
 * These routines may need modification for non-Unix environments or
kusano 7d535a
 * specialized applications.  As they stand, they assume input from
kusano 7d535a
 * an ordinary stdio stream.  They further assume that reading begins
kusano 7d535a
 * at the start of the file; start_input may need work if the
kusano 7d535a
 * user interface has already read some data (e.g., to determine that
kusano 7d535a
 * the file is indeed Targa format).
kusano 7d535a
 *
kusano 7d535a
 * Based on code contributed by Lee Daniel Crocker.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */
kusano 7d535a
kusano 7d535a
#ifdef TARGA_SUPPORTED
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* Macros to deal with unsigned chars as efficiently as compiler allows */
kusano 7d535a
kusano 7d535a
#ifdef HAVE_UNSIGNED_CHAR
kusano 7d535a
typedef unsigned char U_CHAR;
kusano 7d535a
#define UCH(x)	((int) (x))
kusano 7d535a
#else /* !HAVE_UNSIGNED_CHAR */
kusano 7d535a
#ifdef CHAR_IS_UNSIGNED
kusano 7d535a
typedef char U_CHAR;
kusano 7d535a
#define UCH(x)	((int) (x))
kusano 7d535a
#else
kusano 7d535a
typedef char U_CHAR;
kusano 7d535a
#define UCH(x)	((int) (x) & 0xFF)
kusano 7d535a
#endif
kusano 7d535a
#endif /* HAVE_UNSIGNED_CHAR */
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define	ReadOK(file,buffer,len)	(JFREAD(file,buffer,len) == ((size_t) (len)))
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* Private version of data source object */
kusano 7d535a
kusano 7d535a
typedef struct _tga_source_struct * tga_source_ptr;
kusano 7d535a
kusano 7d535a
typedef struct _tga_source_struct {
kusano 7d535a
  struct cjpeg_source_struct pub; /* public fields */
kusano 7d535a
kusano 7d535a
  j_compress_ptr cinfo;		/* back link saves passing separate parm */
kusano 7d535a
kusano 7d535a
  JSAMPARRAY colormap;		/* Targa colormap (converted to my format) */
kusano 7d535a
kusano 7d535a
  jvirt_sarray_ptr whole_image;	/* Needed if funny input row order */
kusano 7d535a
  JDIMENSION current_row;	/* Current logical row number to read */
kusano 7d535a
kusano 7d535a
  /* Pointer to routine to extract next Targa pixel from input file */
kusano 7d535a
  JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
kusano 7d535a
kusano 7d535a
  /* Result of read_pixel is delivered here: */
kusano 7d535a
  U_CHAR tga_pixel[4];
kusano 7d535a
kusano 7d535a
  int pixel_size;		/* Bytes per Targa pixel (1 to 4) */
kusano 7d535a
kusano 7d535a
  /* State info for reading RLE-coded pixels; both counts must be init to 0 */
kusano 7d535a
  int block_count;		/* # of pixels remaining in RLE block */
kusano 7d535a
  int dup_pixel_count;		/* # of times to duplicate previous pixel */
kusano 7d535a
kusano 7d535a
  /* This saves the correct pixel-row-expansion method for preload_image */
kusano 7d535a
  JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
kusano 7d535a
				       cjpeg_source_ptr sinfo));
kusano 7d535a
} tga_source_struct;
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* For expanding 5-bit pixel values to 8-bit with best rounding */
kusano 7d535a
kusano 7d535a
static const UINT8 c5to8bits[32] = {
kusano 7d535a
    0,   8,  16,  25,  33,  41,  49,  58,
kusano 7d535a
   66,  74,  82,  90,  99, 107, 115, 123,
kusano 7d535a
  132, 140, 148, 156, 165, 173, 181, 189,
kusano 7d535a
  197, 206, 214, 222, 230, 239, 247, 255
kusano 7d535a
};
kusano 7d535a
kusano 7d535a
kusano 7d535a
kusano 7d535a
LOCAL(int)
kusano 7d535a
read_byte (tga_source_ptr sinfo)
kusano 7d535a
/* Read next byte from Targa file */
kusano 7d535a
{
kusano 7d535a
  register FILE *infile = sinfo->pub.input_file;
kusano 7d535a
  register int c;
kusano 7d535a
kusano 7d535a
  if ((c = getc(infile)) == EOF)
kusano 7d535a
    ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
kusano 7d535a
  return c;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
LOCAL(void)
kusano 7d535a
read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
kusano 7d535a
/* Read the colormap from a Targa file */
kusano 7d535a
{
kusano 7d535a
  int i;
kusano 7d535a
kusano 7d535a
  /* Presently only handles 24-bit BGR format */
kusano 7d535a
  if (mapentrysize != 24)
kusano 7d535a
    ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
kusano 7d535a
kusano 7d535a
  for (i = 0; i < cmaplen; i++) {
kusano 7d535a
    sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
kusano 7d535a
    sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
kusano 7d535a
    sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
kusano 7d535a
  }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
METHODDEF(void)
kusano 7d535a
read_non_rle_pixel (tga_source_ptr sinfo)
kusano 7d535a
/* Read one Targa pixel from the input file; no RLE expansion */
kusano 7d535a
{
kusano 7d535a
  register FILE *infile = sinfo->pub.input_file;
kusano 7d535a
  register int i;
kusano 7d535a
kusano 7d535a
  for (i = 0; i < sinfo->pixel_size; i++) {
kusano 7d535a
    sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
kusano 7d535a
  }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
METHODDEF(void)
kusano 7d535a
read_rle_pixel (tga_source_ptr sinfo)
kusano 7d535a
/* Read one Targa pixel from the input file, expanding RLE data as needed */
kusano 7d535a
{
kusano 7d535a
  register FILE *infile = sinfo->pub.input_file;
kusano 7d535a
  register int i;
kusano 7d535a
kusano 7d535a
  /* Duplicate previously read pixel? */
kusano 7d535a
  if (sinfo->dup_pixel_count > 0) {
kusano 7d535a
    sinfo->dup_pixel_count--;
kusano 7d535a
    return;
kusano 7d535a
  }
kusano 7d535a
kusano 7d535a
  /* Time to read RLE block header? */
kusano 7d535a
  if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
kusano 7d535a
    i = read_byte(sinfo);
kusano 7d535a
    if (i & 0x80) {		/* Start of duplicate-pixel block? */
kusano 7d535a
      sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
kusano 7d535a
      sinfo->block_count = 0;	/* then read new block header */
kusano 7d535a
    } else {
kusano 7d535a
      sinfo->block_count = i & 0x7F; /* number of pixels after this one */
kusano 7d535a
    }
kusano 7d535a
  }
kusano 7d535a
kusano 7d535a
  /* Read next pixel */
kusano 7d535a
  for (i = 0; i < sinfo->pixel_size; i++) {
kusano 7d535a
    sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
kusano 7d535a
  }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Read one row of pixels.
kusano 7d535a
 *
kusano 7d535a
 * We provide several different versions depending on input file format.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
/* This version is for reading 8-bit grayscale pixels */
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  register JSAMPROW ptr;
kusano 7d535a
  register JDIMENSION col;
kusano 7d535a
  
kusano 7d535a
  ptr = source->pub.buffer[0];
kusano 7d535a
  for (col = cinfo->image_width; col > 0; col--) {
kusano 7d535a
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
kusano 7d535a
    *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
kusano 7d535a
  }
kusano 7d535a
  return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
/* This version is for reading 8-bit colormap indexes */
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  register int t;
kusano 7d535a
  register JSAMPROW ptr;
kusano 7d535a
  register JDIMENSION col;
kusano 7d535a
  register JSAMPARRAY colormap = source->colormap;
kusano 7d535a
kusano 7d535a
  ptr = source->pub.buffer[0];
kusano 7d535a
  for (col = cinfo->image_width; col > 0; col--) {
kusano 7d535a
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
kusano 7d535a
    t = UCH(source->tga_pixel[0]);
kusano 7d535a
    *ptr++ = colormap[0][t];
kusano 7d535a
    *ptr++ = colormap[1][t];
kusano 7d535a
    *ptr++ = colormap[2][t];
kusano 7d535a
  }
kusano 7d535a
  return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
/* This version is for reading 16-bit pixels */
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  register int t;
kusano 7d535a
  register JSAMPROW ptr;
kusano 7d535a
  register JDIMENSION col;
kusano 7d535a
  
kusano 7d535a
  ptr = source->pub.buffer[0];
kusano 7d535a
  for (col = cinfo->image_width; col > 0; col--) {
kusano 7d535a
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
kusano 7d535a
    t = UCH(source->tga_pixel[0]);
kusano 7d535a
    t += UCH(source->tga_pixel[1]) << 8;
kusano 7d535a
    /* We expand 5 bit data to 8 bit sample width.
kusano 7d535a
     * The format of the 16-bit (LSB first) input word is
kusano 7d535a
     *     xRRRRRGGGGGBBBBB
kusano 7d535a
     */
kusano 7d535a
    ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
kusano 7d535a
    t >>= 5;
kusano 7d535a
    ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
kusano 7d535a
    t >>= 5;
kusano 7d535a
    ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
kusano 7d535a
    ptr += 3;
kusano 7d535a
  }
kusano 7d535a
  return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
/* This version is for reading 24-bit pixels */
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  register JSAMPROW ptr;
kusano 7d535a
  register JDIMENSION col;
kusano 7d535a
  
kusano 7d535a
  ptr = source->pub.buffer[0];
kusano 7d535a
  for (col = cinfo->image_width; col > 0; col--) {
kusano 7d535a
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
kusano 7d535a
    *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
kusano 7d535a
    *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
kusano 7d535a
    *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
kusano 7d535a
  }
kusano 7d535a
  return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Targa also defines a 32-bit pixel format with order B,G,R,A.
kusano 7d535a
 * We presently ignore the attribute byte, so the code for reading
kusano 7d535a
 * these pixels is identical to the 24-bit routine above.
kusano 7d535a
 * This works because the actual pixel length is only known to read_pixel.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
#define get_32bit_row  get_24bit_row
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * This method is for re-reading the input data in standard top-down
kusano 7d535a
 * row order.  The entire image has already been read into whole_image
kusano 7d535a
 * with proper conversion of pixel format, but it's in a funny row order.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  JDIMENSION source_row;
kusano 7d535a
kusano 7d535a
  /* Compute row of source that maps to current_row of normal order */
kusano 7d535a
  /* For now, assume image is bottom-up and not interlaced. */
kusano 7d535a
  /* NEEDS WORK to support interlaced images! */
kusano 7d535a
  source_row = cinfo->image_height - source->current_row - 1;
kusano 7d535a
kusano 7d535a
  /* Fetch that row from virtual array */
kusano 7d535a
  source->pub.buffer = (*cinfo->mem->access_virt_sarray)
kusano 7d535a
    ((j_common_ptr) cinfo, source->whole_image,
kusano 7d535a
     source_row, (JDIMENSION) 1, FALSE);
kusano 7d535a
kusano 7d535a
  source->current_row++;
kusano 7d535a
  return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * This method loads the image into whole_image during the first call on
kusano 7d535a
 * get_pixel_rows.  The get_pixel_rows pointer is then adjusted to call
kusano 7d535a
 * get_memory_row on subsequent calls.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
METHODDEF(JDIMENSION)
kusano 7d535a
preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  JDIMENSION row;
kusano 7d535a
  cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
kusano 7d535a
kusano 7d535a
  /* Read the data into a virtual array in input-file row order. */
kusano 7d535a
  for (row = 0; row < cinfo->image_height; row++) {
kusano 7d535a
    if (progress != NULL) {
kusano 7d535a
      progress->pub.pass_counter = (long) row;
kusano 7d535a
      progress->pub.pass_limit = (long) cinfo->image_height;
kusano 7d535a
      (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
kusano 7d535a
    }
kusano 7d535a
    source->pub.buffer = (*cinfo->mem->access_virt_sarray)
kusano 7d535a
      ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
kusano 7d535a
    (*source->get_pixel_rows) (cinfo, sinfo);
kusano 7d535a
  }
kusano 7d535a
  if (progress != NULL)
kusano 7d535a
    progress->completed_extra_passes++;
kusano 7d535a
kusano 7d535a
  /* Set up to read from the virtual array in unscrambled order */
kusano 7d535a
  source->pub.get_pixel_rows = get_memory_row;
kusano 7d535a
  source->current_row = 0;
kusano 7d535a
  /* And read the first row */
kusano 7d535a
  return get_memory_row(cinfo, sinfo);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Read the file header; return image size and component count.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
METHODDEF(void)
kusano 7d535a
start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source = (tga_source_ptr) sinfo;
kusano 7d535a
  U_CHAR targaheader[18];
kusano 7d535a
  int idlen, cmaptype, subtype, flags, interlace_type, components;
kusano 7d535a
  unsigned int width, height, maplen;
kusano 7d535a
  boolean is_bottom_up;
kusano 7d535a
kusano 7d535a
#define GET_2B(offset)	((unsigned int) UCH(targaheader[offset]) + \
kusano 7d535a
			 (((unsigned int) UCH(targaheader[offset+1])) << 8))
kusano 7d535a
kusano 7d535a
  if (! ReadOK(source->pub.input_file, targaheader, 18))
kusano 7d535a
    ERREXIT(cinfo, JERR_INPUT_EOF);
kusano 7d535a
kusano 7d535a
  /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
kusano 7d535a
  if (targaheader[16] == 15)
kusano 7d535a
    targaheader[16] = 16;
kusano 7d535a
kusano 7d535a
  idlen = UCH(targaheader[0]);
kusano 7d535a
  cmaptype = UCH(targaheader[1]);
kusano 7d535a
  subtype = UCH(targaheader[2]);
kusano 7d535a
  maplen = GET_2B(5);
kusano 7d535a
  width = GET_2B(12);
kusano 7d535a
  height = GET_2B(14);
kusano 7d535a
  source->pixel_size = UCH(targaheader[16]) >> 3;
kusano 7d535a
  flags = UCH(targaheader[17]);	/* Image Descriptor byte */
kusano 7d535a
kusano 7d535a
  is_bottom_up = ((flags & 0x20) == 0);	/* bit 5 set => top-down */
kusano 7d535a
  interlace_type = flags >> 6;	/* bits 6/7 are interlace code */
kusano 7d535a
kusano 7d535a
  if (cmaptype > 1 ||		/* cmaptype must be 0 or 1 */
kusano 7d535a
      source->pixel_size < 1 || source->pixel_size > 4 ||
kusano 7d535a
      (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
kusano 7d535a
      interlace_type != 0)	/* currently don't allow interlaced image */
kusano 7d535a
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
  
kusano 7d535a
  if (subtype > 8) {
kusano 7d535a
    /* It's an RLE-coded file */
kusano 7d535a
    source->read_pixel = read_rle_pixel;
kusano 7d535a
    source->block_count = source->dup_pixel_count = 0;
kusano 7d535a
    subtype -= 8;
kusano 7d535a
  } else {
kusano 7d535a
    /* Non-RLE file */
kusano 7d535a
    source->read_pixel = read_non_rle_pixel;
kusano 7d535a
  }
kusano 7d535a
kusano 7d535a
  /* Now should have subtype 1, 2, or 3 */
kusano 7d535a
  components = 3;		/* until proven different */
kusano 7d535a
  cinfo->in_color_space = JCS_RGB;
kusano 7d535a
kusano 7d535a
  switch (subtype) {
kusano 7d535a
  case 1:			/* Colormapped image */
kusano 7d535a
    if (source->pixel_size == 1 && cmaptype == 1)
kusano 7d535a
      source->get_pixel_rows = get_8bit_row;
kusano 7d535a
    else
kusano 7d535a
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
    TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
kusano 7d535a
    break;
kusano 7d535a
  case 2:			/* RGB image */
kusano 7d535a
    switch (source->pixel_size) {
kusano 7d535a
    case 2:
kusano 7d535a
      source->get_pixel_rows = get_16bit_row;
kusano 7d535a
      break;
kusano 7d535a
    case 3:
kusano 7d535a
      source->get_pixel_rows = get_24bit_row;
kusano 7d535a
      break;
kusano 7d535a
    case 4:
kusano 7d535a
      source->get_pixel_rows = get_32bit_row;
kusano 7d535a
      break;
kusano 7d535a
    default:
kusano 7d535a
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
      break;
kusano 7d535a
    }
kusano 7d535a
    TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
kusano 7d535a
    break;
kusano 7d535a
  case 3:			/* Grayscale image */
kusano 7d535a
    components = 1;
kusano 7d535a
    cinfo->in_color_space = JCS_GRAYSCALE;
kusano 7d535a
    if (source->pixel_size == 1)
kusano 7d535a
      source->get_pixel_rows = get_8bit_gray_row;
kusano 7d535a
    else
kusano 7d535a
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
    TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
kusano 7d535a
    break;
kusano 7d535a
  default:
kusano 7d535a
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
    break;
kusano 7d535a
  }
kusano 7d535a
kusano 7d535a
  if (is_bottom_up) {
kusano 7d535a
    /* Create a virtual array to buffer the upside-down image. */
kusano 7d535a
    source->whole_image = (*cinfo->mem->request_virt_sarray)
kusano 7d535a
      ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
kusano 7d535a
       (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
kusano 7d535a
    if (cinfo->progress != NULL) {
kusano 7d535a
      cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
kusano 7d535a
      progress->total_extra_passes++; /* count file input as separate pass */
kusano 7d535a
    }
kusano 7d535a
    /* source->pub.buffer will point to the virtual array. */
kusano 7d535a
    source->pub.buffer_height = 1; /* in case anyone looks at it */
kusano 7d535a
    source->pub.get_pixel_rows = preload_image;
kusano 7d535a
  } else {
kusano 7d535a
    /* Don't need a virtual array, but do need a one-row input buffer. */
kusano 7d535a
    source->whole_image = NULL;
kusano 7d535a
    source->pub.buffer = (*cinfo->mem->alloc_sarray)
kusano 7d535a
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
kusano 7d535a
       (JDIMENSION) width * components, (JDIMENSION) 1);
kusano 7d535a
    source->pub.buffer_height = 1;
kusano 7d535a
    source->pub.get_pixel_rows = source->get_pixel_rows;
kusano 7d535a
  }
kusano 7d535a
  
kusano 7d535a
  while (idlen--)		/* Throw away ID field */
kusano 7d535a
    (void) read_byte(source);
kusano 7d535a
kusano 7d535a
  if (maplen > 0) {
kusano 7d535a
    if (maplen > 256 || GET_2B(3) != 0)
kusano 7d535a
      ERREXIT(cinfo, JERR_TGA_BADCMAP);
kusano 7d535a
    /* Allocate space to store the colormap */
kusano 7d535a
    source->colormap = (*cinfo->mem->alloc_sarray)
kusano 7d535a
      ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
kusano 7d535a
    /* and read it from the file */
kusano 7d535a
    read_colormap(source, (int) maplen, UCH(targaheader[7]));
kusano 7d535a
  } else {
kusano 7d535a
    if (cmaptype)		/* but you promised a cmap! */
kusano 7d535a
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
kusano 7d535a
    source->colormap = NULL;
kusano 7d535a
  }
kusano 7d535a
kusano 7d535a
  cinfo->input_components = components;
kusano 7d535a
  cinfo->data_precision = 8;
kusano 7d535a
  cinfo->image_width = width;
kusano 7d535a
  cinfo->image_height = height;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Finish up at the end of the file.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
METHODDEF(void)
kusano 7d535a
finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
kusano 7d535a
{
kusano 7d535a
  /* no work */
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * The module selection routine for Targa format input.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
GLOBAL(cjpeg_source_ptr)
kusano 7d535a
jinit_read_targa (j_compress_ptr cinfo)
kusano 7d535a
{
kusano 7d535a
  tga_source_ptr source;
kusano 7d535a
kusano 7d535a
  /* Create module interface object */
kusano 7d535a
  source = (tga_source_ptr)
kusano 7d535a
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
kusano 7d535a
				  SIZEOF(tga_source_struct));
kusano 7d535a
  source->cinfo = cinfo;	/* make back link for subroutines */
kusano 7d535a
  /* Fill in method ptrs, except get_pixel_rows which start_input sets */
kusano 7d535a
  source->pub.start_input = start_input_tga;
kusano 7d535a
  source->pub.finish_input = finish_input_tga;
kusano 7d535a
kusano 7d535a
  return (cjpeg_source_ptr) source;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#endif /* TARGA_SUPPORTED */