//=======================================================================================
//
// template for still image processing
//
// templ_ppm.h
//
// developer: Henry Guennadi Levkin
//
//=======================================================================================

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//=======================================================================================
typedef unsigned char byte;

//=======================================================================================
void WritePGM(byte* imagePtr,
              int num_cols, int num_rows,
              char* file_name)
{
    FILE* img_file= fopen(file_name, "wb");

    fprintf( img_file, "P5\n#\n%d %d\n255\n", num_cols, num_rows );
    fwrite( imagePtr, 1, num_cols * num_rows, img_file);
    fclose(img_file);
}

//=======================================================================================
// read ppm image file
int PpmImageFileRead(char* filename, byte** ppPic, int* pnW, int* pnH)
{
 FILE* pInpFile;

 char buf[512];

 // open image file
 pInpFile=fopen(filename,"rb");
 if( pInpFile==NULL) return 1;
 
 fgets(buf,510,pInpFile); // "P6"
 fgets(buf,510,pInpFile); // "#comments"

 fgets(buf,510,pInpFile); // "width height"
 sscanf(buf,"%d %d", pnW, pnH);
 printf("%d %d\n", *pnW, *pnH);

 fgets(buf,510,pInpFile); // "MaxColor"

 *ppPic = malloc(3 * (*pnW) * (*pnH));
 
 fread(*ppPic, 1, (3 * (*pnW) * (*pnH)), pInpFile);

 fclose(pInpFile);

 return 0;
}
//=======================================================================================
// write ppm image file
int PpmImageFileWrite(char* filename, byte* pPic, int nWidth, int nHeight)
{
 FILE* pOutFile;

 pOutFile=fopen(filename,"wb");

 fprintf( pOutFile, "P6\n#\n%d %d\n255\n", nWidth, nHeight );
 fwrite(pPic, 1, 3 * nWidth * nHeight, pOutFile);

 fclose(pOutFile);

 return 0;
}

//=======================================================================================
// make (r,g,b) image from R,G,B components
void MakeRGBfromComponents(byte* pRGB, byte* pRed, byte* pGreen, byte* pBlue,
                           int nWidth, int nHeight)
{
 int i,ii;
 int nn = nWidth*nHeight;

 for(i=0; i<nn; i++)
 {
 	ii = i*3;
 	pRGB[ii+0]=pRed[i];
 	pRGB[ii+1]=pGreen[i];
 	pRGB[ii+2]=pBlue[i];
 }
}

//=======================================================================================
// get R,G,B components  from  (r,g,b) image
void GetComponentsFromRGB(byte* pRGB, byte* pRed, byte* pGreen, byte* pBlue,
                          int nWidth, int nHeight)
{
 int i,ii;
 int nn = nWidth*nHeight;

 for(i=0; i<nn; i++)
 {
 	ii = i*3;
 	pRed[i]   = pRGB[ii+0];
 	pGreen[i] = pRGB[ii+1];
 	pBlue[i]  = pRGB[ii+2];
 }
}

//=======================================================================================
// 4:4:4
void TransformRGBtoLuCbCr(byte* pRed,  byte* pGreen,   byte* pBlue,
                          byte* pLuma, byte* pChromaB, byte* pChromaR,
                          int nWidth, int nHeight)
{
 int i;
 int size = nWidth * nHeight;
 int acc;

 for(i=0; i<size; i++)
 {
 	acc = 0.299*pRed[i] + 0.587*pGreen[i] + 0.114* pBlue[i];
 	pLuma[i] = acc;

 	acc = 0.564*pBlue[i] - 0.564*pLuma[i] + 128.;
 	if(acc<0) acc = 0;
 	else if(acc>255) acc = 255;
 	pChromaB[i] = acc;

 	acc = 0.713*pRed[i] - 0.713*pLuma[i] + 128;
 	if(acc<0) acc = 0;
 	else if(acc>255) acc = 255;
 	pChromaR[i] = acc;
 }
}

//=======================================================================================
// 4:4:4
void TransformLuCbCrToRGB(byte* pLuma, byte* pChromaB, byte* pChromaR,
                          byte* pRed,  byte* pGreen,   byte* pBlue,
                          int nWidth, int nHeight)
{
 int i;
 int size = nWidth * nHeight;
 int acc;

 for(i=0; i<size; i++)
 {
 	acc = (double) pLuma[i] + 1.402*(pChromaR[i]-128.);
 	if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
 	pRed[i] = acc;

 	acc = (double) pLuma[i] - 0.344*(pChromaB[i]-128.) - 0.714*(pChromaR[i]-128.);
 	if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
 	pGreen[i] = acc;

 	acc = (double) pLuma[i] + 1.772*(pChromaB[i]-128.);
 	if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
 	pBlue[i] = acc;
 }
}

