📄 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 "GBezier.h"#include "GRayTrace.h"#include "GHardFont.h"#include "GPNG.h"#include "GBits.h"#include "GFile.h"#include "GMath.h"#include "GFourier.h"#include "GSearch.h"#include "GGreedySearch.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 WIN32void GColorToHSV(GColor c, float* pHue, float* pSaturation, float* pValue){ int r = gRed(c); int g = gGreen(c); int b = gBlue(c); int range; if(g >= r && g >= b) { if(r >= b) range = g - b; else range = g - r; if(range > 0) { *pHue = (float)(b - r) / (range * 6) + (float)1 / 3; *pSaturation = (float)1 - (float)range / (float)g; } else { *pHue = 0; *pSaturation = 0; } *pValue = (float)g / 255; } else if(r >= b) { if(g >= b) range = r - b; else range = r - g; if(range > 0) { *pHue = (float)(g - b) / (range * 6); if(*pHue < 0) (*pHue) += (float)1; *pSaturation = (float)1 - (float)range / (float)r; } else { *pHue = 0; *pSaturation = 0; } *pValue = (float)r / 255; } else { if(g >= r) range = b - r; else range = b - g; if(range > 0) { *pHue = (float)(r - g) / (range * 6) + (float)2 / 3; *pSaturation = (float)1 - (float)range / (float)b; } else { *pHue = 0; *pSaturation = 0; } *pValue = (float)b / 255; }}GColor HSVToGColor(int alpha, float hue, float saturation, float value){ GAssert(hue >= 0 && hue <= 1 && saturation >= 0 && saturation <= 1 && value >= 0 && value <= 1, "out of range"); hue *= (float)5.999999; int h = (int)hue; float f = hue - h; float p = value * ((float)1 - saturation); float q = value * ((float)1 - ((h & 1) == 0 ? (float)1 - f : f) * saturation); switch(h) { case 0: return gARGB(alpha, (int)(value * 255.999999), (int)(q * 255.999999), (int)(p * 255.999999)); case 1: return gARGB(alpha, (int)(q * 255.999999), (int)(value * 255.999999), (int)(p * 255.999999)); case 2: return gARGB(alpha, (int)(p * 255.999999), (int)(value * 255.999999), (int)(q * 255.999999)); case 3: return gARGB(alpha, (int)(p * 255.999999), (int)(q * 255.999999), (int)(value * 255.999999)); case 4: return gARGB(alpha, (int)(q * 255.999999), (int)(p * 255.999999), (int)(value * 255.999999)); case 5: return gARGB(alpha, (int)(value * 255.999999), (int)(p * 255.999999), (int)(q * 255.999999)); } GAssert(false, "shouldn't get here"); return gARGB(alpha, 0, 0, 0);}GImage::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->GetPixelArray(), 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) const{ 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;}int ReadNextPixMapInteger(FILE* pFile){ // Read past any white space and skip comments int n; 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 the integer char pBuff[16]; pBuff[0] = n; int nPos = 1; while(true) { n = fgetc(pFile); if(n == EOF) return -1; if(n <= 32) break; pBuff[nPos] = n; nPos++; if(nPos >= 16) return -1; } pBuff[nPos] = '\0'; return atoi(pBuff);}bool GImage::LoadPixMap(FILE* pFile, bool bTextData, bool bGrayScale){ GAssert(pFile, "no file"); int nWidth = ReadNextPixMapInteger(pFile); if(nWidth < 1) return false; int nHeight = ReadNextPixMapInteger(pFile); if(nHeight < 1) return false; int nRange = ReadNextPixMapInteger(pFile) + 1; if(nRange < 2) return false; // Read the data SetSize(nWidth, nHeight); int x, y, r, g, b; if(bTextData) { for(y = 0; y < nHeight; y++) { for(x = 0; x < nWidth; x++) { if(bGrayScale) { g = ReadNextPixMapInteger(pFile); if(g < 0) return false; SetPixel(x, y, gRGB(g, g, g)); } else { r = ReadNextPixMapInteger(pFile); if(r < 0) return false; g = ReadNextPixMapInteger(pFile); if(g < 0) return false; b = ReadNextPixMapInteger(pFile); if(b < 0) return false; SetPixel(x, y, gRGB(r, g, b)); } } } } else { char pBuff[16]; 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; SetPixel(x, y, gRGB(nRed, nRed, nRed)); } 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 = gGray(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 = gGray(c) >> 8; return gRGB(nGray, nGray, nGray);}void GImage::ConvertToGrayScale(){ unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; int nGray; for(nPos = 0; nPos < nSize; nPos++) { nGray = gGray(m_pPixels[nPos]) >> 8; m_pPixels[nPos] = gARGB(gAlpha(m_pPixels[nPos]), nGray, nGray, nGray); }}void GImage::CreateBrightnessHistogram(GImage* pOutImage){ // Create the histogram data unsigned int pnHistData[257]; memset(pnHistData, '\0', sizeof(int) * 257); unsigned int nSize = m_nWidth * m_nHeight; unsigned int nPos; unsigned int nGray; unsigned int nMaxValue = 0; for(nPos = 0; nPos < nSize; nPos++) { nGray = gGray(m_pPixels[nPos]) >> 8; pnHistData[nGray]++; if(pnHistData[nGray] > nMaxValue) nMaxValue = pnHistData[nGray]; } pnHistData[255] += pnHistData[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -