diff --git a/project/include/graphics/JPEG.h b/project/include/graphics/JPEG.h index 6fcf4fde9..93654aee9 100644 --- a/project/include/graphics/JPEG.h +++ b/project/include/graphics/JPEG.h @@ -2,23 +2,25 @@ #define LIME_GRAPHICS_JPEG_H +#include +#include + + namespace lime { - class Image; - class JPEG { - - + + public: - - static bool Decode (const char *path, Image *image); - - + + static bool Decode (Resource *resource, Image *image); + + }; - - + + } -#endif +#endif \ No newline at end of file diff --git a/project/include/graphics/PNG.h b/project/include/graphics/PNG.h index 263e3b779..8b7424877 100644 --- a/project/include/graphics/PNG.h +++ b/project/include/graphics/PNG.h @@ -2,17 +2,19 @@ #define LIME_GRAPHICS_PNG_H +#include +#include + + namespace lime { - class Image; - class PNG { public: - static bool Decode (const char *path, Image *image); + static bool Decode (Resource *resource, Image *image); }; diff --git a/project/include/io/Resource.h b/project/include/io/Resource.h new file mode 100644 index 000000000..59e59734e --- /dev/null +++ b/project/include/io/Resource.h @@ -0,0 +1,25 @@ +#ifndef LIME_IO_RESOURCE_H +#define LIME_IO_RESOURCE_H + + +#include + + +namespace lime { + + + struct Resource { + + Resource (const char* path) { this->path = path; } + Resource (ByteArray *data) { this->data = data; } + + ByteArray *data; + const char* path; + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index b18ff97c1..600f3eb15 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -57,10 +57,10 @@ namespace lime { value lime_image_load (value path) { Image image; - const char *filePath = val_string (path); + Resource resource = Resource (val_string (path)); #ifdef LIME_PNG - if (PNG::Decode (filePath, &image)) { + if (PNG::Decode (&resource, &image)) { return image.Value (); @@ -68,7 +68,7 @@ namespace lime { #endif #ifdef LIME_JPEG - if (JPEG::Decode (filePath, &image)) { + if (JPEG::Decode (&resource, &image)) { return image.Value (); diff --git a/project/src/graphics/JPEG.cpp b/project/src/graphics/JPEG.cpp index 619eb9d9d..1ba17dce7 100644 --- a/project/src/graphics/JPEG.cpp +++ b/project/src/graphics/JPEG.cpp @@ -6,7 +6,7 @@ extern "C" { } -#include +#include #include #include @@ -14,19 +14,155 @@ extern "C" { namespace lime { - bool JPEG::Decode (const char *path, Image *image) { + struct ErrorData { + + struct jpeg_error_mgr base; + jmp_buf on_error; + + }; + + + static void OnOutput (j_common_ptr cinfo) {} + + + static void OnError (j_common_ptr cinfo) { + + ErrorData * err = (ErrorData *)cinfo->err; + longjmp (err->on_error, 1); + + } + + + struct MySrcManager { + + + MySrcManager (const JOCTET *inData, int inLen) : mData (inData), mLen (inLen) { + + pub.init_source = my_init_source; + pub.fill_input_buffer = my_fill_input_buffer; + pub.skip_input_data = my_skip_input_data; + pub.resync_to_restart = my_resync_to_restart; + pub.term_source = my_term_source; + pub.next_input_byte = 0; + pub.bytes_in_buffer = 0; + mUsed = false; + mEOI[0] = 0xff; + mEOI[1] = JPEG_EOI; + + } + + + struct jpeg_source_mgr pub; /* public fields */ + const JOCTET * mData; + size_t mLen; + bool mUsed; + unsigned char mEOI[2]; + + + static void my_init_source (j_decompress_ptr cinfo) { + + MySrcManager *man = (MySrcManager *)cinfo->src; + man->mUsed = false; + + } + + + static boolean my_fill_input_buffer (j_decompress_ptr cinfo) { + + MySrcManager *man = (MySrcManager *)cinfo->src; + + if (man->mUsed) { + + man->pub.next_input_byte = man->mEOI; + man->pub.bytes_in_buffer = 2; + + } else { + man->pub.next_input_byte = man->mData; + man->pub.bytes_in_buffer = man->mLen; + man->mUsed = true; + + } + + return true; + + } + + + static void my_skip_input_data (j_decompress_ptr cinfo, long num_bytes) { + + MySrcManager *man = (MySrcManager *)cinfo->src; + man->pub.next_input_byte += num_bytes; + man->pub.bytes_in_buffer -= num_bytes; + + // was < 0 and was always false PJK 16JUN12 + if (man->pub.bytes_in_buffer == 0) { + + man->pub.next_input_byte = man->mEOI; + man->pub.bytes_in_buffer = 2; + + } + + } + + + static boolean my_resync_to_restart (j_decompress_ptr cinfo, int desired) { + + MySrcManager *man = (MySrcManager *)cinfo->src; + man->mUsed = false; + return true; + + } + + + static void my_term_source (j_decompress_ptr cinfo) {} + + }; + + + bool JPEG::Decode (Resource *resource, Image* image) { struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - FILE *file = lime::fopen (path, "rb"); + //struct jpeg_error_mgr jerr; + //cinfo.err = jpeg_std_error (&jerr); + + struct ErrorData jpegError; + jpegError.base.error_exit = OnError; + jpegError.base.output_message = OnOutput; + cinfo.err = jpeg_std_error (&jpegError.base); + + FILE *file; + + if (setjmp (jpegError.on_error)) { + + if (file) + lime::fclose (file); + + jpeg_destroy_decompress (&cinfo); + return false; + + } - cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); - jpeg_stdio_src (&cinfo, file); + + if (resource->path) { + + file = lime::fopen (resource->path, "rb"); + jpeg_stdio_src (&cinfo, file); + + } else { + + MySrcManager manager (resource->data->Bytes (), resource->data->Size ()); + cinfo.src = &manager.pub; + + } + + bool decoded = false; if (jpeg_read_header (&cinfo, TRUE) == JPEG_HEADER_OK) { + cinfo.out_color_space = JCS_RGB; + jpeg_start_decompress (&cinfo); int components = cinfo.num_components; image->Resize (cinfo.output_width, cinfo.output_height); @@ -56,13 +192,14 @@ namespace lime { delete[] scanline; jpeg_finish_decompress (&cinfo); + decoded = true; } lime::fclose (file); jpeg_destroy_decompress (&cinfo); - return true; + return decoded; } diff --git a/project/src/graphics/PNG.cpp b/project/src/graphics/PNG.cpp index 8eaedb678..d15363a29 100644 --- a/project/src/graphics/PNG.cpp +++ b/project/src/graphics/PNG.cpp @@ -5,7 +5,6 @@ extern "C" { } -#include #include #include @@ -13,7 +12,7 @@ extern "C" { namespace lime { - bool PNG::Decode (const char *path, Image *image) { + bool PNG::Decode (Resource *resource, Image *image) { unsigned char png_sig[PNG_SIG_SIZE]; png_structp png_ptr; @@ -21,7 +20,7 @@ namespace lime { png_uint_32 width, height; int bit_depth, color_type; - FILE *file = lime::fopen (path, "rb"); + FILE *file = lime::fopen (resource->path, "rb"); if (!file) return false; // verify the PNG signature