void GImage::blit(int x, int y, GImage* pSource) { int sx = 0; int sy = 0; int sw = pSource->width(); int sh = pSource->height(); if(x < 0) { sx -= x; sw += x; x = 0; } if(x + sw > (int)m_width) sw = (int)m_width - x; if(y < 0) { sy -= y; sh += y; y = 0; } if(y + sh > (int)m_height) sh = (int)m_height - y; int dst = y * m_width + x; int src = sy * pSource->m_width + sx; int xx, a; unsigned int 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] = gARGB(std::max(a, (int)gAlpha(pixOld)), (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_width; src += pSource->m_width; } }
void GBillboardWorld::drawSection(GImage* pImage, double* pDepthMap, GCamera& camera, GBBAugmented& bb, G3DVector* pBotLeft, G3DVector* pBotRight, G3DVector* pTopRight, G3DVector* pTopLeft) { double a, b, z; int yBegin = std::max(0, (int)floor(std::max(pBotLeft->m_vals[1], pBotRight->m_vals[1]))); int yEnd = std::min((int)pImage->height(), (int)floor(std::min(pTopLeft->m_vals[1], pTopRight->m_vals[1])) + (pTopLeft == pTopRight ? 1 : 0)); for(int y = yBegin; y < yEnd; y++) { double denom = pTopLeft->m_vals[1] - pBotLeft->m_vals[1]; if(std::abs(denom) > 1e-6) a = ((double)y - pBotLeft->m_vals[1]) / denom * (pTopLeft->m_vals[0] - pBotLeft->m_vals[0]) + pBotLeft->m_vals[0]; else a = pTopLeft->m_vals[0]; denom = pTopRight->m_vals[1] - pBotRight->m_vals[1]; if(std::abs(denom) > 1e-6) b = ((double)y - pBotRight->m_vals[1]) / denom * (pTopRight->m_vals[0] - pBotRight->m_vals[0]) + pBotRight->m_vals[0]; else b = pTopRight->m_vals[0]; if(b < a) std::swap(a, b); int xBegin = std::max(0, (int)floor(a)); int xEnd = std::min((int)pImage->width() - 1, (int)ceil(b)); double* pDM = pDepthMap + pImage->width() * y + xBegin; unsigned int* pPix = xBegin <= xEnd ? pImage->pixelRef(xBegin, pImage->height() - 1 - y) : NULL; for(int x = xBegin; x <= xEnd; x++) { unsigned int col = bb.getPixel(camera, x, y, &z); if(z > 0.0 && z < *pDM && gAlpha(col) > 0) { *pDM = z; *pPix = col; } // *pPix = 0xffffffff; pDM++; pPix++; } } }
void writePng(GImage* pImage, FILE* pFile, bool bIncludeAlphaChannel) { // Set the jump value (This has something to do with enabling the error handler) GPNGWriter writer; if(setjmp(png_jmpbuf(writer.m_pWriteStruct))) throw Ex("Failed to set the jump value"); // Init the IO png_init_io(writer.m_pWriteStruct, pFile); png_set_compression_level(writer.m_pWriteStruct, Z_BEST_COMPRESSION); // Write image stats and settings unsigned long width = pImage->m_width; unsigned long height = pImage->m_height; png_set_IHDR(writer.m_pWriteStruct, writer.m_pInfoStruct, width, height, 8, bIncludeAlphaChannel ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(writer.m_pWriteStruct, writer.m_pInfoStruct); png_set_packing(writer.m_pWriteStruct); // Write the image data unsigned long channels = bIncludeAlphaChannel ? 4 : 3; unsigned long rowbytes = width * channels; unsigned char* pRow = new unsigned char[rowbytes]; unsigned int* pPix = pImage->m_pPixels; if(channels == 4) { for(unsigned int i = 0; i < height; i++) { unsigned char* pBytes = pRow; for(unsigned int j = 0; j < width; j++) { *(pBytes++) = gRed(*pPix); *(pBytes++) = gGreen(*pPix); *(pBytes++) = gBlue(*pPix); *(pBytes++) = gAlpha(*pPix); pPix++; } png_write_row(writer.m_pWriteStruct, pRow); } } else if(channels == 3) { for(unsigned int i = 0; i < height; i++) { unsigned char* pBytes = pRow; for(unsigned int j = 0; j < width; j++) { *(pBytes++) = gRed(*pPix); *(pBytes++) = gGreen(*pPix); *(pBytes++) = gBlue(*pPix); } png_write_row(writer.m_pWriteStruct, pRow); } } else { delete[] pRow; throw Ex("Unsupported number of channels"); } delete[] pRow; png_write_end(writer.m_pWriteStruct, writer.m_pInfoStruct); }