diff --git a/lime/graphics/format/JPEG.hx b/lime/graphics/format/JPEG.hx index 1b52fdaa0..60a762601 100644 --- a/lime/graphics/format/JPEG.hx +++ b/lime/graphics/format/JPEG.hx @@ -2,6 +2,7 @@ package lime.graphics.format; import lime.graphics.Image; +import lime.graphics.ImageBuffer; import lime.system.System; import lime.utils.ByteArray; @@ -9,6 +10,48 @@ import lime.utils.ByteArray; class JPEG { + public static function decodeBytes (bytes:ByteArray, decodeData:Bool = true):Image { + + #if (cpp || neko || nodejs) + + var bufferData = lime_jpeg_decode_bytes (bytes, decodeData); + + if (bufferData != null) { + + var buffer = new ImageBuffer (bufferData.data, bufferData.width, bufferData.height, bufferData.bpp, bufferData.format); + buffer.transparent = bufferData.transparent; + return new Image (buffer); + + } + + #end + + return null; + + } + + + public static function decodeFile (path:String, decodeData:Bool = true):Image { + + #if (cpp || neko || nodejs) + + var bufferData = lime_jpeg_decode_file (path, decodeData); + + if (bufferData != null) { + + var buffer = new ImageBuffer (bufferData.data, bufferData.width, bufferData.height, bufferData.bpp, bufferData.format); + buffer.transparent = bufferData.transparent; + return new Image (buffer); + + } + + #end + + return null; + + } + + public static function encode (image:Image, quality:Int):ByteArray { #if java @@ -32,6 +75,8 @@ class JPEG { #if (cpp || neko || nodejs) + private static var lime_jpeg_decode_bytes:ByteArray -> Bool -> Dynamic = System.load ("lime", "lime_jpeg_decode_bytes", 2); + private static var lime_jpeg_decode_file:String -> Bool -> Dynamic = System.load ("lime", "lime_jpeg_decode_file", 2); private static var lime_image_encode:ImageBuffer -> Int -> Int -> ByteArray = System.load ("lime", "lime_image_encode", 3); #end diff --git a/lime/graphics/format/PNG.hx b/lime/graphics/format/PNG.hx index 66fc189f8..b61eddcc4 100644 --- a/lime/graphics/format/PNG.hx +++ b/lime/graphics/format/PNG.hx @@ -17,6 +17,48 @@ import haxe.io.BytesOutput; class PNG { + public static function decodeBytes (bytes:ByteArray, decodeData:Bool = true):Image { + + #if (cpp || neko || nodejs) + + var bufferData = lime_png_decode_bytes (bytes, decodeData); + + if (bufferData != null) { + + var buffer = new ImageBuffer (bufferData.data, bufferData.width, bufferData.height, bufferData.bpp, bufferData.format); + buffer.transparent = bufferData.transparent; + return new Image (buffer); + + } + + #end + + return null; + + } + + + public static function decodeFile (path:String, decodeData:Bool = true):Image { + + #if (cpp || neko || nodejs) + + var bufferData = lime_png_decode_file (path, decodeData); + + if (bufferData != null) { + + var buffer = new ImageBuffer (bufferData.data, bufferData.width, bufferData.height, bufferData.bpp, bufferData.format); + buffer.transparent = bufferData.transparent; + return new Image (buffer); + + } + + #end + + return null; + + } + + public static function encode (image:Image):ByteArray { #if java @@ -90,6 +132,8 @@ class PNG { #if (cpp || neko || nodejs) + private static var lime_png_decode_bytes:ByteArray -> Bool -> Dynamic = System.load ("lime", "lime_png_decode_bytes", 2); + private static var lime_png_decode_file = System.load ("lime", "lime_png_decode_file", 2); private static var lime_image_encode:ImageBuffer -> Int -> Int -> ByteArray = System.load ("lime", "lime_image_encode", 3); #end diff --git a/project/include/graphics/format/JPEG.h b/project/include/graphics/format/JPEG.h index 48f3cf6e0..a3499d498 100644 --- a/project/include/graphics/format/JPEG.h +++ b/project/include/graphics/format/JPEG.h @@ -15,7 +15,7 @@ namespace lime { public: - static bool Decode (Resource *resource, ImageBuffer *imageBuffer); + static bool Decode (Resource *resource, ImageBuffer *imageBuffer, bool decodeData = true); static bool Encode (ImageBuffer *imageBuffer, ByteArray *bytes, int quality); diff --git a/project/include/graphics/format/PNG.h b/project/include/graphics/format/PNG.h index 6715ca561..c536a59a8 100644 --- a/project/include/graphics/format/PNG.h +++ b/project/include/graphics/format/PNG.h @@ -15,7 +15,7 @@ namespace lime { public: - static bool Decode (Resource *resource, ImageBuffer *imageBuffer); + static bool Decode (Resource *resource, ImageBuffer *imageBuffer, bool decodeData = true); static bool Encode (ImageBuffer *imageBuffer, ByteArray *bytes); diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index e8fbb0732..64b0f5dc6 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -616,6 +616,44 @@ namespace lime { } + value lime_jpeg_decode_bytes (value data, value decodeData) { + + ImageBuffer imageBuffer; + + ByteArray bytes (data); + Resource resource = Resource (&bytes); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, val_bool (decodeData))) { + + return imageBuffer.Value (); + + } + #endif + + return alloc_null (); + + } + + + value lime_jpeg_decode_file (value data, value decodeData) { + + ImageBuffer imageBuffer; + Resource resource = Resource (val_string (data)); + + #ifdef LIME_JPEG + if (JPEG::Decode (&resource, &imageBuffer, val_bool (decodeData))) { + + return imageBuffer.Value (); + + } + #endif + + return alloc_null (); + + } + + value lime_key_event_manager_register (value callback, value eventObject) { KeyEvent::callback = new AutoGCRoot (callback); @@ -718,6 +756,44 @@ namespace lime { } + value lime_png_decode_bytes (value data, value decodeData) { + + ImageBuffer imageBuffer; + + ByteArray bytes (data); + Resource resource = Resource (&bytes); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, val_bool (decodeData))) { + + return imageBuffer.Value (); + + } + #endif + + return alloc_null (); + + } + + + value lime_png_decode_file (value data, value decodeData) { + + ImageBuffer imageBuffer; + Resource resource = Resource (val_string (data)); + + #ifdef LIME_PNG + if (PNG::Decode (&resource, &imageBuffer, val_bool (decodeData))) { + + return imageBuffer.Value (); + + } + #endif + + return alloc_null (); + + } + + value lime_render_event_manager_register (value callback, value eventObject) { RenderEvent::callback = new AutoGCRoot (callback); @@ -1054,6 +1130,8 @@ namespace lime { DEFINE_PRIM (lime_image_encode, 3); DEFINE_PRIM (lime_image_load, 1); DEFINE_PRIM (lime_jni_getenv, 0); + DEFINE_PRIM (lime_jpeg_decode_bytes, 2); + DEFINE_PRIM (lime_jpeg_decode_file, 2); DEFINE_PRIM (lime_key_event_manager_register, 2); DEFINE_PRIM (lime_lzma_decode, 1); DEFINE_PRIM (lime_lzma_encode, 1); @@ -1064,6 +1142,8 @@ namespace lime { DEFINE_PRIM (lime_mouse_show, 0); DEFINE_PRIM (lime_mouse_warp, 3); DEFINE_PRIM (lime_neko_execute, 1); + DEFINE_PRIM (lime_png_decode_bytes, 2); + DEFINE_PRIM (lime_png_decode_file, 2); DEFINE_PRIM (lime_renderer_create, 1); DEFINE_PRIM (lime_renderer_flip, 1); DEFINE_PRIM (lime_renderer_lock, 1); diff --git a/project/src/graphics/ImageBuffer.cpp b/project/src/graphics/ImageBuffer.cpp index 87fe3d9d5..2073e6ff9 100644 --- a/project/src/graphics/ImageBuffer.cpp +++ b/project/src/graphics/ImageBuffer.cpp @@ -117,7 +117,7 @@ namespace lime { alloc_field (mValue, id_height, alloc_int (height)); alloc_field (mValue, id_bpp, alloc_int (bpp)); alloc_field (mValue, id_transparent, alloc_bool (transparent)); - alloc_field (mValue, id_data, data->mValue); + alloc_field (mValue, id_data, data ? data->mValue : alloc_null ()); alloc_field (mValue, id_format, alloc_int (format)); return mValue; diff --git a/project/src/graphics/format/JPEG.cpp b/project/src/graphics/format/JPEG.cpp index 6104b086a..732ad39f7 100644 --- a/project/src/graphics/format/JPEG.cpp +++ b/project/src/graphics/format/JPEG.cpp @@ -178,7 +178,7 @@ namespace lime { }; - bool JPEG::Decode (Resource *resource, ImageBuffer* imageBuffer) { + bool JPEG::Decode (Resource *resource, ImageBuffer* imageBuffer, bool decodeData) { struct jpeg_decompress_struct cinfo; @@ -246,35 +246,45 @@ namespace lime { cinfo.out_color_space = JCS_RGB; - jpeg_start_decompress (&cinfo); - int components = cinfo.num_components; - imageBuffer->Resize (cinfo.output_width, cinfo.output_height); - - unsigned char *bytes = imageBuffer->data->Bytes (); - unsigned char *scanline = new unsigned char [imageBuffer->width * imageBuffer->height * components]; - - while (cinfo.output_scanline < cinfo.output_height) { + if (decodeData) { - jpeg_read_scanlines (&cinfo, &scanline, 1); + jpeg_start_decompress (&cinfo); + int components = cinfo.num_components; + imageBuffer->Resize (cinfo.output_width, cinfo.output_height); - // convert 24-bit scanline to 32-bit - const unsigned char *line = scanline; - const unsigned char *const end = line + imageBuffer->width * components; + unsigned char *bytes = imageBuffer->data->Bytes (); + unsigned char *scanline = new unsigned char [imageBuffer->width * imageBuffer->height * components]; - while (line != end) { + while (cinfo.output_scanline < cinfo.output_height) { - *bytes++ = *line++; - *bytes++ = *line++; - *bytes++ = *line++; - *bytes++ = 0xFF; + jpeg_read_scanlines (&cinfo, &scanline, 1); + + // convert 24-bit scanline to 32-bit + const unsigned char *line = scanline; + const unsigned char *const end = line + imageBuffer->width * components; + + while (line != end) { + + *bytes++ = *line++; + *bytes++ = *line++; + *bytes++ = *line++; + *bytes++ = 0xFF; + + } } + delete[] scanline; + + jpeg_finish_decompress (&cinfo); + + } else { + + imageBuffer->width = cinfo.image_width; + imageBuffer->height = cinfo.image_height; + } - delete[] scanline; - - jpeg_finish_decompress (&cinfo); decoded = true; } diff --git a/project/src/graphics/format/PNG.cpp b/project/src/graphics/format/PNG.cpp index 503f5e2a8..cb652a484 100644 --- a/project/src/graphics/format/PNG.cpp +++ b/project/src/graphics/format/PNG.cpp @@ -75,7 +75,7 @@ namespace lime { void user_flush_data (png_structp png_ptr) {} - bool PNG::Decode (Resource *resource, ImageBuffer *imageBuffer) { + bool PNG::Decode (Resource *resource, ImageBuffer *imageBuffer, bool decodeData) { unsigned char png_sig[PNG_SIG_SIZE]; png_structp png_ptr; @@ -159,46 +159,56 @@ namespace lime { png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); - //bool has_alpha = (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGB_ALPHA || png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)); - - png_set_expand (png_ptr); - - png_set_filler (png_ptr, 0xff, PNG_FILLER_AFTER); - //png_set_gray_1_2_4_to_8 (png_ptr); - png_set_palette_to_rgb (png_ptr); - png_set_gray_to_rgb (png_ptr); - - if (bit_depth < 8) { + if (decodeData) { - png_set_packing (png_ptr); + //bool has_alpha = (color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_RGB_ALPHA || png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)); - } else if (bit_depth == 16) { + png_set_expand (png_ptr); - png_set_scale_16 (png_ptr); + png_set_filler (png_ptr, 0xff, PNG_FILLER_AFTER); + //png_set_gray_1_2_4_to_8 (png_ptr); + png_set_palette_to_rgb (png_ptr); + png_set_gray_to_rgb (png_ptr); - } - - //png_set_bgr (png_ptr); - - int bpp = 4; - const unsigned int stride = width * bpp; - imageBuffer->Resize (width, height, bpp); - unsigned char *bytes = imageBuffer->data->Bytes (); - - int number_of_passes = png_set_interlace_handling (png_ptr); - - for (int pass = 0; pass < number_of_passes; pass++) { - - for (int i = 0; i < height; i++) { + if (bit_depth < 8) { - png_bytep anAddr = (png_bytep)(bytes + i * stride); - png_read_rows (png_ptr, (png_bytepp) &anAddr, NULL, 1); + png_set_packing (png_ptr); + + } else if (bit_depth == 16) { + + png_set_scale_16 (png_ptr); } + //png_set_bgr (png_ptr); + + int bpp = 4; + const unsigned int stride = width * bpp; + imageBuffer->Resize (width, height, bpp); + unsigned char *bytes = imageBuffer->data->Bytes (); + + int number_of_passes = png_set_interlace_handling (png_ptr); + + for (int pass = 0; pass < number_of_passes; pass++) { + + for (int i = 0; i < height; i++) { + + png_bytep anAddr = (png_bytep)(bytes + i * stride); + png_read_rows (png_ptr, (png_bytepp) &anAddr, NULL, 1); + + } + + } + + png_read_end (png_ptr, NULL); + + } else { + + imageBuffer->width = width; + imageBuffer->height = height; + } - png_read_end (png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); if (file) lime::fclose (file);