📄 ximatran.cpp
字号:
// xImaTran.cpp : Transformation functions
/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
* CxImage version 6.0.0 02/Feb/2008
*/
#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 >= 0) 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
for (long y=0;y<head.biHeight;y++){
BYTE *iDst = ima.GetBits(y);
BYTE *iSrc = GetBits(y);
for (long x=0;x<head.biWidth; x++){
//iDst[x]=ppal[BlindGetPixelIndex(x,y)].rgbBlue;
if (head.biBitCount==4){
BYTE pos = (BYTE)(4*(1-x%2));
iDst[x]= ppal[(BYTE)((iSrc[x >> 1]&((BYTE)0x0F<<pos)) >> pos)].rgbBlue;
} else {
BYTE pos = (BYTE)(7-x%8);
iDst[x]= ppal[(BYTE)((iSrc[x >> 3]&((BYTE)0x01<<pos)) >> pos)].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;
}
////////////////////////////////////////////////////////////////////////////////
/**
* \sa Mirror
* \author [qhbo]
*/
bool CxImage::Flip(bool bFlipSelection, bool bFlipAlpha)
{
if (!pDib) return false;
BYTE *buff = (BYTE*)malloc(info.dwEffWidth);
if (!buff) return false;
BYTE *iSrc,*iDst;
iSrc = GetBits(head.biHeight-1);
iDst = GetBits(0);
for (long i=0; i<(head.biHeight/2); ++i)
{
memcpy(buff, iSrc, info.dwEffWidth);
memcpy(iSrc, iDst, info.dwEffWidth);
memcpy(iDst, buff, info.dwEffWidth);
iSrc-=info.dwEffWidth;
iDst+=info.dwEffWidth;
}
free(buff);
if (bFlipSelection){
#if CXIMAGE_SUPPORT_SELECTION
SelectionFlip();
#endif //CXIMAGE_SUPPORT_SELECTION
}
if (bFlipAlpha){
#if CXIMAGE_SUPPORT_ALPHA
AlphaFlip();
#endif //CXIMAGE_SUPPORT_ALPHA
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/**
* \sa Flip
*/
bool CxImage::Mirror(bool bMirrorSelection, bool bMirrorAlpha)
{
if (!pDib) return false;
CxImage* imatmp = new CxImage(*this,false,true,true);
if (!imatmp) return false;
if (!imatmp->IsValid()){
delete 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 (bMirrorSelection){
#if CXIMAGE_SUPPORT_SELECTION
imatmp->SelectionMirror();
#endif //CXIMAGE_SUPPORT_SELECTION
}
if (bMirrorAlpha){
#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
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsValid()) imgDest.SelectionCreate();
#endif
long x,x2,y,dlineup;
// Speedy rotate for BW images <Robert Abram>
if (head.biBitCount == 1) {
BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
ldiv_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 = ldiv(y + dlineup, (long)8);
// set bit pos of src column byte
bitpos = (BYTE)(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
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsValid()) {
imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;
imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;
imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;
imgDest.info.rSelectionBox.top = info.rSelectionBox.right;
for (x = 0; x < newWidth; x++){
x2=newWidth-x-1;
for (y = 0; y < newHeight; y++){
imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));
}//for y
}//for x
}
#endif //CXIMAGE_SUPPORT_SELECTION
} 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 (AlphaIsValid()) {
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
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsValid()) {
imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;
imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;
imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;
imgDest.info.rSelectionBox.top = info.rSelectionBox.right;
for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
x2=newWidth-x-1;
for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));
}//for y
}//for x
}//if (selection)
#endif //CXIMAGE_SUPPORT_SELECTION
}//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
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsValid()) imgDest.SelectionCreate();
#endif
long x,y,y2;
// Speedy rotate for BW images <Robert Abram>
if (head.biBitCount == 1) {
BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
ldiv_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 = ldiv(y, (long)8);
// set bit pos of src column byte
bitpos = (BYTE)(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
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsValid()){
imgDest.info.rSelectionBox.left = info.rSelectionBox.bottom;
imgDest.info.rSelectionBox.right = info.rSelectionBox.top;
imgDest.info.rSelectionBox.bottom = newHeight-info.rSelectionBox.right;
imgDest.info.rSelectionBox.top = newHeight-info.rSelectionBox.left;
for (y = 0; y < newHeight; y++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -