home *** CD-ROM | disk | FTP | other *** search
- /*
- * Resize.cpp
- *
- * Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * FlasKMPEG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- //////////////////////////////////////////////////////////////////////
- //
- // Resize.cpp: implementation of the CResize class.
- //
- // By
- // Alberto Vigata - FlasK version 1.0
- // ultraflask@yahoo.com
- //
- // - YUV to RGB conversion assume YUV input image to be upside down
- // - Both, YUVtoRGBA and RGBtoRGBA output RGB and RGBA images
- // in the next raw sequence: RGB images BGR BGR BGR ...
- // RGBA images BGRA BGRA BGRA ...
- // - Input images up to 1024x1024 pels
- //
- //////////////////////////////////////////////////////////////////////
-
- #include "Resize.h"
- #include <windows.h>
- #include <winbase.h>
-
-
- //////////////////////////////////////////////////////////////////////
- // FILTER DEFINITIONS //
- //////////////////////////////////////////////////////////////////////
- #define filter_support (1.0)
- double filter(double t)
- {
- /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
- if(t < 0.0) t = -t;
- if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
- return(0.0);
- }
-
- #define box_support (0.5)
- double box_filter(double t)
- {
- if((t > -0.5) && (t <= 0.5)) return(1.0);
- return(0.0);
- }
-
- #define triangle_support (1.0)
- double triangle_filter(double t)
- {
- if(t < 0.0) t = -t;
- if(t < 1.0) return(1.0 - t);
- return(0.0);
- }
-
-
- #define bell_support (1.5)
- double
- bell_filter(double t)
- { /* box (*) box (*) box */
- if(t < 0) t = -t;
- if(t < .5) return(.75 - (t * t));
- if(t < 1.5) {
- t = (t - 1.5);
- return(.5 * (t * t));
- }
- return(0.0);
- }
-
-
- #define B_spline_support (2.0)
- double
- B_spline_filter( /* box (*) box (*) box (*) box */
- double t)
- {
- double tt;
-
- if(t < 0) t = -t;
- if(t < 1) {
- tt = t * t;
- return((.5 * tt * t) - tt + (2.0 / 3.0));
- } else if(t < 2) {
- t = 2 - t;
- return((1.0 / 6.0) * (t * t * t));
- }
- return(0.0);
- }
-
-
- #define cubicConv_support (2.0)
- /*
- * cubicConv:
- *
- * Cubic convolution filter.
- */
- double
- cubicConv(
- double t)
- {
- double A, t2, t3;
-
- if(t < 0) t = -t;
- t2 = t * t;
- t3 = t2 * t;
-
- A = -1.0; /* user-specified free parameter */
- if(t < 1.0) return((A+2)*t3 - (A+3)*t2 + 1);
- if(t < 2.0) return(A*(t3 - 5*t2 + 8*t - 4));
- return(0.0);
- }
-
- double sinc(double x)
- {
- x *= M_PI;
- if(x != 0) return(sin(x) / x);
- return(1.0);
- }
-
- #define Lanczos3_support (3.0)
- double
- Lanczos3_filter(
- double t)
- {
- if(t < 0) t = -t;
- if(t < 3.0) return(sinc(t) * sinc(t/3.0));
- return(0.0);
- }
-
-
-
- #define HannWindows_support (4.0) /* In our case N=4 */
- /*
- * hann:
- *
- * Hann windowed sinc function. Assume N (width) = 4.
- */
- double
- hann4(
- double t)
- {
- int N = 4; /* fixed filter width */
-
- if(t < 0) t = -t;
- if(t < N) return(sinc(t) * (.5 + .5*cos(M_PI*t / N)));
- return(0.0);
- }
-
-
-
-
-
-
-
- #define Mitchell_support (2.0)
-
- #define B (1.0 / 3.0)
- #define C (1.0 / 3.0)
-
- double
- Mitchell_filter(
- double t)
- {
- double tt;
-
- tt = t * t;
- if(t < 0) t = -t;
- if(t < 1.0) {
- t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
- + ((-18.0 + 12.0 * B + 6.0 * C) * tt)
- + (6.0 - 2 * B));
- return(t / 6.0);
- } else if(t < 2.0) {
- t = (((-1.0 * B - 6.0 * C) * (t * tt))
- + ((6.0 * B + 30.0 * C) * tt)
- + ((-12.0 * B - 48.0 * C) * t)
- + (8.0 * B + 24 * C));
- return(t / 6.0);
- }
- return(0.0);
- }
-
-
-
-
-
-
-
-
-
- int CResize::Crop(Pixel *image, Pixel *dispImage, int xsize,int ysize,int topCrop,int bottomCrop){
-
- int topStart;
- Pixel *imagetemp, *dispImagetemp;
-
- if(topCrop>ysize)
- topCrop=ysize;
- if(bottomCrop>ysize)
- bottomCrop=ysize;
- // First byte, image bottom
- ZeroMemory(dispImage , bottomCrop*xsize*3);
- ZeroMemory(image, bottomCrop*xsize*4);
- // bottom
- topStart=ysize-topCrop;
-
- dispImagetemp= dispImage + topStart*xsize*3;
- imagetemp = image + topStart*xsize*4;
- ZeroMemory(dispImagetemp, topCrop*xsize*3);
- ZeroMemory(imagetemp, topCrop*xsize*4);
-
-
- return 1;
- }
-
-
- CResize::ResYUVtoRGBA_AR(YUVimage *inp , Pixel *dst,Pixel *dispimage, bool doAR ,double iDAR){
- CLIST *contrib; // array of contribution lists
- CLIST *Ccontrib; // array of contribution lists for Chroma
-
- int weightY, weightU, weightV, y,x;
- Pixel *rasterU, *rasterV,*raster; /* a row or column of pixels */
- Pixel *tmp; /* intermediate image */
- Pixel *tmpU; /* intermediate image croma U */
- Pixel *tmpV; /* intermediate image croma V */
- Pixel *disptemp, *dsttemp;
- int i, j, k; /* loop variables */
- int tempxsize, tempysize, Ctempxsize, Ctempysize;
- double destSAR;
- int rImageX, rImageY,yDestFirst;
-
- //
- if (!inp)
- return 0;
- if (inp->Yysize <= 0 || inp->Yysize >= 1024)
- return 0;
- if (inp->Cysize <= 0 || inp->Cysize >= 1024)
- return 0;
- if (inp->Y==NULL || inp->U==NULL || inp->V==NULL)
- return 0;
-
- if(doAR){
- //Check input DAR (display aspect ratio)
- if(iDAR<=0) return 0;
- if(iDAR>1) return 0;
- //Working out desting Sample Aspect Ratio. Suppose ouput DAR as 3/4
- destSAR=SAR( ((double)3/(double)4), oxsize, oysize);
- //image dimentions
- rImageX=oxsize;
- rImageY= (rImageX*iDAR)/destSAR;
- yDestFirst=((oysize-rImageY)/2);
- if(yDestFirst<0){
- yDestFirst=0;
- rImageY=oysize;
- }
-
- ZeroMemory(dispimage, oxsize*oysize*3 );
- ZeroMemory(dst , oxsize*oysize*4 );
- disptemp=dispimage + (yDestFirst*oxsize*3);
- dsttemp= dst + (yDestFirst*oxsize*4);
- }
- else{
- disptemp=dispimage;
- dsttemp= dst;
- rImageX=oxsize;
- rImageY=oysize;
- }
- /* if( topCrop>=0 && topCrop<=oysize && bottomCrop>=0 && bottomCrop<=oysize)
- doCrop=true;
- else
- doCrop=false;*/
- //IF filter=0. Nearest Neighbourgh. Direct resizing
-
- if(filter==0){
- int yp,Cyp,xp,Cxp,Upel, Vpel, Ypel;
- double stepy, stepx, Cstepy, Cstepx;
- unsigned char *inputline, *Uinputline, *Vinputline;
-
- stepy=(double)inp->Yysize/(double)rImageY;
- stepx=(double)inp->Yxsize/(double)rImageX;
- Cstepy=(double)inp->Cysize/(double)rImageY;
- Cstepx=(double)inp->Cxsize/(double)rImageX;
- for (y=rImageY-1;y>=0;y--)
- {
- yp=y*stepy;
- Cyp=y*Cstepy;
- inputline = inp->Y + ( yp*inp->Yxsize);
- Uinputline= inp->U + (Cyp*inp->Cxsize);
- Vinputline= inp->V + (Cyp*inp->Cxsize);
- for (x=0;x<rImageX;x++)
- {
-
- //YUV to RGB conversion with predefined color primaries crv,cgu,cbu
- // Although colour primaries are predefined they should be an input
- // parameter to the YUVtoRGB conversion
- // MPEG2 video streams can carry different colour primaries embedded in
- /* u = U - 128;
- v = V - 128;
- y = 76309 * (Y - 16); //(255/219)*65536
- R = Clip[(y + crv*v + 32768)>>16];
- G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
- B = Clip[(y + cbu*u + 32786)>>16];
- */
- xp=x*stepx;
- Cxp=x*Cstepx;
-
- Upel = Uinputline[Cxp] - 128;
- Vpel = Vinputline[Cxp] - 128;
- Ypel = 76309*(inputline[xp]-16);
- *disptemp++= *dsttemp++ = CLAMP((Ypel + CBU*Upel + 32768)>>16); //B
- *disptemp++= *dsttemp++ = CLAMP((Ypel - CGU*Upel - CGV*Vpel + 32768)>>16); //G
- *disptemp++= *dsttemp++ = CLAMP((Ypel + CRV*Vpel + 32768)>>16); //R
- *dsttemp++ = 0;
-
- }
- }
- return 0;
- }
- /* create intermediate images to hold horizontal zoom */
- tmp = (Pixel *)malloc(rImageX * inp->Yysize);
- tmpU= (Pixel *)malloc(rImageX * inp->Cysize);
- tmpV= (Pixel *)malloc(rImageX * inp->Cysize);
-
- tempxsize=rImageX;
- tempysize=inp->Yysize;
- Ctempxsize=rImageX;
- Ctempysize=inp->Cysize;
-
-
- // pre-calculate filter contributions for a row
- // LUMINANCE CONTRIBUTIONS
- contrib = AllocateContrib(rImageX);
- WorkOutContributions(contrib, inp->Yxsize, rImageX);
-
- // CHROMA CONTRIBUTIONS
- Ccontrib= AllocateContrib(rImageX);
- WorkOutContributions(Ccontrib, inp->Cxsize, rImageX);
-
- ///////////////////////////////////////////////////////////////////////
- // WORKING OUT TEMPORARY X-SCALED IMAGES
- ///////////////////////////////////////////////////////////////////////
-
- /* apply filter to zoom horizontally from src to tmp */
- //raster = (Pixel *)calloc(ixsize, sizeof(Pixel)*3);
- /* LUMINANCE */
- for(k = 0; k < tempysize; ++k) {
- raster= inp->Y + k*(inp->Yxsize) ;
- for(i = 0; i < tempxsize; ++i) {
- weightY= 0;
- for(j = 0; j < contrib[i].n; ++j) {
- weightY += raster[contrib[i].p[j].pixel]
- * contrib[i].p[j].weightShort;
- }
- tmp[k*(tempxsize)+i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightY >> 15);
- }
- }
-
-
- /* CHROMA */
- for(k = 0; k < Ctempysize; ++k) {
- rasterU= inp->U + k*(inp->Cxsize) ;
- rasterV= inp->V + k*(inp->Cxsize) ;
- for(i = 0; i < Ctempxsize; ++i) {
- weightU=weightV= 0;
- for(j = 0; j < Ccontrib[i].n; ++j) {
- weightU += rasterU[Ccontrib[i].p[j].pixel]
- * Ccontrib[i].p[j].weightShort;
- weightV += rasterV[Ccontrib[i].p[j].pixel]
- * Ccontrib[i].p[j].weightShort;
- }
- tmpU[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightU >> 15);
- tmpV[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightV >> 15);
-
- }
- }
-
-
-
- DeAllocateContrib(contrib, rImageX);
- contrib=NULL;
- DeAllocateContrib(Ccontrib, rImageX);
- Ccontrib=NULL;
-
-
-
-
- // pre-calculate filter contributions for a COLUMN
- // LUMINANCE CONTRIBUTIONS
- contrib = AllocateContrib(rImageY);
- WorkOutContributions(contrib, tempysize, rImageY);
-
- // CHROMA CONTRIBUTIONS
- Ccontrib= AllocateContrib(rImageY);
- WorkOutContributions(Ccontrib, Ctempysize, rImageY);
-
-
- ///////////////////////////////////////////////////////////////////////////
- // FINAL Y-SCALING AND YUV->RGB CONVERSION
- ///////////////////////////////////////////////////////////////////////////
- int Ypel, Upel, Vpel,pointerA,pointerB, rowsizeA, rowsizeB, pixelChroma;
- Pixel *baseY, *baseU, *baseV;
- rowsizeA=rImageX*4;
- rowsizeB=rImageX*3;
-
- /////////////////////////////////////////////////////////////////////////////
- for(k = 0; k < rImageX; k++) {
- //pointerA=(k*4);
- //pointerB=(k*3);
- baseU=tmpU + k;
- baseV=tmpV + k;
- baseY=tmp + k;
- for(i = 0; i < rImageY; i++) {
- weightU=weightV=weightY = 0;
- for(j = 0; j < Ccontrib[i].n; ++j) {
- pixelChroma=Ctempxsize*(Ccontrib[i].p[j].pixel);
- weightU += *( baseU + pixelChroma ) * Ccontrib[i].p[j].weightShort;
- weightV += *( baseV + pixelChroma ) * Ccontrib[i].p[j].weightShort;
- }
- for(j = 0; j < contrib[i].n; ++j) {
- weightY += *( baseY + tempxsize *(contrib[i].p[j].pixel))* contrib[i].p[j].weightShort;
- }
-
- // YUV to RGB conversion with predefined color primaries crv,cgu,cbu
- // Although colour primaries are predefined they should be an input
- // parameter to the YUVtoRGB conversion
- // MPEG2 video streams can carry different colour primaries embedded in
- /* u = U - 128;
- v = V - 128;
- y = 76309 * (Y - 16); //(255/219)*65536
- R = Clip[(y + crv*v + 32768)>>16];
- G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
- B = Clip[(y + cbu*u + 32786)>>16];
- */
-
- Ypel= 76309 * ( (weightY >> 15) - 16);
- Upel= ((weightU>>15)-128);
- Vpel= ((weightV>>15)-128);
-
- pointerA = (k*4) +(rImageY-1-i)*rowsizeA;
- pointerB = (k*3) +(rImageY-1-i)*rowsizeB;
-
- dsttemp[pointerA]=
- disptemp[pointerB]= //B
- (Pixel)CLAMP((Ypel + CBU*Upel + 32786)>>16);
-
- dsttemp[pointerA +1]= //G
- disptemp[pointerB + 1]=
- (Pixel)CLAMP((Ypel - Upel*CGU - Vpel*CGV + 32768)>>16);
-
- dsttemp[pointerA +2]= //R
- disptemp[pointerB + 2]=
- (Pixel)CLAMP((Ypel + Vpel*CRV + 32768)>>16);
-
- dsttemp[pointerA + 3]= 0;
-
-
- }
- }
-
- DeAllocateContrib(contrib, rImageY);
- DeAllocateContrib(Ccontrib, rImageY);
-
- contrib=NULL;
- Ccontrib=NULL;
-
-
- free(tmp);
- free(tmpV);
- free(tmpU);
- return 1;
- }
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CResize::CResize()
- {
-
- }
-
- CResize::ResYUVtoRGBA(YUVimage *inp , Pixel *dst,Pixel *dispimage){
- CLIST *contrib; // array of contribution lists
- CLIST *Ccontrib; // array of contribution lists for Chroma
-
- int weightY, weightU, weightV, y,x;
- Pixel *rasterU, *rasterV,*raster; /* a row or column of pixels */
- Pixel *tmp; /* intermediate image */
- Pixel *tmpU; /* intermediate image croma U */
- Pixel *tmpV; /* intermediate image croma V */
- int i, j, k; /* loop variables */
- int tempxsize, tempysize, Ctempxsize, Ctempysize;
-
- //
- if (!inp)
- return 0;
- if (inp->Yysize <= 0 || inp->Yysize >= 1024)
- return 0;
- if (inp->Cysize <= 0 || inp->Cysize >= 1024)
- return 0;
- if (inp->Y==NULL || inp->U==NULL || inp->V==NULL)
- return 0;
-
- //IF filter=0. Nearest Neighbourgh. Direct resizing
- if(filter==0){
- int yp,Cyp,xp,Cxp,Upel, Vpel, Ypel;
- double stepy, stepx, Cstepy, Cstepx;
- unsigned char *disptemp, *dsttemp, *inputline, *Uinputline, *Vinputline;
- disptemp=dispimage;
- dsttemp= dst;
-
- stepy=(double)inp->Yysize/(double)oysize;
- stepx=(double)inp->Yxsize/(double)oxsize;
- Cstepy=(double)inp->Cysize/(double)oysize;
- Cstepx=(double)inp->Cxsize/(double)oxsize;
- for (y=oysize-1;y>=0;y--)
- {
- yp=y*stepy;
- Cyp=y*Cstepy;
- inputline = inp->Y + ( yp*inp->Yxsize);
- Uinputline= inp->U + (Cyp*inp->Cxsize);
- Vinputline= inp->V + (Cyp*inp->Cxsize);
- for (x=0;x<oxsize;x++)
- {
-
- //YUV to RGB conversion with predefined color primaries crv,cgu,cbu
- // Although colour primaries are predefined they should be an input
- // parameter to the YUVtoRGB conversion
- // MPEG2 video streams can carry different colour primaries embedded in
- /* u = U - 128;
- v = V - 128;
- y = 76309 * (Y - 16); //(255/219)*65536
- R = Clip[(y + crv*v + 32768)>>16];
- G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
- B = Clip[(y + cbu*u + 32786)>>16];
- */
- xp=x*stepx;
- Cxp=x*Cstepx;
-
- Upel = Uinputline[Cxp] - 128;
- Vpel = Vinputline[Cxp] - 128;
- Ypel = 76309*(inputline[xp]-16);
- *disptemp++= *dsttemp++ = CLAMP((Ypel + CBU*Upel + 32768)>>16); //B
- *disptemp++= *dsttemp++ = CLAMP((Ypel - CGU*Upel - CGV*Vpel + 32768)>>16); //G
- *disptemp++= *dsttemp++ = CLAMP((Ypel + CRV*Vpel + 32768)>>16); //R
- *dsttemp++ = 0;
-
- }
- }
- return 0;
- }
- /* create intermediate images to hold horizontal zoom */
- tmp = (Pixel *)malloc(oxsize * inp->Yysize);
- tmpU= (Pixel *)malloc(oxsize * inp->Cysize);
- tmpV= (Pixel *)malloc(oxsize * inp->Cysize);
-
- tempxsize=oxsize;
- tempysize=inp->Yysize;
- Ctempxsize=oxsize;
- Ctempysize=inp->Cysize;
-
-
- // pre-calculate filter contributions for a row
- // LUMINANCE CONTRIBUTIONS
- contrib = AllocateContrib(oxsize);
- WorkOutContributions(contrib, inp->Yxsize, oxsize);
-
- // CHROMA CONTRIBUTIONS
- Ccontrib= AllocateContrib(oxsize);
- WorkOutContributions(Ccontrib, inp->Cxsize, oxsize);
-
- ///////////////////////////////////////////////////////////////////////
- // WORKING OUT TEMPORARY X-SCALED IMAGES
- ///////////////////////////////////////////////////////////////////////
-
- /* apply filter to zoom horizontally from src to tmp */
- //raster = (Pixel *)calloc(ixsize, sizeof(Pixel)*3);
- /* LUMINANCE */
- for(k = 0; k < tempysize; ++k) {
- raster= inp->Y + k*(inp->Yxsize) ;
- for(i = 0; i < tempxsize; ++i) {
- weightY= 0;
- for(j = 0; j < contrib[i].n; ++j) {
- weightY += raster[contrib[i].p[j].pixel]
- * contrib[i].p[j].weightShort;
- }
- tmp[k*(tempxsize)+i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightY >> 15);
- }
- }
-
-
- /* CHROMA */
- for(k = 0; k < Ctempysize; ++k) {
- rasterU= inp->U + k*(inp->Cxsize) ;
- rasterV= inp->V + k*(inp->Cxsize) ;
- for(i = 0; i < Ctempxsize; ++i) {
- weightU=weightV= 0;
- for(j = 0; j < Ccontrib[i].n; ++j) {
- weightU += rasterU[Ccontrib[i].p[j].pixel]
- * Ccontrib[i].p[j].weightShort;
- weightV += rasterV[Ccontrib[i].p[j].pixel]
- * Ccontrib[i].p[j].weightShort;
- }
- tmpU[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightU >> 15);
- tmpV[k*(Ctempxsize) + i]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightV >> 15);
-
- }
- }
-
-
-
- DeAllocateContrib(contrib, oxsize);
- contrib=NULL;
- DeAllocateContrib(Ccontrib, oxsize);
- Ccontrib=NULL;
-
-
-
-
- // pre-calculate filter contributions for a COLUMN
- // LUMINANCE CONTRIBUTIONS
- contrib = AllocateContrib(oysize);
- WorkOutContributions(contrib, tempysize, oysize);
-
- // CHROMA CONTRIBUTIONS
- Ccontrib= AllocateContrib(oysize);
- WorkOutContributions(Ccontrib, Ctempysize, oysize);
-
-
- ///////////////////////////////////////////////////////////////////////////
- // FINAL Y-SCALING AND YUV->RGB CONVERSION
- ///////////////////////////////////////////////////////////////////////////
- int Ypel, Upel, Vpel,pointerA,pointerB, rowsizeA, rowsizeB, pixelChroma;
- Pixel *baseY, *baseU, *baseV;
- rowsizeA=oxsize*4;
- rowsizeB=oxsize*3;
-
- /////////////////////////////////////////////////////////////////////////////
- for(k = 0; k < oxsize; k++) {
- //pointerA=(k*4);
- //pointerB=(k*3);
- baseU=tmpU + k;
- baseV=tmpV + k;
- baseY=tmp + k;
- for(i = 0; i < oysize; i++) {
- weightU=weightV=weightY = 0;
- for(j = 0; j < Ccontrib[i].n; ++j) {
- pixelChroma=Ctempxsize*(Ccontrib[i].p[j].pixel);
- weightU += *( baseU + pixelChroma ) * Ccontrib[i].p[j].weightShort;
- weightV += *( baseV + pixelChroma ) * Ccontrib[i].p[j].weightShort;
- }
- for(j = 0; j < contrib[i].n; ++j) {
- weightY += *( baseY + tempxsize *(contrib[i].p[j].pixel))* contrib[i].p[j].weightShort;
- }
-
- // YUV to RGB conversion with predefined color primaries crv,cgu,cbu
- // Although colour primaries are predefined they should be an input
- // parameter to the YUVtoRGB conversion
- // MPEG2 video streams can carry different colour primaries embedded in
- /* u = U - 128;
- v = V - 128;
- y = 76309 * (Y - 16); //(255/219)*65536
- R = Clip[(y + crv*v + 32768)>>16];
- G = Clip[(y - cgu*u - cgv*v + 32768)>>16];
- B = Clip[(y + cbu*u + 32786)>>16];
- */
-
- Ypel= 76309 * ( (weightY >> 15) - 16);
- Upel= ((weightU>>15)-128);
- Vpel= ((weightV>>15)-128);
-
- pointerA = (k*4) +(oysize-1-i)*rowsizeA;
- pointerB = (k*3) +(oysize-1-i)*rowsizeB;
-
- dst[pointerA]=
- dispimage[pointerB]= //B
- (Pixel)CLAMP((Ypel + CBU*Upel + 32786)>>16);
-
- dst[pointerA +1]= //G
- dispimage[pointerB + 1]=
- (Pixel)CLAMP((Ypel - Upel*CGU - Vpel*CGV + 32768)>>16);
-
- dst[pointerA +2]= //R
- dispimage[pointerB + 2]=
- (Pixel)CLAMP((Ypel + Vpel*CRV + 32768)>>16);
-
- dst[pointerA + 3]= 0;
-
-
- }
- }
-
- DeAllocateContrib(contrib, oysize);
- DeAllocateContrib(Ccontrib, oysize);
-
- contrib=NULL;
- Ccontrib=NULL;
-
-
- free(tmp);
- free(tmpV);
- free(tmpU);
- return 1;
- }
-
-
- CResize::ResRGBtoRGBA(Image *src, Pixel *dst, Pixel *dispimage){
- CLIST *contrib;
- int weightR, weightG, weightB;
- int i, j, k; /* loop variables */
- Pixel *raster; /* a row or column of pixels */
- Pixel *tmp; /* intermediate image */
- int tempxsize, tempysize;
- /* create intermediate image to hold horizontal zoom */
- tmp = (Pixel *)malloc(oxsize * src->ysize *3);
- tempxsize=oxsize;
- tempysize=src->ysize;
-
-
- /* pre-calculate filter contributions for a row */
- contrib = AllocateContrib(oxsize);
- WorkOutContributions(contrib, src->xsize, oxsize);
-
- /* apply filter to zoom horizontally from src to tmp */
- for(k = 0; k < tempysize; ++k) {
- raster= src->data + k*(src->xsize*3) ;
- for(i = 0; i < tempxsize; ++i) {
- weightR=weightG=weightB= 0;
- for(j = 0; j < contrib[i].n; ++j) {
- weightR += raster[contrib[i].p[j].pixel * 3]
- * contrib[i].p[j].weightShort;
- weightG += raster[(contrib[i].p[j].pixel * 3) + 1]
- * contrib[i].p[j].weightShort;
- weightB += raster[(contrib[i].p[j].pixel * 3) + 2]
- * contrib[i].p[j].weightShort;
- }
- tmp[k*(tempxsize*3) +(i*3)]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightR >> 15);
- tmp[k*(tempxsize*3) +(i*3) + 1]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightG >> 15);
- tmp[k*(tempxsize*3) +(i*3) + 2]=/* k= y pos, i= x pos */
- (Pixel)CLAMP(weightB >> 15);
-
-
- }
- }
-
-
- /* free the memory allocated for horizontal filter weights */
- DeAllocateContrib(contrib, oxsize);
- contrib=NULL;
-
-
-
- /* pre-calculate filter contributions for a column */
- contrib = (CLIST *)calloc(oysize, sizeof(CLIST));
- contrib=AllocateContrib(oysize);
- WorkOutContributions(contrib, tempysize, oysize);
-
- /* apply filter to zoom vertically from tmp to dst */
- for(k = 0; k < oxsize; ++k) {
- for(i = 0; i < oysize; ++i) {
- weightR=weightG=weightB= 0;
- for(j = 0; j < contrib[i].n; ++j) {
- weightR += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel))
- * contrib[i].p[j].weightShort;
- weightG += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel) + 1)
- * contrib[i].p[j].weightShort;
- weightB += *(tmp + k*3 + tempxsize*3*(contrib[i].p[j].pixel) + 2)
- * contrib[i].p[j].weightShort;
-
- }
- /* DST image is in RGBA format */
- /* DISP image is in RGB format */
- dispimage[i*(oxsize*3) +(k*3)]=
- dst[i*(oxsize*4) +(k*4)]=/* i= y pos, k= x pos */
- (Pixel)CLAMP(weightR >> 15);
- dispimage[i*(oxsize*3) +(k*3) + 1]=
- dst[i*(oxsize*4) +(k*4) +1]=/* i= y pos, k= x pos */
- (Pixel)CLAMP(weightG >> 15);
- dispimage[i*(oxsize*3) +(k*3) + 2]=
- dst[i*(oxsize*4) +(k*4) +2]=/* i= y pos, k= x pos */
- (Pixel)CLAMP(weightB >> 15);
- dst[i*(oxsize*4) +(k*4) + 3]= 0;
-
- }
- }
-
-
- /* free the memory allocated for vertical filter weights */
- DeAllocateContrib(contrib, oysize);
-
- free(tmp);
- }
-
-
- CResize::Init(int filter,
- int oxsize,
- int oysize)
- {
- CResize::filter=filter;
- CResize::oxsize=oxsize;
- CResize::oysize=oysize;
-
- /* set filter function and width */
- switch( filter ) {
- case '0': filterf=box_filter; fwidth=box_support; break;
- case '1': filterf=triangle_filter; fwidth=triangle_support; break;
- case '2': filterf=bell_filter; fwidth=bell_support; break;
- case '3': filterf=B_spline_filter; fwidth=B_spline_support; break;
- case '5': filterf=Lanczos3_filter; fwidth=Lanczos3_support; break;
- case '6': filterf=Mitchell_filter; fwidth=Mitchell_support; break;
- case '7': filterf=cubicConv ; fwidth=cubicConv_support; break;
- case '8': filterf=hann4 ; fwidth=HannWindows_support; break;
- default: filterf=cubicConv ; fwidth=cubicConv_support; break;
- }
- return 1;
- }
-
- CResize::~CResize()
- {
-
- }
-
-
-
- CLIST* CResize::AllocateContrib(int size)
- {
- return (CLIST *)calloc(size, sizeof(CLIST));
- }
-
- CResize::DeAllocateContrib(CLIST *contrib,int size)
- {
- int i;
- for(i = 0; i < size; ++i) {
- free(contrib[i].p);
- }
- free(contrib);
- }
-
- CResize::WorkOutContributions(CLIST *contrib,int isize, int osize)
- {
- int i,j,k,n;
- double weightFact,scale;
- double center, left, right;
- double width, fscale, weight;
-
- scale = (double)osize/(double)isize;
- if(scale < 1.0){ /* If we are minimizing */
- width = fwidth / scale;
- fscale = 1.0 / scale;
- }
- else{
- width = fwidth;
- fscale = 1.0;
- }
- for(i = 0; i < osize; ++i) {
- contrib[i].n = 0;
- contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), //width of filter
- sizeof(CONTRIB));
- center = (double) i / scale;
- left = ceil(center - width);
- right = floor(center + width);
- weightFact=0;
- for(j = left; j <= right; ++j) {
- weight = center - (double) j;
- weight = (*filterf)(weight / fscale) / fscale;
- if(j < 0) {
- n = -j;
- } else if(j >= isize) {
- n = (isize - j) + isize - 1;
- } else {
- n = j;
- }
- k = contrib[i].n++;
- contrib[i].p[k].pixel = n;
- contrib[i].p[k].weight = weight;
- weightFact+=weight;
- }
- // Coefs must add up to 1 to ensure unity gain
- weightFact= 1 - weightFact;
- weightFact= weightFact/ contrib[i].n;
- for(j=0; j<contrib[i].n; j++){
- contrib[i].p[j].weight+= weightFact;
- contrib[i].p[j].weightShort = floor(contrib[i].p[j].weight * WEIGHT_SCALE);
- }
- }
- }