📄 ximadsp.cpp
字号:
// xImaDsp.cpp : DSP functions/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 */#include "ximage.h"#include "ximaiter.h"#if CXIMAGE_SUPPORT_DSP/////////////////////////////////////////////////////////////////////////////////** * Converts the image to B&W. * The Mean() function can be used for calculating the optimal threshold. * \param level: the lightness threshold. * \return true if everything is ok */bool CxImage::Threshold(BYTE level){ if (!pDib) return false; if (head.biBitCount == 1) return true; GrayScale(); CxImage tmp(head.biWidth,head.biHeight,1); if (!tmp.IsValid()) return false; for (long y=0;y<head.biHeight;y++){ info.nProgress = (long)(100*y/head.biHeight); if (info.nEscape) break; for (long x=0;x<head.biWidth;x++){ if (GetPixelIndex(x,y)>level) tmp.SetPixelIndex(x,y,1); else tmp.SetPixelIndex(x,y,0); } } tmp.SetPaletteColor(0,0,0,0); tmp.SetPaletteColor(1,255,255,255); Transfer(tmp); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract RGB channels from the image. Each channel is an 8 bit grayscale image. * \param r,g,b: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitRGB(CxImage* r,CxImage* g,CxImage* b){ if (!pDib) return false; if (r==NULL && g==NULL && b==NULL) return false; CxImage tmpr(head.biWidth,head.biHeight,8); CxImage tmpg(head.biWidth,head.biHeight,8); CxImage tmpb(head.biWidth,head.biHeight,8); RGBQUAD color; for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ color = GetPixelColor(x,y); if (r) tmpr.SetPixelIndex(x,y,color.rgbRed); if (g) tmpg.SetPixelIndex(x,y,color.rgbGreen); if (b) tmpb.SetPixelIndex(x,y,color.rgbBlue); } } if (r) tmpr.SetGrayPalette(); if (g) tmpg.SetGrayPalette(); if (b) tmpb.SetGrayPalette(); /*for(long j=0; j<256; j++){ BYTE i=(BYTE)j; if (r) tmpr.SetPaletteColor(i,i,0,0); if (g) tmpg.SetPaletteColor(i,0,i,0); if (b) tmpb.SetPaletteColor(i,0,0,i); }*/ if (r) r->Transfer(tmpr); if (g) g->Transfer(tmpg); if (b) b->Transfer(tmpb); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract CMYK channels from the image. Each channel is an 8 bit grayscale image. * \param c,m,y,k: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k){ if (!pDib) return false; if (c==NULL && m==NULL && y==NULL && k==NULL) return false; CxImage tmpc(head.biWidth,head.biHeight,8); CxImage tmpm(head.biWidth,head.biHeight,8); CxImage tmpy(head.biWidth,head.biHeight,8); CxImage tmpk(head.biWidth,head.biHeight,8); RGBQUAD color; for(long yy=0; yy<head.biHeight; yy++){ for(long xx=0; xx<head.biWidth; xx++){ color = GetPixelColor(xx,yy); if (c) tmpc.SetPixelIndex(xx,yy,(BYTE)(255-color.rgbRed)); if (m) tmpm.SetPixelIndex(xx,yy,(BYTE)(255-color.rgbGreen)); if (y) tmpy.SetPixelIndex(xx,yy,(BYTE)(255-color.rgbBlue)); if (k) tmpk.SetPixelIndex(xx,yy,(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)); } } if (c) tmpc.SetGrayPalette(); if (m) tmpm.SetGrayPalette(); if (y) tmpy.SetGrayPalette(); if (k) tmpk.SetGrayPalette(); if (c) c->Transfer(tmpc); if (m) m->Transfer(tmpm); if (y) y->Transfer(tmpy); if (k) k->Transfer(tmpk); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract YUV channels from the image. Each channel is an 8 bit grayscale image. * \param y,u,v: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitYUV(CxImage* y,CxImage* u,CxImage* v){ if (!pDib) return false; if (y==NULL && u==NULL && v==NULL) return false; CxImage tmpy(head.biWidth,head.biHeight,8); CxImage tmpu(head.biWidth,head.biHeight,8); CxImage tmpv(head.biWidth,head.biHeight,8); RGBQUAD color; for(long yy=0; yy<head.biHeight; yy++){ for(long x=0; x<head.biWidth; x++){ color = RGBtoYUV(GetPixelColor(x,yy)); if (y) tmpy.SetPixelIndex(x,yy,color.rgbRed); if (u) tmpu.SetPixelIndex(x,yy,color.rgbGreen); if (v) tmpv.SetPixelIndex(x,yy,color.rgbBlue); } } if (y) tmpy.SetGrayPalette(); if (u) tmpu.SetGrayPalette(); if (v) tmpv.SetGrayPalette(); if (y) y->Transfer(tmpy); if (u) u->Transfer(tmpu); if (v) v->Transfer(tmpv); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract YIQ channels from the image. Each channel is an 8 bit grayscale image. * \param y,i,q: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitYIQ(CxImage* y,CxImage* i,CxImage* q){ if (!pDib) return false; if (y==NULL && i==NULL && q==NULL) return false; CxImage tmpy(head.biWidth,head.biHeight,8); CxImage tmpi(head.biWidth,head.biHeight,8); CxImage tmpq(head.biWidth,head.biHeight,8); RGBQUAD color; for(long yy=0; yy<head.biHeight; yy++){ for(long x=0; x<head.biWidth; x++){ color = RGBtoYIQ(GetPixelColor(x,yy)); if (y) tmpy.SetPixelIndex(x,yy,color.rgbRed); if (i) tmpi.SetPixelIndex(x,yy,color.rgbGreen); if (q) tmpq.SetPixelIndex(x,yy,color.rgbBlue); } } if (y) tmpy.SetGrayPalette(); if (i) tmpi.SetGrayPalette(); if (q) tmpq.SetGrayPalette(); if (y) y->Transfer(tmpy); if (i) i->Transfer(tmpi); if (q) q->Transfer(tmpq); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract XYZ channels from the image. Each channel is an 8 bit grayscale image. * \param x,y,z: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitXYZ(CxImage* x,CxImage* y,CxImage* z){ if (!pDib) return false; if (x==NULL && y==NULL && z==NULL) return false; CxImage tmpx(head.biWidth,head.biHeight,8); CxImage tmpy(head.biWidth,head.biHeight,8); CxImage tmpz(head.biWidth,head.biHeight,8); RGBQUAD color; for(long yy=0; yy<head.biHeight; yy++){ for(long xx=0; xx<head.biWidth; xx++){ color = RGBtoXYZ(GetPixelColor(xx,yy)); if (x) tmpx.SetPixelIndex(xx,yy,color.rgbRed); if (y) tmpy.SetPixelIndex(xx,yy,color.rgbGreen); if (z) tmpz.SetPixelIndex(xx,yy,color.rgbBlue); } } if (x) tmpx.SetGrayPalette(); if (y) tmpy.SetGrayPalette(); if (z) tmpz.SetGrayPalette(); if (x) x->Transfer(tmpx); if (y) y->Transfer(tmpy); if (z) z->Transfer(tmpz); return true;}/////////////////////////////////////////////////////////////////////////////////** * Extract HSL channels from the image. Each channel is an 8 bit grayscale image. * \param h,s,l: pointers to CxImage objects, to store the splited channels * \return true if everything is ok */bool CxImage::SplitHSL(CxImage* h,CxImage* s,CxImage* l){ if (!pDib) return false; if (h==NULL && s==NULL && l==NULL) return false; CxImage tmph(head.biWidth,head.biHeight,8); CxImage tmps(head.biWidth,head.biHeight,8); CxImage tmpl(head.biWidth,head.biHeight,8); RGBQUAD color; for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ color = RGBtoHSL(GetPixelColor(x,y)); if (h) tmph.SetPixelIndex(x,y,color.rgbRed); if (s) tmps.SetPixelIndex(x,y,color.rgbGreen); if (l) tmpl.SetPixelIndex(x,y,color.rgbBlue); } } if (h) tmph.SetGrayPalette(); if (s) tmps.SetGrayPalette(); if (l) tmpl.SetGrayPalette(); /* pseudo-color generator for hue channel (visual debug) if (h) for(long j=0; j<256; j++){ BYTE i=(BYTE)j; RGBQUAD hsl={120,240,i,0}; tmph.SetPaletteColor(i,HSLtoRGB(hsl)); }*/ if (h) h->Transfer(tmph); if (s) s->Transfer(tmps); if (l) l->Transfer(tmpl); return true;}////////////////////////////////////////////////////////////////////////////////#define HSLMAX 255 /* H,L, and S vary over 0-HSLMAX */#define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */ /* HSLMAX BEST IF DIVISIBLE BY 6 */ /* RGBMAX, HSLMAX must each fit in a BYTE. *//* Hue is undefined if Saturation is 0 (grey-scale) *//* This value determines where the Hue scrollbar is *//* initially set for achromatic colors */#define HSLUNDEFINED (HSLMAX*2/3)////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::RGBtoHSL(RGBQUAD lRGBColor){ BYTE R,G,B; /* input RGB values */ BYTE H,L,S; /* output HSL values */ BYTE cMax,cMin; /* max and min RGB values */ WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max*/ R = lRGBColor.rgbRed; /* get R, G, and B out of DWORD */ G = lRGBColor.rgbGreen; B = lRGBColor.rgbBlue; cMax = max( max(R,G), B); /* calculate lightness */ cMin = min( min(R,G), B); L = (BYTE)((((cMax+cMin)*HSLMAX)+RGBMAX)/(2*RGBMAX)); if (cMax==cMin){ /* r=g=b --> achromatic case */ S = 0; /* saturation */ H = HSLUNDEFINED; /* hue */ } else { /* chromatic case */ if (L <= (HSLMAX/2)) /* saturation */ S = (BYTE)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin)); else S = (BYTE)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin)); /* hue */ Rdelta = (WORD)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); Gdelta = (WORD)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); Bdelta = (WORD)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin)); if (R == cMax) H = (BYTE)(Bdelta - Gdelta); else if (G == cMax) H = (BYTE)((HSLMAX/3) + Rdelta - Bdelta); else /* B == cMax */ H = (BYTE)(((2*HSLMAX)/3) + Gdelta - Rdelta);// if (H < 0) H += HSLMAX; //always false if (H > HSLMAX) H -= HSLMAX; } RGBQUAD hsl={L,S,H,0}; return hsl;}////////////////////////////////////////////////////////////////////////////////float CxImage::HueToRGB(float n1,float n2, float hue){ //<F. Livraghi> fixed implementation for HSL2RGB routine float rValue; if (hue > 360) hue = hue - 360; else if (hue < 0) hue = hue + 360; if (hue < 60) rValue = n1 + (n2-n1)*hue/60.0f; else if (hue < 180) rValue = n2; else if (hue < 240) rValue = n1+(n2-n1)*(240-hue)/60; else rValue = n1; return rValue;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::HSLtoRGB(COLORREF cHSLColor){ return HSLtoRGB(RGBtoRGBQUAD(cHSLColor));}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::HSLtoRGB(RGBQUAD lHSLColor){ //<F. Livraghi> fixed implementation for HSL2RGB routine float h,s,l; float m1,m2; BYTE r,g,b; h = (float)lHSLColor.rgbRed * 360.0f/255.0f; s = (float)lHSLColor.rgbGreen/255.0f; l = (float)lHSLColor.rgbBlue/255.0f; if (l <= 0.5) m2 = l * (1+s); else m2 = l + s - l*s; m1 = 2 * l - m2; if (s == 0) { r=g=b=(BYTE)(l*255.0f); } else { r = (BYTE)(HueToRGB(m1,m2,h+120) * 255.0f); g = (BYTE)(HueToRGB(m1,m2,h) * 255.0f); b = (BYTE)(HueToRGB(m1,m2,h-120) * 255.0f); } RGBQUAD rgb = {b,g,r,0}; return rgb;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor){ int U,V,R,G,B; float Y = lYUVColor.rgbRed; U = lYUVColor.rgbGreen - 128; V = lYUVColor.rgbBlue - 128;// R = (int)(1.164 * Y + 2.018 * U);// G = (int)(1.164 * Y - 0.813 * V - 0.391 * U);// B = (int)(1.164 * Y + 1.596 * V); R = (int)( Y + 1.403f * V); G = (int)( Y - 0.344f * U - 0.714f * V); B = (int)( Y + 1.770f * U); R= min(255,max(0,R)); G= min(255,max(0,G)); B= min(255,max(0,B)); RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; return rgb;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor){ int Y,U,V,R,G,B; R = lRGBColor.rgbRed; G = lRGBColor.rgbGreen; B = lRGBColor.rgbBlue;// Y = (int)( 0.257 * R + 0.504 * G + 0.098 * B);// U = (int)( 0.439 * R - 0.368 * G - 0.071 * B + 128);// V = (int)(-0.148 * R - 0.291 * G + 0.439 * B + 128); Y = (int)(0.299f * R + 0.587f * G + 0.114f * B); U = (int)((B-Y) * 0.565f + 128); V = (int)((R-Y) * 0.713f + 128); Y= min(255,max(0,Y)); U= min(255,max(0,U)); V= min(255,max(0,V)); RGBQUAD yuv={(BYTE)V,(BYTE)U,(BYTE)Y,0}; return yuv;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor){ int I,Q,R,G,B; float Y = lYIQColor.rgbRed; I = lYIQColor.rgbGreen - 128; Q = lYIQColor.rgbBlue - 128; R = (int)( Y + 0.956f * I + 0.621f * Q); G = (int)( Y - 0.273f * I - 0.647f * Q); B = (int)( Y - 1.104f * I + 1.701f * Q); R= min(255,max(0,R)); G= min(255,max(0,G)); B= min(255,max(0,B)); RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; return rgb;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor){ int Y,I,Q,R,G,B; R = lRGBColor.rgbRed; G = lRGBColor.rgbGreen; B = lRGBColor.rgbBlue; Y = (int)( 0.2992f * R + 0.5868f * G + 0.1140f * B); I = (int)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128); Q = (int)( 0.2109f * R - 0.5229f * G + 0.3120f * B + 128); Y= min(255,max(0,Y)); I= min(255,max(0,I)); Q= min(255,max(0,Q)); RGBQUAD yiq={(BYTE)Q,(BYTE)I,(BYTE)Y,0}; return yiq;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor){ int X,Y,Z,R,G,B; X = lXYZColor.rgbRed; Y = lXYZColor.rgbGreen; Z = lXYZColor.rgbBlue; double k=1.088751; R = (int)( 3.240479f * X - 1.537150f * Y - 0.498535f * Z * k); G = (int)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k); B = (int)( 0.055648f * X - 0.204043f * Y + 1.057311f * Z * k); R= min(255,max(0,R)); G= min(255,max(0,G)); B= min(255,max(0,B)); RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0}; return rgb;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -