📄 ximadsp.cpp
字号:
for(long x=xmin; x<xmax; x++){
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsInside(x,y))
#endif //CXIMAGE_SUPPORT_SELECTION
{
r=b=g=255;
for(long j=-k2;j<kmax;j++){
for(long k=-k2;k<kmax;k++){
c=GetPixelColor(x+j,y+k);
if (c.rgbRed < r) r=c.rgbRed;
if (c.rgbGreen < g) g=c.rgbGreen;
if (c.rgbBlue < b) b=c.rgbBlue;
}
}
c.rgbRed = r;
c.rgbGreen = g;
c.rgbBlue = b;
tmp.SetPixelColor(x,y,c);
}
}
}
Transfer(tmp);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/**
* Enhance the light areas of the image
* \param Ksize: size of the kernel.
* \return true if everything is ok
*/
bool CxImage::Dilate(long Ksize)
{
if (!pDib) return false;
long k2 = Ksize/2;
long kmax= Ksize-k2;
BYTE r,g,b;
RGBQUAD c;
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
{
r=b=g=0;
for(long j=-k2;j<kmax;j++){
for(long k=-k2;k<kmax;k++){
c=GetPixelColor(x+j,y+k);
if (c.rgbRed > r) r=c.rgbRed;
if (c.rgbGreen > g) g=c.rgbGreen;
if (c.rgbBlue > b) b=c.rgbBlue;
}
}
c.rgbRed = r;
c.rgbGreen = g;
c.rgbBlue = b;
tmp.SetPixelColor(x,y,c);
}
}
}
Transfer(tmp);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/**
* Enhance the variations between adjacent pixels.
* Similar results can be achieved using Filter(),
* but the algorithms are different both in Edge() and in Contour().
* \param Ksize: size of the kernel.
* \return true if everything is ok
*/
bool CxImage::Edge(long Ksize)
{
if (!pDib) return false;
long k2 = Ksize/2;
long kmax= Ksize-k2;
BYTE r,g,b,rr,gg,bb;
RGBQUAD c;
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
{
r=b=g=0;
rr=bb=gg=255;
for(long j=-k2;j<kmax;j++){
for(long k=-k2;k<kmax;k++){
c=GetPixelColor(x+j,y+k);
if (c.rgbRed > r) r=c.rgbRed;
if (c.rgbGreen > g) g=c.rgbGreen;
if (c.rgbBlue > b) b=c.rgbBlue;
if (c.rgbRed < rr) rr=c.rgbRed;
if (c.rgbGreen < gg) gg=c.rgbGreen;
if (c.rgbBlue < bb) bb=c.rgbBlue;
}
}
c.rgbRed = 255-abs(r-rr);
c.rgbGreen = 255-abs(g-gg);
c.rgbBlue = 255-abs(b-bb);
tmp.SetPixelColor(x,y,c);
}
}
}
Transfer(tmp);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/**
* Blends two images
* \param imgsrc2: image to be mixed with this
* \param op: blending method; see ImageOpType
* \param lXOffset, lYOffset: image displacement
* \param bMixAlpha: if true and imgsrc2 has a valid alpha layer, it will be mixed in the destination image.
* \return true if everything is ok
*
* thanks to Mwolski
*/
//
void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset, long lYOffset, bool bMixAlpha)
{
long lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset);
long lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset);
bool bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha;
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 Ballard
void 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -