/* 
   Copyright (C) 1999 E. H. Haley

   does RGB <--> YIQ translations (a matrix multiplication).  Of
   course, "2" in the function name means "to".  "256" in the function
   name means the RGB values are JSAMPLEs (i.e. unsigned char).
   
   rgbk256yiqy takes a ncolors argument.  If nc=3, it does the
   multiplication, rgb to yiq; if nc=1 (grayscale), it sets k to y.

*/

#include "color.h"
#include <jpeglib.h>

/*
>> m = [.299,.587,.114;  .596, -.275, -.321; .212,-.528, .311] 
m =
   0.29900   0.58700   0.11400
   0.59600  -0.27500  -0.32100
   0.21200  -0.52800   0.31100
note 1st row adds to one, 2nd to zero, 3rd nearly to 0 (typo?)

>> inv(m)
ans =
   1.00309   0.95485   0.61786
   0.99678  -0.27071  -0.64479
   1.00850 -1.11049 1.69957 */


void rgb2yiq(float *rgb, float *yiq)
{
  int row,col;
  float rgb2yiq[3][3]={{.299,  .587,  .114},
		       {.596, -.275, -.321},
		       {.212, -.528,  .311}};

  for(row=0; row<3; row++)
    {
      yiq[row]=0;
      for(col=0; col<3; col++)
	yiq[row] += rgb2yiq[row][col] * rgb[col];
    }
}

void rgb256yiq(JSAMPLE *rgb, float *yiq)
{
  int row,col;
  float rgb2yiq[3][3]={{.299,  .587,  .114},
		       {.596, -.275, -.321},
		       {.212, -.528,  .311}};

  for(row=0; row<3; row++)
    {
      yiq[row]=0;
      for(col=0; col<3; col++)
	yiq[row] += rgb2yiq[row][col] * (float)rgb[col];
    }
}

void rgbk256yiqy(JSAMPLE *rgbk, float *yiqy, int nc)
{
  int row,col;
  float rgb2yiq[3][3]={{.299,  .587,  .114},
		       {.596, -.275, -.321},
		       {.212, -.528,  .311}};
  
  if (nc==1)
    yiqy[0]=rgbk[0];
  else if (nc==3)
    for(row=0; row<3; row++)
      {
	yiqy[row]=0;
	for(col=0; col<3; col++)
	  yiqy[row] += rgb2yiq[row][col] * (float)rgbk[col];
      }
  else exit(0);
}

void rgbyiq(JSAMPLE *rgb, float *yiq, int wxh, int ent)
     //for rgb and yiq vectors with all Y entries first (wxh of them
     //of which we're working on the ent entry), then wxh I's then wxh
     //Q's.  always send in rgb+nothing and yiq+0, not +ent.
{
  int row,col;
  float rgb2yiq[3][3]={{.299,  .587,  .114},
		       {.596, -.275, -.321},
		       {.212, -.528,  .311}};

  for(row=0; row<3; row++)
    {
      yiq[row*wxh+ent]=0;
      for(col=0; col<3; col++)
	yiq[row*wxh+ent] += rgb2yiq[row][col] * (float)rgb[col*wxh+ent];
    }
}


void yiq2rgb(float *yiq, float *rgb)
{
  int row,col;
  float yiq2rgb[3][3]= {{1.00309,   0.95485,   0.61786},
			{0.99678,  -0.27071,  -0.64479},
			{1.00850,  -1.11049,   1.69957}};

  for(row=0; row<3; row++)
    {
      rgb[row]=0;
      for(col=0; col<3; col++)
	rgb[row] += yiq2rgb[row][col] * yiq[col];
    }
}

void yiq256rgb(float *yiq, JSAMPLE *rgb)
{
  int row,col;
  float term;
  float yiq2rgb[3][3]= {{1.00309,   0.95485,   0.61786},
			{0.99678,  -0.27071,  -0.64479},
			{1.00850,  -1.11049,   1.69957}};

  for(row=0; row<3; row++)
    {
      term=0.0;
      for(col=0; col<3; col++)
	term += yiq2rgb[row][col] * yiq[col];
      rgb[row]=(JSAMPLE)(term<256.0?(term>=0.0?term:0):255);
    }
}

void yiqy256rgbk(float *yiqy, JSAMPLE *rgbk, int nc)
{
  int row,col;
  float term;
  float yiq2rgb[3][3]= {{1.00309,   0.95485,   0.61786},
			{0.99678,  -0.27071,  -0.64479},
			{1.00850,  -1.11049,   1.69957}};

  if (nc==1)
    rgbk[0]=yiqy[0];
  else if (nc==3)
    for(row=0; row<3; row++)
      {
	term=0.0;
	for(col=0; col<3; col++)
	  term += yiq2rgb[row][col] * yiqy[col];
	rgbk[row]=(JSAMPLE)(term<256.0?(term>=0.0?term:0):255);
      }
  else exit(0);
}

void yiqrgb(float *yiq, JSAMPLE *rgb, int wxh, int ent)
     //for yiq and rgb vectors with all Y entries first (wxh of them
     //of which we're working on the ent entry), then wxh I's then wxh
     //Q's.  always send in rgb+nothing and yiq+0, not +ent.
{
  int row,col;
  float term;
  float yiq2rgb[3][3]= {{1.00309,   0.95485,   0.61786},
			{0.99678,  -0.27071,  -0.64479},
			{1.00850,  -1.11049,   1.69957}};

  for(row=0; row<3; row++)
    {
      term=0.0;
      for(col=0; col<3; col++)
	term += yiq2rgb[row][col] * yiq[col*wxh+ent];
      rgb[row*wxh+ent]=(JSAMPLE)(term<256.0?(term>=0.0?term:0):255);
    }
}


float rgb2y(float *rgb)
{
  int i;
  float y=0.0;
  float rgb2y[3]={.299,.587,.114};

  for(i=0; i<3; i++)
    y += rgb2y[i] * rgb[i];
  return y;
}

float rgb256y(JSAMPLE *rgb)
{
  int i;
  float y=0.0;
  float rgb2y[3]={.299,.587,.114};

  for(i=0; i<3; i++)
    y += rgb2y[i] * (float)rgb[i];
  return y;
}


