#include <config.h>
#include <stdio.h>
#include <string.h>

#include "GFile_DC120.h"
#include "GICBayer.h"

/* Class used to handle processing of .kdc file from KDCFile.
 * 
 * Written by:  Chris Studholme
 * Last Update: 28-May-2000
 * Copyright:   GPL (http://www.fsf.org/copyleft/gpl.html)
 */


//#define _CHECKS

//   848x976 (or is it 850x984)
//   GRGRGR (R is red, G is green, B is blue)
//   BGBGBG
//   GRGRGR
//   BGBGBG


#ifdef _CHECKS
#include <math.h>
#define KDCW 848
#define KDCH 976
double VerifyRedImage(GImageComponent* image, 
		      const unsigned char* imagedata) {
  double error=0;
  for (int y=0; y<KDCH; y+=2)
    for (int x=1; x<KDCW; x+=2) {
      int residule = (imagedata[y*KDCW+x]-128)*128 - 
	image->getPixel(x,y,x+1,y+1);
      error += residule*residule;
    }
  
  return sqrt(error*4/KDCH/KDCW)/128;
}

double VerifyBlueImage(GImageComponent* image, 
		       const unsigned char* imagedata) {
  double error=0;
  for (int y=1; y<KDCH; y+=2)
    for (int x=0; x<KDCW; x+=2) {
      int residule = (imagedata[y*KDCW+x]-128)*128 - 
	image->getPixel(x,y,x+1,y+1);
      error += residule*residule;
    }
  
  return sqrt(error*4/KDCH/KDCW)/128;
}

double VerifyGreenImage(GImageComponent* image, 
			const unsigned char* imagedata) {
  double error=0;
  for (int y=0; y<KDCH; ++y)
    for (int x=(y&1); x<KDCW; x+=2) {
      int residule = (imagedata[y*KDCW+x]-128)*128 - 
	image->getPixel(x,y,x+1,y+1);
      error += residule*residule;
    }

  return sqrt(error*2/KDCH/KDCW)/128;
}
#endif


/* ================ GFile_DC120 methods  ================ */

GFile_DC120::GFile_DC120(KDCFile& file, bool fast) {

  red=blue=green=0;

  w = file.getWidth();
  h = file.getHeight();
  aspect = file.getPixelAspect();

  unsigned char* data = new unsigned char[w*h];
  memset(data,0,sizeof(data));

  if (!file.ReadKDCFile(data)) {
    fprintf(stderr,"GFile_DC120::GFile_DC120() ERROR READING FILE\n");
    delete[] data;
    return;
  }

  fprintf(stderr,"De-bayerizing image: ");

  fprintf(stderr,"green... ");
  green = new GICBayer_Green(data,w,h,fast?-1:0);
#ifdef _CHECKS
  fprintf(stderr,"\nGreen Error(l1): %g\n",green->getTotalError());
  fprintf(stderr,"Green Error(l2): %g\n",VerifyGreenImage(green,data));
#endif

  fprintf(stderr,"red... ");
  red = new GICBayer_Red(data,w,h,*green,fast?-1:0);
#ifdef _CHECKS
  fprintf(stderr,"\nRed Error(l1): %g\n",red->getTotalError());
  fprintf(stderr,"Red Error(l2): %g\n",VerifyRedImage(red,data));
#endif

  fprintf(stderr,"blue... ");
  blue = new GICBayer_Blue(data,w,h,*green,fast?-1:0);
#ifdef _CHECKS
  fprintf(stderr,"\nBlue Error(l1): %g\n",blue->getTotalError());
  fprintf(stderr,"Blue Error(l2): %g\n",VerifyBlueImage(blue,data));
#endif

  fprintf(stderr,"done.\n");
  if (!fast)
    fprintf(stderr,"Mean error is %g\n",(red->getTotalError()
	     +green->getTotalError()+blue->getTotalError())/3);

  memset(histogram,0,sizeof(histogram));
  addToHistogram(histogram,data,w*h);

  delete[] data;
}


GFile_DC120::~GFile_DC120() {
  delete red;
  delete green;
  delete blue;
}

bool GFile_DC120::supportsFile(FILE* file) {
  if (fseek(file,0,SEEK_SET)!=0)
    return false;
  unsigned char header[4];
  if (fread(header,sizeof(header),1,file)!=1)
    return false;
  if ((header[0]!='M')||(header[1]!='M')||
      (header[2]!=0)||(header[3]!=42))
    return false;
  if (fseek(file,0x01dc,SEEK_SET)!=0)
    return false;
  char sig[5];
  if (fread(sig,sizeof(sig),1,file)!=1)
    return false;
  return (strncmp(sig,"DC120",sizeof(sig))==0);
}

