mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-15 12:34:30 +00:00
loaders: Consider colorspaces (#838)
* common: added colorSpace() function This patch introduces colorSpace() function for SW and GL engine. * infra: change LoadModule:read() into LoadModule:read(uint32_t colorspace) This patch changes LoadModule:read() into LoadModule:read(uint32_t colorspace) * picture: implement passing colorspace into loader This patch implements passing colorspace into loaders. Loader->read is now called on the first update. * external_jpg_loader: support colorspaces * external_png_loader: support colorspaces
This commit is contained in:
parent
479cea74cc
commit
cd5116b053
22 changed files with 86 additions and 25 deletions
|
@ -1099,7 +1099,6 @@ public:
|
||||||
* @retval Result::Success When succeed.
|
* @retval Result::Success When succeed.
|
||||||
* @retval Result::InvalidArguments In case the @p path is invalid.
|
* @retval Result::InvalidArguments In case the @p path is invalid.
|
||||||
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
||||||
* @retval Result::Unknown If an error occurs at a later stage.
|
|
||||||
*
|
*
|
||||||
* @note The Load behavior can be asynchronous if the assigned thread number is greater than zero.
|
* @note The Load behavior can be asynchronous if the assigned thread number is greater than zero.
|
||||||
* @see Initializer::init()
|
* @see Initializer::init()
|
||||||
|
@ -1116,7 +1115,6 @@ public:
|
||||||
* @retval Result::Success When succeed.
|
* @retval Result::Success When succeed.
|
||||||
* @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less.
|
* @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less.
|
||||||
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
||||||
* @retval Result::Unknown If an error occurs at a later stage.
|
|
||||||
*
|
*
|
||||||
* @warning: you have responsibility to release the @p data memory if the @p copy is true
|
* @warning: you have responsibility to release the @p data memory if the @p copy is true
|
||||||
* @deprecated Use load(const char* data, uint32_t size, const std::string& mimeType, bool copy) instead.
|
* @deprecated Use load(const char* data, uint32_t size, const std::string& mimeType, bool copy) instead.
|
||||||
|
@ -1135,7 +1133,6 @@ public:
|
||||||
* @retval Result::Success When succeed.
|
* @retval Result::Success When succeed.
|
||||||
* @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less.
|
* @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less.
|
||||||
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
||||||
* @retval Result::Unknown If an error occurs at a later stage.
|
|
||||||
*
|
*
|
||||||
* @warning: It's the user responsibility to release the @p data memory if the @p copy is @c true.
|
* @warning: It's the user responsibility to release the @p data memory if the @p copy is @c true.
|
||||||
*
|
*
|
||||||
|
|
|
@ -246,6 +246,13 @@ bool GlRenderer::viewport(TVG_UNUSED const RenderRegion& vp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t GlRenderer::colorSpace()
|
||||||
|
{
|
||||||
|
//TODO:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int GlRenderer::init(uint32_t threads)
|
int GlRenderer::init(uint32_t threads)
|
||||||
{
|
{
|
||||||
if ((initEngineCnt++) > 0) return true;
|
if ((initEngineCnt++) > 0) return true;
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
RenderRegion region(RenderData data) override;
|
RenderRegion region(RenderData data) override;
|
||||||
RenderRegion viewport() override;
|
RenderRegion viewport() override;
|
||||||
bool viewport(const RenderRegion& vp) override;
|
bool viewport(const RenderRegion& vp) override;
|
||||||
|
uint32_t colorSpace() override;
|
||||||
|
|
||||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||||
bool sync() override;
|
bool sync() override;
|
||||||
|
|
|
@ -299,6 +299,12 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SwRenderer::colorSpace()
|
||||||
|
{
|
||||||
|
return surface->cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::preRender()
|
bool SwRenderer::preRender()
|
||||||
{
|
{
|
||||||
return rasterClear(surface);
|
return rasterClear(surface);
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
RenderRegion region(RenderData data) override;
|
RenderRegion region(RenderData data) override;
|
||||||
RenderRegion viewport() override;
|
RenderRegion viewport() override;
|
||||||
bool viewport(const RenderRegion& vp) override;
|
bool viewport(const RenderRegion& vp) override;
|
||||||
|
uint32_t colorSpace() override;
|
||||||
|
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
bool sync() override;
|
bool sync() override;
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
//Override this if the vector-format has own resizing policy.
|
//Override this if the vector-format has own resizing policy.
|
||||||
virtual bool resize(Paint* paint, float w, float h) { return false; };
|
virtual bool resize(Paint* paint, float w, float h) { return false; };
|
||||||
|
|
||||||
virtual bool read() = 0;
|
virtual bool read(uint32_t colorspace) = 0;
|
||||||
virtual bool close() = 0;
|
virtual bool close() = 0;
|
||||||
virtual const uint32_t* pixels() { return nullptr; };
|
virtual const uint32_t* pixels() { return nullptr; };
|
||||||
virtual unique_ptr<Paint> paint() { return nullptr; };
|
virtual unique_ptr<Paint> paint() { return nullptr; };
|
||||||
|
|
|
@ -66,6 +66,7 @@ struct Picture::Impl
|
||||||
void* rdata = nullptr; //engine data
|
void* rdata = nullptr; //engine data
|
||||||
float w = 0, h = 0;
|
float w = 0, h = 0;
|
||||||
bool resizing = false;
|
bool resizing = false;
|
||||||
|
bool justloaded = false;
|
||||||
|
|
||||||
Impl(Picture* p) : picture(p)
|
Impl(Picture* p) : picture(p)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +91,7 @@ struct Picture::Impl
|
||||||
|
|
||||||
uint32_t reload()
|
uint32_t reload()
|
||||||
{
|
{
|
||||||
if (loader) {
|
if (loader && !justloaded) {
|
||||||
if (!paint) {
|
if (!paint) {
|
||||||
if (auto p = loader->paint()) {
|
if (auto p = loader->paint()) {
|
||||||
paint = p.release();
|
paint = p.release();
|
||||||
|
@ -127,6 +128,14 @@ struct Picture::Impl
|
||||||
|
|
||||||
void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
||||||
{
|
{
|
||||||
|
if (loader && justloaded) {
|
||||||
|
justloaded = false;
|
||||||
|
if (!loader->read(renderer.colorSpace())) {
|
||||||
|
TVGERR("Picture", "Loader read failure!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto flag = reload();
|
auto flag = reload();
|
||||||
|
|
||||||
if (pixels) {
|
if (pixels) {
|
||||||
|
@ -194,9 +203,9 @@ struct Picture::Impl
|
||||||
if (invalid) return Result::InvalidArguments;
|
if (invalid) return Result::InvalidArguments;
|
||||||
return Result::NonSupport;
|
return Result::NonSupport;
|
||||||
}
|
}
|
||||||
if (!loader->read()) return Result::Unknown;
|
|
||||||
w = loader->w;
|
w = loader->w;
|
||||||
h = loader->h;
|
h = loader->h;
|
||||||
|
justloaded = true;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,9 +215,9 @@ struct Picture::Impl
|
||||||
if (loader) loader->close();
|
if (loader) loader->close();
|
||||||
loader = LoaderMgr::loader(data, size, mimeType, copy);
|
loader = LoaderMgr::loader(data, size, mimeType, copy);
|
||||||
if (!loader) return Result::NonSupport;
|
if (!loader) return Result::NonSupport;
|
||||||
if (!loader->read()) return Result::Unknown;
|
|
||||||
w = loader->w;
|
w = loader->w;
|
||||||
h = loader->h;
|
h = loader->h;
|
||||||
|
justloaded = true;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +229,7 @@ struct Picture::Impl
|
||||||
if (!loader) return Result::NonSupport;
|
if (!loader) return Result::NonSupport;
|
||||||
this->w = loader->w;
|
this->w = loader->w;
|
||||||
this->h = loader->h;
|
this->h = loader->h;
|
||||||
|
justloaded = true;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,8 @@ public:
|
||||||
virtual Compositor* target(const RenderRegion& region) = 0;
|
virtual Compositor* target(const RenderRegion& region) = 0;
|
||||||
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
|
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
|
||||||
virtual bool endComposite(Compositor* cmp) = 0;
|
virtual bool endComposite(Compositor* cmp) = 0;
|
||||||
|
|
||||||
|
virtual uint32_t colorSpace() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,14 +124,15 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool JpgLoader::read()
|
bool JpgLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
if (image) tjFree(image);
|
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[TJPF_BGRX]);
|
||||||
if (!image) return false;
|
if (!image) return false;
|
||||||
|
|
||||||
//decompress jpg image
|
//decompress jpg image
|
||||||
if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), TJPF_BGRX, 0) < 0) {
|
auto pixelFormat = (colorspace == tvg::SwCanvas::ABGR8888) ? TJPF_RGBX : TJPF_BGRX;
|
||||||
|
if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), pixelFormat, 0) < 0) {
|
||||||
TVGERR("JPG LOADER", "%s", tjGetErrorStr());
|
TVGERR("JPG LOADER", "%s", tjGetErrorStr());
|
||||||
tjFree(image);
|
tjFree(image);
|
||||||
image = nullptr;
|
image = nullptr;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const string& path) override;
|
bool open(const string& path) override;
|
||||||
bool open(const char* data, uint32_t size, bool copy) override;
|
bool open(const char* data, uint32_t size, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
const uint32_t* pixels() override;
|
const uint32_t* pixels() override;
|
||||||
|
|
|
@ -20,9 +20,27 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
#include "tvgPngLoader.h"
|
#include "tvgPngLoader.h"
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Internal Class Implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
void PngLoader::clear()
|
||||||
|
{
|
||||||
|
if (freeData) free(data);
|
||||||
|
data = nullptr;
|
||||||
|
freeData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* External Class Implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
PngLoader::PngLoader()
|
PngLoader::PngLoader()
|
||||||
{
|
{
|
||||||
image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
|
image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
|
||||||
|
@ -32,6 +50,9 @@ PngLoader::PngLoader()
|
||||||
|
|
||||||
PngLoader::~PngLoader()
|
PngLoader::~PngLoader()
|
||||||
{
|
{
|
||||||
|
if (freeData) free(data);
|
||||||
|
data = nullptr;
|
||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
free((void*)content);
|
free((void*)content);
|
||||||
content = nullptr;
|
content = nullptr;
|
||||||
|
@ -41,6 +62,7 @@ PngLoader::~PngLoader()
|
||||||
|
|
||||||
bool PngLoader::open(const string& path)
|
bool PngLoader::open(const string& path)
|
||||||
{
|
{
|
||||||
|
clear();
|
||||||
image->opaque = NULL;
|
image->opaque = NULL;
|
||||||
|
|
||||||
if (!png_image_begin_read_from_file(image, path.c_str())) return false;
|
if (!png_image_begin_read_from_file(image, path.c_str())) return false;
|
||||||
|
@ -53,9 +75,19 @@ bool PngLoader::open(const string& path)
|
||||||
|
|
||||||
bool PngLoader::open(const char* data, uint32_t size, bool copy)
|
bool PngLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
{
|
{
|
||||||
|
clear();
|
||||||
image->opaque = NULL;
|
image->opaque = NULL;
|
||||||
|
|
||||||
if (!png_image_begin_read_from_memory(image, data, size)) return false;
|
if (copy) {
|
||||||
|
this->data = (char *) malloc(size);
|
||||||
|
if (!this->data) return false;
|
||||||
|
memcpy(this->data, data, size);
|
||||||
|
freeData = true;
|
||||||
|
} else {
|
||||||
|
this->data = (char *) data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!png_image_begin_read_from_memory(image, this->data, size)) return false;
|
||||||
|
|
||||||
w = (float)image->width;
|
w = (float)image->width;
|
||||||
h = (float)image->height;
|
h = (float)image->height;
|
||||||
|
@ -63,10 +95,10 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PngLoader::read()
|
bool PngLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
png_bytep buffer;
|
png_bytep buffer;
|
||||||
image->format = PNG_FORMAT_BGRA;
|
image->format = (colorspace == tvg::SwCanvas::ABGR8888) ? PNG_FORMAT_RGBA : PNG_FORMAT_BGRA;
|
||||||
buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
|
buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
//out of memory, only time when libpng doesnt free its data
|
//out of memory, only time when libpng doesnt free its data
|
||||||
|
|
|
@ -33,12 +33,16 @@ public:
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const string& path) override;
|
bool open(const string& path) override;
|
||||||
bool open(const char* data, uint32_t size, bool copy) override;
|
bool open(const char* data, uint32_t size, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
const uint32_t* pixels() override;
|
const uint32_t* pixels() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
char* data = nullptr;
|
||||||
|
bool freeData = false;
|
||||||
png_imagep image = nullptr;
|
png_imagep image = nullptr;
|
||||||
const uint32_t* content = nullptr;
|
const uint32_t* content = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,8 +90,7 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool JpgLoader::read(uint32_t colorspace)
|
||||||
bool JpgLoader::read()
|
|
||||||
{
|
{
|
||||||
if (!decoder || w <= 0 || h <= 0) return false;
|
if (!decoder || w <= 0 || h <= 0) return false;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const string& path) override;
|
bool open(const string& path) override;
|
||||||
bool open(const char* data, uint32_t size, bool copy) override;
|
bool open(const char* data, uint32_t size, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
const uint32_t* pixels() override;
|
const uint32_t* pixels() override;
|
||||||
|
|
|
@ -123,7 +123,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PngLoader::read()
|
bool PngLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
if (!data || w <= 0 || h <= 0) return false;
|
if (!data || w <= 0 || h <= 0) return false;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const string& path) override;
|
bool open(const string& path) override;
|
||||||
bool open(const char* data, uint32_t size, bool copy) override;
|
bool open(const char* data, uint32_t size, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
const uint32_t* pixels() override;
|
const uint32_t* pixels() override;
|
||||||
|
|
|
@ -60,8 +60,9 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RawLoader::read()
|
bool RawLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
|
//NOTE: raw data is used "as it is"- developer must take care of it so the same color space used
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
|
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override;
|
bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
const uint32_t* pixels() override;
|
const uint32_t* pixels() override;
|
||||||
|
|
|
@ -2927,7 +2927,7 @@ bool SvgLoader::resize(Paint* paint, float w, float h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SvgLoader::read()
|
bool SvgLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
if (!content || size == 0) return false;
|
if (!content || size == 0) return false;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
bool open(const string& path) override;
|
bool open(const string& path) override;
|
||||||
bool open(const char* data, uint32_t size, bool copy) override;
|
bool open(const char* data, uint32_t size, bool copy) override;
|
||||||
bool resize(Paint* paint, float w, float h) override;
|
bool resize(Paint* paint, float w, float h) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
unique_ptr<Paint> paint() override;
|
unique_ptr<Paint> paint() override;
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ bool TvgLoader::resize(Paint* paint, float w, float h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TvgLoader::read()
|
bool TvgLoader::read(uint32_t colorspace)
|
||||||
{
|
{
|
||||||
if (!ptr || size == 0) return false;
|
if (!ptr || size == 0) return false;
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
using LoadModule::open;
|
using LoadModule::open;
|
||||||
bool open(const string &path) override;
|
bool open(const string &path) override;
|
||||||
bool open(const char *data, uint32_t size, bool copy) override;
|
bool open(const char *data, uint32_t size, bool copy) override;
|
||||||
bool read() override;
|
bool read(uint32_t colorspace) override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
bool resize(Paint* paint, float w, float h) override;
|
bool resize(Paint* paint, float w, float h) override;
|
||||||
unique_ptr<Paint> paint() override;
|
unique_ptr<Paint> paint() override;
|
||||||
|
|
Loading…
Add table
Reference in a new issue