From: Michal Maciola Date: Tue, 14 Sep 2021 07:29:14 +0000 (+0200) Subject: common: Unmultiplicated colorspace X-Git-Tag: accepted/tizen/unified/20211112.135649~56 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c65937e872e8951f9ba03507d90cd21753622855;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git common: Unmultiplicated colorspace This patch introduces _STRAIGHT colorspaces (ABGR8888_STRAIGHT and ARGB8888_STRAIGHT) whose colors are un-alpha-premultiplied. Unmultiplicated colors are especially needed for wasm thorvg loader and svg2png / tvg2png. Only C version now. @issue: #791 --- diff --git a/inc/thorvg.h b/inc/thorvg.h index 1b2afdf..e5dcc66 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1310,8 +1310,10 @@ public: */ enum Colorspace { - ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. - ARGB8888 ///< The channels are joined in the order: alpha, red, green, blue. + ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. + ARGB8888, ///< The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. + ABGR8888_STRAIGHT, ///< @BETA_API The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. + ARGB8888_STRAIGHT, ///< @BETA_API The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. }; /** diff --git a/src/bin/svg2png/svg2png.cpp b/src/bin/svg2png/svg2png.cpp index 6428c33..c646918 100644 --- a/src/bin/svg2png/svg2png.cpp +++ b/src/bin/svg2png/svg2png.cpp @@ -90,7 +90,7 @@ public: return 1; } - if (canvas->target(buffer, w, w, h, tvg::SwCanvas::ARGB8888) != tvg::Result::Success) { + if (canvas->target(buffer, w, w, h, tvg::SwCanvas::ARGB8888_STRAIGHT) != tvg::Result::Success) { cout << "Error: Canvas target failure" << endl; return 1; } diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 4f6968d..85b9052 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -358,5 +358,6 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); bool rasterClear(SwSurface* surface); void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); +void rasterUnpremultiply(SwSurface* surface); #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 35d0ba4..e4a0092 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1399,10 +1399,10 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) bool rasterCompositor(SwSurface* surface) { - if (surface->cs == SwCanvas::ABGR8888) { + if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) { surface->blender.alpha = _colorAlpha; surface->blender.join = _abgrJoin; - } else if (surface->cs == SwCanvas::ARGB8888) { + } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { surface->blender.alpha = _colorAlpha; surface->blender.join = _argbJoin; } else { @@ -1515,6 +1515,31 @@ bool rasterClear(SwSurface* surface) } +void rasterUnpremultiply(SwSurface* surface) +{ + //TODO: Create simd avx and neon version + for (uint32_t y = 0; y < surface->h; y++) { + auto buffer = surface->buffer + surface->stride * y; + for (uint32_t x = 0; x < surface->w; ++x) { + uint8_t a = buffer[x] >> 24; + if (a == 255) { + continue; + } else if (a == 0) { + buffer[x] = 0x00ffffff; + } else { + uint16_t r = ((buffer[x] >> 8) & 0xff00) / a; + uint16_t g = ((buffer[x]) & 0xff00) / a; + uint16_t b = ((buffer[x] << 8) & 0xff00) / a; + if (r > 0xff) r = 0xff; + if (g > 0xff) g = 0xff; + if (b > 0xff) b = 0xff; + buffer[x] = (a << 24) | (r << 16) | (g << 8) | (b); + } + } + } +} + + bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity) { Matrix invTransform; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 81cb80a..8b3ec2c 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -318,6 +318,11 @@ void SwRenderer::clearCompositors() bool SwRenderer::postRender() { + //Unmultiply alpha if needed + if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { + rasterUnpremultiply(surface); + } + tasks.clear(); clearCompositors(); return true; diff --git a/src/wasm/thorvgwasm.cpp b/src/wasm/thorvgwasm.cpp index ba76449..ca615ab 100644 --- a/src/wasm/thorvgwasm.cpp +++ b/src/wasm/thorvgwasm.cpp @@ -224,7 +224,7 @@ private: mWidth = width; mHeight = height; mBuffer = make_unique(mWidth * mHeight * 4); - mSwCanvas->target((uint32_t *)mBuffer.get(), mWidth, mWidth, mHeight, SwCanvas::ABGR8888); + mSwCanvas->target((uint32_t *)mBuffer.get(), mWidth, mWidth, mHeight, SwCanvas::ABGR8888_STRAIGHT); if (mPicture) mPicture->size(width, height); }