/*
 * jdcolor.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 output colorspace conversion routines.
 * These routines are invoked via the methods color_convert
 * and colorout_init/term.
 */

#include "jinclude.h"


/*
 * Initialize for colorspace conversion.
 */

METHODDEF void
colorout_init (decompress_info_ptr cinfo)
{
  /* no work needed */
}


/*
 * Convert some rows of samples to the output colorspace.
 * This version handles YCbCr -> RGB conversion.
 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
 */

METHODDEF void
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows,
		 JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
  register INT32 y, u, v, x;
  register JSAMPROW inptr0, inptr1, inptr2;
  register JSAMPROW outptr0, outptr1, outptr2;
  register long col;
  register long width = cinfo->image_width;
  register int row;
  
  for (row = 0; row < num_rows; row++) {
    inptr0 = input_data[0][row];
    inptr1 = input_data[1][row];
    inptr2 = input_data[2][row];
    outptr0 = output_data[0][row];
    outptr1 = output_data[1][row];
    outptr2 = output_data[2][row];
    for (col = width; col > 0; col--) {
      y = GETJSAMPLE(*inptr0++);
      u = (int) GETJSAMPLE(*inptr1++) - CENTERJSAMPLE;
      v = (int) GETJSAMPLE(*inptr2++) - CENTERJSAMPLE;
      /* Note: if the inputs were computed directly from RGB values,
       * range-limiting would be unnecessary here; but due to possible
       * noise in the DCT/IDCT phase, we do need to apply range limits.
       */
      y *= 1024;	/* in case compiler can't spot common subexpression */
      x = y          + 1436*v + 512; /* red */
      if (x < 0) x = 0;
      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
      *outptr0++ = x >> 10;
      x = y -  352*u -  731*v + 512; /* green */
      if (x < 0) x = 0;
      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
      *outptr1++ = x >> 10;
      x = y + 1815*u          + 512; /* blue */
      if (x < 0) x = 0;
      if (x > ((INT32) MAXJSAMPLE*1024)) x = (INT32) MAXJSAMPLE*1024;
      *outptr2++ = x >> 10;
    }
  }
}


/*
 * Color conversion for no colorspace change: just copy the data.
 */

METHODDEF void
null_convert (decompress_info_ptr cinfo, int num_rows,
	      JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
  short ci;

  for (ci = 0; ci < cinfo->num_components; ci++) {
    jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
		      num_rows, cinfo->image_width);
  }
}


/*
 * Color conversion for grayscale: just copy the data.
 * This also works for YCbCr/YIQ -> grayscale conversion, in which
 * we just copy the Y (luminance) component and ignore chrominance.
 */

METHODDEF void
grayscale_convert (decompress_info_ptr cinfo, int num_rows,
		   JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
  jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
		    num_rows, cinfo->image_width);
}


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

METHODDEF void
colorout_term (decompress_info_ptr cinfo)
{
  /* no work needed */
}


/*
 * The method selection routine for output colorspace conversion.
 */

GLOBAL void
jseldcolor (decompress_info_ptr cinfo)
{
  /* Make sure num_components agrees with jpeg_color_space */
  switch (cinfo->jpeg_color_space) {
  case CS_GRAYSCALE:
    if (cinfo->num_components != 1)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  case CS_RGB:
  case CS_YIQ:
  case CS_YCbCr:
    if (cinfo->num_components != 3)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  case CS_CMYK:
    if (cinfo->num_components != 4)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  default:
    ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
    break;
  }

  /* Set color_out_comps and conversion method based on requested space */
  switch (cinfo->out_color_space) {
  case CS_GRAYSCALE:
    cinfo->color_out_comps = 1;
    if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
	cinfo->jpeg_color_space == CS_YCbCr ||
	cinfo->jpeg_color_space == CS_YIQ)
      cinfo->methods->color_convert = grayscale_convert;
    else
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;

  case CS_RGB:
    cinfo->color_out_comps = 3;
    if (cinfo->jpeg_color_space == CS_YCbCr)
      cinfo->methods->color_convert = ycc_rgb_convert;
    else if (cinfo->jpeg_color_space == CS_RGB)
      cinfo->methods->color_convert = null_convert;
    else
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;

  case CS_CMYK:
    cinfo->color_out_comps = 4;
    if (cinfo->jpeg_color_space == CS_CMYK)
      cinfo->methods->color_convert = null_convert;
    else
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;

  default:
    ERREXIT(cinfo->emethods, "Unsupported output colorspace");
    break;
  }

  if (cinfo->quantize_colors)
    cinfo->final_out_comps = 1;	/* single colormapped output component */
  else
    cinfo->final_out_comps = cinfo->color_out_comps;

  cinfo->methods->colorout_init = colorout_init;
  cinfo->methods->colorout_term = colorout_term;
}
