mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
loaders: enhance decoding efficiency
enhance decoding efficiency by determining the desired canvas format during image loading. This allows loaders to preemptively decode the image in the specified format, to not convert the format again.
This commit is contained in:
parent
8a4862bc37
commit
5fe9b432ec
8 changed files with 45 additions and 21 deletions
|
@ -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<int>(w) * static_cast<int>(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<int>(w) * static_cast<int>(h) * tjPixelSize[format]);
|
||||
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), 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();
|
||||
|
|
|
@ -84,14 +84,15 @@ bool PngLoader::read()
|
|||
|
||||
if (w == 0 || h == 0) return false;
|
||||
|
||||
png_bytep buffer;
|
||||
if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
|
||||
image->format = PNG_FORMAT_BGRA;
|
||||
buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
|
||||
if (!buffer) {
|
||||
//out of memory, only time when libpng doesnt free its data
|
||||
png_image_free(image);
|
||||
return false;
|
||||
surface.cs = ColorSpace::ARGB8888;
|
||||
} else {
|
||||
image->format = PNG_FORMAT_RGBA;
|
||||
surface.cs = ColorSpace::ABGR8888;
|
||||
}
|
||||
|
||||
auto buffer = static_cast<png_bytep>(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;
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ void PngLoader::run(unsigned tid)
|
|||
auto width = static_cast<unsigned>(w);
|
||||
auto height = static_cast<unsigned>(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<float>(width);
|
||||
h = static_cast<float>(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<float>(height);
|
||||
this->size = size;
|
||||
|
||||
surface.cs = ColorSpace::ABGR8888;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -35,12 +35,17 @@ void WebpLoader::clear()
|
|||
|
||||
void WebpLoader::run(unsigned tid)
|
||||
{
|
||||
//TODO: we can figure out the requested image format in advance.
|
||||
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<uint32_t>(w);
|
||||
surface.w = static_cast<uint32_t>(w);
|
||||
surface.h = static_cast<uint32_t>(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;
|
||||
|
|
|
@ -68,6 +68,8 @@ struct LoadModule
|
|||
|
||||
struct ImageLoader : LoadModule
|
||||
{
|
||||
static ColorSpace cs; //desired value
|
||||
|
||||
float w = 0, h = 0; //default image size
|
||||
Surface surface;
|
||||
|
||||
|
|
|
@ -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<LoadModule> _activeLoaders;
|
||||
|
||||
|
|
|
@ -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<ColorSpace>(cs);
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
return Result::NonSupport;
|
||||
|
|
Loading…
Add table
Reference in a new issue