diff --git a/src/loaders/external_jpg/tvgJpgLoader.cpp b/src/loaders/external_jpg/tvgJpgLoader.cpp index 58338da4..5b7d240b 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.cpp +++ b/src/loaders/external_jpg/tvgJpgLoader.cpp @@ -126,13 +126,21 @@ bool JpgLoader::read() if (w == 0 || h == 0) return false; - /* OPTIMIZE: We assume the desired colorspace is ColorSpace::ARGB - How could we notice the renderer colorspace at this time? */ - auto image = (unsigned char *)tjAlloc(static_cast(w) * static_cast(h) * tjPixelSize[TJPF_BGRX]); + //determine the image format + TJPF format; + if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) { + format = TJPF_BGRX; + surface.cs = ColorSpace::ARGB8888; + } else { + format = TJPF_RGBX; + surface.cs = ColorSpace::ABGR8888; + } + + auto image = (unsigned char *)tjAlloc(static_cast(w) * static_cast(h) * tjPixelSize[format]); 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), format, 0) < 0) { TVGERR("JPG LOADER", "%s", tjGetErrorStr()); tjFree(image); image = nullptr; @@ -145,7 +153,6 @@ bool JpgLoader::read() surface.w = w; surface.h = h; surface.channelSize = sizeof(uint32_t); - surface.cs = ColorSpace::ARGB8888; surface.premultiplied = true; clear(); diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index a1b672c8..fcc29844 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -84,14 +84,15 @@ bool PngLoader::read() if (w == 0 || h == 0) return false; - png_bytep buffer; - image->format = PNG_FORMAT_BGRA; - buffer = static_cast(malloc(PNG_IMAGE_SIZE((*image)))); - if (!buffer) { - //out of memory, only time when libpng doesnt free its data - png_image_free(image); - return false; + if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) { + image->format = PNG_FORMAT_BGRA; + surface.cs = ColorSpace::ARGB8888; + } else { + image->format = PNG_FORMAT_RGBA; + surface.cs = ColorSpace::ABGR8888; } + + auto buffer = static_cast(malloc(PNG_IMAGE_SIZE((*image)))); if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) { free(buffer); return false; @@ -103,7 +104,6 @@ bool PngLoader::read() surface.w = (uint32_t)w; surface.h = (uint32_t)h; surface.channelSize = sizeof(uint32_t); - surface.cs = ColorSpace::ARGB8888; //TODO: we can acquire a pre-multiplied image. See "png_structrp" surface.premultiplied = false; diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index 2e042771..e71f3c13 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -35,6 +35,8 @@ void PngLoader::run(unsigned tid) auto width = static_cast(w); auto height = static_cast(h); + state.info_raw.colortype = LCT_RGBA; //request this image format + if (lodepng_decode(&surface.buf8, &width, &height, &state, data, size)) { TVGERR("PNG", "Failed to decode image"); } @@ -43,6 +45,7 @@ void PngLoader::run(unsigned tid) surface.stride = width; surface.w = width; surface.h = height; + surface.cs = ColorSpace::ABGR8888; surface.channelSize = sizeof(uint32_t); if (state.info_png.color.colortype == LCT_RGBA) surface.premultiplied = false; @@ -95,9 +98,6 @@ bool PngLoader::open(const string& path) w = static_cast(width); h = static_cast(height); - if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888; - else surface.cs = ColorSpace::ARGB8888; - ret = true; goto finalize; @@ -127,8 +127,6 @@ bool PngLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& r h = static_cast(height); this->size = size; - surface.cs = ColorSpace::ABGR8888; - return true; } diff --git a/src/loaders/webp/dec/webp.cpp b/src/loaders/webp/dec/webp.cpp index df0d61f7..dd21736d 100644 --- a/src/loaders/webp/dec/webp.cpp +++ b/src/loaders/webp/dec/webp.cpp @@ -654,6 +654,10 @@ uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, return Decode(MODE_bgrA, data, data_size, width, height, NULL); } +uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height) { + return Decode(MODE_rgbA, data, data_size, width, height, NULL); +} int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height) { diff --git a/src/loaders/webp/tvgWebpLoader.cpp b/src/loaders/webp/tvgWebpLoader.cpp index 72de6e7a..cc8a690b 100644 --- a/src/loaders/webp/tvgWebpLoader.cpp +++ b/src/loaders/webp/tvgWebpLoader.cpp @@ -35,12 +35,17 @@ void WebpLoader::clear() void WebpLoader::run(unsigned tid) { - //TODO: we can figure out the requested image format in advance. - surface.buf8 = WebPDecodeBGRA(data, size, nullptr, nullptr); + if (surface.cs == ColorSpace::ARGB8888 || surface.cs == ColorSpace::ARGB8888S) { + surface.buf8 = WebPDecodeBGRA(data, size, nullptr, nullptr); + surface.cs = ColorSpace::ARGB8888; + } else { + surface.buf8 = WebPDecodeRGBA(data, size, nullptr, nullptr); + surface.cs = ColorSpace::ABGR8888; + } + surface.stride = static_cast(w); surface.w = static_cast(w); surface.h = static_cast(h); - surface.cs = ColorSpace::ARGB8888; surface.channelSize = sizeof(uint32_t); surface.premultiplied = true; @@ -128,6 +133,8 @@ bool WebpLoader::read() if (!data || w == 0 || h == 0) return false; + surface.cs = this->cs; + TaskScheduler::request(this); return true; diff --git a/src/renderer/tvgLoadModule.h b/src/renderer/tvgLoadModule.h index d50aa5f6..1f7ea63e 100644 --- a/src/renderer/tvgLoadModule.h +++ b/src/renderer/tvgLoadModule.h @@ -68,6 +68,8 @@ struct LoadModule struct ImageLoader : LoadModule { + static ColorSpace cs; //desired value + float w = 0, h = 0; //default image size Surface surface; diff --git a/src/renderer/tvgLoader.cpp b/src/renderer/tvgLoader.cpp index 99fb2987..bde4bbd3 100644 --- a/src/renderer/tvgLoader.cpp +++ b/src/renderer/tvgLoader.cpp @@ -66,6 +66,8 @@ uint64_t HASH_KEY(const char* data, uint64_t size) /* Internal Class Implementation */ /************************************************************************/ +ColorSpace ImageLoader::cs = ColorSpace::ARGB8888; + static Key key; static Inlist _activeLoaders; diff --git a/src/renderer/tvgSwCanvas.cpp b/src/renderer/tvgSwCanvas.cpp index 44040570..d154a600 100644 --- a/src/renderer/tvgSwCanvas.cpp +++ b/src/renderer/tvgSwCanvas.cpp @@ -21,6 +21,7 @@ */ #include "tvgCanvas.h" +#include "tvgLoadModule.h" #ifdef THORVG_SW_RASTER_SUPPORT #include "tvgSwRenderer.h" @@ -90,6 +91,9 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t //Paints must be updated again with this new target. Canvas::pImpl->needRefresh(); + //FIXME: The value must be associated with an individual canvas instance. + ImageLoader::cs = static_cast(cs); + return Result::Success; #endif return Result::NonSupport;