📄 gimage.cpp
字号:
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 = (77 * (int)gRed(col) + 150 * (int)gGreen(col) + 29 * (int)gBlue(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( (char)MAX(0, MIN((int)((float)gRed(col) * fFactorInterpolated), 255)), (char)MAX(0, MIN((int)((float)gGreen(col) * fFactorInterpolated), 255)), (char)MAX(0, MIN((int)((float)gBlue(col) * fFactorInterpolated), 255)) )); } }}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(true) { col = GetPixel(nX - 1, nY); nDif = ABS((int)gRed(col) - nSrcR) + ABS((int)gGreen(col) - nSrcG) + ABS((int)gBlue(col) - nSrcB); if(nDif > nTolerance || nX < 1) 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)); if(nY > 0) { col = GetPixel(nX, nY - 1); if(gRed(col) != nFillR || gGreen(col) != nFillG || gBlue(col) != nFillB) { nDif = ABS((int)gRed(col) - nBoundaryR) + ABS((int)gGreen(col) - nBoundaryG) + ABS((int)gBlue(col) - nBoundaryB); if(nDif > nTolerance) btUp.SetBit(nX, true); } } if(nY < (int)m_nHeight - 1) { col = GetPixel(nX, nY + 1); if(gRed(col) != nFillR || gGreen(col) != nFillG || gBlue(col) != nFillB) { nDif = ABS((int)gRed(col) - nBoundaryR) + ABS((int)gGreen(col) - nBoundaryG) + ABS((int)gBlue(col) - nBoundaryB); if(nDif > nTolerance) btDn.SetBit(nX, true); } } nX++; if(nX >= (int)m_nWidth) break; col = GetPixel(nX, nY); nDif = ABS((int)gRed(col) - nBoundaryR) + ABS((int)gGreen(col) - nBoundaryG) + ABS((int)gBlue(col) - nBoundaryB); 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) != nFillR || gGreen(col) != nFillG || gBlue(col) != nFillB) BoundaryFill(nX, nY - 1, nBoundaryR, nBoundaryG, nBoundaryB, nFillR, nFillG, nFillB, 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) != nFillR || gGreen(col) != nFillG || gBlue(col) != nFillB) BoundaryFill(nX, nY + 1, nBoundaryR, nBoundaryG, nBoundaryB, nFillR, nFillG, nFillB, nTolerance); } bPrev = true; } else bPrev = false; }}void GImage::DrawPolygon(int nPoints, int* pnPtArray, GColor color){ if(nPoints < 3) return; float* pnPointArray = new float[nPoints << 1]; int n; for(n = 0; n < nPoints << 1; n++) pnPointArray[n] = ((float)pnPtArray[n]) + .1f; for(n = 0; n < nPoints; n++) { int n2 = n + 1; if(n2 >= nPoints) n2 = 0; SafeDrawLine(pnPtArray[n << 1], pnPtArray[(n << 1) + 1], pnPtArray[n2 << 1], pnPtArray[(n2 << 1) + 1], color); } // Find Max and Min values int nXMin = (int)pnPointArray[0]; int nXMax = (int)pnPointArray[0]; int nYMin = (int)pnPointArray[1]; int nYMax = (int)pnPointArray[1]; int nPos = 2; for(n = 1; n < nPoints; n++) { if(pnPointArray[nPos] < nXMin) nXMin = (int)pnPointArray[nPos]; if(pnPointArray[nPos] + 1 > nXMax) nXMax = (int)pnPointArray[nPos] + 1; nPos++; if(pnPointArray[nPos] < nYMin) nYMin = (int)pnPointArray[nPos]; if(pnPointArray[nPos] + 1 > nYMax) nYMax = (int)pnPointArray[nPos] + 1; nPos++; } int nX, nY; int* pArrPts = new int[m_nWidth]; for(nY = nYMin; nY <= nYMax; nY++) { memset(pArrPts, '\0', sizeof(int) * m_nWidth); // Calculate Intercepts for(n = 0; n < nPoints; n++) { int n2 = n + 1; if(n2 >= nPoints) n2 = 0; float nX1 = pnPointArray[n << 1]; float nY1 = pnPointArray[(n << 1) + 1]; float nX2 = pnPointArray[n2 << 1]; float nY2 = pnPointArray[(n2 << 1) + 1]; if(nY < nY1 && nY < nY2) continue; if(nY > nY1 && nY > nY2) continue; nX = (int)(nX1 + (nY - nY1) * (nX2 - nX1) / (nY2 - nY1)); if(nX < 0) nX = 0; if(nX >= (int)m_nWidth) nX = (int)m_nWidth - 1; pArrPts[nX]++; } // Draw the Scan Line bool bOn = false; for(nX = nXMin; nX <= nXMax; nX++) { if(bOn || pArrPts[nX]) SafeSetPixel(nX, nY, color); if(pArrPts[nX] & 1) bOn = !bOn; } } delete(pArrPts);}void GImage::DrawCircle(int nX, int nY, float fRadius, GColor color){ int radiusSquared = (int)(fRadius * fRadius + (float).5); int x = 0; int y = (int)fRadius; while(y >= x) { // Draw the eight symmetric pixels SafeSetPixel(nX + x, nY - y, color); SafeSetPixel(nX - x, nY - y, color); SafeSetPixel(nX + x, nY + y, color); SafeSetPixel(nX - x, nY + y, color); SafeSetPixel(nX + y, nY - x, color); SafeSetPixel(nX - y, nY - x, color); SafeSetPixel(nX + y, nY + x, color); SafeSetPixel(nX - y, nY + x, color); // Compute the next position if(x * x + y * y > radiusSquared) y--; x++; } /* double dAngle; double dStep = .9 / dRadius; if(dStep == 0) return; double dSin; double dCos; for(dAngle = 0; dAngle < 0.79; dAngle += dStep) { dSin = sin(dAngle); dCos = cos(dAngle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -