//===================================================================================
//
//  clip.c
//
// CLassic Image Processing (CLIP) Library
//
// version 0.1 (Jan 2004)
//
// developer: Henry Guennadi Levkin
//
// all functions are clear for reading, but not speed optimized
//
// frame - grey scale image or color component
// image - 3 frames with color information
//
// B at the end of function name means that pixel has byte size
// S at the end of function name means that pixel has short (2 bytes) size
//
// v - intensity of pixel
//
//===================================================================================

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>

#include "clip.h"

//-----------------------------------------------------------------------------------
// allocate memory and fill by zeros
void FrameConstructB(byte**  ppFrm, int nW, int nH)
{
  int nSize = nW * nH;
  int i;
  
  *ppFrm = (byte*) malloc(nSize);
  for(i=0; i<nSize; i++) (*ppFrm)[i] = 0;
}

//-----------------------------------------------------------------------------------
// allocate memory and fill by zeros
void FrameConstructS(short** ppFrm, int nW, int nH)
{
  int nSize = nW * nH;
  int i;
  
  *ppFrm = (short*) malloc(sizeof(short) * nSize);
  
  for(i=0; i<nSize; i++) (*ppFrm)[i] = 0;
}

//-----------------------------------------------------------------------------------
void FrameFreeB(byte*  pFrm)
{
  free(pFrm);
}

//-----------------------------------------------------------------------------------
void FrameFreeS(short* pFrm)
{
  free(pFrm);
}

//-----------------------------------------------------------------------------------
// fill pixel values by nConst
void FrameFillConstB(byte*  pFrm, int nW, int nH, int nConst)
{
  int nSize = nW * nH;
  byte c = (byte) nConst;

  memset(pFrm, c, nSize);
}

//-----------------------------------------------------------------------------------
// fill pixel values by uniform noise from [nLow, nHigh]
void FrameFillNoiseB(byte*  pFrm, int nW, int nH, int nLow, int nHigh)
{
  int nSize = nW * nH;
  int i;
  double fr;

  for(i=0; i<nSize; i++)
  {
    fr = ( (double)rand()/(double)RAND_MAX ) * (nHigh-nLow) + (double)nLow;
    pFrm[i] = (byte) fr;
  }
}

//-----------------------------------------------------------------------------------
// fill pixel values by uniform noise from [nLow, nHigh]
void FrameFillNoiseS(short* pFrm, int nW, int nH, int nLow, int nHigh)
{
  int nSize = nW * nH;
  int i;
  double fr;

  for(i=0; i<nSize; i++)
  {
    fr = ( (double)rand()/(double)RAND_MAX ) * (nHigh-nLow) + (double)nLow;
    pFrm[i] = (short) fr;
  }
}

//-----------------------------------------------------------------------------------
void FrameFillTextureB(byte* pFrm, int nW, int nH, byte* pTexture, int nWT, int nHT)
{
  int i, j;
  int ii;
  int jj = nW / nWT; // number of repetitions
  char* rowShift = pFrm;
  char* tShift;
  
  for(i=0; i<nH; i++)
  {
    ii = i%nHT;                // corresponding row number from texture
    tShift = pTexture + ii*nWT;  // pointer to the corresponding row of texture
    for(j=0; j<jj; j += nWT)
    {
      memcpy(rowShift+j, tShift, nWT);
    }
    rowShift += nW;
  }
}

//-----------------------------------------------------------------------------------
// frame copy
void FrameCopyB2B(byte* pSrc, byte* pDst, int nW, int nH)
{
  int nSize = nW * nH;
  int i;

  for(i=0; i<nSize; i++) pDst[i] = pSrc[i];
}

//-----------------------------------------------------------------------------------
// copy byte frame to short frame
void FrameB2S(byte* pSrc, short* pDst, int nW, int nH)
{
  int nSize = nW * nH;
  int i;

  for(i=0; i<nSize; i++) pDst[i] = (short) pSrc[i];
}

//-----------------------------------------------------------------------------------
// transform with cut to (0,255)
void FrameS2B(short* pSrc, byte* pDst, int nW, int nH)
{
  int nSize = nW * nH;
  int i;
  byte b;
  short pixel;

  for(i=0; i<nSize; i++) 
  {
    pixel = pSrc[i];
    if(pixel<0) b = 0;
    else if(pixel>0) b = 255;
    else b = (byte) pixel;
    pDst[i] = b;
  }
}

//-----------------------------------------------------------------------------------
// transform from (min,max) to (0,255)
void FrameS2BSqueeze(short* pSrc, byte* pDst, int nW, int nH)
{
  int nSize = nW * nH;
  int i;
  int nMin = pSrc[0];
  int nMax = pSrc[0];
  int nDelta;

  for(i=1; i<nSize; i++)
  {
    if(pSrc[i] < nMin) nMin = pSrc[i];
    if(pSrc[i] > nMax) nMax = pSrc[i];
  }
  
  if(nMin==nMax)
  {
    if(nMin<0) nMin = 0;
    else if(nMin>255) nMin = 255;

    memset(pDst, (byte)nMin, nSize);

    return;
  }

  nDelta = nMax - nMin;
  for(i=0; i<nSize; i++)
  {
    pDst[i] = (byte) (((int)(pSrc[i]-nMin)*255 + nDelta/2) / nDelta);
  }
}

//-----------------------------------------------------------------------------------
// pHist - histogram vector with dimension 256
void FrameHistB(byte* pFrm, int nW, int nH, int* pHist)
{
  int nSize = nW * nH;
  int i;
  
  for(i=0; i<256; i++) pHist[i] = 0;
  
  for(i=0; i<nSize; i++) pHist[ pFrm[i] ]++;
}

//-----------------------------------------------------------------------------------
// pHist - histogram vector with dimension nMax-nMin+1
void FrameHistS(short* pFrm, int nW, int nH, int* pHist, short nMin, short nMax)
{
  int nSize = nW * nH;
  int nHistSize = nMax-nMin+1;
  int i;
  int k;

  for(i=0; i<nHistSize; i++) pHist[i] = 0;

  for(i=0; i<nSize; i++) 
  {
    k = pFrm[i] - nMin;
    if((k>=0) && (k<nHistSize))
	  pHist[ k ]++;
  }
}

//-----------------------------------------------------------------------------------
// *pnMin - minimal intensity of pixels
// *pnMax - maximal intensity of pixels
void FrameMinMaxB(byte*  pFrm, int nW, int nH, int* pnMin, int* pnMax)
{
  int nSize = nW * nH;
  int i;
  int nMin = pFrm[0];
  int nMax = pFrm[0];

  for(i=1; i<nSize; i++)
  {
    if(pFrm[i] < nMin) nMin = pFrm[i];
    if(pFrm[i] > nMax) nMax = pFrm[i];
  }
  *pnMin = nMin;
  *pnMax = nMax;
}

//-----------------------------------------------------------------------------------
// *pnMin - minimal intensity of pixels
// *pnMax - maximal intensity of pixels
void FrameMinMaxS(short* pFrm, int nW, int nH, int* pnMin, int* pnMax)
{
  int nSize = nW * nH;
  int i;
  int nMin = pFrm[0];
  int nMax = pFrm[0];

  for(i=0; i<nSize; i++) 
  {
    if(pFrm[i] < nMin) nMin = pFrm[i];
    if(pFrm[i] > nMax) nMax = pFrm[i];
  }
  *pnMin = nMin;
  *pnMax = nMax;
}

//-----------------------------------------------------------------------------------
void FrameMeanStdDevB(byte* pFrm, int nW, int nH, double* pfMean, double* pfStdDev)
{
  int nSize = nW * nH;
  int i;
  double fMean = 0.;
  double fStdDev = 0.;

  for(i=0; i<nSize; i++) 
  {
    fMean   += pFrm[i];
    fStdDev += (pFrm[i] * pFrm[i]);
  }
  fMean = fMean / nSize;
  fStdDev = (fStdDev - nSize*fMean*fMean)/(nSize-1);
  
  *pfMean   = fMean;
  *pfStdDev = fStdDev;
}

//-----------------------------------------------------------------------------------
void FrameMeanStdDevS(short* pFrm, int nW, int nH, double* pfMean, double* pfStdDev)
{
  int nSize = nW * nH;
  int i;
  double fMean = 0.;
  double fStdDev = 0.;

  for(i=0; i<nSize; i++) 
  {
    fMean   += pFrm[i];
    fStdDev += (pFrm[i] * pFrm[i]);
  }
  fMean = fMean / nSize;
  fStdDev = (fStdDev - nSize*fMean*fMean)/(nSize-1);
  
  *pfMean   = fMean;
  *pfStdDev = fStdDev;
}

//-----------------------------------------------------------------------------------
// destination image size = (nW+2*nDelta) * (nH+2*nDelta)
// new pixels fills by closest border pixel values
void FrameAddBordersB(byte* pSr, byte* pDs, int nW, int nH, int nDelta)
{
  int nSize = nW * nH;
  int i;
  
  char* pSrc = pSr;
  char* pDst = pDs+nDelta*(nW+2*nDelta);

  for(i=0; i<nH; i++)
  {
    memcpy(pDst+nDelta, pSrc, nW);
    memset(pDst, pSrc[0], nDelta);
    memset(pDst+nW+nDelta,pSrc[nW-1],nDelta);
    pDst += (nW+2*nDelta);
    pSrc += nW;
  }
  
  for(i=0; i<nDelta; i++)
  {
    memcpy(pDs+i*(nW+2*nDelta), pDs+nDelta*(nW+2*nDelta), nW+2*nDelta);
  }
  for(i=nH+nDelta; i<nH+2*nDelta; i++)
  {
    memcpy(pDs+i*(nW+2*nDelta), pDs+(nH+nDelta)*(nW+2*nDelta), nW+2*nDelta);
  }
}

//-----------------------------------------------------------------------------------
void FrameGetBlockB(byte* pFr, int nW, int nH, byte* pBlk, SRect rect)
{
  int i;
 
  if( (rect.xL+rect.nW) > nW ) return;
  if( (rect.yT+rect.nH) > nH ) return;

  for(i=0; i<rect.nH; i++)
  {
    memcpy(pBlk + i*rect.nW, pFr + (rect.yT+i)*nW + rect.xL, rect.nW);
  }
}

//-----------------------------------------------------------------------------------
void FrameGetBlockS(short* pFr, int nW, int nH, short* pBlk, SRect rect)
{
  int i;
 
  if( (rect.xL+rect.nW) > nW ) return;
  if( (rect.yT+rect.nH) > nH ) return;

  for(i=0; i<rect.nH; i++)
  {
    memcpy(pBlk + 2*i*rect.nW, pFr + (rect.yT+i)*2*nW + 2*rect.xL, 2*rect.nW);
  }
}

//-----------------------------------------------------------------------------------
void FramePutBlockB(byte* pFr, int nW, int nH, byte* pBlk, SRect rect)
{
  int i;
 
  if( (rect.xL + rect.nW) > nW ) return;
  if( (rect.yT + rect.nH) > nH ) return;

  for(i=0; i<rect.nH; i++)
  {
    memcpy(pFr + (rect.yT+i)*nW + rect.xL, pBlk + i*rect.nW, rect.nW);
  }
}

//-----------------------------------------------------------------------------------
void FramePutBlockS(short* pFr, int nW, int nH, short* pBlk, SRect rect)
{
  int i;
 
  if( (rect.xL+rect.nW)>nW ) return;
  if( (rect.yT+rect.nH)>nH ) return;

  for(i=0; i<rect.nH; i++)
  {
    memcpy(pFr + (rect.yT+i)*2*nW + 2*rect.xL, pBlk + 2*i*rect.nW, 2*rect.nW);
  }
}

//-----------------------------------------------------------------------------------
// zeros fill free pixels
void FrameShiftB(byte* pSrc, byte* pDst, int nW, int nH, int nX, int nY)
{
}

//-----------------------------------------------------------------------------------
void FrameShiftS(short* pSrc, short* pDst, int nW, int nH, int nX, int nY)
{
}

//-----------------------------------------------------------------------------------
// separate R,G,B frames
void FrameRGB2YUV(byte* pR, byte* pG, byte* pB, byte* pYUV, int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// separate R,G,B frames
void FrameYUV2RGB(byte* pYOV, byte* pR, byte* pG, byte* pB, int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// frame magnification 2x2 times
void FrameMagnifyB(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int i2;
  int iw;
  int nW2 = nW*2;

  for(i=0; i<nH; i++)
  {
    i2 = i * 2;
    iw = i * nW;
    for(j=0; j<nW; j++)
    {
      pDst[i2*nW2 + j*2]         = pSrc[iw + j];
      pDst[i2*nW2 + j*2 + 1]     = pSrc[iw + j];
      pDst[(i2+1)*nW2 + j*2]     = pSrc[iw + j];
      pDst[(i2+1)*nW2 + j*2 + 1] = pSrc[iw + j];
    }
  }
}

//-----------------------------------------------------------------------------------
// frame magnification 2x2 times
void FrameMagnifyS(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i2;
  int iw;
  int nW2 = nW*2;

  for(i=0; i<nH; i++)
  {
    i2 = i * 2;
    iw = i * nW;
    for(j=0; j<nW; j++)
    {
      pDst[i2*nW2 + j*2]         = pSrc[iw + j];
      pDst[i2*nW2 + j*2 + 1]     = pSrc[iw + j];
      pDst[(i2+1)*nW2 + j*2]     = pSrc[iw + j];
      pDst[(i2+1)*nW2 + j*2 + 1] = pSrc[iw + j];
    }
  }
}

//-----------------------------------------------------------------------------------
// frame downsampling 2x2 times
void FrameDownsampleB(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int nW2 = nW/2;
  int iW, i1W;
  int i2;

  int acc;

  for(i=0; i<nH; i++,i++)
  {
    iW  = i * nW;
    i1W = (i+1) * nW;
    i2  = i / 2;
    for(j=0; j<nW; j++,j++)
    {
      acc = pSrc[iW + j] + pSrc[iW + j + 1];
      acc = acc + pSrc[i1W + j] + pSrc[i1W + j + 1];
      pDst[i2*nW2 + j/2] = (acc + 2) / 4;
    }
  }
}

//-----------------------------------------------------------------------------------
// frame downsampling 2x2 times
void FrameDownsampleS(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int nW2 = nW/2;
  int iW, i1W;
  int i2;

  int acc;

  for(i=0; i<nH; i++,i++)
  {
    iW  = i * nW;
    i1W = (i+1) * nW;
    i2  = i / 2;
    for(j=0; j<nW; j++,j++)
    {
      acc = pSrc[iW + j] + pSrc[iW + j + 1];
      acc = acc + pSrc[i1W + j] + pSrc[i1W + j + 1];
      pDst[i2*nW2 + j/2] = (acc + 2) / 4;
    }
  }
}

//-----------------------------------------------------------------------------------
// v=v+nConst
void FrameAddConstB(byte* pSrc, short* pDst, int nW, int nH, int nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] = (short) (nConst + (int) pSrc[i]);
}

//-----------------------------------------------------------------------------------
// v=v+nConst
void FrameAddConstS(short* pSrc, short* pDst, int nW, int nH, short nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] = nConst + pSrc[i];
}

//-----------------------------------------------------------------------------------
// v=(short)(v*fConst + 0.5)
void FrameMultConstB(byte* pSrc, short* pDst, int nW, int nH, double fConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] = (short) (fConst * (double) pSrc[i]);
}

//-----------------------------------------------------------------------------------
// v=(short)(v*fConst + 0.5)
void FrameMultConstS(short* pSrc, short* pDst, int nW, int nH, double fConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] = (short) (fConst * (double) pSrc[i]);
}

//-----------------------------------------------------------------------------------
// v= v & nConst
void FrameBinaryAndConstB(byte* pSrc, byte* pDst, int nW, int nH, byte nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  nConst & pSrc[i];
}

//-----------------------------------------------------------------------------------
// v= v & nConst
void FrameBinaryAndConstS(short* pSrc, short* pDst, int nW, int nH, short nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  nConst & pSrc[i];
}

//-----------------------------------------------------------------------------------
// v= v | nConst
void FrameBinaryOrConstB(byte* pSrc, byte* pDst, int nW, int nH, byte nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  nConst | pSrc[i];
}

//-----------------------------------------------------------------------------------
// v= v | nConst
void FrameBinaryOrConstS(short* pSrc, short* pDst, int nW, int nH, short nConst)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  nConst | pSrc[i];
}

//-----------------------------------------------------------------------------------
// v= v >> nConst
void FrameBinaryShiftRightConstB(byte* pSrc, byte* pDst, int nW, int nH, int nConst)
{
  int i;
  int nSize = nW * nH;

  if (nConst>7) return;

  for(i=0; i<nSize; i++) pDst[i] =  pSrc[i] >> nConst;
}

