long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace) { if (!pDib) return 0; RGBQUAD color; if (red) memset(red,0,256*sizeof(long)); if (green) memset(green,0,256*sizeof(long)); if (blue) memset(blue,0,256*sizeof(long)); if (gray) memset(gray,0,256*sizeof(long)); 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 { switch (colorspace){ case 1: color = HSLtoRGB(GetPixelColor(x,y)); break; case 2: color = YUVtoRGB(GetPixelColor(x,y)); break; case 3: color = YIQtoRGB(GetPixelColor(x,y)); break; case 4: color = XYZtoRGB(GetPixelColor(x,y)); break; default: color = GetPixelColor(x,y); } if (red) red[color.rgbRed]++; if (green) green[color.rgbGreen]++; if (blue) blue[color.rgbBlue]++; if (gray) gray[(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++; } } } long n=0; for (int i=0; i<256; i++){ if (red && red[i]>n) n=red[i]; if (green && green[i]>n) n=green[i]; if (blue && blue[i]>n) n=blue[i]; if (gray && gray[i]>n) n=gray[i]; } return n; }
//////////////////////////////////////////////////////////////////////////////// // HistogramLog function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramLog() { if (!pDib) return false; //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|); int x, y, i; RGBQUAD color; RGBQUAD yuvClr; unsigned int YVal, high = 1; // Find Highest Luminance Value in the Image if( head.biClrUsed == 0 ){ // No Palette for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); for(x=0; x < head.biWidth; x++){ color = GetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } } else { // Palette for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor((BYTE)i); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } // Logarithm Operator double k = 255.0 / ::log( 1.0 + (double)high ); if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); for( x = 0; x < head.biWidth; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); color = YUVtoRGB( yuvClr ); SetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
/** * Adds to the selection all the pixels matching the specified color. */ bool CxImage::SelectionAddColor(RGBQUAD c) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; RECT localbox = {head.biWidth,0,0,head.biHeight}; for (long y = 0; y < head.biHeight; y++){ for (long x = 0; x < head.biWidth; x++){ RGBQUAD color = GetPixelColor(x, y); if (color.rgbRed == c.rgbRed && color.rgbGreen == c.rgbGreen && color.rgbBlue == c.rgbBlue) { pSelection[x + y * head.biWidth] = 255; // set the correct mask bit if (localbox.top < y) localbox.top = y; if (localbox.left > x) localbox.left = x; if (localbox.right < x) localbox.right = x; if (localbox.bottom > y) localbox.bottom = y; } } } if (info.rSelectionBox.top < localbox.top) info.rSelectionBox.top = localbox.top; if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; if (info.rSelectionBox.right < localbox.right) info.rSelectionBox.right = localbox.right; if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; return true; }
void ComplementScanLineColor(int x1, int x2, int y) { y = (MAX_MAP_HEIGHT - 1) - y; for(int x = x1; x <= x2; x++) { int color = GetPixelColor(x, y); SetPixelColor(x, y, A - color); } }
bool IsPixelValid(int x, int y, int old_color, int new_color, int boundary_color) { bool bValid = false; int color = GetPixelColor(x, y); if (color == old_color && color != new_color && color != boundary_color) { bValid = true; } return bValid; }
void FloodSeedFill(int x, int y, int old_color, int new_color) { if(GetPixelColor(x, y) == old_color) { SetPixelColor(x, y, new_color); for(int i = 0; i < COUNT_OF(direction_8); i++) { FloodSeedFill(x + direction_8[i].x_offset, y + direction_8[i].y_offset, old_color, new_color); } } }
/** * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image. * The background color can be selected using SetTransColor(). */ void CxImage::AlphaStrip() { bool bAlphaPaletteIsValid = AlphaPaletteIsValid(); bool bAlphaIsValid = AlphaIsValid(); if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return; RGBQUAD c; long a, a1; if (head.biBitCount==24){ for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ c=GetPixelColor(x,y); if (bAlphaIsValid) a=(AlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax; a1 = 255-a; c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)/255); c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)/255); c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)/255); SetPixelColor(x,y,c); } } AlphaDelete(); } else { CxImage tmp(head.biWidth,head.biHeight,24); if (!tmp.IsValid()) return; for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ c=GetPixelColor(x,y); if (bAlphaIsValid) a=(AlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax; if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255; a1 = 255-a; c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)/255); c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)/255); c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)/255); tmp.SetPixelColor(x,y,c); } } Transfer(tmp); } return; }
void BoundarySeedFill(int x, int y, int new_color, int boundary_color) { int curColor = GetPixelColor(x, y); if( (curColor != boundary_color) && (curColor != new_color) ) { SetPixelColor(x, y, new_color); for(int i = 0; i < COUNT_OF(direction_8); i++) { BoundarySeedFill(x + direction_8[i].x_offset, y + direction_8[i].y_offset, new_color, boundary_color); } } }
void BlendTev(u16 x, u16 y, u8 *color) { u32 dstClr; u32 offset = GetColorOffset(x, y); u8 *dstClrPtr = (u8*)&dstClr; GetPixelColor(offset, dstClrPtr); if (bpmem.blendmode.blendenable) { if (bpmem.blendmode.subtract) SubtractBlend(color, dstClrPtr); else BlendColor(color, dstClrPtr); } else if (bpmem.blendmode.logicopenable) { LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode); } else { dstClrPtr = color; } if (bpmem.dstalpha.enable) dstClrPtr[ALP_C] = bpmem.dstalpha.alpha; if (bpmem.blendmode.colorupdate) { if (bpmem.blendmode.alphaupdate) SetPixelAlphaColor(offset, dstClrPtr); else SetPixelColorOnly(offset, dstClrPtr); } else if (bpmem.blendmode.alphaupdate) { SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]); } // branchless bounding box update PixelEngine::bbox[0] = std::min(x, PixelEngine::bbox[0]); PixelEngine::bbox[1] = std::max(x, PixelEngine::bbox[1]); PixelEngine::bbox[2] = std::min(y, PixelEngine::bbox[2]); PixelEngine::bbox[3] = std::max(y, PixelEngine::bbox[3]); }
void BlendTev(u16 x, u16 y, u8 *color) { u32 dstClr; u32 offset = GetColorOffset(x, y); u8 *dstClrPtr = (u8*)&dstClr; GetPixelColor(offset, dstClrPtr); if (bpmem.blendmode.blendenable) { if (bpmem.blendmode.subtract) SubtractBlend(color, dstClrPtr); else BlendColor(color, dstClrPtr); } else if (bpmem.blendmode.logicopenable) { LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode); } else { dstClrPtr = color; } if (bpmem.dstalpha.enable) dstClrPtr[ALP_C] = bpmem.dstalpha.alpha; if (bpmem.blendmode.colorupdate) { if (bpmem.blendmode.alphaupdate) SetPixelAlphaColor(offset, dstClrPtr); else SetPixelColorOnly(offset, dstClrPtr); } else if (bpmem.blendmode.alphaupdate) { SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]); } // branchless bounding box update SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft; SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight; SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop; SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom; }
bool CxImage::AlphaPaletteSplit(CxImage *dest) { if (!AlphaPaletteIsValid() || !dest) return false; CxImage tmp(head.biWidth,head.biHeight,8); for(long y=0; y<head.biHeight; y++){ for(long x=0; x<head.biWidth; x++){ tmp.SetPixelIndex(x,y,GetPixelColor(x,y).rgbReserved); } } tmp.SetGrayPalette(); dest->Transfer(tmp); return true; }
void UpdateColorTexture() { u32 color; u8* colorPtr = (u8*)&color; u32* texturePtr = (u32*)efbColorTexture; u32 textureAddress = 0; u32 efbOffset = 0; for (u16 y = 0; y < EFB_HEIGHT; y++) { for (u16 x = 0; x < EFB_WIDTH; x++) { GetPixelColor(efbOffset, colorPtr); efbOffset += 3; texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA } } }
void CLoad3DS::CreateTexture(UINT textureArray[], LPSTR strFileName, int textureID) { if(!strFileName) return; CImage *img = new CImage; // 新建CImage对象 HRESULT hResult = img->Load(strFileName); // 读入图像文件 if(hResult == E_FAIL){ char error[255]; sprintf(error, "%s不存在", strFileName); MessageBox(NULL, error, "错误", MB_OK|MB_ICONINFORMATION); exit(0); } int width = img->GetWidth(); // 获取图像宽度 int height = img->GetHeight(); // 获取图像高度 GLubyte *image = new GLubyte[width * height * 3]; // 用于保存图像数据的数组 // 将图像数据读入image数组 for(int j = 0; j < height; j++){ for(int i = 0; i < width; i++){ int index = (j * width + i) * 3; RGBQUAD rgb = GetPixelColor(img, i, j); image[index] = rgb.rgbRed; image[index+1] = rgb.rgbGreen; image[index+2] = rgb.rgbBlue; } } delete img; // CImage对象已无用,数据已读入image数组 glGenTextures(1, &textureArray[textureID]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 图像每行数据紧密排列 glBindTexture(GL_TEXTURE_2D, textureArray[textureID]); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, width, height, GL_RGB, GL_UNSIGNED_BYTE, image); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); delete image; // 纹理数据已在显卡纹理内存中了,主机内存中的image已无用 }
/** * HistogramStretch * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels. * \return true if everything is ok * \author [dave] and [nipper] */ bool CxImage::HistogramStretch(long method) { if (!pDib) return false; if ((head.biBitCount==8) && IsGrayScale()){ // get min/max info BYTE minc = 255, maxc = 0; BYTE gray; long y; double dbScaler = 50.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { gray = GetPixelIndex(x, y); if (gray < minc) minc = gray; if (gray > maxc) maxc = gray; } } if (minc == 0 && maxc == 255) return true; // calculate LUT BYTE lut[256]; BYTE range = maxc - minc; if (range != 0){ for (long x = minc; x <= maxc; x++){ lut[x] = (BYTE)(255 * (x - minc) / range); } } else lut[minc] = minc; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(50.0+y*dbScaler); for (long x=0; x<head.biWidth; x++) { SetPixelIndex(x, y, lut[GetPixelIndex(x, y)]); } } } else { switch(method){ case 1: { // <nipper> // get min/max info BYTE minc = 255, maxc = 0; RGBQUAD color; long y; for (y=0; y<head.biHeight; y++) { for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); if (color.rgbRed < minc) minc = color.rgbRed; if (color.rgbBlue < minc) minc = color.rgbBlue; if (color.rgbGreen < minc) minc = color.rgbGreen; if (color.rgbRed > maxc) maxc = color.rgbRed; if (color.rgbBlue > maxc) maxc = color.rgbBlue; if (color.rgbGreen > maxc) maxc = color.rgbGreen; } } if (minc == 0 && maxc == 255) return true; // calculate LUT BYTE lut[256]; BYTE range = maxc - minc; if (range != 0){ for (long x = minc; x <= maxc; x++){ lut[x] = (BYTE)(255 * (x - minc) / range); } } else lut[minc] = minc; // normalize image double dbScaler = 100.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); color.rgbRed = lut[color.rgbRed]; color.rgbBlue = lut[color.rgbBlue]; color.rgbGreen = lut[color.rgbGreen]; SetPixelColor(x, y, color); } } } break; case 2: { // <nipper> // get min/max info BYTE minR = 255, maxR = 0; BYTE minG = 255, maxG = 0; BYTE minB = 255, maxB = 0; RGBQUAD color; long y; for (y=0; y<head.biHeight; y++) { for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); if (color.rgbRed < minR) minR = color.rgbRed; if (color.rgbBlue < minB) minB = color.rgbBlue; if (color.rgbGreen < minG) minG = color.rgbGreen; if (color.rgbRed > maxR) maxR = color.rgbRed; if (color.rgbBlue > maxB) maxB = color.rgbBlue; if (color.rgbGreen > maxG) maxG = color.rgbGreen; } } if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255) return true; // calculate LUT BYTE lutR[256]; BYTE range = maxR - minR; if (range != 0) { for (long x = minR; x <= maxR; x++){ lutR[x] = (BYTE)(255 * (x - minR) / range); } } else lutR[minR] = minR; BYTE lutG[256]; range = maxG - minG; if (range != 0) { for (long x = minG; x <= maxG; x++){ lutG[x] = (BYTE)(255 * (x - minG) / range); } } else lutG[minG] = minG; BYTE lutB[256]; range = maxB - minB; if (range != 0) { for (long x = minB; x <= maxB; x++){ lutB[x] = (BYTE)(255 * (x - minB) / range); } } else lutB[minB] = minB; // normalize image double dbScaler = 100.0/head.biHeight; for (y=0; y<head.biHeight; y++) { info.nProgress = (long)(y*dbScaler); for (long x=0; x<head.biWidth; x++) { color = GetPixelColor(x, y); color.rgbRed = lutR[color.rgbRed]; color.rgbBlue = lutB[color.rgbBlue]; color.rgbGreen = lutG[color.rgbGreen]; SetPixelColor(x, y, color); } } } break; default: { // <dave> // S = ( R - C ) ( B - A / D - C ) double alimit = 0.0; double blimit = 255.0; double lowerc = 255.0; double upperd = 0.0; double tmpGray; RGBQUAD color; RGBQUAD yuvClr; double stretcheds; if ( head.biClrUsed == 0 ){ long x, y, xmin, xmax, ymin, ymax; xmin = ymin = 0; xmax = head.biWidth; ymax = head.biHeight; for( y = ymin; y < ymax; y++ ){ info.nProgress = (long)(50*y/ymax); for( x = xmin; x < xmax; x++ ){ color = GetPixelColor( x, y ); tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if ( tmpGray < lowerc ) lowerc = tmpGray; if ( tmpGray > upperd ) upperd = tmpGray; } } if (upperd==lowerc) return false; for( y = ymin; y < ymax; y++ ){ info.nProgress = (long)(50+50*y/ymax); for( x = xmin; x < xmax; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV(color); // Stretch Luminance tmpGray = (double)yuvClr.rgbRed; stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; if ( stretcheds < 0.0 ) stretcheds = 0.0; else if ( stretcheds > 255.0 ) stretcheds = 255.0; yuvClr.rgbRed = (BYTE)stretcheds; color = YUVtoRGB(yuvClr); SetPixelColor( x, y, color ); } } } else { DWORD j; for( j = 0; j < head.biClrUsed; j++ ){ color = GetPaletteColor( (BYTE)j ); tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if ( tmpGray < lowerc ) lowerc = tmpGray; if ( tmpGray > upperd ) upperd = tmpGray; } if (upperd==lowerc) return false; for( j = 0; j < head.biClrUsed; j++ ){ color = GetPaletteColor( (BYTE)j ); yuvClr = RGBtoYUV( color ); // Stretch Luminance tmpGray = (double)yuvClr.rgbRed; stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit; if ( stretcheds < 0.0 ) stretcheds = 0.0; else if ( stretcheds > 255.0 ) stretcheds = 255.0; yuvClr.rgbRed = (BYTE)stretcheds; color = YUVtoRGB(yuvClr); SetPaletteColor( (BYTE)j, color ); } } } } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramNormalize function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramNormalize() { if (!pDib) return false; int histogram[256]; int threshold_intensity, intense; int x, y, i; unsigned int normalize_map[256]; unsigned int high, low, YVal; RGBQUAD color; RGBQUAD yuvClr; memset( &histogram, 0, sizeof( int ) * 256 ); memset( &normalize_map, 0, sizeof( unsigned int ) * 256 ); // form histogram for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); for(x=0; x < head.biWidth; x++){ color = GetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); histogram[YVal]++; } } // find histogram boundaries by locating the 1 percent levels threshold_intensity = ( head.biWidth * head.biHeight) / 100; intense = 0; for( low = 0; low < 255; low++ ){ intense += histogram[low]; if( intense > threshold_intensity ) break; } intense = 0; for( high = 255; high != 0; high--){ intense += histogram[ high ]; if( intense > threshold_intensity ) break; } if ( low == high ){ // Unreasonable contrast; use zero threshold to determine boundaries. threshold_intensity = 0; intense = 0; for( low = 0; low < 255; low++){ intense += histogram[low]; if( intense > threshold_intensity ) break; } intense = 0; for( high = 255; high != 0; high-- ){ intense += histogram [high ]; if( intense > threshold_intensity ) break; } } if( low == high ) return false; // zero span bound // Stretch the histogram to create the normalized image mapping. for(i = 0; i <= 255; i++){ if ( i < (int) low ){ normalize_map[i] = 0; } else { if(i > (int) high) normalize_map[i] = 255; else normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low ); } } // Normalize if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); for( x = 0; x < head.biWidth; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; color = YUVtoRGB( yuvClr ); SetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramEqualize function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramEqualize() { if (!pDib) return false; int histogram[256]; int map[256]; int equalize_map[256]; int x, y, i, j; RGBQUAD color; RGBQUAD yuvClr; unsigned int YVal, high, low; memset( &histogram, 0, sizeof(int) * 256 ); memset( &map, 0, sizeof(int) * 256 ); memset( &equalize_map, 0, sizeof(int) * 256 ); // form histogram for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); for(x=0; x < head.biWidth; x++){ color = GetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); histogram[YVal]++; } } // integrate the histogram to get the equalization map. j = 0; for(i=0; i <= 255; i++){ j += histogram[i]; map[i] = j; } // equalize low = map[0]; high = map[255]; if (low == high) return false; for( i = 0; i <= 255; i++ ){ equalize_map[i] = (unsigned int)((((double)( map[i] - low ) ) * 255) / ( high - low ) ); } // stretch the histogram if(head.biClrUsed == 0){ // No Palette for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); for( x = 0; x < head.biWidth; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV(color); yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; color = YUVtoRGB(yuvClr); SetPixelColor( x, y, color ); } } } else { // Palette for( i = 0; i < (int)head.biClrUsed; i++ ){ color = GetPaletteColor((BYTE)i); yuvClr = RGBtoYUV(color); yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; color = YUVtoRGB(yuvClr); SetPaletteColor( (BYTE)i, color ); } } return true; }
//////////////////////////////////////////////////////////////////////////////// // HistogramRoot function by <dave> : dave(at)posortho(dot)com bool CxImage::HistogramRoot() { if (!pDib) return false; //q(i,j) = sqrt(|p(i,j)|); int x, y, i; RGBQUAD color; RGBQUAD yuvClr; double dtmp; unsigned int YVal, high = 1; // Find Highest Luminance Value in the Image if( head.biClrUsed == 0 ){ // No Palette for(y=0; y < head.biHeight; y++){ info.nProgress = (long)(50*y/head.biHeight); if (info.nEscape) break; for(x=0; x < head.biWidth; x++){ color = GetPixelColor( x, y ); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } } else { // Palette for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor((BYTE)i); YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); if (YVal > high ) high = YVal; } } // Root Operator double k = 128.0 / ::log( 1.0 + (double)high ); if( head.biClrUsed == 0 ){ for( y = 0; y < head.biHeight; y++ ){ info.nProgress = (long)(50+50*y/head.biHeight); if (info.nEscape) break; for( x = 0; x < head.biWidth; x++ ){ color = GetPixelColor( x, y ); yuvClr = RGBtoYUV( color ); dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); if ( dtmp > 255.0 ) dtmp = 255.0; if ( dtmp < 0 ) dtmp = 0; yuvClr.rgbRed = (BYTE)dtmp; color = YUVtoRGB( yuvClr ); SetPixelColor( x, y, color ); } } } else { for(i = 0; i < (int)head.biClrUsed; i++){ color = GetPaletteColor( (BYTE)i ); yuvClr = RGBtoYUV( color ); dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); if ( dtmp > 255.0 ) dtmp = 255.0; if ( dtmp < 0 ) dtmp = 0; yuvClr.rgbRed = (BYTE)dtmp; color = YUVtoRGB( yuvClr ); SetPaletteColor( (BYTE)i, color ); } } return true; }
bool CxImageJ2K::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; if (head.biClrUsed!=0 && !IsGrayScale()){ strcpy(info.szLastError,"J2K can save only RGB or GrayScale images"); return false; } int i,x,y; j2k_image_t *img; j2k_cp_t *cp; j2k_tcp_t *tcp; j2k_tccp_t *tccp; img = (j2k_image_t *)calloc(sizeof(j2k_image_t),1); cp = (j2k_cp_t *)calloc(sizeof(j2k_cp_t),1); cp->tx0=0; cp->ty0=0; cp->tw=1; cp->th=1; cp->tcps=(j2k_tcp_t*)calloc(sizeof(j2k_tcp_t),1); tcp=&cp->tcps[0]; long w=head.biWidth; long h=head.biHeight; tcp->numlayers=1; for (i=0;i<tcp->numlayers;i++) tcp->rates[i]=(w*h*GetJpegQuality())/600; if (IsGrayScale()) { img->x0=0; img->y0=0; img->x1=w; img->y1=h; img->numcomps=1; img->comps=(j2k_comp_t*)calloc(sizeof(j2k_comp_t),1); img->comps[0].data=(int*)calloc(w*h*sizeof(int),1); img->comps[0].prec=8; img->comps[0].sgnd=0; img->comps[0].dx=1; img->comps[0].dy=1; for (i=0,y=0; y<h; y++) { for (x=0; x<w; x++,i++){ img->comps[0].data[i]=GetPixelIndex(x,h-1-y); } } } else if (!IsIndexed()) { img->x0=0; img->y0=0; img->x1=w; img->y1=h; img->numcomps=3; img->comps=(j2k_comp_t*)calloc(img->numcomps*sizeof(j2k_comp_t),1); for (i=0; i<img->numcomps; i++) { img->comps[i].data=(int*)calloc(w*h*sizeof(int),1); img->comps[i].prec=8; img->comps[i].sgnd=0; img->comps[i].dx=1; img->comps[i].dy=1; } RGBQUAD c; for (i=0,y=0; y<h; y++) { for (x=0; x<w; x++,i++){ c=GetPixelColor(x,h-1-y); img->comps[0].data[i]=c.rgbRed; img->comps[1].data[i]=c.rgbGreen; img->comps[2].data[i]=c.rgbBlue; } } } else { return 0; } cp->tdx=img->x1-img->x0; cp->tdy=img->y1-img->y0; tcp->csty=0; tcp->prg=0; tcp->mct=img->numcomps==3?1:0; tcp->tccps=(j2k_tccp_t*)calloc(img->numcomps*sizeof(j2k_tccp_t),1); int ir=0; /* or 1 ???*/ for (i=0; i<img->numcomps; i++) { tccp=&tcp->tccps[i]; tccp->csty=0; tccp->numresolutions=6; tccp->cblkw=6; tccp->cblkh=6; tccp->cblksty=0; tccp->qmfbid=ir?0:1; tccp->qntsty=ir?J2K_CCP_QNTSTY_SEQNT:J2K_CCP_QNTSTY_NOQNT; tccp->numgbits=2; tccp->roishift=0; j2k_calc_explicit_stepsizes(tccp, img->comps[i].prec); } BYTE* dest=(BYTE*)calloc(tcp->rates[tcp->numlayers-1]+2,1); long len = j2k_encode(img, cp, dest, tcp->rates[tcp->numlayers-1]+2); if (len==0) { strcpy(info.szLastError,"J2K failed to encode image"); } else { hFile->Write(dest, len, 1); } free(dest); j2k_destroy(&img,&cp); return (len!=0); }
bool CxImagePCX::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; try { PCXHEADER pcxHeader; memset(&pcxHeader,0,sizeof(pcxHeader)); pcxHeader.Manufacturer = PCX_MAGIC; pcxHeader.Version = 5; pcxHeader.Encoding = 1; pcxHeader.Xmin = 0; pcxHeader.Ymin = 0; pcxHeader.Xmax = (WORD)head.biWidth-1; pcxHeader.Ymax = (WORD)head.biHeight-1; pcxHeader.Hres = (WORD)info.xDPI; pcxHeader.Vres = (WORD)info.yDPI; pcxHeader.Reserved = 0; pcxHeader.PaletteType = head.biClrUsed==0; switch(head.biBitCount){ case 24: case 8: { pcxHeader.BitsPerPixel = 8; pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1; #if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4; #endif //CXIMAGE_SUPPORT_ALPHA pcxHeader.BytesPerLine = (WORD)head.biWidth; break; } default: //(4 1) pcxHeader.BitsPerPixel = 1; pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1; pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3); } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0; pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255; } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){ RGBQUAD c; for (int i = 0; i < 16; i++){ c=GetPaletteColor(i); pcxHeader.ColorMap[i][0] = c.rgbRed; pcxHeader.ColorMap[i][1] = c.rgbGreen; pcxHeader.ColorMap[i][2] = c.rgbBlue; } } pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1); if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 ) throw "cannot write PCX header"; CxMemFile buffer; buffer.Open(); BYTE c,n; long x,y; if (head.biClrUsed==0){ for (y = head.biHeight-1; y >=0 ; y--){ for (int p=0; p<pcxHeader.ColorPlanes; p++){ c=n=0; for (x = 0; x<head.biWidth; x++){ if (p==0) PCX_PackPixels(GetPixelColor(x,y).rgbRed,c,n,buffer); else if (p==1) PCX_PackPixels(GetPixelColor(x,y).rgbGreen,c,n,buffer); else if (p==2) PCX_PackPixels(GetPixelColor(x,y).rgbBlue,c,n,buffer); #if CXIMAGE_SUPPORT_ALPHA else if (p==3) PCX_PackPixels(AlphaGet(x,y),c,n,buffer); #endif //CXIMAGE_SUPPORT_ALPHA } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } else if (head.biBitCount==8) { for (y = head.biHeight-1; y >=0 ; y--){ c=n=0; for (x = 0; x<head.biWidth; x++){ PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer); } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); if (head.biBitCount == 8){ hFile->PutC(0x0C); BYTE* pal = (BYTE*)malloc(768); RGBQUAD c; for (int i=0;i<256;i++){ c=GetPaletteColor(i); pal[3*i+0] = c.rgbRed; pal[3*i+1] = c.rgbGreen; pal[3*i+2] = c.rgbBlue; } hFile->Write(pal,768,1); free(pal); } } else { //(head.biBitCount==4) || (head.biBitCount==1) RGBQUAD *rgb = GetPalette(); bool binvert = false; if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1); BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine); BYTE* raw = (BYTE*)malloc(head.biWidth); for(y = head.biHeight-1; y >=0 ; y--) { for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y); if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x]; for( x = 0; x < pcxHeader.ColorPlanes; x++ ) { PCX_PixelsToPlanes(raw, head.biWidth, plane, x); PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer); } } free(plane); free(raw); hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; }
bool CxImageICO::Decode(CxFile *hFile) { if (hFile==NULL) return false; DWORD off = hFile->Tell(); //<yuandi> int page=info.nFrame; //internal icon structure indexes // read the first part of the header ICONHEADER icon_header; hFile->Read(&icon_header,sizeof(ICONHEADER),1); icon_header.idType = my_ntohs(icon_header.idType); icon_header.idCount = my_ntohs(icon_header.idCount); // check if it's an icon or a cursor if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) { info.nNumFrames = icon_header.idCount; // load the icon descriptions ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY)); int c; for (c = 0; c < icon_header.idCount; c++) { hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1); icon_list[c].wPlanes = my_ntohs(icon_list[c].wPlanes); icon_list[c].wBitCount = my_ntohs(icon_list[c].wBitCount); icon_list[c].dwBytesInRes = my_ntohl(icon_list[c].dwBytesInRes); icon_list[c].dwImageOffset = my_ntohl(icon_list[c].dwImageOffset); } if ((page>=0)&&(page<icon_header.idCount)){ if (info.nEscape == -1) { // Return output dimensions only head.biWidth = icon_list[page].bWidth; head.biHeight = icon_list[page].bHeight; #if CXIMAGE_SUPPORT_PNG if (head.biWidth==0 && head.biHeight==0) { // Vista icon support hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET); CxImage png; png.SetEscape(-1); if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){ Transfer(png); info.nNumFrames = icon_header.idCount; } } #endif //CXIMAGE_SUPPORT_PNG free(icon_list); info.dwType = CXIMAGE_FORMAT_ICO; return true; } // get the bit count for the colors in the icon <CoreyRLucier> BITMAPINFOHEADER bih; hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET); if (icon_list[page].bWidth==0 && icon_list[page].bHeight==0) { // Vista icon support #if CXIMAGE_SUPPORT_PNG CxImage png; if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){ Transfer(png); info.nNumFrames = icon_header.idCount; } SetType(CXIMAGE_FORMAT_ICO); #endif //CXIMAGE_SUPPORT_PNG } else { // standard icon hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1); bihtoh(&bih); c = bih.biBitCount; // allocate memory for one icon Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO); //image creation // read the palette RGBQUAD pal[256]; if (bih.biClrUsed) hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1); else hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1); SetPalette(pal,head.biClrUsed); //palette assign //read the icon if (c<=24){ hFile->Read(info.pImage, head.biSizeImage, 1); } else { // 32 bit icon BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth); BYTE* src = buf; hFile->Read(buf, 4*head.biHeight*head.biWidth, 1); #if CXIMAGE_SUPPORT_ALPHA if (!AlphaIsValid()) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA for (long y = 0; y < head.biHeight; y++) { BYTE* dst = GetBits(y); for(long x=0;x<head.biWidth;x++){ *dst++=src[0]; *dst++=src[1]; *dst++=src[2]; #if CXIMAGE_SUPPORT_ALPHA AlphaSet(x,y,src[3]); #endif //CXIMAGE_SUPPORT_ALPHA src+=4; } } free(buf); } // apply the AND and XOR masks int maskwdt = ((head.biWidth+31) / 32) * 4; //line width of AND mask (always 1 Bpp) int masksize = head.biHeight * maskwdt; //size of mask BYTE *mask = (BYTE *)malloc(masksize); if (hFile->Read(mask, masksize, 1)){ bool bGoodMask=false; for (int im=0;im<masksize;im++){ if (mask[im]!=255){ bGoodMask=true; break; } } if (bGoodMask && c != 32){ #if CXIMAGE_SUPPORT_ALPHA bool bNeedAlpha = false; if (!AlphaIsValid()){ AlphaCreate(); } else { bNeedAlpha=true; //32bit icon } int x,y; for (y = 0; y < head.biHeight; y++) { for (x = 0; x < head.biWidth; x++) { if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){ AlphaSet(x,y,0); bNeedAlpha=true; } } } if (!bNeedAlpha) AlphaDelete(); #endif //CXIMAGE_SUPPORT_ALPHA //check if there is only one transparent color RGBQUAD cc,ct; long* pcc = (long*)&cc; long* pct = (long*)&ct; int nTransColors=0; int nTransIndex=0; for (y = 0; y < head.biHeight; y++){ for (x = 0; x < head.biWidth; x++){ if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){ cc = GetPixelColor(x,y,false); if (nTransColors==0){ nTransIndex = GetPixelIndex(x,y); nTransColors++; ct = cc; } else { if (*pct!=*pcc){ nTransColors++; } } } } } if (nTransColors==1){ SetTransColor(ct); SetTransIndex(nTransIndex); #if CXIMAGE_SUPPORT_ALPHA AlphaDelete(); //because we have a unique transparent color in the image #endif //CXIMAGE_SUPPORT_ALPHA } // <vho> - Transparency support w/o Alpha support if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha). // find a color index, which is not used in the image // it is almost sure to find one, bcs. nobody uses all possible colors for an icon BYTE colorsUsed[256]; memset(colorsUsed, 0, sizeof(colorsUsed)); for (y = 0; y < head.biHeight; y++){ for (x = 0; x < head.biWidth; x++){ colorsUsed[BlindGetPixelIndex(x,y)] = 1; } } int iTransIdx = -1; for (x = (int)(head.biClrUsed-1); x>=0 ; x--){ if (colorsUsed[x] == 0){ iTransIdx = x; // this one is not in use. we may use it as transparent color break; } } // Go thru image and set unused color as transparent index if needed if (iTransIdx >= 0){ bool bNeedTrans = false; for (y = 0; y < head.biHeight; y++){ for (x = 0; x < head.biWidth; x++){ // AND mask (Each Byte represents 8 Pixels) if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){ // AND mask is set (!=0). This is a transparent part SetPixelIndex(x, y, (BYTE)iTransIdx); bNeedTrans = true; } } } // set transparent index if needed if (bNeedTrans) SetTransIndex(iTransIdx); #if CXIMAGE_SUPPORT_ALPHA AlphaDelete(); //because we have a transparent color in the palette #endif //CXIMAGE_SUPPORT_ALPHA } } } else if(c != 32){
void GetColor(u16 x, u16 y, u8 *color) { u32 offset = GetColorOffset(x, y); GetPixelColor(offset, color); }
bool PlayerWindow::IsBattleHappens() const { const DWORD color = GetPixelColor(GetFlashHwnd(), WindowSize.cx - 20, WindowSize.cy - 11); return bool(color == 0xFFFFFF); }
bool CxImageICO::Decode(CxFile *hFile) { if (hFile==NULL) return false; DWORD off = hFile->Tell(); //<yuandi> int page=info.nFrame; //internal icon structure indexes // read the first part of the header ICONHEADER icon_header; hFile->Read(&icon_header,sizeof(ICONHEADER),1); // check if it's an icon if ((icon_header.idReserved == 0) && (icon_header.idType == 1)) { info.nNumFrames = icon_header.idCount; // load the icon descriptions ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY)); int c; for (c = 0; c < icon_header.idCount; c++) hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1); if ((info.nFrame>=0)&&(info.nFrame<icon_header.idCount)){ // get the bit count for the colors in the icon <CoreyRLucier> BITMAPINFOHEADER bih; hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET); hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1); c = bih.biBitCount; // allocate memory for one icon Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO); //image creation // read the palette RGBQUAD pal[256]; hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1); SetPalette(pal,head.biClrUsed); //palette assign //read the icon if (c<=24){ hFile->Read(info.pImage, head.biSizeImage, 1); } else { // 32 bit icon BYTE* dst = info.pImage; BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth); BYTE* src = buf; hFile->Read(buf, 4*head.biHeight*head.biWidth, 1); #if CXIMAGE_SUPPORT_ALPHA if (!AlphaIsValid()) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA for (long y = 0; y < head.biHeight; y++) { for(long x=0;x<head.biWidth;x++){ *dst++=src[0]; *dst++=src[1]; *dst++=src[2]; #if CXIMAGE_SUPPORT_ALPHA AlphaSet(x,y,src[3]); #endif //CXIMAGE_SUPPORT_ALPHA src+=4; } } free(buf); } // apply the AND and XOR masks int maskwdt = ((head.biWidth+31) / 32) * 4; //line width of AND mask (always 1 Bpp) int masksize = head.biHeight * maskwdt; //size of mask BYTE *mask = (BYTE *)malloc(masksize); if (hFile->Read(mask, masksize, 1)){ #if CXIMAGE_SUPPORT_ALPHA bool bNeedAlpha = false; if (!AlphaIsValid()){ AlphaCreate(); AlphaSet(255); } else { bNeedAlpha=true; //32bit icon } for (int y = 0; y < head.biHeight; y++) { for (int x = 0; x < head.biWidth; x++) { if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){ AlphaSet(x,y,0); bNeedAlpha=true; } } } if (!bNeedAlpha) AlphaDelete(); #endif //CXIMAGE_SUPPORT_ALPHA if (c==24){ //check if there is only one transparent color RGBQUAD cc,ct; long* pcc = (long*)&cc; long* pct = (long*)&ct; int nTransColors=0; for (int y = 0; y < head.biHeight; y++){ for (int x = 0; x < head.biWidth; x++){ if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){ cc = GetPixelColor(x,y); if (nTransColors==0){ nTransColors++; ct = cc; } else { if (*pct!=*pcc){ nTransColors++; } } } } } if (nTransColors==1){ SetTransColor(ct); SetTransIndex(0); #if CXIMAGE_SUPPORT_ALPHA AlphaDelete(); //because we have a unique transparent color in the image #endif //CXIMAGE_SUPPORT_ALPHA } }