diff options
-rwxr-xr-x | gtk/PlatGTK.cxx | 15 | ||||
-rw-r--r-- | src/XPM.cxx | 15 | ||||
-rw-r--r-- | src/XPM.h | 2 | ||||
-rw-r--r-- | win32/PlatWin.cxx | 27 |
4 files changed, 28 insertions, 31 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index a319e31ba..2947ffa11 100755 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -601,18 +601,13 @@ void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsi rc.top += (rc.Height() - height) / 2; rc.bottom = rc.top + height; - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); + const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); const int ucs = stride * height; std::vector<unsigned char> image(ucs); - for (int iy=0; iy<height; iy++) { - for (int ix=0; ix<width; ix++) { - unsigned char *pixel = &image[0] + iy*stride + ix * 4; - const unsigned char alpha = pixelsImage[3]; - pixel[2] = (*pixelsImage++) * alpha / 255; - pixel[1] = (*pixelsImage++) * alpha / 255; - pixel[0] = (*pixelsImage++) * alpha / 255; - pixel[3] = *pixelsImage++; - } + for (ptrdiff_t iy=0; iy<height; iy++) { + unsigned char *pixel = &image[0] + iy*stride; + RGBAImage::BGRAFromRGBA(pixel, pixelsImage, width); + pixelsImage += RGBAImage::bytesPerPixel * width; } cairo_surface_t *psurfImage = cairo_image_surface_create_for_data(&image[0], CAIRO_FORMAT_ARGB32, width, height, stride); diff --git a/src/XPM.cxx b/src/XPM.cxx index f95580403..380ae14c4 100644 --- a/src/XPM.cxx +++ b/src/XPM.cxx @@ -264,6 +264,21 @@ void RGBAImage::SetPixel(int x, int y, ColourDesired colour, int alpha) { pixel[3] = static_cast<unsigned char>(alpha); } +// Transform a block of pixels from RGBA to BGRA with premultiplied alpha. +// Used for DrawRGBAImage on some platforms. +void RGBAImage::BGRAFromRGBA(unsigned char *pixelsBGRA, const unsigned char *pixelsRGBA, size_t count) noexcept { + for (size_t i = 0; i < count; i++) { + const unsigned char alpha = pixelsRGBA[3]; + // Input is RGBA, output is BGRA with premultiplied alpha + pixelsBGRA[2] = pixelsRGBA[0] * alpha / 255; + pixelsBGRA[1] = pixelsRGBA[1] * alpha / 255; + pixelsBGRA[0] = pixelsRGBA[2] * alpha / 255; + pixelsBGRA[3] = alpha; + pixelsRGBA += bytesPerPixel; + pixelsBGRA += bytesPerPixel; + } +} + RGBAImageSet::RGBAImageSet() : height(-1), width(-1) { } @@ -50,6 +50,7 @@ class RGBAImage { float scale; std::vector<unsigned char> pixelBytes; public: + static constexpr size_t bytesPerPixel = 4; RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_); explicit RGBAImage(const XPM &xpm); RGBAImage(const RGBAImage &) = default; @@ -65,6 +66,7 @@ public: int CountBytes() const; const unsigned char *Pixels() const; void SetPixel(int x, int y, ColourDesired colour, int alpha); + static void BGRAFromRGBA(unsigned char *pixelsBGRA, const unsigned char *pixelsRGBA, size_t count) noexcept; }; /** diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 6e5859ca3..fadc7d0f0 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -780,15 +780,10 @@ void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsig HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem); for (int y=height-1; y>=0; y--) { - for (int x=0; x<width; x++) { - unsigned char *pixel = static_cast<unsigned char *>(image) + (y*width+x) * 4; - const unsigned char alpha = pixelsImage[3]; - // Input is RGBA, output is BGRA with premultiplied alpha - pixel[2] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255); - pixel[1] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255); - pixel[0] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255); - pixel[3] = *pixelsImage++; - } + // Bits flipped vertically + unsigned char *pixel = static_cast<unsigned char *>(image) + RGBAImage::bytesPerPixel * y * width; + RGBAImage::BGRAFromRGBA(pixel, pixelsImage, width); + pixelsImage += RGBAImage::bytesPerPixel * width; } const BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; @@ -1445,18 +1440,8 @@ void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsig rc.top += std::floor((rc.Height() - height) / 2); rc.bottom = rc.top + height; - std::vector<unsigned char> image(height * width * 4); - for (int yPixel=0; yPixel<height; yPixel++) { - for (int xPixel = 0; xPixel<width; xPixel++) { - unsigned char *pixel = &image[0] + (yPixel*width + xPixel) * 4; - const unsigned char alpha = pixelsImage[3]; - // Input is RGBA, output is BGRA with premultiplied alpha - pixel[2] = (*pixelsImage++) * alpha / 255; - pixel[1] = (*pixelsImage++) * alpha / 255; - pixel[0] = (*pixelsImage++) * alpha / 255; - pixel[3] = *pixelsImage++; - } - } + std::vector<unsigned char> image(RGBAImage::bytesPerPixel * height * width); + RGBAImage::BGRAFromRGBA(image.data(), pixelsImage, static_cast<ptrdiff_t>(height) * width); ID2D1Bitmap *bitmap = nullptr; const D2D1_SIZE_U size = D2D1::SizeU(width, height); |