Add JPEG and PNG decodeBytes/decodeFile, with support for skipping imageBuffer.data
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user