//-----------------------------------------------------------------------------------
// v= v << nConst
void FrameBinaryShiftLeftConstB(byte* pSrc, byte* pDst, int nW, int nH, int nConst)
{
  int i;
  int nSize = nW * nH;

  if (nConst>7) return;

  for(i=0; i<nSize; i++) pDst[i] =  pSrc[i] << nConst;
}

//-----------------------------------------------------------------------------------
// v = v1 & v2
void FrameBinaryAndB(byte* pFrm1, byte* pFrm2, byte* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] & pFrm2[i];
}

//-----------------------------------------------------------------------------------
// v = v1 & v2
void FrameBinaryAndS(short* pFrm1, short* pFrm2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] & pFrm2[i];
}

//-----------------------------------------------------------------------------------
// v = v1 | v2
void FrameBinaryOrB(byte* pFrm1, byte* pFrm2, byte* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] | pFrm2[i];
}

//-----------------------------------------------------------------------------------
// v = v1 | v2
void FrameBinaryOrS(short* pFrm1, short* pFrm2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] | pFrm2[i];
}

//-----------------------------------------------------------------------------------
void FrameBinaryXorB(byte* pFrm1, byte* pFrm2, byte* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] ^ pFrm2[i];
}

//-----------------------------------------------------------------------------------
void FrameBinaryXorS(short* pFrm1, short* pFrm2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  pFrm1[i] ^ pFrm2[i];
}

//-----------------------------------------------------------------------------------
// v = v1 + v2
void FrameAddB(byte* pSrc1, byte* pSrc2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  (short) pSrc1[i] + (short) pSrc2[i];
}

//-----------------------------------------------------------------------------------
// v = v1 + v2
void FrameAddS(short* pSrc1, short* pSrc2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  (short) pSrc1[i] + (short) pSrc2[i];
}

//-----------------------------------------------------------------------------------
// Dst = Src1 - Src2
void FrameSubtractB(byte* pSrc1, byte* pSrc2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  (short) pSrc1[i] - (short) pSrc2[i];
}

//-----------------------------------------------------------------------------------
// Dst = Src1 - Src2
void FrameSubtractS(short* pSrc1, short* pSrc2, short* pDst, int nW, int nH)
{
  int i;
  int nSize = nW * nH;

  for(i=0; i<nSize; i++) pDst[i] =  (short) pSrc1[i] - (short) pSrc2[i];
}

