📄 gimage.cpp
字号:
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++; }}void GImage::DrawEllipse(int nX, int nY, double dRadius, double dHeightToWidthRatio, GColor color){ double dAngle; double dStep = .9 / dRadius; if(dHeightToWidthRatio > 1) dStep /= dHeightToWidthRatio; if(dStep == 0) return; double dSin; double dCos; for(dAngle = 0; dAngle < 0.79; dAngle += dStep) { dSin = sin(dAngle); dCos = cos(dAngle); SafeSetPixel((int)(nX + dCos * dRadius), (int)(nY + dHeightToWidthRatio * dSin * dRadius), color); SafeSetPixel((int)(nX - dCos * dRadius), (int)(nY + dHeightToWidthRatio * dSin * dRadius), color); SafeSetPixel((int)(nX + dCos * dRadius), (int)(nY - dHeightToWidthRatio * dSin * dRadius), color); SafeSetPixel((int)(nX - dCos * dRadius), (int)(nY - dHeightToWidthRatio * dSin * dRadius), color); SafeSetPixel((int)(nX + dSin * dRadius), (int)(nY + dHeightToWidthRatio * dCos * dRadius), color); SafeSetPixel((int)(nX - dSin * dRadius), (int)(nY + dHeightToWidthRatio * dCos * dRadius), color); SafeSetPixel((int)(nX + dSin * dRadius), (int)(nY - dHeightToWidthRatio * dCos * dRadius), color); SafeSetPixel((int)(nX - dSin * dRadius), (int)(nY - dHeightToWidthRatio * dCos * dRadius), color); }}void GImage::Rotate(GImage* pSourceImage, int nX, int nY, double dAngle){ int x; int y; float dCos = (float)cos(dAngle); float dSin = (float)sin(dAngle); for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < (int)m_nWidth; x++) { float dX = (x - nX) * dCos - (y - nY) * dSin + nX; float dY = (x - nX) * dSin + (y - nY) * dCos + nY; GColor col = pSourceImage->InterpolatePixel(dX, dY); SetPixel(x, y, col); } }}bool GImage::LoadPNGFile(const unsigned char* pRawData, int nBytes){ return LoadPng(this, pRawData, nBytes);}bool GImage::LoadPNGFile(const char* szFilename){ int nSize; char* pRawData = GFile::LoadFileToBuffer(szFilename, &nSize); if(!pRawData) return false; ArrayHolder<char*> hRawData(pRawData); return LoadPng(this, (const unsigned char*)pRawData, nSize);}bool GImage::SavePNGFile(FILE* pFile){ return SavePng(this, pFile, true);}bool GImage::SavePNGFile(const char* szFilename){ FILE* pFile = fopen(szFilename, "wb"); if(!pFile) return false; bool bOK = SavePNGFile(pFile); fclose(pFile); return bOK;}bool GImage::SaveBMPFile(const char* szFilename){ unsigned int nSize = m_nWidth * m_nHeight; BITMAPFILEHEADER h1; h1.bfType = GBits::N16ToLittleEndian((unsigned short)19778); // "BM" h1.bfSize = GBits::N32ToLittleEndian((unsigned int)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * nSize)); h1.bfReserved1 = 0; h1.bfReserved2 = 0; h1.bfOffBits = GBits::N32ToLittleEndian((unsigned int)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))); BITMAPINFOHEADER h2; h2.biSize = GBits::N32ToLittleEndian((unsigned int)sizeof(BITMAPINFOHEADER)); h2.biWidth = GBits::N32ToLittleEndian((unsigned int)m_nWidth); h2.biHeight = GBits::N32ToLittleEndian((unsigned int)m_nHeight); h2.biPlanes = GBits::N16ToLittleEndian((unsigned short)1); h2.biBitCount = GBits::N16ToLittleEndian((unsigned short)24); h2.biCompression = 0; h2.biSizeImage = GBits::N32ToLittleEndian(3 * nSize); h2.biXPelsPerMeter = GBits::N32ToLittleEndian((unsigned int)3780); h2.biYPelsPerMeter = GBits::N32ToLittleEndian((unsigned int)3780); h2.biClrUsed = 0; h2.biClrImportant = 0; FILE* pFile = fopen(szFilename, "wb"); if(!pFile) return false; if(fwrite(&h1, sizeof(BITMAPFILEHEADER), 1, pFile) != 1) { fclose(pFile); return false; } if(fwrite(&h2, sizeof(BITMAPINFOHEADER), 1, pFile) != 1) { fclose(pFile); return false; } int y; int x; GColor col; for(y = (int)m_nHeight - 1; y >= 0; y--) { for(x = 0; x < (int)m_nWidth; x++) { col = GetPixel(x, y); int nR = gRed(col); int nG = gGreen(col); int nB = gBlue(col); if( fwrite(&nB, 1, 1, pFile) != 1 || fwrite(&nG, 1, 1, pFile) != 1 || fwrite(&nR, 1, 1, pFile) != 1 ) { fclose(pFile); return false; } } int n = (x * 3) % 4; if(n > 0) { int nR = 0; while(n < 4) // Allign on word boundaries { fwrite(&nR, 1, 1, pFile); n++; } } } fclose(pFile); return true;}bool GImage::LoadBMPFile(const char* szFilename){ FILE* pFile = fopen(szFilename, "rb"); if(!pFile) return false; bool bRet = LoadBMPFile(pFile); fclose(pFile); return bRet;}bool GImage::LoadBMPFile(FILE* pFile){ BITMAPFILEHEADER h1; BITMAPINFOHEADER h2; if(fread(&h1, sizeof(BITMAPFILEHEADER), 1, pFile) != 1) return false; if(fread(&h2, sizeof(BITMAPINFOHEADER), 1, pFile) != 1) return false; if(h2.biBitCount != 24) { GAssert(false, "Sorry, this only supports 24-bit bitmaps"); return false; } if(h2.biWidth < 1 || h2.biHeight < 1) { GAssert(false, "Sorry, this only supports bottom-up bitmaps"); return false; } SetSize(h2.biWidth, h2.biHeight); int y; int x; unsigned char nR; unsigned char nG; unsigned char nB; for(y = (int)m_nHeight - 1; y >= 0; y--) { for(x = 0; x < (int)m_nWidth; x++) { if( fread(&nB, 1, 1, pFile) != 1 || fread(&nG, 1, 1, pFile) != 1 || fread(&nR, 1, 1, pFile) != 1 ) return false; SetPixel(x, y, gRGB(nR, nG, nB)); } int n = (x * 3) % 4; if(n > 0) { nR = 0; while(n < 4) // Align on word boundaries { fread(&nR, 1, 1, pFile); n++; } } } return true;}bool GImage::LoadBMPFile(const unsigned char* pRawData, int nLen){ if(nLen < (int)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))) return false; BITMAPFILEHEADER* h1 = (BITMAPFILEHEADER*)pRawData; BITMAPINFOHEADER* h2 = (BITMAPINFOHEADER*)((char*)h1 + sizeof(BITMAPFILEHEADER)); const unsigned char* pData = (const unsigned char*)((char*)h2 + sizeof(BITMAPINFOHEADER)); if(h2->biBitCount != 24) { GAssert(false, "Sorry, this only supports 24-bit bitmaps"); return false; } if(h2->biWidth < 1 || h2->biHeight < 1) { GAssert(false, "Sorry, this only supports bottom-up bitmaps"); return false; } SetSize(h2->biWidth, h2->biHeight); // todo: make sure nLen is big enough to hold all the data int y; int x; unsigned char nR; unsigned char nG; unsigned char nB; for(y = (int)m_nHeight - 1; y >= 0; y--) { for(x = 0; x < (int)m_nWidth; x++) { nB = *(pData++); nG = *(pData++); nR = *(pData++); SetPixel(x, y, gRGB(nR, nG, nB)); } int n = (x * 3) % 4; if(n > 0) { while(n < 4) // Align on word boundaries { pData++; n++; } } } return true;}bool GImage::Crop(int nLeft, int nTop, int nRight, int nBottom){ nRight++; nBottom++; int nWidth = nRight - nLeft; int nHeight = nBottom - nTop; if(nWidth < 1 || nHeight < 1) return false; unsigned int nNewSize = nWidth * nHeight; GColor* pNewQuads = new GColor[nNewSize]; // Copy overlapping parts of the pics GColor col; unsigned int nPos; int x, y; for(y = 0; y < (int)m_nHeight; y++) { if(y < nTop) continue; if(y >= nBottom) continue; for(x = 0; x < (int)m_nWidth; x++) { if(x < nLeft) continue; if(x >= nRight) continue; col = GetPixel(x, y); nPos = (nWidth * (y - nTop) + x - nLeft) << 2; pNewQuads[nPos] = col; } } // Replace the old buffer with the new one delete(m_pPixels); m_pPixels = pNewQuads; m_nWidth = nWidth; m_nHeight = nHeight; return true;}
void GImage::FillBox(int x, int y, int w, int h, GColor c)
{
GAssert(x + w <= m_nWidth && y + h <= m_nHeight, "out of range");
GColor* pPixels;
int xx, yy;
for(yy = 0; yy < h; yy++)
{
pPixels = GetPixelRef(x, y + yy);
for(xx = 0; xx < w; xx++)
*(pPixels++) = c;
}
}
void GImage::DrawBox(int nX1, int nY1, int nX2, int nY2, GColor color){ int tmp; if(nX1 > nX2) { tmp = nX2; nX2 = nX1; nX1 = tmp; } if(nY1 > nY2) { tmp = nY2; nY2 = nY1; nY1 = tmp; } int n; for(n = nX1; n <= nX2; n++) { SetPixel(n, nY1, color); SetPixel(n, nY2, color); } for(n = nY1 + 1; n < nY2; n++) { SetPixel(nX1, n, color); SetPixel(nX2, n, color); }}void GImage::SoftDrawBox(int nX1, int nY1, int nX2, int nY2, GColor color, double dOpacity){ int x, y; for(x = nX1; x <= nX2; x++) { for(y = nY1; y <= nY2; y++) SoftSetPixel(x, y, color, dOpacity); }}void GImage::Scale(unsigned int nNewWidth, unsigned int nNewHeight){ int nOldWidth = m_nWidth; int nOldHeight = m_nHeight; GImage tmpImage; tmpImage.SwapData(this); SetSize(nNewWidth, nNewHeight); GColor col; int x, y; for(y = 0; y < (int)nNewHeight; y++) { for(x = 0; x < (int)nNewWidth; x++) { col = tmpImage.InterpolatePixel((float)(x * nOldWidth) / nNewWidth, (float)(y * nOldHeight) / nNewHeight); SetPixel(x, y, col); } }}void GImage::FlipHorizontally(){ GColor c1; GColor c2; int x, y; int nHalfWidth = (int)m_nWidth >> 1; for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < nHalfWidth; x++) { c1 = GetPixel(x, y); c2 = GetPixel(m_nWidth - 1 - x, y); SetPixel(x, y, c2); SetPixel(m_nWidth - 1 - x, y, c1); } }}void GImage::FlipVertically(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -