loader: Support ABGR colorspace 03/289903/1
authorJunsuChoi <jsuya.choi@samsung.com>
Fri, 20 Jan 2023 04:13:01 +0000 (13:13 +0900)
committerMichal Szczecinski <m.szczecinsk@partner.samsung.com>
Wed, 15 Mar 2023 07:30:30 +0000 (08:30 +0100)
Since the color space is set at the time of specifying the target buffer of the canvas,
there is no way to know the color space when the picture is loaded.
So, check the color space applied to SwCanvas at the time of reload()
and change the color space.

There is an issue of BGR color space support for each loader.
The external_jpg loader resets the TJPF color space and calls read() to get a new buffer.
In the case of external_png, we need to change the color value directly
because it have to start over from begin_read_*.

This solution can affect performance as much as it access again image buffer
that have already been `read()` done. However, this only happens once.

Change-Id: Ib7f25b5bc5871cfe59ad3963d26536269b48a3f5

17 files changed:
src/lib/gl_engine/tvgGlRenderer.cpp
src/lib/gl_engine/tvgGlRenderer.h
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwRenderer.h
src/lib/tvgLoadModule.h
src/lib/tvgPictureImpl.h
src/lib/tvgRender.h
src/loaders/external_jpg/tvgJpgLoader.cpp
src/loaders/external_jpg/tvgJpgLoader.h
src/loaders/external_png/tvgPngLoader.cpp
src/loaders/external_png/tvgPngLoader.h
src/loaders/jpg/tvgJpgLoader.cpp
src/loaders/jpg/tvgJpgLoader.h
src/loaders/png/tvgPngLoader.cpp
src/loaders/png/tvgPngLoader.h
src/loaders/raw/tvgRawLoader.cpp
src/loaders/raw/tvgRawLoader.h

index 517e64e4e47bb3b7a7e6c2df74dec6541a8a5e95..fcd33ad0dd2fdf33514817ab102397428d6d9916 100644 (file)
@@ -123,6 +123,13 @@ bool GlRenderer::endComposite(TVG_UNUSED Compositor* cmp)
 }
 
 
+int32_t GlRenderer::colorSpace()
+{
+    //TODO: return a proper color space value.
+    return -1;
+}
+
+
 bool GlRenderer::renderImage(TVG_UNUSED void* data)
 {
     return false;
index 4d1bb877946eddf443f47045141e4a18b69a4d15..3263231e15b1f2a0dc44d4843db966d6c8de6ec5 100644 (file)
@@ -50,6 +50,8 @@ public:
     bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
     bool endComposite(Compositor* cmp) override;
 
+    uint32_t colorSpace() override;
+
     static GlRenderer* gen();
     static int init(TVG_UNUSED uint32_t threads);
     static int32_t init();
index 17dff5727863d8d54426336625a24f1b9d66f1ac..6a1a881932fd8666f3165cdbd26c26a4cdc8ee89 100644 (file)
@@ -296,7 +296,7 @@ bool SwRenderer::viewport(const RenderRegion& vp)
 }
 
 
-bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs)
+bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace)
 {
     if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
 
@@ -306,7 +306,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
     surface->stride = stride;
     surface->w = w;
     surface->h = h;
-    surface->cs = cs;
+    surface->cs = colorSpace;
 
     vport.x = vport.y = 0;
     vport.w = surface->w;
@@ -661,6 +661,13 @@ SwRenderer::SwRenderer():mpool(globalMpool)
 }
 
 
+uint32_t SwRenderer::colorSpace()
+{
+    if (surface) return surface->cs;
+    return tvg::SwCanvas::ARGB8888;
+}
+
+
 bool SwRenderer::init(uint32_t threads)
 {
     if ((initEngineCnt++) > 0) return true;
index c3eadbde941793775eed381365b06398e7b4b142..690b7ff0dbe4784757c3afdc56a7948dd9c16975 100644 (file)
@@ -50,7 +50,7 @@ public:
 
     bool clear() override;
     bool sync() override;
-    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
+    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace);
     bool mempool(bool shared);
 
     Compositor* target(const RenderRegion& region) override;
@@ -58,6 +58,8 @@ public:
     bool endComposite(Compositor* cmp) override;
     void clearCompositors();
 
+    uint32_t colorSpace() override;
+
     static SwRenderer* gen();
     static bool init(uint32_t threads);
     static int32_t init();
index 2c2ffda2094f0ed9d3c5c16846a57ecfcd78cf04..4637c90d81718bbab0d45bbf4c3d7c7d0591b293 100644 (file)
@@ -37,6 +37,7 @@ public:
     float vw = 0;
     float vh = 0;
     float w = 0, h = 0;         //default image size
+    uint32_t colorSpace = SwCanvas::ARGB8888;
 
     virtual ~LoadModule() {}
 
@@ -49,7 +50,7 @@ public:
 
     virtual bool read() = 0;
     virtual bool close() = 0;
-    virtual unique_ptr<Surface> bitmap() { return nullptr; }
+    virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; }
     virtual unique_ptr<Paint> paint() { return nullptr; }
 };
 
index b7e2ba038fa8b7304f6e7e51f7405ee2a790f6c6..6ef231322a7a7bfdbf395ae5f096647276281cda 100644 (file)
@@ -69,6 +69,7 @@ struct Picture::Impl
     void* rdata = nullptr;            //engine data
     float w = 0, h = 0;
     bool resizing = false;
+    uint32_t rendererColorSpace = 0;
 
     ~Impl()
     {
@@ -104,7 +105,7 @@ struct Picture::Impl
                 }
             }
             free(surface);
-            if ((surface = loader->bitmap().release())) {
+            if ((surface = loader->bitmap(rendererColorSpace).release())) {
                 loader->close();
                 return RenderUpdateFlag::Image;
             }
@@ -128,6 +129,7 @@ struct Picture::Impl
 
     void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
     {
+        rendererColorSpace = renderer.colorSpace();
         auto flag = reload();
 
         if (surface) {
index e9ad821093c92ddc0b7204d4b282e1fa3bf5206d..55bbec1fc469944d5c7c98d75737305468e90fe5 100644 (file)
@@ -203,6 +203,8 @@ public:
     virtual Compositor* target(const RenderRegion& region) = 0;
     virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
     virtual bool endComposite(Compositor* cmp) = 0;
+
+    virtual uint32_t colorSpace() = 0;
 };
 
 }
index 5920f7cf83b01acbf00be9094b332ee2716b5ab9..7ead54c185b27b7e1299d5544f5a533a592b9bd5 100644 (file)
@@ -37,6 +37,24 @@ void JpgLoader::clear()
     freeData = false;
 }
 
+uint32_t convertColorSpaceType(uint32_t colorSpace)
+{
+    uint32_t tjpfColorSpace = TJPF_RGBX;
+    switch (colorSpace)
+    {
+        case SwCanvas::ARGB8888:
+        case SwCanvas::ARGB8888_STRAIGHT:
+        default:
+           tjpfColorSpace = TJPF_BGRX;
+        break;
+        case SwCanvas::ABGR8888:
+        case SwCanvas::ABGR8888_STRAIGHT:
+           tjpfColorSpace = TJPF_RGBX;
+        break;
+    }
+    return tjpfColorSpace;
+}
+
 /************************************************************************/
 /* External Class Implementation                                        */
 /************************************************************************/
@@ -127,11 +145,11 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
 bool JpgLoader::read()
 {
     if (image) tjFree(image);
-    image = (unsigned char *)tjAlloc(static_cast<int>(w) * static_cast<int>(h) * tjPixelSize[TJPF_BGRX]);
+    image = (unsigned char *)tjAlloc(static_cast<int>(w) * static_cast<int>(h) * tjPixelSize[convertColorSpaceType(colorSpace)]);
     if (!image) return false;
 
     //decompress jpg image
-    if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), TJPF_BGRX, 0) < 0) {
+    if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), convertColorSpaceType(colorSpace), 0) < 0) {
         TVGERR("JPG LOADER", "%s", tjGetErrorStr());
         tjFree(image);
         image = nullptr;
@@ -149,16 +167,20 @@ bool JpgLoader::close()
 }
 
 
-unique_ptr<Surface> JpgLoader::bitmap()
+unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
 {
     if (!image) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        read();
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
     surface->buffer = (uint32_t*)(image);
     surface->stride = w;
     surface->w = w;
     surface->h = h;
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
index c8c934583e2965b839ae87d51ba0e0b639662ac0..da7b59ed1dd1c782363a942e94a440ebdf909750 100644 (file)
@@ -38,7 +38,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
 
 private:
     void clear();
index 4061a49fc14746cd5fca93cb06e24542a39599ef..2dbedd86b51bc2179e882ef8e6f581bf32c0401b 100644 (file)
@@ -42,6 +42,24 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
 }
 
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
+
 PngLoader::PngLoader()
 {
     image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
@@ -110,16 +128,21 @@ bool PngLoader::close()
     return true;
 }
 
