📄 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 + -