📄 ximadsp.cpp
字号:
if (bEditAlpha && AlphaIsValid()==false){ AlphaCreate(); } RGBQUAD rgbBackgrnd = GetTransColor(); RGBQUAD rgb1, rgb2, rgbDest; for(long lY=0;lY<lHeight;lY++) { info.nProgress = (long)(100*lY/head.biHeight); if (info.nEscape) break; for(long lX=0;lX<lWide;lX++) {#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(lX,lY) && imgsrc2.SelectionIsInside(lX+lXOffset,lY+lYOffset))#endif //CXIMAGE_SUPPORT_SELECTION { rgb1 = GetPixelColor(lX,lY); rgb2 = imgsrc2.GetPixelColor(lX+lXOffset,lY+lYOffset); switch(op) { case OpAdd: rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue+rgb2.rgbBlue)); rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen+rgb2.rgbGreen)); rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed+rgb2.rgbRed)); if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved+rgb2.rgbReserved)); break; case OpSub: rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue-rgb2.rgbBlue)); rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen-rgb2.rgbGreen)); rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed-rgb2.rgbRed)); if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved-rgb2.rgbReserved)); break; case OpAnd: rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue&rgb2.rgbBlue); rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen&rgb2.rgbGreen); rgbDest.rgbRed = (BYTE)(rgb1.rgbRed&rgb2.rgbRed); if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved&rgb2.rgbReserved); break; case OpXor: rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue^rgb2.rgbBlue); rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen^rgb2.rgbGreen); rgbDest.rgbRed = (BYTE)(rgb1.rgbRed^rgb2.rgbRed); if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved^rgb2.rgbReserved); break; case OpOr: rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue|rgb2.rgbBlue); rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen|rgb2.rgbGreen); rgbDest.rgbRed = (BYTE)(rgb1.rgbRed|rgb2.rgbRed); if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved|rgb2.rgbReserved); break; case OpMask: if(rgb2.rgbBlue==0 && rgb2.rgbGreen==0 && rgb2.rgbRed==0) rgbDest = rgbBackgrnd; else rgbDest = rgb1; break; case OpSrcCopy: if(memcmp(&rgb1,&rgbBackgrnd,sizeof(RGBQUAD))==0) rgbDest = rgb2; else // copy straight over rgbDest = rgb1; break; case OpDstCopy: if(memcmp(&rgb2,&rgbBackgrnd,sizeof(RGBQUAD))==0) rgbDest = rgb1; else // copy straight over rgbDest = rgb2; break; case OpScreen: { BYTE a,a1; if (imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset)){ a=0; } else if (imgsrc2.AlphaIsValid()){ a=imgsrc2.AlphaGet(lX+lXOffset,lY+lYOffset); a =(BYTE)((a*(1+imgsrc2.info.nAlphaMax))>>8); } else { a=255; } if (a==0){ //transparent rgbDest = rgb1; } else if (a==255){ //opaque rgbDest = rgb2; } else { //blend a1 = (BYTE)~a; rgbDest.rgbBlue = (BYTE)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)>>8); rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)>>8); rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)>>8); } if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(((1+rgb1.rgbReserved)*a)>>8); } break; case OpSrcBlend: if(memcmp(&rgb1,&rgbBackgrnd,sizeof(RGBQUAD))==0) rgbDest = rgb2; else { long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd.rgbBlue); long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd.rgbGreen); long lRDiff = abs(rgb1.rgbRed - rgbBackgrnd.rgbRed); double lAverage = (lBDiff+lGDiff+lRDiff)/3; double lThresh = 16; double dLarge = lAverage/lThresh; double dSmall = (lThresh-lAverage)/lThresh; double dSmallAmt = dSmall*((double)rgb2.rgbBlue); if( lAverage < lThresh+1){ rgbDest.rgbBlue = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbBlue) + dSmallAmt))); rgbDest.rgbGreen = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbGreen) + dSmallAmt))); rgbDest.rgbRed = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbRed) + dSmallAmt))); } else rgbDest = rgb1; } break; default: return; } SetPixelColor(lX,lY,rgbDest,bEditAlpha); } } }}////////////////////////////////////////////////////////////////////////////////// thanks to Kenneth Ballardvoid CxImage::MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset){ RGBQUAD rgbBackgrnd = imagesrc2.GetTransColor(); RGBQUAD rgb1; long width = imagesrc2.GetWidth(); long height = imagesrc2.GetHeight(); int x, y; for(x = 0; x < width; x++) { for(y = 0; y < height; y++) { rgb1 = imagesrc2.GetPixelColor(x, y); if(memcmp(&rgb1, &rgbBackgrnd, sizeof(RGBQUAD)) != 0) SetPixelColor(x + lXOffset, y + lYOffset, rgb1); } }}/////////////////////////////////////////////////////////////////////////////////** * Adjusts separately the red, green, and blue values in the image. * \param r, g, b: can be from -255 to +255. * \return true if everything is ok */bool CxImage::ShiftRGB(long r, long g, long b){ if (!pDib) return false; RGBQUAD color; if (head.biClrUsed==0){ long xmin,xmax,ymin,ymax; if (pSelection){ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; } else { xmin = ymin = 0; xmax = head.biWidth; ymax=head.biHeight; } for(long y=ymin; y<ymax; y++){ for(long x=xmin; x<xmax; x++){#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y))#endif //CXIMAGE_SUPPORT_SELECTION { color = GetPixelColor(x,y); color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r))); color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g))); color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b))); SetPixelColor(x,y,color); } } } } else { for(DWORD j=0; j<head.biClrUsed; j++){ color = GetPaletteColor((BYTE)j); color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r))); color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g))); color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b))); SetPaletteColor((BYTE)j,color); } } return true;}/////////////////////////////////////////////////////////////////////////////////** * Adjusts the color balance of the image * \param gamma can be from 0.1 to 5. * \return true if everything is ok */bool CxImage::Gamma(float gamma){ if (!pDib) return false; double dinvgamma = 1/gamma; double dMax = pow(255.0, dinvgamma) / 255.0; BYTE cTable[256]; //<nipper> for (int i=0;i<256;i++) { cTable[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax))); } return Lut(cTable);}////////////////////////////////////////////////////////////////////////////////#if CXIMAGE_SUPPORT_WINCE == 0/** * Adjusts the intensity of each pixel to the median intensity of its surrounding pixels. * \param Ksize: size of the kernel. * \return true if everything is ok */bool CxImage::Median(long Ksize){ if (!pDib) return false; long k2 = Ksize/2; long kmax= Ksize-k2; long i,j,k; RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD)); CxImage tmp(*this,pSelection!=0,true,true); if (!tmp.IsValid()) return false; long xmin,xmax,ymin,ymax; if (pSelection){ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; } else { xmin = ymin = 0; xmax = head.biWidth; ymax=head.biHeight; } for(long y=ymin; y<ymax; y++){ info.nProgress = (long)(100*y/head.biHeight); if (info.nEscape) break; for(long x=xmin; x<xmax; x++){#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y))#endif //CXIMAGE_SUPPORT_SELECTION { for(j=-k2, i=0;j<kmax;j++) for(k=-k2;k<kmax;k++, i++) kernel[i]=GetPixelColor(x+j,y+k); qsort(kernel, i, sizeof(RGBQUAD), CompareColors); tmp.SetPixelColor(x,y,kernel[i/2]); } } } free(kernel); Transfer(tmp); return true;}#endif //CXIMAGE_SUPPORT_WINCE/////////////////////////////////////////////////////////////////////////////////** * Adds an uniform noise to the image * \param level: can be from 0 (no noise) to 255 (lot of noise). * \return true if everything is ok */bool CxImage::Noise(long level){ if (!pDib) return false; RGBQUAD color; long xmin,xmax,ymin,ymax,n; if (pSelection){ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; } else { xmin = ymin = 0; xmax = head.biWidth; ymax=head.biHeight; } for(long y=ymin; y<ymax; y++){ info.nProgress = (long)(100*y/ymax); //<Anatoly Ivasyuk> for(long x=xmin; x<xmax; x++){#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y))#endif //CXIMAGE_SUPPORT_SELECTION { color = GetPixelColor(x,y); n=(long)((rand()/(float)RAND_MAX - 0.5)*level); color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + n))); n=(long)((rand()/(float)RAND_MAX - 0.5)*level); color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + n))); n=(long)((rand()/(float)RAND_MAX - 0.5)*level); color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + n))); SetPixelColor(x,y,color); } } } return true;}/////////////////////////////////////////////////////////////////////////////////** * Computes the bidimensional FFT or DFT of the image. * - The images are processed as grayscale * - If the dimensions of the image are a power of, 2 the FFT is performed automatically. * - If dstReal and/or dstImag are NULL, the resulting images replaces the original(s). * - Note: with 8 bits there is a HUGE loss in the dynamics. The function tries * to keep an acceptable SNR, but 8bit = 48dB... * * \param srcReal, srcImag: source images: One can be NULL, but not both * \param dstReal, dstImag: destination images. Can be NULL. * \param direction: 1 = forward, -1 = inverse. * \param bForceFFT: if true, the images are resampled to make the dimensions a power of 2. * \param bMagnitude: if true, the real part returns the magnitude, the imaginary part returns the phase * \return true if everything is ok */bool CxImage::FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag, long direction, bool bForceFFT, bool bMagnitude){ //check if there is something to convert if (srcReal==NULL && srcImag==NULL) return false; long w,h; //get width and height if (srcReal) { w=srcReal->GetWidth(); h=srcReal->GetHeight(); } else { w=srcImag->GetWidth(); h=srcImag->GetHeight(); } bool bXpow2 = IsPowerof2(w); bool bYpow2 = IsPowerof2(h); //if bForceFFT, width AND height must be powers of 2 if (bForceFFT && !(bXpow2 && bYpow2)) { long i; i=0; while((1<<i)<w) i++; w=1<<i; bXpow2=true; i=0; while((1<<i)<h) i++; h=1<<i; bYpow2=true; } // I/O images for FFT CxImage *tmpReal,*tmpImag; // select output tmpReal = (dstReal) ? dstReal : srcReal; tmpImag = (dstImag) ? dstImag : srcImag; // src!=dst -> copy the image if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false); if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false); // dst&&src are empty -> create new one, else turn to GrayScale if (srcReal==0 && dstReal==0){ tmpReal = new CxImage(w,h,8); tmpReal->Clear(0); tmpReal->SetGrayPalette(); } else { if (!tmpReal->IsGrayScale()) tmpReal->GrayScale(); } if (srcImag==0 && dstImag==0){ tmpImag = new CxImage(w,h,8); tmpImag->Clear(0); tmpImag->SetGrayPalette(); } else { if (!tmpImag->IsGrayScale()) tmpImag->GrayScale(); } if (!(tmpReal->IsValid() && tmpImag->IsValid())){ if (srcReal==0 && dstReal==0) delete tmpReal; if (srcImag==0 && dstImag==0) delete tmpImag; return false; } //resample for FFT, if necessary tmpReal->Resample(w,h,0); tmpImag->Resample(w,h,0); //ok, here we have 2 (w x h), grayscale images ready for a FFT double* real; double* imag; long j,k,m; _complex **grid; //double mean = tmpReal->Mean(); /* Allocate memory for the grid */ grid = (_complex **)malloc(w * sizeof(_complex)); for (k=0;k<w;k++) { grid[k] = (_complex *)malloc(h * sizeof(_complex)); } for (j=0;j<h;j++) { for (k=0;k<w;k++) { grid[k][j].x = tmpReal->GetPixelIndex(k,j)-128; grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128; } } //DFT buffers double *real2,*imag2; real2 = (double*)malloc(max(w,h) * sizeof(double)); imag2 = (double*)malloc(max(w,h) * sizeof(double)); /* Transform the rows */ real = (double *)malloc(w * sizeof(double)); imag = (double *)malloc(w * sizeof(double)); m=0; while((1<<m)<w) m++; for (j=0;j<h;j++) { for (k=0;k<w;k++) { real[k] = grid[k][j].x; imag[k] = grid[k][j].y; } if (bXpow2) FFT(direction,m,real,imag); else DFT(direction,w,real,imag,real2,imag2); for (k=0;k<w;k++) { grid[k][j].x = real[k]; grid[k][j].y = imag[k]; } } free(real); free(imag); /* Transform the columns */ real = (double *)malloc(h * sizeof(double)); imag = (double *)malloc(h * sizeof(double)); m=0; while((1<<m)<h) m++; for (k=0;k<w;k++) { for (j=0;j<h;j++) { real[j] = grid[k][j].x; imag[j] = grid[k][j].y; } if (bYpow2) FFT(direction,m,real,imag); else DFT(direction,h,real,imag,real2,imag2); for (j=0;j<h;j++) { grid[k][j].x = real[j]; grid[k][j].y = imag[j]; } } free(real); free(imag); free(real2); free(imag2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -