/*
 * rdtarga.c
 *
 * This file was part of the Independent JPEG Group's software:
 * Copyright (C) 1991-1996, Thomas G. Lane.
 * Modified 2017 by Guido Vollbeding.
 * libjpeg-turbo Modifications:
 * Copyright (C) 2018, 2021, D. R. Commander.
 * For conditions of distribution and use, see the accompanying README.ijg
 * file.
 *
 * This file contains routines to read input images in Targa format.
 *
 * These routines may need modification for non-Unix environments or
 * specialized applications.  As they stand, they assume input from
 * an ordinary stdio stream.  They further assume that reading begins
 * at the start of the file; start_input may need work if the
 * user interface has already read some data (e.g., to determine that
 * the file is indeed Targa format).
 *
 * Based on code contributed by Lee Daniel Crocker.
 */

#include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */

#ifdef TARGA_SUPPORTED


/* Macros to deal with unsigned chars as efficiently as compiler allows */

typedef unsigned char U_CHAR;
#define UCH(x)  ((int)(x))


#define ReadOK(file, buffer, len) \
  (JFREAD(file, buffer, len) == ((size_t)(len)))


/* Private version of data source object */

typedef struct _tga_source_struct *tga_source_ptr;

typedef struct _tga_source_struct {
  struct cjpeg_source_struct pub; /* public fields */

  j_compress_ptr cinfo;         /* back link saves passing separate parm */

  JSAMPARRAY colormap;          /* Targa colormap (converted to my format) */

  jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
  JDIMENSION current_row;       /* Current logical row number to read */

  /* Pointer to routine to extract next Targa pixel from input file */
  void (*read_pixel) (tga_source_ptr sinfo);

  /* Result of read_pixel is delivered here: */
  U_CHAR tga_pixel[4];

  int pixel_size;               /* Bytes per Targa pixel (1 to 4) */
  int cmap_length;              /* colormap length */

  /* State info for reading RLE-coded pixels; both counts must be init to 0 */
  int block_count;              /* # of pixels remaining in RLE block */
  int dup_pixel_count;          /* # of times to duplicate previous pixel */

  /* This saves the correct pixel-row-expansion method for preload_image */
  JDIMENSION (*get_pixel_rows) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
} tga_source_struct;


/* For expanding 5-bit pixel values to 8-bit with best rounding */

static const UINT8 c5to8bits[32] = {
    0,   8,  16,  25,  33,  41,  49,  58,
   66,  74,  82,  90,  99, 107, 115, 123,
  132, 140, 148, 156, 165, 173, 181, 189,
  197, 206, 214, 222, 230, 239, 247, 255
};



LOCAL(int)
read_byte(tga_source_ptr sinfo)
/* Read next byte from Targa file */
{
  register FILE *infile = sinfo->pub.input_file;
  register int c;

  if ((c = getc(infile)) == EOF)
    ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
  return c;
}


LOCAL(void)
read_colormap(tga_source_ptr sinfo, int cmaplen, int mapentrysize)
/* Read the colormap from a Targa file */
{
  int i;

  /* Presently only handles 24-bit BGR format */
  if (mapentrysize != 24)
    ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);

  for (i = 0; i < cmaplen; i++) {
    sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo);
    sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo);
    sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo);
  }
}


/*
 * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
 */

METHODDEF(void)
read_non_rle_pixel(tga_source_ptr sinfo)
/* Read one Targa pixel from the input file; no RLE expansion */
{
  register int i;

  for (i = 0; i < sinfo->pixel_size; i++) {
    sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
  }
}


METHODDEF(void)
read_rle_pixel(tga_source_ptr sinfo)
/* Read one Targa pixel from the input file, expanding RLE data as needed */
{
  register int i;

  /* Duplicate previously read pixel? */
  if (sinfo->dup_pixel_count > 0) {
    sinfo->dup_pixel_count--;
    return;
  }

  /* Time to read RLE block header? */
  if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
    i = read_byte(sinfo);
    if (i & 0x80) {             /* Start of duplicate-pixel block? */
      sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
      sinfo->block_count = 0;   /* then read new block header */
    } else {
      sinfo->block_count = i & 0x7F; /* number of pixels after this one */
    }
  }

  /* Read next pixel */
  for (i = 0; i < sinfo->pixel_size; i++) {
    sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
  }
}


/*
 * Read one row of pixels.
 *
 * We provide several different versions depending on input file format.
 */


METHODDEF(JDIMENSION)
get_8bit_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 8-bit grayscale pixels */
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  register JSAMPROW ptr;
  register JDIMENSION col;

  ptr = source->pub.buffer[0];
  for (col = cinfo->image_width; col > 0; col--) {
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
    *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
  }
  return 1;
}

METHODDEF(JDIMENSION)
get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 8-bit colormap indexes */
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  register int t;
  register JSAMPROW ptr;
  register JDIMENSION col;
  register JSAMPARRAY colormap = source->colormap;
  int cmaplen = source->cmap_length;

  ptr = source->pub.buffer[0];
  for (col = cinfo->image_width; col > 0; col--) {
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
    t = UCH(source->tga_pixel[0]);
    if (t >= cmaplen)
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    *ptr++ = colormap[0][t];
    *ptr++ = colormap[1][t];
    *ptr++ = colormap[2][t];
  }
  return 1;
}

METHODDEF(JDIMENSION)
get_16bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 16-bit pixels */
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  register int t;
  register JSAMPROW ptr;
  register JDIMENSION col;

  ptr = source->pub.buffer[0];
  for (col = cinfo->image_width; col > 0; col--) {
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
    t = UCH(source->tga_pixel[0]);
    t += UCH(source->tga_pixel[1]) << 8;
    /* We expand 5 bit data to 8 bit sample width.
     * The format of the 16-bit (LSB first) input word is
     *     xRRRRRGGGGGBBBBB
     */
    ptr[2] = (JSAMPLE)c5to8bits[t & 0x1F];
    t >>= 5;
    ptr[1] = (JSAMPLE)c5to8bits[t & 0x1F];
    t >>= 5;
    ptr[0] = (JSAMPLE)c5to8bits[t & 0x1F];
    ptr += 3;
  }
  return 1;
}

METHODDEF(JDIMENSION)
get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 24-bit pixels */
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  register JSAMPROW ptr;
  register JDIMENSION col;

  ptr = source->pub.buffer[0];
  for (col = cinfo->image_width; col > 0; col--) {
    (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
    *ptr++ = (JSAMPLE)UCH(source->tga_pixel[2]); /* change BGR to RGB order */
    *ptr++ = (JSAMPLE)UCH(source->tga_pixel[1]);
    *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
  }
  return 1;
}

/*
 * Targa also defines a 32-bit pixel format with order B,G,R,A.
 * We presently ignore the attribute byte, so the code for reading
 * these pixels is identical to the 24-bit routine above.
 * This works because the actual pixel length is only known to read_pixel.
 */

#define get_32bit_row  get_24bit_row


/*
 * This method is for re-reading the input data in standard top-down
 * row order.  The entire image has already been read into whole_image
 * with proper conversion of pixel format, but it's in a funny row order.
 */

METHODDEF(JDIMENSION)
get_memory_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  JDIMENSION source_row;

  /* Compute row of source that maps to current_row of normal order */
  /* For now, assume image is bottom-up and not interlaced. */
  /* NEEDS WORK to support interlaced images! */
  source_row = cinfo->image_height - source->current_row - 1;

  /* Fetch that row from virtual array */
  source->pub.buffer = (*cinfo->mem->access_virt_sarray)
    ((j_common_ptr)cinfo, source->whole_image,
     source_row, (JDIMENSION)1, FALSE);

  source->current_row++;
  return 1;
}


/*
 * This method loads the image into whole_image during the first call on
 * get_pixel_rows.  The get_pixel_rows pointer is then adjusted to call
 * get_memory_row on subsequent calls.
 */

METHODDEF(JDIMENSION)
preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  JDIMENSION row;
  cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;

  /* Read the data into a virtual array in input-file row order. */
  for (row = 0; row < cinfo->image_height; row++) {
    if (progress != NULL) {
      progress->pub.pass_counter = (long)row;
      progress->pub.pass_limit = (long)cinfo->image_height;
      (*progress->pub.progress_monitor) ((j_common_ptr)cinfo);
    }
    source->pub.buffer = (*cinfo->mem->access_virt_sarray)
      ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE);
    (*source->get_pixel_rows) (cinfo, sinfo);
  }
  if (progress != NULL)
    progress->completed_extra_passes++;

  /* Set up to read from the virtual array in unscrambled order */
  source->pub.get_pixel_rows = get_memory_row;
  source->current_row = 0;
  /* And read the first row */
  return get_memory_row(cinfo, sinfo);
}


/*
 * Read the file header; return image size and component count.
 */

METHODDEF(void)
start_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  tga_source_ptr source = (tga_source_ptr)sinfo;
  U_CHAR targaheader[18];
  int idlen, cmaptype, subtype, flags, interlace_type, components;
  unsigned int width, height, maplen;
  boolean is_bottom_up;

#define GET_2B(offset) \
  ((unsigned int)UCH(targaheader[offset]) + \
   (((unsigned int)UCH(targaheader[offset + 1])) << 8))

  if (!ReadOK(source->pub.input_file, targaheader, 18))
    ERREXIT(cinfo, JERR_INPUT_EOF);

  /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  if (targaheader[16] == 15)
    targaheader[16] = 16;

  idlen = UCH(targaheader[0]);
  cmaptype = UCH(targaheader[1]);
  subtype = UCH(targaheader[2]);
  maplen = GET_2B(5);
  width = GET_2B(12);
  height = GET_2B(14);
  source->pixel_size = UCH(targaheader[16]) >> 3;
  flags = UCH(targaheader[17]); /* Image Descriptor byte */

  is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
  interlace_type = flags >> 6;  /* bits 6/7 are interlace code */

  if (cmaptype > 1 ||           /* cmaptype must be 0 or 1 */
      source->pixel_size < 1 || source->pixel_size > 4 ||
      (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
      interlace_type != 0 ||      /* currently don't allow interlaced image */
      width == 0 || height == 0)  /* image width/height must be non-zero */
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  if (sinfo->max_pixels &&
      (unsigned long long)width * height > sinfo->max_pixels)
    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
#endif

  if (subtype > 8) {
    /* It's an RLE-coded file */
    source->read_pixel = read_rle_pixel;
    source->block_count = source->dup_pixel_count = 0;
    subtype -= 8;
  } else {
    /* Non-RLE file */
    source->read_pixel = read_non_rle_pixel;
  }

  /* Now should have subtype 1, 2, or 3 */
  components = 3;               /* until proven different */
  cinfo->in_color_space = JCS_RGB;

  switch (subtype) {
  case 1:                       /* Colormapped image */
    if (source->pixel_size == 1 && cmaptype == 1)
      source->get_pixel_rows = get_8bit_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
    break;
  case 2:                       /* RGB image */
    switch (source->pixel_size) {
    case 2:
      source->get_pixel_rows = get_16bit_row;
      break;
    case 3:
      source->get_pixel_rows = get_24bit_row;
      break;
    case 4:
      source->get_pixel_rows = get_32bit_row;
      break;
    default:
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
      break;
    }
    TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
    break;
  case 3:                       /* Grayscale image */
    components = 1;
    cinfo->in_color_space = JCS_GRAYSCALE;
    if (source->pixel_size == 1)
      source->get_pixel_rows = get_8bit_gray_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
    break;
  default:
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
    break;
  }

  if (is_bottom_up) {
    /* Create a virtual array to buffer the upside-down image. */
    source->whole_image = (*cinfo->mem->request_virt_sarray)
      ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
       (JDIMENSION)width * components, (JDIMENSION)height, (JDIMENSION)1);
    if (cinfo->progress != NULL) {
      cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
      progress->total_extra_passes++; /* count file input as separate pass */
    }
    /* source->pub.buffer will point to the virtual array. */
    source->pub.buffer_height = 1; /* in case anyone looks at it */
    source->pub.get_pixel_rows = preload_image;
  } else {
    /* Don't need a virtual array, but do need a one-row input buffer. */
    source->whole_image = NULL;
    source->pub.buffer = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr)cinfo, JPOOL_IMAGE,
       (JDIMENSION)width * components, (JDIMENSION)1);
    source->pub.buffer_height = 1;
    source->pub.get_pixel_rows = source->get_pixel_rows;
  }

  while (idlen--)               /* Throw away ID field */
    (void)read_byte(source);

  if (maplen > 0) {
    if (maplen > 256 || GET_2B(3) != 0)
      ERREXIT(cinfo, JERR_TGA_BADCMAP);
    /* Allocate space to store the colormap */
    source->colormap = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)maplen, (JDIMENSION)3);
    source->cmap_length = (int)maplen;
    /* and read it from the file */
    read_colormap(source, (int)maplen, UCH(targaheader[7]));
  } else {
    if (cmaptype)               /* but you promised a cmap! */
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    source->colormap = NULL;
    source->cmap_length = 0;
  }

  cinfo->input_components = components;
  cinfo->data_precision = 8;
  cinfo->image_width = width;
  cinfo->image_height = height;
}


/*
 * Finish up at the end of the file.
 */

METHODDEF(void)
finish_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  /* no work */
}


/*
 * The module selection routine for Targa format input.
 */

GLOBAL(cjpeg_source_ptr)
jinit_read_targa(j_compress_ptr cinfo)
{
  tga_source_ptr source;

  /* Create module interface object */
  source = (tga_source_ptr)
    (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
                                sizeof(tga_source_struct));
  source->cinfo = cinfo;        /* make back link for subroutines */
  /* Fill in method ptrs, except get_pixel_rows which start_input sets */
  source->pub.start_input = start_input_tga;
  source->pub.finish_input = finish_input_tga;
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  source->pub.max_pixels = 0;
#endif

  return (cjpeg_source_ptr)source;
}

#endif /* TARGA_SUPPORTED */
