📄 gimage.cpp
字号:
SafeSetPixel((int)(nX + dCos * dRadius), (int)(nY + dSin * dRadius), color); SafeSetPixel((int)(nX - dCos * dRadius), (int)(nY + dSin * dRadius), color); SafeSetPixel((int)(nX + dCos * dRadius), (int)(nY - dSin * dRadius), color); SafeSetPixel((int)(nX - dCos * dRadius), (int)(nY - dSin * dRadius), color); SafeSetPixel((int)(nX + dSin * dRadius), (int)(nY + dCos * dRadius), color); SafeSetPixel((int)(nX - dSin * dRadius), (int)(nY + dCos * dRadius), color); SafeSetPixel((int)(nX + dSin * dRadius), (int)(nY - dCos * dRadius), color); SafeSetPixel((int)(nX - dSin * dRadius), (int)(nY - dCos * dRadius), color); } */}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); } }}void GImage::PasteImage(int nX, int nY, GImage* pSourceImage, GColor colTransparent){ int x; int y; for(y = 0; y < pSourceImage->m_nHeight; y++) { if(nY + y >= m_nHeight) break; for(x = 0; x < pSourceImage->m_nWidth; x++) { if(nX + x >= m_nWidth) break; GColor col = pSourceImage->GetPixel(x, y); if(col != colTransparent) SetPixel(nX + x, nY + y, col); } }}void GImage::PasteImage(int nX, int nY, GImage* pSourceImage){ int x; int y; for(y = 0; y < pSourceImage->m_nHeight; y++) { if(nY + y >= m_nHeight) break; for(x = 0; x < pSourceImage->m_nWidth; x++) { if(nX + x >= m_nWidth) break; GColor col = pSourceImage->GetPixel(x, y); SetPixel(nX + x, nY + 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::SavePIGFile(FILE* pFile){ // Copy to a buffer int nSize = m_nWidth * m_nHeight * 3 + 2 * sizeof(int); unsigned char* pBytes = new unsigned char[nSize]; ((int*)pBytes)[0] = m_nWidth; ((int*)pBytes)[1] = m_nHeight; int nPos = 2 * sizeof(int); int x, y; GColor col; for(y = 0; y < m_nHeight; y++) { for(x = 0; x < m_nWidth; x++) { col = GetPixel(x, y); pBytes[nPos++] = gRed(col); pBytes[nPos++] = gGreen(col); pBytes[nPos++] = gBlue(col); } } GAssert(nPos == nSize, "internal error"); // Compress it int nNewSize; unsigned char* pCompressed = GCompress::Compress(pBytes, nSize, &nNewSize); delete(pBytes); if(!pCompressed) { GAssert(false, "error compressing image"); return false; } // Save it bool bOK = true; if(fwrite(&nNewSize, sizeof(int), 1, pFile) != 1) bOK = false; else if(fwrite(pCompressed, nNewSize, 1, pFile) != 1) bOK = false; delete(pCompressed); return bOK;}bool GImage::SavePIGFile(const char* szFilename){ FILE* pFile = fopen(szFilename, "wb"); if(!pFile) return false; bool bOK = SavePIGFile(pFile); fclose(pFile); return bOK;}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::LoadPIGFile(const unsigned char* pBytes, int nSize){ // Decompress the data GAssert(*(int*)pBytes == nSize - (int)sizeof(int), "bad data"); int nNewSize; unsigned char* pData = GCompress::Decompress(pBytes + sizeof(int), nSize - sizeof(int), &nNewSize); if(!pData) return false; // Parse the data int nWidth = ((int*)pData)[0]; int nHeight = ((int*)pData)[1]; if(nSize != nWidth * nHeight * 3 + 2 * (int)sizeof(int)) { GAssert(false, "bad PIG file"); return false; } SetSize(nWidth, nHeight); int nPos = 2 * sizeof(int); int x, y, r, g, b; for(y = 0; y < nHeight; y++) { for(x = 0; x < nHeight; x++) { r = pData[nPos++]; g = pData[nPos++]; b = pData[nPos++]; SetPixel(x, y, gRGB(r, g, b)); } } 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::DrawBox(int nX1, int nY1, int nX2, int nY2, GColor color, bool bFill){ int tmp; if(nX1 > nX2) { tmp = nX2; nX2 = nX1; nX1 = tmp; } if(nY1 > nY2) { tmp = nY2; nY2 = nY1; nY1 = tmp; } if(bFill) { int x, y; for(x = nX1; x <= nX2; x++) { for(y = nY1; y <= nY2; y++) SetPixel(x, y, color); } } else { 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(){ GColor c1; GColor c2; int x, y; int nHalfHeight = (int)m_nHeight >> 1; for(x = 0; x < (int)m_nWidth; x++) { for(y = 0; y < nHalfHeight; y++) { c1 = GetPixel(x, y); c2 = GetPixel(x, m_nHeight - 1 - y); SetPixel(x, y, c2); SetPixel(x, m_nHeight - 1 - y, c1); } }}void GImage::SwapData(GImage* pSwapImage){ GColor* pTmpRGBQuads = m_pPixels; unsigned int nTmpWidth = m_nWidth; unsigned int nTmpHeight = m_nHeight; m_pPixels = pSwapImage->m_pPixels; m_nWidth = pSwapImage->m_nWidth; m_nHeight = pSwapImage->m_nHeight; pSwapImage->m_pPixels = pTmpRGBQuads; pSwapImage->m_nWidth = nTmpWidth; pSwapImage->m_nHeight = nTmpHeight;}void GImage::Convolve(GImage* pKernel){ GImage NewImage; NewImage.SetSize(m_nWidth, m_nHeight); GColor c1; GColor c2; int nHalfKWidth = (int)pKernel->m_nWidth >> 1; int nHalfKHeight = (int)pKernel->m_nHeight >> 1; int nRSum, nGSum, nBSum; int nRTot, nGTot, nBTot; nRTot = 0; nGTot = 0; nBTot = 0; int kx, ky; for(ky = 0; ky < (int)pKernel->m_nHeight; ky++) { for(kx = 0; kx < (int)pKernel->m_nWidth; kx++) { c1 = pKernel->GetPixel(kx, ky); nRTot += gRed(c1); nGTot += gGreen(c1); nBTot += gBlue(c1); } } int x, y; for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < (int)m_nWidth; x++) { nRSum = 0; nGSum = 0; nBSum = 0; for(ky = 0; ky < (int)pKernel->m_nHeight; ky++) { for(kx = 0; kx < (int)pKernel->m_nWidth; kx++) { 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); } } NewImage.SetPixel(x, y, gRGB(nRSum / nRTot, nGSum / nGTot, nBSum / nBTot)); } } SwapData(&NewImage);}void GImage::ConvolveKernel(GImage* pKernel){ GImage NewImage; NewImage.SetSize(m_nWidth, m_nHeight); GColor c1; GColor c2; int nHalfKWidth = (int)pKernel->m_nWidth >> 1; int nHalfKHeight = (int)pKernel->m_nHeight >> 1; int nRSum, nGSum, nBSum; int x, y; int kx, ky; for(y = 0; y < (int)m_nHeight; y++) { for(x = 0; x < (int)m_nWidth; x++) { nRSum = 0; nGSum = 0; nBSum = 0; for(ky = 0; ky < (int)pKernel->m_nHeight; ky++) { for(kx = 0; kx < (int)pKernel->m_nWidth; kx++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -