📄 gimage.cpp
字号:
// 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[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]; if(pnHistData[255] > nMaxValue) nMaxValue = pnHistData[255]; // Turn it into cumulative histogram data int n; 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 = gGray(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 = gGray(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++) { nVert = nY / nHalfRegionSize; GAssert(nVert < nVertRegions, "Region out of range"); nDY = nY % nHalfRegionSize; for(nX = 0; nX < (int)m_nWidth; nX++) { // Get the Pixel nHoriz = nX / nHalfRegionSize; GAssert(nHoriz < nHorizRegions, "Region out of range"); nDX = nX % nHalfRegionSize; col = GetPixel(nX, nY); nGrayscale = gGray(col) >> 8; // Calculate equalization factor for quadrant 1 pHist = pArrHistograms + 256 * (nHorizRegions * nVert + nHoriz); fFactor1 = ((float)pHist[nGrayscale] / (float)pHist[255]) * 255 / nGrayscale; // Calculate equalization factor for quadrant 2 pHist = pArrHistograms + 256 * (nHorizRegions * nVert + (nHoriz + 1)); fFactor2 = ((float)pHist[nGrayscale] / (float)pHist[255]) * 255 / nGrayscale; // Calculate equalization factor for quadrant 3 pHist = pArrHistograms + 256 * (nHorizRegions * (nVert + 1) + nHoriz); fFactor3 = ((float)pHist[nGrayscale] / (float)pHist[255]) * 255 / nGrayscale; // Calculate equalization factor for quadrant 4 pHist = pArrHistograms + 256 * (nHorizRegions * (nVert + 1) + (nHoriz + 1)); fFactor4 = ((float)pHist[nGrayscale] / (float)pHist[255]) * 255 / nGrayscale; // Interpolate a factor from all 4 quadrants fInterp = (float)nDX / (float)(nHalfRegionSize - 1); fFactorTop = fInterp * fFactor2 + (1 - fInterp) * fFactor1; fFactorBottom = fInterp * fFactor4 + (1 - fInterp) * fFactor3; fInterp = (float)nDY / (float)(nHalfRegionSize - 1); fFactorInterpolated = (fInterp * fFactorBottom + (1 - fInterp) * fFactorTop) * fExtent + 1 - fExtent; // Set the Pixel SetPixel(nX, nY, gRGB( ClipChan((int)((float)gRed(col) * fFactorInterpolated)), ClipChan((int)((float)gGreen(col) * fFactorInterpolated)), ClipChan((int)((float)gBlue(col) * fFactorInterpolated)) )); } }}void GImage::SafeDrawLine(int nX1, int nY1, int nX2, int nY2, GColor color){ /* // Note: This uses the DDA line drawing algorythm (which is slower than the // Bresenham algorythm, but I had to do it this way for a class I'm taking.) int nSteps = MAX(ABS(nX2 - nX1), ABS(nY2 - nY1)); double dXStep = (double)(nX2 - nX1) / (double)nSteps; double dYStep = (double)(nY2 - nY1) / (double)nSteps; int n; double dX = nX1 + .5; double dY = nY1 + .5; SafeSetPixel((int)dX, (int)dY, color); for(n = 0; n < nSteps; n++) { dX += dXStep; dY += dYStep; SafeSetPixel((int)dX, (int)dY, color); } */ // Check nX1 if(nX1 < 0) { if(nX2 < 0) return; nY1 = (nY1 - nY2) * nX2 / (nX2 - nX1) + nY2; nX1 = 0; } if(nX1 >= m_nWidth) { if(nX2 >= m_nWidth) return; nY1 = (nY1 - nY2) * (m_nWidth - 1 - nX2) / (nX2 - nX1) + nY2; nX1 = m_nWidth - 1; } // Check nY1 if(nY1 < 0) { if(nY2 < 0) return; nX1 = (nX1 - nX2) * nY2 / (nY2 - nY1) + nX2; nY1 = 0; } if(nY1 >= m_nHeight) { if(nY2 >= m_nHeight) return; nX1 = (nX1 - nX2) * (m_nHeight - 1 - nY2) / (nY2 - nY1) + nX2; nY1 = m_nHeight - 1; } // Check nX2 if(nX2 < 0) { if(nX1 < 0) return; nY2 = (nY2 - nY1) * nX1 / (nX1 - nX2) + nY1; nX2 = 0; } if(nX2 >= m_nWidth) { if(nX1 >= m_nWidth) return; nY2 = (nY2 - nY1) * (m_nWidth - 1 - nX1) / (nX2 - nX1) + nY1; nX2 = m_nWidth - 1; } // Check nY2 if(nY2 < 0) { if(nY1 < 0) return; nX2 = (nX2 - nX1) * nY1 / (nY1 - nY2) + nX1; nY2 = 0; } if(nY2 >= m_nHeight) { if(nY1 >= m_nHeight) return; nX2 = (nX2 - nX1) * (m_nHeight - 1 - nY1) / (nY1 - nY2) + nX1; nY2 = m_nHeight - 1; } DrawLine(nX1, nY1, nX2, nY2, color);}// Note: This uses the Bresenham line drawing algorythmvoid GImage::DrawLine(int nX1, int nY1, int nX2, int nY2, GColor color){ int n; int nXDif = ABS(nX2 - nX1); int nYDif = ABS(nY2 - nY1); int nOverflow; int m; if(nXDif > nYDif) { if(nX2 < nX1) { n = nX2; nX2 = nX1; nX1 = n; n = nY2; nY2 = nY1; nY1 = n; } nOverflow = nXDif >> 1; m = nY1; if(nY1 < nY2) { for(n = nX1; n <= nX2; n++) { SetPixel(n, m, color); nOverflow += nYDif; if(nOverflow >= nXDif) { nOverflow -= nXDif; m++; } } } else { for(n = nX1; n <= nX2; n++) { SetPixel(n, m, color); nOverflow += nYDif; if(nOverflow >= nXDif) { nOverflow -= nXDif; m--; } } } } else { if(nY2 < nY1) { n = nX2; nX2 = nX1; nX1 = n; n = nY2; nY2 = nY1; nY1 = n; } nOverflow = nYDif >> 1; m = nX1; if(nX1 < nX2) { for(n = nY1; n <= nY2; n++) { SetPixel(m, n, color); nOverflow += nXDif; if(nOverflow >= nYDif) { nOverflow -= nYDif; m++; } } } else { for(n = nY1; n <= nY2; n++) { SetPixel(m, n, color); nOverflow += nXDif; if(nOverflow >= nYDif) { nOverflow -= nYDif; m--; } } } }}void GImage::DrawLineAntiAlias(int nX1, int nY1, int nX2, int nY2, GColor color){ int n; int m; int nXDif = ABS(nX2 - nX1); int nYDif = ABS(nY2 - nY1); int nOverflow; GColor col; double d; if(nXDif > nYDif) { if(nX2 < nX1) { n = nX2; nX2 = nX1; nX1 = n; n = nY2; nY2 = nY1; nY1 = n; } nOverflow = 0; m = nY1; if(nY1 < nY2) { for(n = nX1; n <= nX2; n++) { d = (double)nOverflow / nXDif; col = GetPixel(n, m); SetPixel(n, m, gRGB((unsigned char)(d * gRed(col) + (1 - d) * gRed(color)), (unsigned char)(d * gGreen(col) + (1 - d) * gGreen(color)), (unsigned char)(d * gBlue(col) + (1 - d) * gBlue(color)))); col = GetPixel(n, m + 1); SetPixel(n, m + 1, gRGB((unsigned char)((1 - d) * gRed(col) + d * gRed(color)), (unsigned char)((1 - d) * gGreen(col) + d * gGreen(color)), (unsigned char)((1 - d) * gBlue(col) + d * gBlue(color)))); nOverflow += nYDif; if(nOverflow >= nXDif) { nOverflow -= nXDif; m++; } } } else { for(n = nX1; n <= nX2; n++) { d = (double)nOverflow / nXDif; col = GetPixel(n, m); SetPixel(n, m, gRGB((unsigned char)(d * gRed(col) + (1 - d) * gRed(color)), (unsigned char)(d * gGreen(col) + (1 - d) * gGreen(color)), (unsigned char)(d * gBlue(col) + (1 - d) * gBlue(color)))); col = GetPixel(n, m - 1); SetPixel(n, m - 1, gRGB((unsigned char)((1 - d) * gRed(col) + d * gRed(color)), (unsigned char)((1 - d) * gGreen(col) + d * gGreen(color)), (unsigned char)((1 - d) * gBlue(col) + d * gBlue(color)))); nOverflow += nYDif; if(nOverflow >= nXDif) { nOverflow -= nXDif; m--; } } } } else { if(nY2 < nY1) { n = nX2; nX2 = nX1; nX1 = n; n = nY2; nY2 = nY1; nY1 = n; } nOverflow = 0; m = nX1; if(nX1 < nX2) { for(n = nY1; n <= nY2; n++) { d = (double)nOverflow / nYDif; col = GetPixel(m, n); SetPixel(m, n, gRGB((unsigned char)(d * gRed(col) + (1 - d) * gRed(color)), (unsigned char)(d * gGreen(col) + (1 - d) * gGreen(color)), (unsigned char)(d * gBlue(col) + (1 - d) * gBlue(color)))); col = GetPixel(m + 1, n); SetPixel(m + 1, n, gRGB((unsigned char)((1 - d) * gRed(col) + d * gRed(color)), (unsigned char)((1 - d) * gGreen(col) + d * gGreen(color)), (unsigned char)((1 - d) * gBlue(col) + d * gBlue(color)))); nOverflow += nXDif; if(nOverflow >= nYDif) { nOverflow -= nYDif; m++; } } } else { for(n = nY1; n <= nY2; n++) { d = (double)nOverflow / nYDif; col = GetPixel(m, n); SetPixel(m, n, gRGB((unsigned char)(d * gRed(col) + (1 - d) * gRed(color)), (unsigned char)(d * gGreen(col) + (1 - d) * gGreen(color)), (unsigned char)(d * gBlue(col) + (1 - d) * gBlue(color)))); col = GetPixel(m - 1, n); SetPixel(m - 1, n, gRGB((unsigned char)((1 - d) * gRed(col) + d * gRed(color)), (unsigned char)((1 - d) * gGreen(col) + d * gGreen(color)), (unsigned char)((1 - d) * gBlue(col) + d * gBlue(color)))); nOverflow += nXDif; if(nOverflow >= nYDif) { nOverflow -= nYDif; m--; } } } }}void GImage::FloodFillRecurser(int nX, int nY, unsigned char nSrcR, unsigned char nSrcG, unsigned char nSrcB, unsigned char nDstR, unsigned char nDstG, unsigned char nDstB, int nTolerance){ GColor col; int nDif; while(nX > 0) { col = GetPixel(nX - 1, nY); nDif = ABS((int)gRed(col) - nSrcR) + ABS((int)gGreen(col) - nSrcG) + ABS((int)gBlue(col) - nSrcB); if(nDif > nTolerance) break; nX--; } GBitTable btUp(m_nWidth); GBitTable btDn(m_nWidth); while(true) { SetPixel(nX, nY, gRGB(nDstR, nDstG, nDstB)); if(nY > 0) { col = GetPixel(nX, nY - 1); if(gRed(col) != nDstR || gGreen(col) != nDstG || gBlue(col) != nDstB) { nDif = ABS((int)gRed(col) - nSrcR) + ABS((int)gGreen(col) - nSrcG) + ABS((int)gBlue(col) - nSrcB); if(nDif <= nTolerance) btUp.SetBit(nX, true); } } if(nY < (int)m_nHeight - 1) { col = GetPixel(nX, nY + 1); if(gRed(col) != nDstR || gGreen(col) != nDstG || gBlue(col) != nDstB) { nDif = ABS((int)gRed(col) - nSrcR) + ABS((int)gGreen(col) - nSrcG) + ABS((int)gBlue(col) - nSrcB); if(nDif <= nTolerance) btDn.SetBit(nX, true); } } nX++; if(nX >= (int)m_nWidth) break; col = GetPixel(nX, nY); nDif = ABS((int)gRed(col) - nSrcR) + ABS((int)gGreen(col) - nSrcG) + ABS((int)gBlue(col) - nSrcB); if(nDif > nTolerance) break; } bool bPrev = false; for(nX = 0; nX < (int)m_nWidth; nX++) { if(btUp.GetBit(nX)) { if(!bPrev) { col = GetPixel(nX, nY - 1); if(gRed(col) != nDstR || gGreen(col) != nDstG || gBlue(col) != nDstB) FloodFillRecurser(nX, nY - 1, nSrcR, nSrcG, nSrcB, nDstR, nDstG, nDstB, nTolerance); } bPrev = true; } else bPrev = false; } bPrev = false; for(nX = 0; nX < (int)m_nWidth; nX++) { if(btDn.GetBit(nX)) { if(!bPrev) { col = GetPixel(nX, nY + 1); if(gRed(col) != nDstR || gGreen(col) != nDstG || gBlue(col) != nDstB) FloodFillRecurser(nX, nY + 1, nSrcR, nSrcG, nSrcB, nDstR, nDstG, nDstB, nTolerance); } bPrev = true; } else bPrev = false; }}void GImage::FloodFill(int nX, int nY, GColor color, int nTolerance){ GColor col = GetPixel(nX, nY); FloodFillRecurser(nX, nY, gRed(col), gGreen(col), gBlue(col), gRed(color), gGreen(color), gBlue(color), nTolerance);}void GImage::BoundaryFill(int nX, int nY, unsigned char nBoundaryR, unsigned char nBoundaryG, unsigned char nBoundaryB, unsigned char nFillR, unsigned char nFillG, unsigned char nFillB, int nTolerance){ int nDif; GColor col = GetPixel(nX, nY); nDif = ABS((int)gRed(col) - nBoundaryR) + ABS((int)gGreen(col) - nBoundaryG) + ABS((int)gBlue(col) - nBoundaryB); if(nDif <= nTolerance) return; while(true) { col = GetPixel(nX - 1, nY); nDif = ABS((int)gRed(col) - nBoundaryR) + ABS((int)gGreen(col) - nBoundaryG) + ABS((int)gBlue(col) - nBoundaryB); if(nDif <= nTolerance || nX < 1) break; nX--; } GBitTable btUp(m_nWidth); GBitTable btDn(m_nWidth); while(true) { SetPixel(nX, nY, gRGB(nFillR, nFillG, nFillB));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -