📄 ximatran.cpp
字号:
// xImaTran.cpp : Transformation functions/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 */#include "ximage.h"#include "ximath.h"#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS////////////////////////////////////////////////////////////////////////////////bool CxImage::GrayScale(){ if (!pDib) return false; if (head.biBitCount<=8){ RGBQUAD* ppal=GetPalette(); int gray; //converts the colors to gray, use the blue channel only for(DWORD i=0;i<head.biClrUsed;i++){ gray=(int)RGB2GRAY(ppal[i].rgbRed,ppal[i].rgbGreen,ppal[i].rgbBlue); ppal[i].rgbBlue = (BYTE)gray; } // preserve transparency if (info.nBkgndIndex != -1) info.nBkgndIndex = ppal[info.nBkgndIndex].rgbBlue; //create a "real" 8 bit gray scale image if (head.biBitCount==8){ BYTE *img=info.pImage; for(DWORD i=0;i<head.biSizeImage;i++) img[i]=ppal[img[i]].rgbBlue; SetGrayPalette(); } //transform to 8 bit gray scale if (head.biBitCount==4 || head.biBitCount==1){ CxImage ima; ima.CopyInfo(*this); if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false; ima.SetGrayPalette();#if CXIMAGE_SUPPORT_SELECTION ima.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA ima.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA BYTE *img=ima.GetBits(); long l=ima.GetEffWidth(); for (long y=0;y<head.biHeight;y++){ for (long x=0;x<head.biWidth; x++){ img[x+y*l]=ppal[GetPixelIndex(x,y)].rgbBlue; } } Transfer(ima); } } else { //from RGB to 8 bit gray scale BYTE *iSrc=info.pImage; CxImage ima; ima.CopyInfo(*this); if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false; ima.SetGrayPalette();#if CXIMAGE_SUPPORT_SELECTION ima.SelectionCopy(*this);#endif //CXIMAGE_SUPPORT_SELECTION#if CXIMAGE_SUPPORT_ALPHA ima.AlphaCopy(*this);#endif //CXIMAGE_SUPPORT_ALPHA BYTE *img=ima.GetBits(); long l8=ima.GetEffWidth(); long l=head.biWidth * 3; for(long y=0; y < head.biHeight; y++) { for(long x=0,x8=0; x < l; x+=3,x8++) { img[x8+y*l8]=(BYTE)RGB2GRAY(*(iSrc+x+2),*(iSrc+x+1),*(iSrc+x+0)); } iSrc+=info.dwEffWidth; } Transfer(ima); } return true;}////////////////////////////////////////////////////////////////////////////////bool CxImage::Flip(){ if (!pDib) return false; CxImage* imatmp = new CxImage(*this,false,false,true); if (!imatmp) return false; if (!imatmp->IsValid()) return false; BYTE *iSrc,*iDst; iSrc=info.pImage + (head.biHeight-1)*info.dwEffWidth; iDst=imatmp->info.pImage; for(long y=0; y < head.biHeight; y++){ memcpy(iDst,iSrc,info.dwEffWidth); iSrc-=info.dwEffWidth; iDst+=info.dwEffWidth; }#if CXIMAGE_SUPPORT_ALPHA imatmp->AlphaFlip();#endif //CXIMAGE_SUPPORT_ALPHA Transfer(*imatmp); delete imatmp; return true;}////////////////////////////////////////////////////////////////////////////////bool CxImage::Mirror(){ if (!pDib) return false; CxImage* imatmp = new CxImage(*this,false,false,true); if (!imatmp) return false; BYTE *iSrc,*iDst; long wdt=(head.biWidth-1) * (head.biBitCount==24 ? 3:1); iSrc=info.pImage + wdt; iDst=imatmp->info.pImage; long x,y; switch (head.biBitCount){ case 24: for(y=0; y < head.biHeight; y++){ for(x=0; x <= wdt; x+=3){ *(iDst+x)=*(iSrc-x); *(iDst+x+1)=*(iSrc-x+1); *(iDst+x+2)=*(iSrc-x+2); } iSrc+=info.dwEffWidth; iDst+=info.dwEffWidth; } break; case 8: for(y=0; y < head.biHeight; y++){ for(x=0; x <= wdt; x++) *(iDst+x)=*(iSrc-x); iSrc+=info.dwEffWidth; iDst+=info.dwEffWidth; } break; default: for(y=0; y < head.biHeight; y++){ for(x=0; x <= wdt; x++) imatmp->SetPixelIndex(x,y,GetPixelIndex(wdt-x,y)); } }#if CXIMAGE_SUPPORT_ALPHA imatmp->AlphaMirror();#endif //CXIMAGE_SUPPORT_ALPHA Transfer(*imatmp); delete imatmp; return true;}////////////////////////////////////////////////////////////////////////////////#define RBLOCK 64////////////////////////////////////////////////////////////////////////////////bool CxImage::RotateLeft(CxImage* iDst){ if (!pDib) return false; long newWidth = GetHeight(); long newHeight = GetWidth(); CxImage imgDest; imgDest.CopyInfo(*this); imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); imgDest.SetPalette(GetPalette());#if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid()) imgDest.AlphaCreate();#endif long x,x2,y,dlineup; // Speedy rotate for BW images <Robert Abram> if (head.biBitCount == 1) { BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp; div_t div_r; BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits(); dbitsmax = bdest + imgDest.head.biSizeImage - 1; dlineup = 8 * imgDest.info.dwEffWidth - imgDest.head.biWidth; imgDest.Clear(0); for (y = 0; y < head.biHeight; y++) { // Figure out the Column we are going to be copying to div_r = div(y + dlineup, 8); // set bit pos of src column byte bitpos = 1 << div_r.rem; srcdisp = bsrc + y * info.dwEffWidth; for (x = 0; x < (long)info.dwEffWidth; x++) { // Get Source Bits sbits = srcdisp + x; // Get destination column nrow = bdest + (x * 8) * imgDest.info.dwEffWidth + imgDest.info.dwEffWidth - 1 - div_r.quot; for (long z = 0; z < 8; z++) { // Get Destination Byte dbits = nrow + z * imgDest.info.dwEffWidth; if ((dbits < bdest) || (dbits > dbitsmax)) break; if (*sbits & (128 >> z)) *dbits |= bitpos; } } }//for y#if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid()) { for (x = 0; x < newWidth; x++){ x2=newWidth-x-1; for (y = 0; y < newHeight; y++){ imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2)); }//for y }//for x }#endif //CXIMAGE_SUPPORT_ALPHA } else { //anything other than BW: //bd, 10. 2004: This optimized version of rotation rotates image by smaller blocks. It is quite //a bit faster than obvious algorithm, because it produces much less CPU cache misses. //This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current //CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase //speed somehow, but once you drop out of CPU's cache, things will slow down drastically. //For older CPUs with less cache, lower value would yield better results. BYTE *srcPtr, *dstPtr; //source and destionation for 24-bit version int xs, ys; //x-segment and y-segment for (xs = 0; xs < newWidth; xs+=RBLOCK) { //for all image blocks of RBLOCK*RBLOCK pixels for (ys = 0; ys < newHeight; ys+=RBLOCK) { if (head.biBitCount==24) { //RGB24 optimized pixel access: for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ //do rotation info.nProgress = (long)(100*x/newWidth); x2=newWidth-x-1; dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(x,ys); srcPtr = (BYTE*) BlindGetPixelPointer(ys, x2); for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ //imgDest.SetPixelColor(x, y, GetPixelColor(y, x2)); *(dstPtr) = *(srcPtr); *(dstPtr+1) = *(srcPtr+1); *(dstPtr+2) = *(srcPtr+2); srcPtr += 3; dstPtr += imgDest.info.dwEffWidth; }//for y }//for x } else { //anything else than 24bpp (and 1bpp): palette for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ info.nProgress = (long)(100*x/newWidth); //<Anatoly Ivasyuk> x2=newWidth-x-1; for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y, x2)); }//for y }//for x }//if (version selection)#if CXIMAGE_SUPPORT_ALPHA if (pAlpha) { for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ x2=newWidth-x-1; for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2)); }//for y }//for x }//if (alpha channel)#endif //CXIMAGE_SUPPORT_ALPHA }//for ys }//for xs }//if //select the destination if (iDst) iDst->Transfer(imgDest); else Transfer(imgDest); return true;}////////////////////////////////////////////////////////////////////////////////bool CxImage::RotateRight(CxImage* iDst){ if (!pDib) return false; long newWidth = GetHeight(); long newHeight = GetWidth(); CxImage imgDest; imgDest.CopyInfo(*this); imgDest.Create(newWidth,newHeight,GetBpp(),GetType()); imgDest.SetPalette(GetPalette());#if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid()) imgDest.AlphaCreate();#endif long x,y,y2; // Speedy rotate for BW images <Robert Abram> if (head.biBitCount == 1) { BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp; div_t div_r; BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits(); dbitsmax = bdest + imgDest.head.biSizeImage - 1; imgDest.Clear(0); for (y = 0; y < head.biHeight; y++) { // Figure out the Column we are going to be copying to div_r = div(y, 8); // set bit pos of src column byte bitpos = 128 >> div_r.rem; srcdisp = bsrc + y * info.dwEffWidth; for (x = 0; x < (long)info.dwEffWidth; x++) { // Get Source Bits sbits = srcdisp + x; // Get destination column nrow = bdest + (imgDest.head.biHeight-1-(x*8)) * imgDest.info.dwEffWidth + div_r.quot; for (long z = 0; z < 8; z++) { // Get Destination Byte dbits = nrow - z * imgDest.info.dwEffWidth; if ((dbits < bdest) || (dbits > dbitsmax)) break; if (*sbits & (128 >> z)) *dbits |= bitpos; } } }#if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid()){ for (y = 0; y < newHeight; y++){ y2=newHeight-y-1; for (x = 0; x < newWidth; x++){ imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x)); } } }#endif //CXIMAGE_SUPPORT_ALPHA } else { //anything else but BW BYTE *srcPtr, *dstPtr; //source and destionation for 24-bit version int xs, ys; //x-segment and y-segment for (xs = 0; xs < newWidth; xs+=RBLOCK) { for (ys = 0; ys < newHeight; ys+=RBLOCK) { if (head.biBitCount==24) { //RGB24 optimized pixel access: for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ info.nProgress = (long)(100*y/newHeight); //<Anatoly Ivasyuk> y2=newHeight-y-1; dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(xs,y); srcPtr = (BYTE*) BlindGetPixelPointer(y2, xs); for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ //imgDest.SetPixelColor(x, y, GetPixelColor(y2, x)); *(dstPtr) = *(srcPtr); *(dstPtr+1) = *(srcPtr+1); *(dstPtr+2) = *(srcPtr+2); dstPtr += 3; srcPtr += info.dwEffWidth; }//for x }//for y } else { //anything else than BW & RGB24: palette for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ info.nProgress = (long)(100*y/newHeight); //<Anatoly Ivasyuk> y2=newHeight-y-1; for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y2, x)); }//for x }//for y }//if#if CXIMAGE_SUPPORT_ALPHA if (pAlpha){ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){ y2=newHeight-y-1; for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x)); }//for x }//for y }//if (has alpha)#endif //CXIMAGE_SUPPORT_ALPHA }//for ys }//for xs }//if //select the destination if (iDst) iDst->Transfer(imgDest); else Transfer(imgDest); return true;}////////////////////////////////////////////////////////////////////////////////bool CxImage::Negative(){ if (!pDib) return false; if (head.biBitCount<=8){ if (IsGrayScale()){ //GRAYSCALE, selection if (pSelection){ for(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){ for(long x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y))#endif //CXIMAGE_SUPPORT_SELECTION { SetPixelIndex(x,y,(BYTE)(255-GetPixelIndex(x,y))); } } } } else { for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ SetPixelIndex(x,y,(BYTE)(255-GetPixelIndex(x,y))); } } } } else { //PALETTE, full image RGBQUAD* ppal=GetPalette(); for(DWORD i=0;i<head.biClrUsed;i++){ ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue); ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen); ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed); } } } else { if (pSelection==NULL){ //RGB, full image BYTE *iSrc=info.pImage; for(unsigned long i=0; i < head.biSizeImage; i++){ *iSrc=(BYTE)~(*(iSrc)); iSrc++; } } else { // RGB with selection RGBQUAD color; for(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){ for(long x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){#if CXIMAGE_SUPPORT_SELECTION if (SelectionIsInside(x,y))#endif //CXIMAGE_SUPPORT_SELECTION { color = GetPixelColor(x,y); color.rgbRed = (BYTE)(255-color.rgbRed); color.rgbGreen = (BYTE)(255-color.rgbGreen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -