/*
 * jwrrle.c
 *
 * Copyright (C) 1991, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains routines to write output images in RLE format.
 * The Utah Raster Toolkit library is required (version 3.0).
 *
 * These routines may need modification for non-Unix environments or
 * specialized applications.  As they stand, they assume output to
 * an ordinary stdio stream.
 *
 * These routines are invoked via the methods put_pixel_rows, put_color_map,
 * and output_init/term.
 *
 * Based on code contributed by Mike Lijewski.
 */

#include "jinclude.h"

#ifdef RLE_SUPPORTED

/* rle.h is provided by the Utah Raster Toolkit. */

#include <rle.h>


/*
 * output_term assumes that JSAMPLE has the same representation as rle_pixel,
 * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
 */

#ifndef EIGHT_BIT_SAMPLES
  Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
#endif


/*
 * Since RLE stores scanlines bottom-to-top, we have to invert the image
 * from JPEG's top-to-bottom order.  To do this, we save the outgoing data
 * in virtual array(s) during put_pixel_row calls, then actually emit the
 * RLE file during output_term.  We use one virtual array if the output is
 * grayscale or colormapped, more if it is full color.
 */

#define MAX_CHANS	4	/* allow up to four color components */
static big_sarray_ptr channels[MAX_CHANS]; /* Virtual arrays for saved data */

static long cur_output_row;	/* next row# to write to virtual array(s) */


/*
 * For now, if we emit an RLE color map then it is always 256 entries long,
 * though not all of the entries need be used.
 */

#define CMAPBITS	8
#define CMAPLENGTH	(1<<(CMAPBITS))

static rle_map *output_colormap; /* RLE-style color map, or NULL if none */
static int number_colors;	/* Number of colors actually used */


/*
 * Write the file header.
 *
 * In this module it's easier to wait till output_term to actually write
 * anything; here we just request the big arrays we'll need.
 */

METHODDEF void
output_init (decompress_info_ptr cinfo)
{
  short ci;
  
  if (cinfo->final_out_comps > MAX_CHANS)
    ERREXIT1(cinfo->emethods, "Cannot handle %d output channels for RLE",
	     cinfo->final_out_comps);
  
  for (ci = 0; ci < cinfo->final_out_comps; ci++) {
    channels[ci] = (*cinfo->emethods->request_big_sarray)
			(cinfo->image_width, cinfo->image_height, 1L);
  }
  
  output_colormap = NULL;	/* No output colormap as yet */
  number_colors = 0;
  cur_output_row = 0;		/* Start filling virtual arrays at row 0 */
}


/*
 * Write some pixel data.
 *
 * This routine just saves the data away in virtual arrays.
 */

METHODDEF void
put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
		JSAMPIMAGE pixel_data)
{
  JSAMPROW outputrow[1];	/* a pseudo JSAMPARRAY structure */
  int row;
  short ci;
  
  for (row = 0; row < num_rows; row++) {
    for (ci = 0; ci < cinfo->final_out_comps; ci++) {
      outputrow[0] = *((*cinfo->emethods->access_big_sarray)
			(channels[ci], cur_output_row, TRUE));
      jcopy_sample_rows(pixel_data[ci], row, outputrow, 0,
			1, cinfo->image_width);
    }
    cur_output_row++;
  }
}


/*
 * Write the color map.
 *
 *  For RLE output we just save the colormap for the output stage.
 */

METHODDEF void
put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
{
  size_t cmapsize;
  short ci;
  int i;

  if (num_colors > CMAPLENGTH)
    ERREXIT1(cinfo->emethods, "Cannot handle %d colormap entries for RLE",
	     num_colors);

  /* Allocate storage for RLE-style cmap, zero any extra entries */
  cmapsize = cinfo->color_out_comps * CMAPLENGTH * SIZEOF(rle_map);
  output_colormap = (rle_map *) (*cinfo->emethods->alloc_small) (cmapsize);
  MEMZERO((void *) output_colormap, cmapsize);

  /* Save away data in RLE format --- note 8-bit left shift! */
  /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
  for (ci = 0; ci < cinfo->color_out_comps; ci++) {
    for (i = 0; i < num_colors; i++) {
      output_colormap[ci * CMAPLENGTH + i] = GETJSAMPLE(colormap[ci][i]) << 8;
    }
  }
  number_colors = num_colors;
}


/*
 * Finish up at the end of the file.
 *
 * Here is where we really output the RLE file.
 */

METHODDEF void
output_term (decompress_info_ptr cinfo)
{
  rle_hdr header;		/* Output file information */
  rle_pixel *output_rows[MAX_CHANS];
  char cmapcomment[80];
  short ci;
  long row;

  /* Initialize the header info */
  MEMZERO((void *) &header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */
  header.rle_file = cinfo->output_file;
  header.xmin     = 0;
  header.xmax     = cinfo->image_width  - 1;
  header.ymin     = 0;
  header.ymax     = cinfo->image_height - 1;
  header.alpha    = 0;
  header.ncolors  = cinfo->final_out_comps;
  for (ci = 0; ci < cinfo->final_out_comps; ci++) {
    RLE_SET_BIT(header, ci);
  }
  if (number_colors > 0) {
    header.ncmap   = cinfo->color_out_comps;
    header.cmaplen = CMAPBITS;
    header.cmap    = output_colormap;
    /* Add a comment to the output image with the true colormap length. */
    sprintf(cmapcomment, "color_map_length=%d", number_colors);
    rle_putcom(cmapcomment, &header);
  }
  /* Emit the RLE header and color map (if any) */
  rle_put_setup(&header);

  /* Now output the RLE data from our virtual array(s).
   * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
   * and (b) we are not on a machine where FAR pointers differ from regular.
   */
  for (row = cinfo->image_height-1; row >= 0; row--) {
    for (ci = 0; ci < cinfo->final_out_comps; ci++) {
      output_rows[ci] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
					(channels[ci], row, FALSE));
    }
    rle_putrow(output_rows, (int) cinfo->image_width, &header);
  }

  /* Emit file trailer */
  rle_puteof(&header);
  fflush(cinfo->output_file);
  if (ferror(cinfo->output_file))
    ERREXIT(cinfo->emethods, "Output file write error");

  /* Release memory */
  for (ci = 0; ci < cinfo->final_out_comps; ci++) {
    (*cinfo->emethods->free_big_sarray) (channels[ci]);
  }
  if (output_colormap != NULL)
    (*cinfo->emethods->free_small) ((void *) output_colormap);
}


/*
 * The method selection routine for RLE format output.
 * This should be called from d_ui_method_selection if RLE output is wanted.
 */

GLOBAL void
jselwrle (decompress_info_ptr cinfo)
{
  cinfo->methods->output_init    = output_init;
  cinfo->methods->put_color_map  = put_color_map;
  cinfo->methods->put_pixel_rows = put_pixel_rows;
  cinfo->methods->output_term    = output_term;
}

#endif /* RLE_SUPPORTED */
