📄 gimage.cpp
字号:
/* Copyright (C) 2006, Mike Gashler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. see http://www.gnu.org/copyleft/lesser.html*/#include "GImage.h"#include "GBitTable.h"#include <math.h>#include "GMacros.h"#include <stdlib.h>#include "GCompress.h"#include "GBezier.h"#include "GRayTrace.h"#include "GHardFont.h"#include "GPNG.h"#include "GBits.h"#include "GFile.h"#ifdef WIN32#include <windows.h>#else // WIN32typedef unsigned int DWORD;typedef long LONG;typedef short WORD;#pragma pack(1)typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant;} BITMAPINFOHEADER;typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER, *PBITMAPFILEHEADER; #pragma pack()#endif // not WIN32GImage::GImage(){ m_pPixels = NULL; m_nWidth = 0; m_nHeight = 0;}GImage::~GImage(){ delete[] m_pPixels;}void GImage::SetSize(int nWidth, int nHeight){ if(nWidth == (int)m_nWidth && nHeight == (int)m_nHeight) return; delete(m_pPixels); if(nWidth == 0 || nHeight == 0) m_pPixels = NULL; else { unsigned int nSize = nWidth * nHeight; m_pPixels = new GColor[nSize]; memset(m_pPixels, '\0', nSize * sizeof(GColor)); } m_nWidth = nWidth; m_nHeight = nHeight;}void GImage::CopyImage(GImage* pSourceImage){ SetSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()); memcpy(m_pPixels, pSourceImage->GetRGBQuads(), m_nWidth * m_nHeight * sizeof(GColor));}void GImage::CopyImage(GImage* pSourceImage, int nLeft, int nTop, int nRight, int nBottom){ int nWidth = nRight - nLeft + 1; int nHeight = nBottom - nTop + 1; SetSize(nWidth, nHeight); int x, y; GColor c; for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { c = pSourceImage->GetPixel(x + nLeft, y + nTop); SetPixel(x, y, c); } }}void GImage::Clear(GColor color){ unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; for(nPos = 0; nPos < nSize; nPos++) m_pPixels[nPos] = color;}void GImage::SoftSetPixel(int nX, int nY, GColor color, double dOpacity){ GColor cOld = GetPixel(nX, nY); GColor c = gRGB( (unsigned char)((1 - dOpacity) * gRed(cOld) + dOpacity * gRed(color)), (unsigned char)((1 - dOpacity) * gGreen(cOld) + dOpacity * gGreen(color)), (unsigned char)((1 - dOpacity) * gBlue(cOld) + dOpacity * gBlue(color))); SetPixel(nX, nY, c);}void GImage::SafeSetPixel(int nX, int nY, GColor color){ if(nX < 0 || nX >= (int)m_nWidth) return; if(nY < 0 || nY >= (int)m_nHeight) return; SetPixel(nX, nY, color);}GColor GImage::SafeGetPixel(int nX, int nY){ if(nX >= 0 && nX < (int)m_nWidth && nY >= 0 && nY < (int)m_nHeight) return GetPixel(nX, nY); else return 0;}GColor GImage::InterpolatePixel(float dX, float dY){ int nX = (int)dX; int nY = (int)dY; float dXDif = dX - nX; float dYDif = dY - nY; GColor c1; GColor c2; c1 = SafeGetPixel(nX, nY); c2 = SafeGetPixel(nX + 1, nY); float dA1 = dXDif * (float)gAlpha(c2) + (1 - dXDif) * (float)gAlpha(c1); float dR1 = dXDif * (float)gRed(c2) + (1 - dXDif) * (float)gRed(c1); float dG1 = dXDif * (float)gGreen(c2) + (1 - dXDif) * (float)gGreen(c1); float dB1 = dXDif * (float)gBlue(c2) + (1 - dXDif) * (float)gBlue(c1); c1 = SafeGetPixel(nX, nY + 1); c2 = SafeGetPixel(nX + 1, nY + 1); float dA2 = dXDif * (float)gAlpha(c2) + (1 - dXDif) * (float)gAlpha(c1); float dR2 = dXDif * (float)gRed(c2) + (1 - dXDif) * (float)gRed(c1); float dG2 = dXDif * (float)gGreen(c2) + (1 - dXDif) * (float)gGreen(c1); float dB2 = dXDif * (float)gBlue(c2) + (1 - dXDif) * (float)gBlue(c1); return gARGB((int)(dYDif * dA2 + (1 - dYDif) * dA1), (int)(dYDif * dR2 + (1 - dYDif) * dR1), (int)(dYDif * dG2 + (1 - dYDif) * dG1), (int)(dYDif * dB2 + (1 - dYDif) * dB1));}bool GImage::LoadFile(const char* szFilename){ int nLen = strlen(szFilename); if(nLen < 4) return false; const char* szExt = szFilename + nLen - 4; if(stricmp(szExt, ".png") == 0) return LoadPNGFile(szFilename); else if(stricmp(szExt, ".bmp") == 0) return LoadBMPFile(szFilename); else if(stricmp(szExt, ".ppm") == 0) return LoadPPMFile(szFilename); else if(stricmp(szExt, ".pgm") == 0) return LoadPGMFile(szFilename); else return false;}bool GImage::LoadPPMFile(const char* szFilename){ GAssert(szFilename, "no filename"); FILE* pFile = fopen(szFilename, "rb"); if(!pFile) return false; char pBuff[2]; if(fread(pBuff, 2, 1, pFile) != 1) { fclose(pFile); return false; } if(pBuff[0] != 'P' && pBuff[0] != 'p') { fclose(pFile); return false; } bool bRet = false; if(pBuff[1] == '3') bRet = LoadPixMap(pFile, true, false); else if(pBuff[1] == '6') bRet = LoadPixMap(pFile, false, false); fclose(pFile); return bRet;}bool GImage::LoadPixMap(FILE* pFile, bool bTextData, bool bGrayScale){ GAssert(pFile, "no file"); int n; // Read past any white space and skip comments while(true) { n = fgetc(pFile); if(n == '#') { while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n == '\n') break; } } if(n == EOF) return false; if(n > 32) break; } // Read until the next white space to get width char pBuff[16]; pBuff[0] = n; int nPos = 1; while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n <= 32) break; pBuff[nPos] = n; nPos++; if(nPos >= 16) return false; } pBuff[nPos] = '\0'; int nWidth = atoi(pBuff); if(nWidth < 1) return false; // Read past any white space and skip comments while(true) { n = fgetc(pFile); if(n == '#') { while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n == '\n') break; } } if(n == EOF) return false; if(n > 32) break; } // Read until the next white space to get height pBuff[0] = n; nPos = 1; while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n <= 32) break; pBuff[nPos] = n; nPos++; if(nPos >= 16) return false; } pBuff[nPos] = '\0'; int nHeight = atoi(pBuff); if(nHeight < 1) return false; // Read past any white space and skip comments while(true) { n = fgetc(pFile); if(n == '#') { while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n == '\n') break; } } if(n == EOF) return false; if(n > 32) break; } // Read until the next white space to get range pBuff[0] = n; nPos = 1; while(true) { n = fgetc(pFile); if(n == EOF) return false; if(n <= 32) break; pBuff[nPos] = n; nPos++; if(nPos >= 16) return false; } pBuff[nPos] = '\0'; int nRange = atoi(pBuff) + 1; if(nRange < 2) return false; // Read the data SetSize(nWidth, nHeight); if(bTextData) { return false; } else { int x; int y; unsigned int nRed; unsigned int nGreen; unsigned int nBlue; for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { if(bGrayScale) { if(fread(pBuff, 1, 1, pFile) != 1) return false; nRed = (pBuff[0] << 8) / nRange; nGreen = (pBuff[0] << 8) / nRange; nBlue = (pBuff[0] << 8) / nRange; } else { if(fread(pBuff, 3, 1, pFile) != 1) return false; nRed = (pBuff[0] << 8) / nRange; nGreen = (pBuff[1] << 8) / nRange; nBlue = (pBuff[2] << 8) / nRange; } SetPixel(x, y, gRGB(nRed, nGreen, nBlue)); } } } return true;}bool GImage::LoadPGMFile(const char* szFilename){ GAssert(szFilename, "no filename"); FILE* pFile = fopen(szFilename, "rb"); if(!pFile) return false; char pBuff[2]; if(fread(pBuff, 2, 1, pFile) != 1) { fclose(pFile); return false; } if(pBuff[0] != 'P' && pBuff[0] != 'p') { fclose(pFile); return false; } bool bRet = false; if(pBuff[1] == '2') bRet = LoadPixMap(pFile, true, true); else if(pBuff[1] == '5') bRet = LoadPixMap(pFile, false, true); fclose(pFile); return bRet;}bool GImage::SavePixMap(FILE* pFile, bool bTextData, bool bGrayScale){ // Write header junk char szBuff[24]; itoa(m_nWidth, szBuff, 10); fputs(szBuff, pFile); fputs(" ", pFile); itoa(m_nHeight, szBuff, 10); fputs(szBuff, pFile); fputs("\n255\n", pFile); // Write pixel data int x; int y; GColor col; for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { if(bGrayScale) { col = GetPixel(x, y); unsigned char nGray = (77 * (int)gRed(col) + 150 * (int)gGreen(col) + 29 * (int)gBlue(col)) >> 8; if(fwrite(&nGray, 1, 1, pFile) != 1) return false; } else { col = GetPixel(x, y); int n; n = gRed(col); if(fwrite(&n, 1, 1, pFile) != 1) return false; n = gGreen(col); if(fwrite(&n, 1, 1, pFile) != 1) return false; n = gBlue(col); if(fwrite(&n, 1, 1, pFile) != 1) return false; } } } return true;}bool GImage::SavePPMFile(const char* szFilename){ FILE* pFile = fopen(szFilename, "wb"); if(!pFile) return false; if(fputs("P6\n", pFile) == EOF) return false; bool bRet = SavePixMap(pFile, false, false); fclose(pFile); return bRet;}bool GImage::SavePGMFile(const char* szFilename){ FILE* pFile = fopen(szFilename, "wb"); if(!pFile) return false; if(fputs("P5\n", pFile) == EOF) return false; bool bRet = SavePixMap(pFile, false, true); fclose(pFile); return bRet;}inline GColor ColorToGrayScale(GColor c){ int nGray = (77 * gRed(c) + 150 * gGreen(c) + 29 * gBlue(c)) >> 8; return gRGB(nGray, nGray, nGray);}void GImage::ConvertToGrayScale(){ unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; for(nPos = 0; nPos < nSize; nPos++) m_pPixels[nPos] = ColorToGrayScale(m_pPixels[nPos]);}void GImage::CreateBrightnessHistogram(GImage* pOutImage){ // Create the histogram data unsigned int pnHistData[256]; int n; for(n = 0; n < 256; n++) pnHistData[n] = 0; unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; unsigned int nGray; unsigned int nMaxValue = 0; for(nPos = 0; nPos < nSize; nPos++) { nGray = ColorToGrayScale(m_pPixels[nPos]); pnHistData[nGray]++; if(pnHistData[nGray] > nMaxValue) nMaxValue = pnHistData[nGray]; } // turn it into a picture pOutImage->SetSize(256, 256); pOutImage->Clear(gRGB(220, 220, 180)); int x; int y; for(x = 0; x < 256; x++) { int nHeight = pnHistData[x] * 256 / nMaxValue; for(y = 0; y < nHeight; y++) pOutImage->SetPixel(x, 255 - y, gRGB(y, 255 - y, 80)); }}void GImage::EqualizeColorSpread(){ // Create the histogram data unsigned int pnHistData[256]; int n; for(n = 0; n < 256; n++) pnHistData[n] = 0; unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; unsigned int nGray; unsigned int nMaxValue = 0; for(nPos = 0; nPos < nSize; nPos++) { nGray = ColorToGrayScale(m_pPixels[nPos]); pnHistData[nGray]++; if(pnHistData[nGray] > nMaxValue) nMaxValue = pnHistData[nGray]; } // Turn it into cumulative histogram data for(n = 1; n < 256; n++) pnHistData[n] += pnHistData[n - 1]; int nFactor = pnHistData[255] >> 8; // turn it into a picture int x; int y; GColor col; float fFactor; for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { col = GetPixel(x, y); nGray = (77 * (int)gRed(col) + 150 * (int)gGreen(col) + 29 * (int)gBlue(col)) >> 8; fFactor = ((float)pnHistData[nGray] / (float)nFactor) / nGray; SetPixel(x, y, gRGB( (char)MIN((int)((float)gRed(col) * fFactor), 255), (char)MIN((int)((float)gGreen(col) * fFactor), 255), (char)MIN((int)((float)gBlue(col) * fFactor), 255) )); } }}void GImage::LocallyEqualizeColorSpread(int nLocalSize, float fExtent){ if(nLocalSize % 2 != 0) nLocalSize++; GAssert(nLocalSize > 2, "Local size must be more than 2"); // Create histograms for all the local regions int nHalfRegionSize = nLocalSize >> 1; int nHorizRegions = (m_nWidth + nHalfRegionSize - 1) / nHalfRegionSize + 1; int nVertRegions = (m_nHeight + nHalfRegionSize - 1) / nHalfRegionSize + 1; int* pArrHistograms = new int[256 * nHorizRegions * nVertRegions]; memset(pArrHistograms, '\0', 256 * nHorizRegions * nVertRegions * sizeof(int)); int* pHist; GAssert(pArrHistograms, "Failed to allocate memory"); int nHoriz, nVert, nDX, nDY, nX, nY, nGrayscale, n; GColor col; for(nVert = 0; nVert < nVertRegions; nVert++) { for(nHoriz = 0; nHoriz < nHorizRegions; nHoriz++) { // Make a histogram for the local region pHist = pArrHistograms + 256 * (nHorizRegions * nVert + nHoriz); for(nDY = 0; nDY < nLocalSize; nDY++) { nY = (nVert - 1) * nHalfRegionSize + nDY; for(nDX = 0; nDX < nLocalSize; nDX++) { nX = (nHoriz - 1) * nHalfRegionSize + nDX; if(nX >= 0 && nX < (int)m_nWidth && nY >= 0 && nY < (int)m_nHeight) { col = GetPixel(nX, nY); nGrayscale = (77 * (int)gRed(col) + 150 * (int)gGreen(col) + 29 * (int)gBlue(col)) >> 8; pHist[nGrayscale]++; } } } // Turn the histogram into cumulative histogram data for(n = 1; n < 256; n++) pHist[n] += pHist[n - 1]; } } // Equalize the colors float fFactor1, fFactor2, fFactor3, fFactor4, fFactorTop, fFactorBottom, fFactorInterpolated; float fInterp; for(nY = 0; nY < (int)m_nHeight; nY++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -