mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-20 06:52:03 +00:00
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
This commit is contained in:
parent
86a8bbbb88
commit
479cea74cc
6 changed files with 39 additions and 6 deletions
|
@ -1310,8 +1310,10 @@ public:
|
||||||
*/
|
*/
|
||||||
enum Colorspace
|
enum Colorspace
|
||||||
{
|
{
|
||||||
ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red.
|
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.
|
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.
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
return 1;
|
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;
|
cout << "Error: Canvas target failure" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
|
||||||
bool rasterClear(SwSurface* surface);
|
bool rasterClear(SwSurface* surface);
|
||||||
void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
||||||
|
void rasterUnpremultiply(SwSurface* surface);
|
||||||
|
|
||||||
#endif /* _TVG_SW_COMMON_H_ */
|
#endif /* _TVG_SW_COMMON_H_ */
|
||||||
|
|
|
@ -1399,10 +1399,10 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
||||||
|
|
||||||
bool rasterCompositor(SwSurface* surface)
|
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.alpha = _colorAlpha;
|
||||||
surface->blender.join = _abgrJoin;
|
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.alpha = _colorAlpha;
|
||||||
surface->blender.join = _argbJoin;
|
surface->blender.join = _argbJoin;
|
||||||
} else {
|
} 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)
|
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity)
|
||||||
{
|
{
|
||||||
Matrix invTransform;
|
Matrix invTransform;
|
||||||
|
|
|
@ -318,6 +318,11 @@ void SwRenderer::clearCompositors()
|
||||||
|
|
||||||
bool SwRenderer::postRender()
|
bool SwRenderer::postRender()
|
||||||
{
|
{
|
||||||
|
//Unmultiply alpha if needed
|
||||||
|
if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
|
||||||
|
rasterUnpremultiply(surface);
|
||||||
|
}
|
||||||
|
|
||||||
tasks.clear();
|
tasks.clear();
|
||||||
clearCompositors();
|
clearCompositors();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -224,7 +224,7 @@ private:
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
mBuffer = make_unique<uint8_t[]>(mWidth * mHeight * 4);
|
mBuffer = make_unique<uint8_t[]>(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);
|
if (mPicture) mPicture->size(width, height);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue