diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 3bba5d4c..c72c66ef 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -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; diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index 4d1bb877..3263231e 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -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(); diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 17dff572..6a1a8819 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -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; diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index c3eadbde..690b7ff0 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -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(); diff --git a/src/lib/tvgLoadModule.h b/src/lib/tvgLoadModule.h index 2c2ffda2..4637c90d 100644 --- a/src/lib/tvgLoadModule.h +++ b/src/lib/tvgLoadModule.h @@ -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 bitmap() { return nullptr; } + virtual unique_ptr bitmap(uint32_t colorSpace) { return nullptr; } virtual unique_ptr paint() { return nullptr; } }; diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index b7e2ba03..6ef23132 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -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& clips, RenderUpdateFlag pFlag, bool clipper) { + rendererColorSpace = renderer.colorSpace(); auto flag = reload(); if (surface) { diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index e9ad8210..55bbec1f 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -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; }; } diff --git a/src/loaders/external_jpg/tvgJpgLoader.cpp b/src/loaders/external_jpg/tvgJpgLoader.cpp index 5920f7cf..7ead54c1 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.cpp +++ b/src/loaders/external_jpg/tvgJpgLoader.cpp @@ -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(w) * static_cast(h) * tjPixelSize[TJPF_BGRX]); + image = (unsigned char *)tjAlloc(static_cast(w) * static_cast(h) * tjPixelSize[convertColorSpaceType(colorSpace)]); if (!image) return false; //decompress jpg image - if (tjDecompress2(jpegDecompressor, data, size, image, static_cast(w), 0, static_cast(h), TJPF_BGRX, 0) < 0) { + if (tjDecompress2(jpegDecompressor, data, size, image, static_cast(w), 0, static_cast(h), convertColorSpaceType(colorSpace), 0) < 0) { TVGERR("JPG LOADER", "%s", tjGetErrorStr()); tjFree(image); image = nullptr; @@ -149,16 +167,20 @@ bool JpgLoader::close() } -unique_ptr JpgLoader::bitmap() +unique_ptr JpgLoader::bitmap(uint32_t colorSpace) { if (!image) return nullptr; + if (this->colorSpace != colorSpace) { + this->colorSpace = colorSpace; + read(); + } auto surface = static_cast(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); } diff --git a/src/loaders/external_jpg/tvgJpgLoader.h b/src/loaders/external_jpg/tvgJpgLoader.h index c8c93458..da7b59ed 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.h +++ b/src/loaders/external_jpg/tvgJpgLoader.h @@ -38,7 +38,7 @@ public: bool read() override; bool close() override; - unique_ptr bitmap() override; + unique_ptr bitmap(uint32_t colorSpace) override; private: void clear(); diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index 4061a49f..2dbedd86 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -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(calloc(1, sizeof(png_image))); @@ -110,16 +128,21 @@ bool PngLoader::close() return true; } -unique_ptr PngLoader::bitmap() +unique_ptr PngLoader::bitmap(uint32_t colorSpace) { if (!content) return nullptr; + if (this->colorSpace != colorSpace) { + this->colorSpace = colorSpace; + _changeColorSpace(content, w, h); + } auto surface = static_cast(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); } + diff --git a/src/loaders/external_png/tvgPngLoader.h b/src/loaders/external_png/tvgPngLoader.h index 39d5fdb0..48f44f57 100644 --- a/src/loaders/external_png/tvgPngLoader.h +++ b/src/loaders/external_png/tvgPngLoader.h @@ -37,11 +37,11 @@ public: bool read() override; bool close() override; - unique_ptr bitmap() override; + unique_ptr bitmap(uint32_t colorSpace) override; private: png_imagep image = nullptr; - const uint32_t* content = nullptr; + uint32_t* content = nullptr; }; #endif //_TVG_PNG_LOADER_H_ diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index dc50848f..2b16090f 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -28,6 +28,24 @@ /* 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 JpgLoader::bitmap() +unique_ptr JpgLoader::bitmap(uint32_t colorSpace) { this->done(); if (!image) return nullptr; + if (this->colorSpace != colorSpace) { + this->colorSpace = colorSpace; + _changeColorSpace(reinterpret_cast(image), w, h); + } auto surface = static_cast(malloc(sizeof(Surface))); - surface->buffer = (uint32_t*)(image); + surface->buffer = reinterpret_cast(image); surface->stride = static_cast(w); surface->w = static_cast(w); surface->h = static_cast(h); - surface->cs = SwCanvas::ARGB8888; + surface->cs = colorSpace; return unique_ptr(surface); } diff --git a/src/loaders/jpg/tvgJpgLoader.h b/src/loaders/jpg/tvgJpgLoader.h index 6d2febe9..02aee45c 100644 --- a/src/loaders/jpg/tvgJpgLoader.h +++ b/src/loaders/jpg/tvgJpgLoader.h @@ -45,7 +45,7 @@ public: bool read() override; bool close() override; - unique_ptr bitmap() override; + unique_ptr bitmap(uint32_t colorSpace) override; void run(unsigned tid) override; }; diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index cc44b0d0..7233f30a 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -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 PngLoader::bitmap() +unique_ptr PngLoader::bitmap(uint32_t colorSpace) { this->done(); if (!image) return nullptr; + if (this->colorSpace != colorSpace) { + this->colorSpace = colorSpace; + _changeColorSpace(reinterpret_cast(image), w, h); + } auto surface = static_cast(malloc(sizeof(Surface))); - surface->buffer = (uint32_t*)(image); + surface->buffer = reinterpret_cast(image); surface->stride = static_cast(w); surface->w = static_cast(w); surface->h = static_cast(h); - surface->cs = SwCanvas::ARGB8888; + surface->cs = colorSpace; return unique_ptr(surface); } diff --git a/src/loaders/png/tvgPngLoader.h b/src/loaders/png/tvgPngLoader.h index 579d197a..5e3c9304 100644 --- a/src/loaders/png/tvgPngLoader.h +++ b/src/loaders/png/tvgPngLoader.h @@ -48,7 +48,7 @@ public: bool read() override; bool close() override; - unique_ptr bitmap() override; + unique_ptr bitmap(uint32_t colorSpace) override; void run(unsigned tid) override; }; diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index d8c05594..524cff1c 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -29,6 +29,23 @@ /* 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(data); return true; } @@ -73,16 +90,20 @@ bool RawLoader::close() } -unique_ptr RawLoader::bitmap() +unique_ptr RawLoader::bitmap(uint32_t colorSpace) { if (!content) return nullptr; + if (this->colorSpace != colorSpace) { + this->colorSpace = colorSpace; + _changeColorSpace(content, w, h); + } auto surface = static_cast(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(w); + surface->w = static_cast(w); + surface->h = static_cast(h); + surface->cs = colorSpace; return unique_ptr(surface); } diff --git a/src/loaders/raw/tvgRawLoader.h b/src/loaders/raw/tvgRawLoader.h index d3810107..a5e3d593 100644 --- a/src/loaders/raw/tvgRawLoader.h +++ b/src/loaders/raw/tvgRawLoader.h @@ -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 bitmap() override; + unique_ptr bitmap(uint32_t colorSpace) override; };