/******************************************************************************
 * program:     rasimg library                                                *
 * function:    Usefull block operations. 				      *
 * modul:       img_tool.c                                                    *
 * licency:     GPL or LGPL                                                   *
 ******************************************************************************/
#include "img_tool.h"


/** Flip R and B coupounds inplace. 
 * param[in]	Data	Pointer to data.
 * param[in]	Size	Amount of RGB tripplets. */
void RGB_BGR(char *Data, int PixelCount)
{
char c;
  while(PixelCount-->0)
  {
    c = Data[2];
    Data[2] = *Data;
    *Data = c;
    Data += 3;
  }
}


/** Flip R and B coupounds to the different buffer. */
void RGB_BGR2(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
{
  while(PixelCount-->0)
  {
    OutData[0] = InData[2];
    OutData[1] = InData[1];
    OutData[2] = InData[0];
    OutData += 3;
    InData += 3;	      
  }
}


void RGB32_BGR24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
{
  while(PixelCount-->0)
  {
    OutData[0] = InData[2];
    OutData[1] = InData[1];
    OutData[2] = InData[0];
    OutData += 3;
    InData += 4;	      
  }
}


void BGR_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
{
  while(PixelCount-->0)
  {
    OutData[2]=OutData[1]=OutData[0] = (InData[0]*4731 + InData[1]*46871 + InData[2]*13932)/65536;
    InData+=3;
    OutData+=3;
  }
}


void RGB32_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
{
  while(PixelCount-->0)
  {
    *(OutData++) = (*(InData++) + *(InData++) + *(InData++)) / 3;
    InData++;
  }
}


void RGB_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
{
  while(PixelCount-->0)
  {
    *(OutData++) = (*(InData++) + *(InData++) + *(InData++)) / 3;
  }
}


/** Invert block of data.
 * @param[in]	size	Block size in Bytes. */
void NotR(char *R, int size)	//R1:=not(R1)
{
  while(size-->0)
    {
    *R = ~*R;
    R++;
    }
}


void YUV_RGB(unsigned char *OutData, const unsigned char *y, const unsigned char *u, const unsigned char *v, unsigned PixelCount)
{
int X;

  while(PixelCount>=2)   //converts to RGB
  {
    signed char U = *u++ - 128;
    signed char V = *v++ - 128;
    int Y = 256 * *(y++);

    X = (Y + 291*V) >> 8;	// Y + 1.137*V;
    if(X>255) OutData[0]=255;
    else if(X<0) OutData[0]=0;
    else OutData[0] = X;
    X = (Y -102*U - 148*V) >> 8; // Y - 0.397*U - 0.58*V;
    if(X>255) OutData[1]=255;                    
    else if(X<0) OutData[1]=0;
    else OutData[1] = X;
    X = (Y + 521*U) >> 8;	// Y + 2.034*U;
    if(X>255) OutData[2]=255;                    
    else if(X<0) OutData[2]=0;
    else OutData[2] = X;

    OutData += 3;	    
    Y = 256 * *(y++);

    X = (Y + 291*V) >> 8;	// Y + 1.137*V;
    if(X>255) OutData[0]=255;
    else if(X<0) OutData[0]=0;
    else OutData[0] = X;
    X = (Y -102*U - 148*V) >> 8; // Y - 0.397*U - 0.58*V;
    if(X>255) OutData[1]=255;                    
    else if(X<0) OutData[1]=0;
    else OutData[1] = X;
    X = (Y + 521*U) >> 8;	// Y + 2.034*U;
    if(X>255) OutData[2]=255;                    
    else if(X<0) OutData[2]=0;
    else OutData[2] = X;                    

    OutData += 3;    
    PixelCount -= 2;
  }
}


void YUYV_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount)
{
int X;

  while(PixelCount>=2)
  {
    const int Y = 256 * *(yuyv++);
    const signed char U = *yuyv++ - 128;
    const int Y2 = 256 * *(yuyv++);
    const signed char V = *yuyv++ - 128;    

    X = (Y + 291*V) >> 8;	// Y + 1.137*V;
    if(X>255) OutData[0]=255;
    else if(X<0) OutData[0]=0;
    else OutData[0] = X;
    X = (Y -102*U - 148*V) >> 8; // Y - 0.397*U - 0.58*V;
    if(X>255) OutData[1]=255;                    
    else if(X<0) OutData[1]=0;
    else OutData[1] = X;
    X = (Y + 521*U) >> 8;	// Y + 2.034*U;
    if(X>255) OutData[2]=255;                    
    else if(X<0) OutData[2]=0;
    else OutData[2] = X;

    OutData += 3;    

    X = (Y2 + 291*V) >> 8;	// Y + 1.137*V;
    if(X>255) OutData[0]=255;
    else if(X<0) OutData[0]=0;
    else OutData[0] = X;
    X = (Y2 -102*U - 148*V) >> 8; // Y - 0.397*U - 0.58*V;
    if(X>255) OutData[1]=255;                    
    else if(X<0) OutData[1]=0;
    else OutData[1] = X;
    X = (Y2 + 521*U) >> 8;	// Y + 2.034*U;
    if(X>255) OutData[2]=255;                    
    else if(X<0) OutData[2]=0;
    else OutData[2] = X;                    

    OutData += 3;    
    PixelCount -= 2;
  }
}
