📄 gimage.cpp
字号:
c1 = pKernel->GetPixel(pKernel->m_nWidth - kx - 1, pKernel->m_nHeight - ky - 1); c2 = SafeGetPixel(x + kx - nHalfKWidth, y + ky - nHalfKHeight); nRSum += gRed(c1) * gRed(c2); nGSum += gGreen(c1) * gGreen(c2); nBSum += gBlue(c1) * gBlue(c2); } } nRSum = MIN(MAX(nRSum, 0), 255); nGSum = MIN(MAX(nGSum, 0), 255); nBSum = MIN(MAX(nBSum, 0), 255); NewImage.SetPixel(x, y, gRGB(nRSum, nGSum, nBSum)); } } SwapData(&NewImage);}void GImage::Blur(double dFactor){ // Calculate how big of a kernel we need int nFactor = (int)dFactor; int nWidth = nFactor * 2 + 1; GImage imgKernel; imgKernel.SetSize(nWidth, nWidth); // Produce the blurring kernel double dTmp = dFactor / 8; double d; int n; int x, y; for(y = 0; y < nWidth; y++) { for(x = 0; x < nWidth; x++) { d = pow((double)2, -(sqrt((double)((nFactor - x) * (nFactor - x) + (nFactor - y) * (nFactor - y))) / dTmp)); n = MAX(0, MIN(255, (int)(d * 256))); imgKernel.SetPixel(x, y, gRGB(n, n, n)); } } // Convolve the kernel with the image Convolve(&imgKernel);}void GImage::Sharpen(double dFactor){ GImage imgBlurred; imgBlurred.CopyImage(this); imgBlurred.Blur(dFactor); GImage imgTmp; imgTmp.SetSize(m_nWidth, m_nHeight); GColor col; int nRed, nGreen, nBlue; int x, y; for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < (int)m_nWidth; x++) { col = GetPixel(x, y); nRed = 2 * gRed(col); nGreen = 2 * gGreen(col); nBlue = 2 * gBlue(col); col = imgBlurred.GetPixel(x, y); nRed = MAX(0, MIN(255, (int)(nRed - gRed(col)))); nGreen = MAX(0, MIN(255, (int)(nGreen - gGreen(col)))); nBlue = MAX(0, MIN(255, (int)(nBlue - gBlue(col)))); imgTmp.SetPixel(x, y, gRGB(nRed, nGreen, nBlue)); } } SwapData(&imgTmp);}void GImage::Invert(){ int x, y; GColor col; for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < (int)m_nWidth; x++) { col = GetPixel(x, y); SetPixel(x, y, gRGB(255 - gRed(col), 255 - gGreen(col), 255 - gBlue(col))); } }}void GImage::InvertRect(GRect* pRect){ int x, y; GColor col; for(y = pRect->y; y < pRect->y + pRect->h; y++) { for(x = pRect->x; x < pRect->x + pRect->w; x++) { col = GetPixel(x, y); SetPixel(x, y, gRGB(255 - gRed(col), 255 - gGreen(col), 255 - gBlue(col))); } }}void GImage::MakeEdgesGlow(float fThresh, int nThickness, int nOpacity, GColor color){ // Make initial mask GImage tmp; tmp.SetSize(m_nWidth, m_nHeight); GColor col, colLeft, colRight, colTop, colBottom; int x, y, dif; for(y = m_nHeight - 2; y > 0; y--) { for(x = m_nWidth - 2; x > 0; x--) { col = GetPixel(x, y); colLeft = GetPixel(x - 1, y); colRight = GetPixel(x + 1, y); colTop = GetPixel(x, y - 1); colBottom = GetPixel(x, y + 1); dif = ABS((int)gRed(col) - (int)gRed(colLeft)) + ABS((int)gGreen(col) - (int)gGreen(colLeft)) + ABS((int)gBlue(col) - (int)gBlue(colLeft)) + ABS((int)gRed(col) - (int)gRed(colRight)) + ABS((int)gGreen(col) - (int)gGreen(colRight)) + ABS((int)gBlue(col) - (int)gBlue(colRight)) + ABS((int)gRed(col) - (int)gRed(colTop)) + ABS((int)gGreen(col) - (int)gGreen(colTop)) + ABS((int)gBlue(col) - (int)gBlue(colTop)) + ABS((int)gRed(col) - (int)gRed(colBottom)) + ABS((int)gGreen(col) - (int)gGreen(colBottom)) + ABS((int)gBlue(col) - (int)gBlue(colBottom)); if((float)dif * gAlpha(col) / 49152 > fThresh) tmp.SetPixel(x, y, nThickness + 1);/* dif = ABS((int)gAlpha(col) - (int)gAlpha(colLeft)) + ABS((int)gAlpha(col) - (int)gAlpha(colRight)) + ABS((int)gAlpha(col) - (int)gAlpha(colTop)) + ABS((int)gAlpha(col) - (int)gAlpha(colBottom)); if((float)dif / 1024 > fThresh) tmp.SetPixel(x, y, nThickness + 1);*/ } } // Make the glowing int n; for(n = nThickness; n >= 0; n--) { for(y = m_nHeight - 2; y > 0; y--) { for(x = m_nWidth - 2; x > 0; x--) { col = tmp.GetPixel(x, y); if(col > (unsigned int)n) { tmp.SetPixel(x - 1, y, tmp.GetPixel(x - 1, y) | n); tmp.SetPixel(x + 1, y, tmp.GetPixel(x + 1, y) | n); tmp.SetPixel(x, y - 1, tmp.GetPixel(x, y - 1) | n); tmp.SetPixel(x, y + 1, tmp.GetPixel(x, y + 1) | n); col = MixColors(color, GetPixel(x, y), nOpacity); SetPixel(x, y, col); } } } }}void GImage::HorizDifferenceize(){ if(m_nWidth <= 1) return; GColor c1, c2; int x, y; for(y = 0; y < m_nHeight; y++) { c1 = GetPixel(0, y); for(x = 1; x < m_nWidth; x++) { c2 = GetPixel(x, y); SetPixel(x, y, gRGB( (256 + gRed(c2) - gRed(c1)) % 256, (256 + gGreen(c2) - gGreen(c1)) % 256, (256 + gBlue(c2) - gBlue(c1)) % 256)); c1 = c2; } }}void GImage::HorizSummize(){ if(m_nWidth <= 1) return; GColor c1, c2; int x, y; for(y = 0; y < m_nHeight; y++) { c1 = GetPixel(0, y); for(x = 1; x < m_nWidth; x++) { c2 = GetPixel(x, y); SetPixel(x, y, gRGB( (256 + gRed(c2) + gRed(c1)) % 256, (256 + gGreen(c2) + gGreen(c1)) % 256, (256 + gBlue(c2) + gBlue(c1)) % 256)); c1 = c2; } }}void GImage::Draw3DLine(const struct Point3D* pA, const struct Point3D* pB, struct Transform* pCamera, GColor color){ struct Point3D a = *pA; struct Point3D b = *pB; a.Transform(pCamera); b.Transform(pCamera); SafeDrawLine((int)a.m_vals[0], (int)a.m_vals[1], (int)b.m_vals[0], (int)b.m_vals[1], color);}void GImage::DrawBezier(GBezier* pCurve, GColor color, double dStart, double dEnd, double dStep, struct Transform* pCamera){ Transform t; Point3D prev; Point3D point; pCurve->GetPoint(dStart, &prev); point.Transform(pCamera); while(true) { dStart += dStep; if(dStart > dEnd) break; pCurve->GetPoint(dStart, &point); Draw3DLine(&point, &prev, pCamera, color); prev = point; }}int GImage::MeasureHardTextWidth(int height, const char* szText, float width){ bool bBig = (height > 24); int sx, sy, sw, sh; int x = 0; int nCharWidth; while(true) { char c = *szText; if(c == '\0') break; if(bBig) { GHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); nCharWidth = (int)(sw * height * width) / sh; } else { GSmallHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); nCharWidth = sw; } x += nCharWidth; szText++; } return x;}int GImage::CountHardTextChars(int horizArea, int height, const char* szText, float width){ bool bBig = (height > 24); int sx, sy, sw, sh; int x = 0; int nCharWidth; int nChars = 0; while(true) { char c = *szText; if(c == '\0') break; if(bBig) { GHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); nCharWidth = (int)(sw * height * width) / sh; } else { GSmallHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); nCharWidth = sw; } x += nCharWidth; szText++; if(x > horizArea) break; nChars++; } return nChars;}void GImage::DrawHardText(GRect* pRect, const char* szText, GColor col, float width){ bool bBig = (pRect->h > 24); int sx, sy, sw, sh; int x = 0; while(true) { char c = *szText; if(c == '\0') break; if(bBig) GHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); else { GSmallHardFont_GetCharCoords(c, &sx, &sy, &sw, &sh); GAssert(sh <= 24, "problem with big threshold"); } GAssert(pRect->x >= 0, "todo: this case not handled yet"); int yStart = 0; if(pRect->y < 0) yStart = -pRect->y; if(bBig) { int h = pRect->h; if(pRect->y + h > m_nHeight) h = m_nHeight - pRect->y; int nCharWidth = (int)(sw * pRect->h * width) / sh; int n; for(n = 0; n < nCharWidth; n++) { if(x >= pRect->w) break; int y; for(y = yStart; y < h; y++) SetPixel(pRect->x + x, pRect->y + y, GHardFont_GetAlphaBlended(sx + n * sw / nCharWidth, sy + y * sh / pRect->h, col, GetPixel(pRect->x + x, pRect->y + y))); x++; } } else { if(pRect->y + sh > m_nHeight) sh = m_nHeight - pRect->y; int n; for(n = 0; n < sw; n++) { if(x >= pRect->w) break; int y; for(y = yStart; y < sh; y++) SetPixel(pRect->x + x, pRect->y + y, GSmallHardFont_GetAlphaBlended(sx + n, sy + y, col, GetPixel(pRect->x + x, pRect->y + y))); x++; } } szText++; }}void GImage::Blit(int x, int y, GImage* pSource, GRect* pSourceRect){ int sx = pSourceRect->x; int sy = pSourceRect->y; int sw = pSourceRect->w; int sh = pSourceRect->h; if(x < 0) { sx -= x; sw += x; x = 0; } if(x + sw > m_nWidth) sw = m_nWidth - x; if(y < 0) { sy -= y; sh += y; y = 0; } if(y + sh > m_nHeight) sh = m_nHeight - y; int dst = y * m_nWidth + x; int src = sy * pSource->m_nWidth + sx; sw *= sizeof(GColor); for( ; sh > 0; sh--) { memcpy(&m_pPixels[dst], &pSource->m_pPixels[src], sw); dst += m_nWidth; src += pSource->m_nWidth; }}void GImage::AlphaBlit(int x, int y, GImage* pSource, GRect* pSourceRect){ int sx = pSourceRect->x; int sy = pSourceRect->y; int sw = pSourceRect->w; int sh = pSourceRect->h; if(x < 0) { sx -= x; sw += x; x = 0; } if(x + sw > m_nWidth) sw = m_nWidth - x; if(y < 0) { sy -= y; sh += y; y = 0; } if(y + sh > m_nHeight) sh = m_nHeight - y; int dst = y * m_nWidth + x; int src = sy * pSource->m_nWidth + sx; int xx, a; GColor pix, pixOld; for( ; sh > 0; sh--) { for(xx = 0; xx < sw; xx++) { pix = pSource->m_pPixels[src + xx]; a = gAlpha(pix); pixOld = m_pPixels[dst + xx]; m_pPixels[dst + xx] = gRGB((a * gRed(pix) + (256 - a) * gRed(pixOld)) >> 8, (a * gGreen(pix) + (256 - a) * gGreen(pixOld)) >> 8, (a * gBlue(pix) + (256 - a) * gBlue(pixOld)) >> 8); } dst += m_nWidth; src += pSource->m_nWidth; }}GImage* GImage::Munge(int nStyle, float fExtent){ GImage* pMunged = new GImage(); pMunged->SetSize(m_nWidth, m_nHeight); int x, y; GColor col; double d; switch(nStyle) { case 0: // particle-blur (pick a random pixel in the proximity) for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { col = SafeGetPixel( (int)(x + fExtent * m_nWidth * (GBits::GetRandomDouble() - .5)), (int)(y + fExtent * m_nHeight * (GBits::GetRandomDouble() - .5)) ); pMunged->SetPixel(x, y, col); } } break; case 1: // shadow threshold (throw out all pixels below a certain percent of the total brighness) { fExtent = 1 - fExtent; fExtent *= fExtent; fExtent *= fExtent; fExtent = 1 - fExtent; // 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; for(nPos = 0; nPos < nSize; nPos++) { nGray = ColorToGrayScale(m_pPixels[nPos]); pnHistData[gGreen(nGray)]++; } // Turn it into cumulative histogram data for(n = 1; n < 256; n++) pnHistData[n] += pnHistData[n - 1]; // Find the cut-off unsigned int nCutOff = (unsigned int)(fExtent * pnHistData[255]); for(n = 0; n < 256 && pnHistData[n] < nCutOff; n++) { } // Copy all the data above the threshold for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { col = GetPixel(x, y); nGray = gGreen(ColorToGrayScale(col)); if(nGray > (unsigned int)n) pMunged->SetPixel(x, y, col); } } } break; case 2: // waves for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { col = SafeGetPixel( (int)(x + fExtent * (m_nWidth / 2) * cos((double)x * 16 / m_nWidth)), (int)(y + fExtent * (m_nHeight / 2) * sin((double)y * 16 / m_nHeight)) ); pMunged->SetPixel(x, y, col); } } break; case 3: // waved in or out of the middle fExtent = 1 - fExtent; fExtent *= fExtent; fExtent = 1 - fExtent; for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { d = atan2((double)(y - m_nHeight / 2), (double)(x - m_nWidth / 2)); d = fExtent * cos(d * 5); col = SafeGetPixel( (int)((1 - d) * x + d * (m_nWidth / 2)), (int)((1 - d) * y + d * (m_nHeight / 2)) ); pMunged->SetPixel(x, y, col); } } break; } return pMunged;}void GImage::FillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, GColor c){ // Get y1 on top int t; if(y2 < y1) { t = y2; y2 = y1; y1 = t; t = x2; x2 = x1; x1 = t; } if(y3 < y1) { t = y3; y3 = y1; y1 = t; t = x3; x3 = x1; x1 = t; } // Get y2 in the middle if(y3 < y2) { t = y3; y3 = y2; y2 = t; t = x3; x3 = x2; x2 = t; } // Compute step sizes float fx1 = (float).5 + x1; float fx2 = (float).5 + x1; float dx1, dx2; if(y1 == y2) { fx1 = (float).5 + x2; dx1 = 0; } else dx1 = (float)(x2 - x1) / (y2 - y1); if(y1 == y3) { fx2 = (float).5 + x3; dx2 = 0; } else dx2 = (float)(x3 - x1) / (y3 - y1); // Draw the first half int x, xMax, y; for(y = y1; y <= y2; y++) { if(fx1 < fx2) { x = (int)fx1; xMax = (int)fx2; } else { x = (int)fx2; xMax = (int)fx1; } for( ; x <= xMax; x++) SetPixel(x, y, c); fx1 += dx1; fx2 += dx2; } // Draw the second half fx1 = (float).5 + x2; if(y2 == y3) dx1 = 0; else dx1 = (float)(x3 - x2) / (y3 - y2); fx1 += dx1; for( ; y <= y3; y++) { if(fx1 < fx2) { x = (int)fx1; xMax = (int)fx2; } else { x = (int)fx2; xMax = (int)fx1; } for( ; x <= xMax; x++) SetPixel(x, y, c); fx1 += dx1; fx2 += dx2; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -