void Image::BitmapData::setPixelColour (const int x, const int y, const Colour& colour) const noexcept { jassert (isPositiveAndBelow (x, width) && isPositiveAndBelow (y, height)); uint8* const pixel = getPixelPointer (x, y); const PixelARGB col (colour.getPixelARGB()); switch (pixelFormat) { case Image::ARGB: ((PixelARGB*) pixel)->set (col); break; case Image::RGB: ((PixelRGB*) pixel)->set (col); break; case Image::SingleChannel: *pixel = col.getAlpha(); break; default: jassertfalse; break; } }
//============================================================================== void Image::clear (const Rectangle<int>& area, const Colour& colourToClearTo) { const Rectangle<int> clipped (area.getIntersection (getBounds())); if (! clipped.isEmpty()) { const PixelARGB col (colourToClearTo.getPixelARGB()); const BitmapData destData (*this, clipped.getX(), clipped.getY(), clipped.getWidth(), clipped.getHeight(), BitmapData::writeOnly); uint8* dest = destData.data; int dh = clipped.getHeight(); while (--dh >= 0) { uint8* line = dest; dest += destData.lineStride; if (isARGB()) { for (int x = clipped.getWidth(); --x >= 0;) { ((PixelARGB*) line)->set (col); line += destData.pixelStride; } } else if (isRGB()) { for (int x = clipped.getWidth(); --x >= 0;) { ((PixelRGB*) line)->set (col); line += destData.pixelStride; } } else { for (int x = clipped.getWidth(); --x >= 0;) { *line = col.getAlpha(); line += destData.pixelStride; } } } } }
bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) { using namespace pnglibNamespace; const int width = image.getWidth(); const int height = image.getHeight(); png_structp pngWriteStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); if (pngWriteStruct == nullptr) return false; png_infop pngInfoStruct = png_create_info_struct (pngWriteStruct); if (pngInfoStruct == nullptr) { png_destroy_write_struct (&pngWriteStruct, (png_infopp) nullptr); return false; } png_set_write_fn (pngWriteStruct, &out, PNGHelpers::writeDataCallback, 0); png_set_IHDR (pngWriteStruct, pngInfoStruct, (png_uint_32) width, (png_uint_32) height, 8, image.hasAlphaChannel() ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); HeapBlock<uint8> rowData ((size_t) width * 4); png_color_8 sig_bit; sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; sig_bit.gray = 0; sig_bit.alpha = 8; png_set_sBIT (pngWriteStruct, pngInfoStruct, &sig_bit); png_write_info (pngWriteStruct, pngInfoStruct); png_set_shift (pngWriteStruct, &sig_bit); png_set_packing (pngWriteStruct); const Image::BitmapData srcData (image, Image::BitmapData::readOnly); for (int y = 0; y < height; ++y) { uint8* dst = rowData; const uint8* src = srcData.getLinePointer (y); if (image.hasAlphaChannel()) { for (int i = width; --i >= 0;) { PixelARGB p (*(const PixelARGB*) src); p.unpremultiply(); *dst++ = p.getRed(); *dst++ = p.getGreen(); *dst++ = p.getBlue(); *dst++ = p.getAlpha(); src += srcData.pixelStride; } } else { for (int i = width; --i >= 0;) { *dst++ = ((const PixelRGB*) src)->getRed(); *dst++ = ((const PixelRGB*) src)->getGreen(); *dst++ = ((const PixelRGB*) src)->getBlue(); src += srcData.pixelStride; } } png_bytep rowPtr = rowData; png_write_rows (pngWriteStruct, &rowPtr, 1); } png_write_end (pngWriteStruct, pngInfoStruct); png_destroy_write_struct (&pngWriteStruct, &pngInfoStruct); return true; }