-unique_ptr<Surface> PngLoader::bitmap()
+unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
 {
     if (!content) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(content, w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(content);
+    surface->buffer = content;
     surface->stride = w;
     surface->w = w;
     surface->h = h;
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
+
index 39d5fdb0dc0c4db1503e22f4b4b897fa6d380bf3..48f44f579fb2c1a2882ceae775c315acbb5fa189 100644 (file)
@@ -37,11 +37,11 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
 
 private:
     png_imagep image = nullptr;
-    const uint32_t* content = nullptr;
+    uint32_t* content = nullptr;
 };
 
 #endif //_TVG_PNG_LOADER_H_
index dc50848f823764160b38bf3e6c7fd27733718cfc..2b16090f287a894b1b62b195ffbefd715a10caba 100644 (file)
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
+
 void JpgLoader::clear()
 {
     jpgdDelete(decoder);
@@ -110,18 +128,22 @@ bool JpgLoader::close()
 }
 
 
-unique_ptr<Surface> JpgLoader::bitmap()
+unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
 {
     this->done();
 
     if (!image) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(image);
+    surface->buffer = reinterpret_cast<uint32_t*>(image);
     surface->stride = static_cast<uint32_t>(w);
     surface->w = static_cast<uint32_t>(w);
     surface->h = static_cast<uint32_t>(h);
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
index 6d2febe94f01fc6d94668dd3ee2d2b64b6e9f180..02aee45cfd93d33e0ce86ad2c7465a734771eeb4 100644 (file)
@@ -45,7 +45,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
     void run(unsigned tid) override;
 };
 
index cc44b0d0909debfd24bd693521b352e6536d764e..7233f30a33191b63b83ce5d243d7a633a49436b1 100644 (file)
@@ -49,6 +49,24 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
 }
 
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
+
 void PngLoader::clear()
 {
     lodepng_state_cleanup(&state);
@@ -163,18 +181,22 @@ bool PngLoader::close()
 }
 
 
-unique_ptr<Surface> PngLoader::bitmap()
+unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
 {
     this->done();
 
     if (!image) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(image);
+    surface->buffer = reinterpret_cast<uint32_t*>(image);
     surface->stride = static_cast<uint32_t>(w);
     surface->w = static_cast<uint32_t>(w);
     surface->h = static_cast<uint32_t>(h);
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
index 579d197ad6559a8023b8b55928819436929a7324..5e3c930443dd87c69dd7348daeba5ba44d2ddecc 100644 (file)
@@ -48,7 +48,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
     void run(unsigned tid) override;
 };
 
index d8c05594f2f69f9ebb58f56750d047b5679c2816..524cff1c56f1d81a113157ef0c8c60115ac89a0c 100644 (file)
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
 /************************************************************************/
 /* External Class Implementation                                        */
 /************************************************************************/
@@ -55,7 +72,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
         if (!content) return false;
         memcpy((void*)content, data, sizeof(uint32_t) * w * h);
     }
-    else content = data;
+    else content = const_cast<uint32_t*>(data);
 
     return true;
 }
@@ -73,16 +90,20 @@ bool RawLoader::close()
 }
 
 
-unique_ptr<Surface> RawLoader::bitmap()
+unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
 {
     if (!content) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(content, w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(content);
-    surface->stride = (uint32_t)w;
-    surface->w = (uint32_t)w;
-    surface->h = (uint32_t)h;
-    surface->cs = SwCanvas::ARGB8888;
+    surface->buffer = content;
+    surface->stride = static_cast<uint32_t>(w);
+    surface->w = static_cast<uint32_t>(w);
+    surface->h = static_cast<uint32_t>(h);
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
index d3810107e87ecd90aa2ebb01a6f5b49084a7c657..a5e3d5936712787e97724a9372e86b692605a09e 100644 (file)
@@ -26,7 +26,7 @@
 class RawLoader : public LoadModule
 {
 public:
-    const uint32_t* content = nullptr;
+    uint32_t* content = nullptr;
     bool copy = false;
 
     ~RawLoader();
@@ -36,7 +36,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
 };