From: Hermet Park Date: Wed, 27 Oct 2021 04:47:52 +0000 (+0900) Subject: jpg_loader: support multi-thread and header reading in prior to decoding. X-Git-Tag: accepted/tizen/unified/20211102.024808~18 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8a72e75434e01c6b464b764ecb35d68afc34799a;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git jpg_loader: support multi-thread and header reading in prior to decoding. revise the code to support async loading of the static jpeg_loader, also support header reading in prior to decoding. --- diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 7e6c375..599d2fe 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -20,7 +20,7 @@ * SOFTWARE. */ -#include "tvgJpgd.h" +#include #include "tvgLoader.h" #include "tvgJpgLoader.h" @@ -28,6 +28,15 @@ /* Internal Class Implementation */ /************************************************************************/ +void JpgLoader::clear() +{ + jpgdDelete(decoder); + if (freeData) free(data); + decoder = nullptr; + data = nullptr; + freeData = false; +} + /************************************************************************/ /* External Class Implementation */ @@ -36,48 +45,79 @@ JpgLoader::~JpgLoader() { - free(image); - image = NULL; + jpgdDelete(decoder); + if (freeData) free(data); } + bool JpgLoader::open(const string& path) { - int width, height, actual_comps; - image = decompress_jpeg_image_from_file(path.c_str(), &width, &height, &actual_comps, 4); - if (!image) return false; + clear(); - vw = w = static_cast(width); - vh = h = static_cast(height); + int width, height; + decoder = jpgdHeader(path.c_str(), &width, &height); + if (!decoder) return false; + + w = static_cast(width); + h = static_cast(height); return true; } + bool JpgLoader::open(const char* data, uint32_t size, bool copy) { - int width, height, actual_comps; - image = decompress_jpeg_image_from_memory((const unsigned char *)data, size, &width, &height, &actual_comps, 4); - if (!image) return false; + clear(); + + if (copy) { + this->data = (char *) malloc(size); + if (!this->data) return false; + memcpy((char *)this->data, data, size); + freeData = true; + } else { + this->data = (char *) data; + freeData = false; + } + + int width, height; + decoder = jpgdHeader(this->data, size, &width, &height); + if (!decoder) return false; - vw = w = static_cast(width); - vh = h = static_cast(height); + w = static_cast(width); + h = static_cast(height); return true; } + bool JpgLoader::read() { + if (!decoder || w <= 0 || h <= 0) return false; + + TaskScheduler::request(this); + return true; } bool JpgLoader::close() { + this->done(); + clear(); return true; } const uint32_t* JpgLoader::pixels() { + this->done(); + return (const uint32_t*)image; } + + +void JpgLoader::run(unsigned tid) +{ + image = jpgdDecompress(decoder); +} \ No newline at end of file diff --git a/src/loaders/jpg/tvgJpgLoader.h b/src/loaders/jpg/tvgJpgLoader.h index e12a907..e7ec3ab 100644 --- a/src/loaders/jpg/tvgJpgLoader.h +++ b/src/loaders/jpg/tvgJpgLoader.h @@ -22,9 +22,19 @@ #ifndef _TVG_JPG_LOADER_H_ #define _TVG_JPG_LOADER_H_ -//TODO: Use Task? -class JpgLoader : public LoadModule +#include "tvgTaskScheduler.h" +#include "tvgJpgd.h" + +class JpgLoader : public LoadModule, public Task { +private: + jpeg_decoder* decoder = nullptr; + char* data = nullptr; + unsigned char *image = nullptr; + bool freeData = false; + + void clear(); + public: ~JpgLoader(); @@ -35,9 +45,7 @@ public: bool close() override; const uint32_t* pixels() override; - -private: - unsigned char *image = nullptr; + void run(unsigned tid) override; }; #endif //_TVG_JPG_LOADER_H_ diff --git a/src/loaders/jpg/tvgJpgd.cpp b/src/loaders/jpg/tvgJpgd.cpp index 7a59829..1bf5e6f 100644 --- a/src/loaders/jpg/tvgJpgd.cpp +++ b/src/loaders/jpg/tvgJpgd.cpp @@ -110,11 +110,12 @@ class jpeg_decoder_file_stream : public jpeg_decoder_stream jpeg_decoder_file_stream(const jpeg_decoder_file_stream &); jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &); - FILE *m_pFile; - bool m_eof_flag, m_error_flag; + FILE *m_pFile = nullptr; + bool m_eof_flag = false; + bool m_error_flag = false; public: - jpeg_decoder_file_stream(); + jpeg_decoder_file_stream() {} virtual ~jpeg_decoder_file_stream(); bool open(const char *Pfilename); void close(); @@ -2814,14 +2815,7 @@ int jpeg_decoder::begin_decoding() jpeg_decoder::~jpeg_decoder() { free_all_blocks(); -} - - -jpeg_decoder_file_stream::jpeg_decoder_file_stream() -{ - m_pFile = nullptr; - m_eof_flag = false; - m_error_flag = false; + delete(m_pStream); } @@ -2910,23 +2904,62 @@ int jpeg_decoder_mem_stream::read(uint8_t *pBuf, int max_bytes_to_read, bool *pE } -unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps) +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + + +jpeg_decoder* jpgdHeader(const char* data, int size, int* width, int* height) { - if (!actual_comps) return nullptr; - *actual_comps = 0; + auto decoder = new jpeg_decoder(new jpeg_decoder_mem_stream((const uint8_t*)data, size)); + if (decoder->get_error_code() != JPGD_SUCCESS) { + delete(decoder); + return nullptr; + } + + if (width) *width = decoder->get_width(); + if (height) *height = decoder->get_height(); + + return decoder; +} + + +jpeg_decoder* jpgdHeader(const char* filename, int* width, int* height) +{ + auto fileStream = new jpeg_decoder_file_stream(); + if (!fileStream->open(filename)) return nullptr; + + auto decoder = new jpeg_decoder(fileStream); + if (decoder->get_error_code() != JPGD_SUCCESS) { + delete(decoder); + return nullptr; + } + + if (width) *width = decoder->get_width(); + if (height) *height = decoder->get_height(); + + return decoder; +} + + +void jpgdDelete(jpeg_decoder* decoder) +{ + delete(decoder); +} - if ((!pStream) || (!width) || (!height) || (!req_comps)) return nullptr; - if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4)) return nullptr; - jpeg_decoder decoder(pStream); - if (decoder.get_error_code() != JPGD_SUCCESS) return nullptr; +unsigned char* jpgdDecompress(jpeg_decoder* decoder) +{ + if (!decoder) return nullptr; + + int req_comps = 4; //TODO: fixed 4 channel components now? + if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4)) return nullptr; - const int image_width = decoder.get_width(), image_height = decoder.get_height(); - *width = image_width; - *height = image_height; - *actual_comps = decoder.get_num_components(); + auto image_width = decoder->get_width(); + auto image_height = decoder->get_height(); + //auto actual_comps = decoder->get_num_components(); - if (decoder.begin_decoding() != JPGD_SUCCESS) return nullptr; + if (decoder->begin_decoding() != JPGD_SUCCESS) return nullptr; const int dst_bpl = image_width * req_comps; uint8_t *pImage_data = (uint8_t*)malloc(dst_bpl * image_height); @@ -2935,7 +2968,7 @@ unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, i for (int y = 0; y < image_height; y++) { const uint8_t* pScan_line; uint32_t scan_line_len; - if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { + if (decoder->decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) { free(pImage_data); return nullptr; } @@ -2943,17 +2976,17 @@ unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, i uint8_t *pDst = pImage_data + y * dst_bpl; //Return as BGRA - if ((req_comps == 4) && (decoder.get_num_components() == 3)) { + if ((req_comps == 4) && (decoder->get_num_components() == 3)) { for (int x = 0; x < image_width; x++) { pDst[0] = pScan_line[x*4+2]; pDst[1] = pScan_line[x*4+1]; pDst[2] = pScan_line[x*4+0]; pDst[3] = 255; pDst += 4; - } - } else if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3))) { + } + } else if (((req_comps == 1) && (decoder->get_num_components() == 1)) || ((req_comps == 4) && (decoder->get_num_components() == 3))) { memcpy(pDst, pScan_line, dst_bpl); - } else if (decoder.get_num_components() == 1) { + } else if (decoder->get_num_components() == 1) { if (req_comps == 3) { for (int x = 0; x < image_width; x++) { uint8_t luma = pScan_line[x]; @@ -2972,7 +3005,7 @@ unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, i pDst += 4; } } - } else if (decoder.get_num_components() == 3) { + } else if (decoder->get_num_components() == 3) { if (req_comps == 1) { const int YR = 19595, YG = 38470, YB = 7471; for (int x = 0; x < image_width; x++) { @@ -2992,23 +3025,4 @@ unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, i } } return pImage_data; -} - - -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - -unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps) -{ - jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size); - return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps); -} - - -unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps) -{ - jpeg_decoder_file_stream file_stream; - if (!file_stream.open(pSrc_filename)) return nullptr; - return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps); } \ No newline at end of file diff --git a/src/loaders/jpg/tvgJpgd.h b/src/loaders/jpg/tvgJpgd.h index 61c6969..a0e56e6 100644 --- a/src/loaders/jpg/tvgJpgd.h +++ b/src/loaders/jpg/tvgJpgd.h @@ -25,12 +25,11 @@ #ifndef _TVG_JPGD_H_ #define _TVG_JPGD_H_ -// Loads a JPEG image from a memory buffer or a file. -// req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA). -// On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB). -// Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly. -// Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp. -unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps); -unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps); +class jpeg_decoder; + +jpeg_decoder* jpgdHeader(const char* data, int size, int* width, int* height); +jpeg_decoder* jpgdHeader(const char* filename, int* width, int* height); +unsigned char* jpgdDecompress(jpeg_decoder* decoder); +void jpgdDelete(jpeg_decoder* decoder); #endif //_TVG_JPGD_H_ diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index 31af358..e50f34e 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -136,7 +136,6 @@ bool PngLoader::read() bool PngLoader::close() { this->done(); - clear(); return true; } diff --git a/src/loaders/png/tvgPngLoader.h b/src/loaders/png/tvgPngLoader.h index 97c91a4..fa1860c 100644 --- a/src/loaders/png/tvgPngLoader.h +++ b/src/loaders/png/tvgPngLoader.h @@ -48,7 +48,6 @@ public: bool close() override; const uint32_t* pixels() override; - void run(unsigned tid) override; };