* SOFTWARE.
*/
-#include "tvgJpgd.h"
+#include <memory.h>
#include "tvgLoader.h"
#include "tvgJpgLoader.h"
/* Internal Class Implementation */
/************************************************************************/
+void JpgLoader::clear()
+{
+ jpgdDelete(decoder);
+ if (freeData) free(data);
+ decoder = nullptr;
+ data = nullptr;
+ freeData = false;
+}
+
/************************************************************************/
/* External Class Implementation */
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<float>(width);
- vh = h = static_cast<float>(height);
+ int width, height;
+ decoder = jpgdHeader(path.c_str(), &width, &height);
+ if (!decoder) return false;
+
+ w = static_cast<float>(width);
+ h = static_cast<float>(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<float>(width);
- vh = h = static_cast<float>(height);
+ w = static_cast<float>(width);
+ h = static_cast<float>(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
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();
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);
}
}
-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);
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;
}
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];
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++) {
}
}
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
#ifndef _TVG_JPGD_H_\r
#define _TVG_JPGD_H_\r
\r
-// Loads a JPEG image from a memory buffer or a file.\r
-// req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).\r
-// 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).\r
-// 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.\r
-// 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.\r
-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);\r
-unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps);\r
+class jpeg_decoder;\r
+\r
+jpeg_decoder* jpgdHeader(const char* data, int size, int* width, int* height);\r
+jpeg_decoder* jpgdHeader(const char* filename, int* width, int* height);\r
+unsigned char* jpgdDecompress(jpeg_decoder* decoder);\r
+void jpgdDelete(jpeg_decoder* decoder);\r
\r
#endif //_TVG_JPGD_H_\r