//-----------------------------------------------------------------------------------
// -1 0 1
// -1 0 1
// -1 0 1
void FrameGradX3B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =       (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i*nW   + j1m] - (int) pSrc[i*nW   + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] - (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 0 1
// -1 0 1
// -1 0 1
void FrameGradX3S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =       (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i*nW   + j1m] - (int) pSrc[i*nW   + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] - (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -1 -1
//  0  0  0
//  1  1  1
void FrameGradY3B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     - (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -1 -1
//  0  0  0
//  1  1  1
void FrameGradY3S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     - (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// abs = |Gx| + |Gy|
void FrameGradAbs3B(byte* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int nGx, nGy;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      nGx =       (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j1p];
      nGx = nGx + (int) pSrc[i*nW   + j1m] - (int) pSrc[i*nW   + j1p];
      nGx = nGx + (int) pSrc[i1p*nW + j1m] - (int) pSrc[i1p*nW + j1p];

      nGy =     - (int) pSrc[i1m*nW + j1m] - (int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      nGy = nGy + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) (abs(nGx)+abs(nGy));
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 0 1
// -2 0 2
// -1 0 1
void FrameSobelX3B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     -   (int) pSrc[i1m*nW + j1m] +   (int) pSrc[i1m*nW + j1p];
      acc = acc - 2*(int) pSrc[i*nW   + j1m] + 2*(int) pSrc[i*nW   + j1p];
      acc = acc -   (int) pSrc[i1p*nW + j1m] +   (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 0 1
// -2 0 2
// -1 0 1
void FrameSobelX3S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     -   (int) pSrc[i1m*nW + j1m] +   (int) pSrc[i1m*nW + j1p];
      acc = acc - 2*(int) pSrc[i*nW   + j1m] + 2*(int) pSrc[i*nW   + j1p];
      acc = acc -   (int) pSrc[i1p*nW + j1m] +   (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -2 -1
//  0  0  0
//  1  2  1
void FrameSobelY3B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     - (int) pSrc[i1m*nW + j1m] - 2*(int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + 2*(int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -2 -1
//  0  0  0
//  1  2  1
void FrameSobelY3S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;  
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     - (int) pSrc[i1m*nW + j1m] - 2*(int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + 2*(int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
void FrameGradX5B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     - 2*(int) pSrc[i2m*nW + j2m] - (int) pSrc[i2m*nW + j1m] + (int) pSrc[i2m*nW + j1p] + 2*(int) pSrc[i2m*nW + j2p];
      acc = acc - 2*(int) pSrc[i1m*nW + j2m] - (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j1p] + 2*(int) pSrc[i1m*nW + j2p];
      acc = acc - 2*(int) pSrc[i*nW   + j2m] - (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j1p] + 2*(int) pSrc[i*nW   + j2p];
      acc = acc - 2*(int) pSrc[i1p*nW + j2m] - (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j1p] + 2*(int) pSrc[i1p*nW + j2p];
      acc = acc - 2*(int) pSrc[i2p*nW + j2m] - (int) pSrc[i2p*nW + j1m] + (int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
// -2 -1 0 1  2
void FrameGradX5S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     - 2*(int) pSrc[i2m*nW + j2m] - (int) pSrc[i2m*nW + j1m] + (int) pSrc[i2m*nW + j1p] + 2*(int) pSrc[i2m*nW + j2p];
      acc = acc - 2*(int) pSrc[i1m*nW + j2m] - (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j1p] + 2*(int) pSrc[i1m*nW + j2p];
      acc = acc - 2*(int) pSrc[i*nW   + j2m] - (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j1p] + 2*(int) pSrc[i*nW   + j2p];
      acc = acc - 2*(int) pSrc[i1p*nW + j2m] - (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j1p] + 2*(int) pSrc[i1p*nW + j2p];
      acc = acc - 2*(int) pSrc[i2p*nW + j2m] - (int) pSrc[i2p*nW + j1m] + (int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// -2 -2 -2 -2 -2
// -1 -1 -1 -1 -1
//  0  0  0  0  0
//  1  1  1  1  1
//  2  2  2  2  2
void FrameGradY5B(byte* pSrc,  short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     - 2*(int) pSrc[i2m*nW + j2m] - 2*(int) pSrc[i2m*nW + j1m] - 2*(int) pSrc[i2m*nW + j] - 2*(int) pSrc[i2m*nW + j1p] - 2*(int) pSrc[i2m*nW + j2p];
      acc = acc -   (int) pSrc[i1m*nW + j2m] -   (int) pSrc[i1m*nW + j1m] -   (int) pSrc[i1m*nW + j] -   (int) pSrc[i1m*nW + j1p] -   (int) pSrc[i1m*nW + j2p];
      acc = acc +   (int) pSrc[i1p*nW + j2m] +   (int) pSrc[i1p*nW + j1m] +   (int) pSrc[i1p*nW + j] +   (int) pSrc[i1p*nW + j1p] +   (int) pSrc[i1p*nW + j2p];
      acc = acc + 2*(int) pSrc[i2p*nW + j2m] + 2*(int) pSrc[i2p*nW + j1m] + 2*(int) pSrc[i2p*nW + j] + 2*(int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (short) acc;
    } 
  }
}

//-----------------------------------------------------------------------------------
// -2 -2 -2 -2 -2
// -1 -1 -1 -1 -1
//  0  0  0  0  0
//  1  1  1  1  1
//  2  2  2  2  2
void FrameGradY5S(short* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     - 2*(int) pSrc[i2m*nW + j2m] - 2*(int) pSrc[i2m*nW + j1m] - 2*(int) pSrc[i2m*nW + j] - 2*(int) pSrc[i2m*nW + j1p] - 2*(int) pSrc[i2m*nW + j2p];
      acc = acc -   (int) pSrc[i1m*nW + j2m] -   (int) pSrc[i1m*nW + j1m] -   (int) pSrc[i1m*nW + j] -   (int) pSrc[i1m*nW + j1p] -   (int) pSrc[i1m*nW + j2p];
      acc = acc +   (int) pSrc[i1p*nW + j2m] +   (int) pSrc[i1p*nW + j1m] +   (int) pSrc[i1p*nW + j] +   (int) pSrc[i1p*nW + j1p] +   (int) pSrc[i1p*nW + j2p];
      acc = acc + 2*(int) pSrc[i2p*nW + j2m] + 2*(int) pSrc[i2p*nW + j1m] + 2*(int) pSrc[i2p*nW + j] + 2*(int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (short) acc;
    }
  }
}

//-----------------------------------------------------------------------------------
// abs = |Gx| + |Gy|
void FrameGradAbs5B(byte* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int nGx, nGy;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      nGx =     - 2*(int) pSrc[i2m*nW + j2m] - (int) pSrc[i2m*nW + j1m] + (int) pSrc[i2m*nW + j1p] + 2*(int) pSrc[i2m*nW + j2p];
      nGx = nGx - 2*(int) pSrc[i1m*nW + j2m] - (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j1p] + 2*(int) pSrc[i1m*nW + j2p];
      nGx = nGx - 2*(int) pSrc[i*nW   + j2m] - (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j1p] + 2*(int) pSrc[i*nW   + j2p];
      nGx = nGx - 2*(int) pSrc[i1p*nW + j2m] - (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j1p] + 2*(int) pSrc[i1p*nW + j2p];
      nGx = nGx - 2*(int) pSrc[i2p*nW + j2m] - (int) pSrc[i2p*nW + j1m] + (int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      nGy =     - 2*(int) pSrc[i2m*nW + j2m] - 2*(int) pSrc[i2m*nW + j1m] - 2*(int) pSrc[i2m*nW + j] - 2*(int) pSrc[i2m*nW + j1p] - 2*(int) pSrc[i2m*nW + j2p];
      nGy = nGy -   (int) pSrc[i1m*nW + j2m] -   (int) pSrc[i1m*nW + j1m] -   (int) pSrc[i1m*nW + j] -   (int) pSrc[i1m*nW + j1p] -   (int) pSrc[i1m*nW + j2p];
      nGy = nGy +   (int) pSrc[i1p*nW + j2m] +   (int) pSrc[i1p*nW + j1m] +   (int) pSrc[i1p*nW + j] +   (int) pSrc[i1p*nW + j1p] +   (int) pSrc[i1p*nW + j2p];
      nGy = nGy + 2*(int) pSrc[i2p*nW + j2m] + 2*(int) pSrc[i2p*nW + j1m] + 2*(int) pSrc[i2p*nW + j] + 2*(int) pSrc[i2p*nW + j1p] + 2*(int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (short) (abs(nGx) + abs(nGy));
    }
  }
}

//-----------------------------------------------------------------------------------
//  0 -1  0
// -1  4 -1
//  0 -1  0
void FrameLaplace3CrossB(byte* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =                                -   (int) pSrc[i1m*nW + j];
      acc = acc - (int) pSrc[i*nW   + j1m] + 4*(int) pSrc[i*nW   + j] - (int) pSrc[i*nW   + j1p];
      acc = acc                            -   (int) pSrc[i1p*nW + j];

      pDst[i*nW + j] = (byte) (acc + 4) / 9;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -1 -1
// -1  8 -1
// -1 -1 -1
void FrameLaplace3B(byte* pSrc, short* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =     -  (int) pSrc[i1m*nW + j1m] -   (int) pSrc[i1m*nW + j] - (int) pSrc[i1m*nW + j1p];
      acc = acc - (int) pSrc[i*nW   + j1m]  + 8*(int) pSrc[i*nW   + j] - (int) pSrc[i*nW   + j1p];
      acc = acc - (int) pSrc[i1p*nW + j1m]  -   (int) pSrc[i1p*nW + j] - (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (byte) (acc + 4) / 9;
    }
  }
}

//-----------------------------------------------------------------------------------
// -1 -1 -1 -1 -1
// -1 -1 -1 -1 -1
// -1 -1 24 -1 -1
// -1 -1 -1 -1 -1
// -1 -1 -1 -1 -1
void FrameLaplace5B(byte* pSrc, short* pDst, int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// 0 1 0
// 1 1 1
// 0 1 0
void FrameSmooth3CrossB(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =                                  (int) pSrc[i1m*nW + j];
      acc = acc + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p];
      acc = acc                            + (int) pSrc[i1p*nW + j];

      pDst[i*nW + j] = (byte) (acc + 2) / 5;
    }
  }
}

//-----------------------------------------------------------------------------------
// 0 1 0
// 1 1 1
// 0 1 0
void FrameSmooth3CrossThresholdB(byte* pSrc, byte* pDst, int nW, int nH, int nThreshold)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =                                  (int) pSrc[i1m*nW + j];
      acc = acc + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p];
      acc = acc                            + (int) pSrc[i1p*nW + j];

      acc = (acc + 2) / 5;

      if (abs(acc-pSrc[i*nW + j]) <= nThreshold) pDst[i*nW + j] = acc;
      else pDst[i*nW + j] = pSrc[i*nW + j];
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 1 1
// 1 1 1
// 1 1 1
void FrameSmooth3B(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =       (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j] + (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (byte) (acc + 4) / 9;
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 1 1
// 1 1 1
// 1 1 1
void FrameSmooth3ThresholdB(byte* pSrc, byte* pDst, int nW, int nH, int nThreshold)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =       (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j] + (int) pSrc[i1m*nW + j1p];
      acc = acc + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p];
      acc = acc + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p];

      acc = (acc + 4) / 9;
      
      if(abs(acc-pSrc[i*nW + j]) <= nThreshold)   pDst[i*nW + j] = acc;
      else pDst[i*nW + j] = pSrc[i*nW + j];
      
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 2 1
// 2 4 2
// 1 2 1
void FrameSmooth3GaussB(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =         (int) pSrc[i1m*nW + j1m] + 2*(int) pSrc[i1m*nW + j] +   (int) pSrc[i1m*nW + j1p];
      acc = acc + 2*(int) pSrc[i*nW   + j1m] + 4*(int) pSrc[i*nW   + j] + 2*(int) pSrc[i*nW   + j1p];
      acc = acc +   (int) pSrc[i1p*nW + j1m] + 2*(int) pSrc[i1p*nW + j] +   (int) pSrc[i1p*nW + j1p];

      pDst[i*nW + j] = (acc + 8) / 16;
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 2 1
// 2 4 2
// 1 2 1
void FrameSmooth3GaussThresholdB(byte* pSrc, byte* pDst, int nW, int nH, int nThreshold)
{
  int i,j;
  int i1m, i1p;
  int j1m, j1p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;
      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      acc =         (int) pSrc[i1m*nW + j1m] + 2*(int) pSrc[i1m*nW + j] +   (int) pSrc[i1m*nW + j1p];
      acc = acc + 2*(int) pSrc[i*nW   + j1m] + 4*(int) pSrc[i*nW   + j] + 2*(int) pSrc[i*nW   + j1p];
      acc = acc +   (int) pSrc[i1p*nW + j1m] + 2*(int) pSrc[i1p*nW + j] +   (int) pSrc[i1p*nW + j1p];

      acc = (acc + 8) / 16;
      
      if(abs(acc-pSrc[i*nW + j]) <= nThreshold)   pDst[i*nW + j] = acc;
      else                                        pDst[i*nW + j] = pSrc[i*nW + j];
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
void FrameSmooth5B(byte* pSrc, byte* pDst, int nW, int nH)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     + (int) pSrc[i2m*nW + j2m] + (int) pSrc[i2m*nW + j1m] + (int) pSrc[i2m*nW + j] + (int) pSrc[i2m*nW + j1p] + (int) pSrc[i2m*nW + j2p];
      acc = acc + (int) pSrc[i1m*nW + j2m] + (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j] + (int) pSrc[i1m*nW + j1p] + (int) pSrc[i1m*nW + j2p];
      acc = acc + (int) pSrc[i*nW   + j2m] + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p] + (int) pSrc[i*nW   + j2p];
      acc = acc + (int) pSrc[i1p*nW + j2m] + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p] + (int) pSrc[i1p*nW + j2p];
      acc = acc + (int) pSrc[i2p*nW + j2m] + (int) pSrc[i2p*nW + j1m] + (int) pSrc[i2p*nW + j] + (int) pSrc[i2p*nW + j1p] + (int) pSrc[i2p*nW + j2p];

      pDst[i*nW + j] = (byte) ( (acc+12) / 25);
    }
  }
}

//-----------------------------------------------------------------------------------
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
// 1 1 1 1 1
void FrameSmooth5ThresholdB(byte* pSrc, byte* pDst, int nW, int nH, int nThreshold)
{
  int i,j;
  int i1m, i1p;
  int i2m, i2p;
  int j1m, j1p;
  int j2m, j2p;
  int acc;

  for(i=0; i<nH; i++)
  {
    i1m = i - 1;
    if(i1m == (-1)) i1m = 0;

    i2m = i - 2;
    if(i2m < 0) i2m = 0;

    i1p = i + 1;
    if(i1m == nH) i1m = nH-1;

    i2p = i + 2;
    if(i2p >= nH) i2p = nH-1;

    for(j=0; j<nW; j++)
    {
      j1m = j - 1;
      if(j1m == (-1)) j1m = 0;

      j2m = j - 2;
      if(j2m < 0) j2m = 0;

      j1p = j + 1;
      if(j1p == nW) j1p = nW - 1;

      j2p = j + 2;
      if(j2p >= nW) j1p = nW - 1;

      acc =     + (int) pSrc[i2m*nW + j2m] + (int) pSrc[i2m*nW + j1m] + (int) pSrc[i2m*nW + j] + (int) pSrc[i2m*nW + j1p] + (int) pSrc[i2m*nW + j2p];
      acc = acc + (int) pSrc[i1m*nW + j2m] + (int) pSrc[i1m*nW + j1m] + (int) pSrc[i1m*nW + j] + (int) pSrc[i1m*nW + j1p] + (int) pSrc[i1m*nW + j2p];
      acc = acc + (int) pSrc[i*nW   + j2m] + (int) pSrc[i*nW   + j1m] + (int) pSrc[i*nW   + j] + (int) pSrc[i*nW   + j1p] + (int) pSrc[i*nW   + j2p];
      acc = acc + (int) pSrc[i1p*nW + j2m] + (int) pSrc[i1p*nW + j1m] + (int) pSrc[i1p*nW + j] + (int) pSrc[i1p*nW + j1p] + (int) pSrc[i1p*nW + j2p];
      acc = acc + (int) pSrc[i2p*nW + j2m] + (int) pSrc[i2p*nW + j1m] + (int) pSrc[i2p*nW + j] + (int) pSrc[i2p*nW + j1p] + (int) pSrc[i2p*nW + j2p];

      acc = (acc+12) / 25;

      if(abs(acc-pSrc[i*nW + j]) <= nThreshold)   pDst[i*nW + j] = acc;
      else                                      pDst[i*nW + j] = pSrc[i*nW + j];
    }
  }
}

//-----------------------------------------------------------------------------------
//  2  7  12  7  2
//  7 31  52 31  7
// 12 52 127 52 12
//  7 31  52 31  7
//  2  7  12  7  2
void FrameSmooth5GaussB(byte* pSrc, byte* pDst, int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
//  2  7  12  7  2
//  7 31  52 31  7
// 12 52 127 52 12
//  7 31  52 31  7
//  2  7  12  7  2
void FrameSmooth5GaussThresholdB(byte* pSrc, byte* pDst, int nW, int nH, int nThreshold)
{
}

//-----------------------------------------------------------------------------------
// pCon array (convolution coefficients) has dimension = 9 (row after row)
void FrameConvolution3B(byte* pSrc,  short* pDst, int nW, int nH, int* pCon)
{
}

//-----------------------------------------------------------------------------------
// pCon array (convolution coefficients) has dimension = 9 (row after row)
void FrameConvolution3S(short* pSrc, short* pDst, int nW, int nH, int* pCon)
{
}

//-----------------------------------------------------------------------------------
// pCon array (convolution coefficients) has dimension = 25 (row after row)
void FrameConvolution5B(byte* pSrc,  short* pDst, int nW, int nH, int* pCon)
{
}

//-----------------------------------------------------------------------------------
// pCon array (convolution coefficients) has dimension = 25 (row after row)
void FrameConvolution5S(short* pSrc, short* pDst, int nW, int nH, int* pCon)
{
}

//-----------------------------------------------------------------------------------
// return Sum of Absolute Differences
int FrameSADB(byte* pFrm1,  byte* pFrm2,  int nW, int nH)
{
  int nSAD = 0;
  
  return nSAD;
}

//-----------------------------------------------------------------------------------
// return Sum of Absolute Differences
double FrameSADS(short* pFrm1, short* pFrm2, int nW, int nH)
{
  double fSAD = 0;
  
  return fSAD;
}

//-----------------------------------------------------------------------------------
// v= 255 - v
void FrameNegativeB(byte* pSrc, byte* pDst, int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// if (v<nLow)  v=0
// if (v>nHigh) v=0
void FrameCutsB(byte* pSrc, byte* pDst,  int nW, int nH, int nLow, int nHigh)
{
}

//-----------------------------------------------------------------------------------
// (nLow,nHigh) to (0,255)
void FrameRenormB(byte* pSrc, byte* pDst, int nW, int nH, int nLow, int nHigh)
{
}

//-----------------------------------------------------------------------------------
void FrameMedianFilter3B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
void FrameMedianFilter5B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// -1 -1 -1
// -1 16 -1
// -1 -1 -1
void FrameSharpenFilter3B(byte* pSrc, short* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// -1 -1 -1 -1 -1
// -1 -2 -2 -2 -1
// -1 -2 64 -2 -1
// -1 -2 -2 -2 -1
// -1 -1 -1 -1 -1
void FrameSharpenFilter5B(byte* pSrc, short* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=min from window 3x3
void FrameMinFilter3B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=max from window 3x3
void FrameMaxFilter3B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=(min+max)/2 from window 3x3
void FrameMinMaxFilter3B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=min from window 5x5
void FrameMinFilter5B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=max from window 5x5
void FrameMaxFilter5B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
// v=(min+max)/2 from window 5x5
void FrameMinMaxFilter5B(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
void FrameMirrorXB(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
void FrameMirrorYB(byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
void FrameMirrorRotate90LeftB (byte* pSrc, byte* pDst,  int nW, int nH)
{
}

//-----------------------------------------------------------------------------------
void FrameMirrorRotate90RightB(byte* pSrc, byte* pDst,  int nW, int nH)
{
}



//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------
int ReadPGM(char* file_name, byte** ppImg, int* pnWidth, int* pnHeight)
{
 char buf[512];

 FILE* pInpFile = fopen(file_name,"rb");
 if( pInpFile==NULL) return 1;
 
 fgets(buf,510,pInpFile); // "P5"
 fgets(buf,510,pInpFile); // "#comments"

 fgets(buf,510,pInpFile); // "width height"
 sscanf(buf,"%d %d", pnWidth, pnHeight);
 printf("width=%d height=%d\n", *pnWidth, *pnHeight);

 fgets(buf,510,pInpFile); // "MaxColor"

 *ppImg = malloc((*pnWidth) * (*pnHeight));
 
 fread(*ppImg, 1, (*pnWidth) * (*pnHeight), pInpFile);

 fclose(pInpFile);

 return 0;
}

//-----------------------------------------------------------------------------------
void WritePGM(char* file_name, byte* pImg, int nWidth, int nHeight)
{
    FILE* img_file= fopen(file_name, "wb");

    fprintf( img_file, "P5\n#\n%d %d\n255\n", nWidth, nHeight );

    fwrite( pImg, 1, nWidth * nHeight, 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;
}


//-----------------------------------------------------------------------------------
void YCC420ToRGB(byte* pLu, byte* pCb, byte* pCr, int nW, int nH,
                 byte* pR, byte* pG, byte* pB)
{
  int i, j, k ,l;
  int acc;

  for(i=0; i<nH; i++)
  for(j=0; j<nW; j++) 
	{
	  k = i*nW + j;
	  l = (i/2)*(nW/2) + (j/2);
 	  acc = (double) pLu[k] + 1.402*(pCr[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pR[k] = acc;
		 
 	  acc = (double) pLu[k] - 0.344*(pCb[l]-128.) - 0.714*(pCr[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pG[k] = acc;
		 
 	  acc = (double) pLu[k] + 1.772*(pCb[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pB[k] = acc;
	}
}

//-----------------------------------------------------------------------------------
void YUV420ToRGB(byte* pY, byte* pU, byte* pV, int nW, int nH,
                 byte* pR, byte* pG, byte* pB)
{
  int i, j, k ,l;
  int acc;
  
  for(i=0; i<nH; i++)
  for(j=0; j<nW; j++) 
	{
	  k = i*nW + j;
	  l = (i/2)*(nW/2) + (j/2);
 	  acc = (double) pY[k] + 1.140*(pV[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pR[k] = acc;
		 
 	  acc = (double) pY[k] - 0.394*(pU[l]-128.) - 0.581*(pV[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pG[k] = acc;
		 
 	  acc = (double) pY[k] + 2.028*(pU[l]-128.);
 	  if(acc<0) acc = 0; 	else if(acc>255) acc = 255;
		pB[k] = acc;
	}
}

//-----------------------------------------------------------------------------------
// 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;
 }
}

//-----------------------------------------------------------------------------------
// 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];
 }
}



//-----------------------------------------------------------------------------------
// Get width and height of bmp file from its memory buffer
// Works in Windows and Unix
int BmpWidthHeight(byte* pBmpFile, int* pnWidth, int* pnHeight)
{
  *pnWidth  = *((int*) (pBmpFile + 14 + 4 ));
  *pnHeight = *((int*) (pBmpFile + 14 + 4 + 4));

  return 0;
}

//-----------------------------------------------------------------------------------
// reading of file with bmp
// Works in Windows and Unix
int ReadBmpFile(char* pFileName, byte* pBmpFile)
{
  FILE* fp;
  int fSize;
  int count;

  fp=fopen(pFileName,"rb");

  if(fp==NULL) return 1;

  fseek(fp,2,SEEK_SET);
  fread(&fSize,4,1,fp);

  // back to the beginning of the file
  fseek(fp,0,SEEK_SET);
  count=fread((void*)pBmpFile,1,fSize,fp);

  fclose(fp);

  if(count!=fSize) return 2;

  return 0;
}

//-----------------------------------------------------------------------------------
// pBmp - buffer with all bmp file, including headers
// Works in Windows and Unix
int GetColorComponentFromBmp(byte* pBmp, byte* pRed, byte* pGreen, byte* pBlue)
{
  int nWidth, nHeight;
  byte* pBmpMat= pBmp + 14 + 40;
  int bWidth;

  int i,j;

  nWidth = *((int*) (pBmp+14+4));
  nHeight= *((int*) (pBmp+14+4+4));
  bWidth=( (nWidth*24+31)/32 )*4; // byte width of one line

  for(i=0; i<nHeight; i++)
    for(j=0; j<nWidth; j++)
    {
      pBlue[i*nWidth+j]   = pBmpMat[i*bWidth+3*j+0]; //blue 
      pGreen[i*nWidth+j] = pBmpMat[i*bWidth+3*j+1];  //green
      pRed[i*nWidth+j]  = pBmpMat[i*bWidth+3*j+2];   //red
    }

  return 0;
}

//-----------------------------------------------------------------------------------
double FrameSnrCalcB(byte* pFrm1, byte* pFrm2, int nWidth, int nHeight)
{
  double fSnr = 0.;
  int nn = nWidth * nHeight;
  int i;
  
  for(i=0; i<nn; i++)
  {
	  fSnr += (double)(pFrm1[i]-pFrm2[i]) * (double)(pFrm1[i]-pFrm2[i]);
  }
  fSnr = fSnr / nn;
  
  if(fSnr)
  {
	  fSnr = 255. * 255. / fSnr;
    fSnr = 10. * log10(fSnr);
	}
	else
	{
	  fSnr = 10000.;
	}  
  return fSnr;
}


//-----------------------------------------------------------------------------------



