Got JPG/PNG loading from disk and from memory
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package lime.graphics;
|
||||
|
||||
|
||||
import lime.utils.ByteArray;
|
||||
import lime.utils.UInt8Array;
|
||||
import lime.system.System;
|
||||
|
||||
@@ -115,6 +116,22 @@ class Image {
|
||||
}
|
||||
|
||||
|
||||
public static function loadFromBytes (bytes:ByteArray):Image {
|
||||
|
||||
#if (cpp || neko)
|
||||
|
||||
var imageData = lime_image_load_bytes (bytes);
|
||||
return (imageData == null ? null : new Image (new UInt8Array (imageData.data), imageData.width, imageData.height, imageData.bpp));
|
||||
|
||||
#else
|
||||
|
||||
throw "Image.loadFromFile not supported on this target";
|
||||
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function loadFromFile (path:String) {
|
||||
|
||||
#if (cpp || neko)
|
||||
@@ -193,6 +210,7 @@ class Image {
|
||||
|
||||
#if (cpp || neko)
|
||||
private static var lime_image_load = System.load ("lime", "lime_image_load", 1);
|
||||
private static var lime_image_load_bytes = System.load ("lime", "lime_image_load_bytes", 1);
|
||||
#end
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@ namespace lime {
|
||||
|
||||
struct Resource {
|
||||
|
||||
Resource (const char* path) { this->path = path; }
|
||||
Resource (ByteArray *data) { this->data = data; }
|
||||
|
||||
Resource (const char* path) : data (NULL), path (path) {}
|
||||
Resource (ByteArray *data) : data (data), path (NULL) {}
|
||||
|
||||
ByteArray *data;
|
||||
const char* path;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,34 @@ namespace lime {
|
||||
value lime_image_load (value path) {
|
||||
|
||||
Image image;
|
||||
Resource resource = Resource (val_string (path));
|
||||
Resource resource (val_string (path));
|
||||
|
||||
#ifdef LIME_PNG
|
||||
if (PNG::Decode (&resource, &image)) {
|
||||
|
||||
return image.Value ();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LIME_JPEG
|
||||
if (JPEG::Decode (&resource, &image)) {
|
||||
|
||||
return image.Value ();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
value lime_image_load_bytes (value bytes) {
|
||||
|
||||
Image image;
|
||||
ByteArray data (bytes);
|
||||
Resource resource (&data);
|
||||
|
||||
#ifdef LIME_PNG
|
||||
if (PNG::Decode (&resource, &image)) {
|
||||
@@ -251,6 +278,7 @@ namespace lime {
|
||||
DEFINE_PRIM (lime_application_exec, 1);
|
||||
DEFINE_PRIM (lime_application_get_ticks, 0);
|
||||
DEFINE_PRIM (lime_image_load, 1);
|
||||
DEFINE_PRIM (lime_image_load_bytes, 1);
|
||||
DEFINE_PRIM (lime_font_load, 1);
|
||||
DEFINE_PRIM (lime_font_load_glyphs, 3);
|
||||
DEFINE_PRIM (lime_key_event_manager_register, 2);
|
||||
|
||||
@@ -127,17 +127,20 @@ namespace lime {
|
||||
//cinfo.err = jpeg_std_error (&jerr);
|
||||
|
||||
struct ErrorData jpegError;
|
||||
cinfo.err = jpeg_std_error (&jpegError.base);
|
||||
jpegError.base.error_exit = OnError;
|
||||
jpegError.base.output_message = OnOutput;
|
||||
cinfo.err = jpeg_std_error (&jpegError.base);
|
||||
|
||||
FILE *file;
|
||||
FILE *file = NULL;
|
||||
|
||||
if (setjmp (jpegError.on_error)) {
|
||||
|
||||
if (file)
|
||||
if (file) {
|
||||
|
||||
lime::fclose (file);
|
||||
|
||||
}
|
||||
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
return false;
|
||||
|
||||
@@ -196,9 +199,13 @@ namespace lime {
|
||||
|
||||
}
|
||||
|
||||
lime::fclose (file);
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
if (file) {
|
||||
|
||||
lime::fclose (file);
|
||||
|
||||
}
|
||||
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
return decoded;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,110 @@
|
||||
extern "C" {
|
||||
|
||||
#include <png.h>
|
||||
#include <pngstruct.h>
|
||||
#define PNG_SIG_SIZE 8
|
||||
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <graphics/PNG.h>
|
||||
#include <utils/FileIO.h>
|
||||
#include <utils/QuickVec.h>
|
||||
|
||||
|
||||
namespace lime {
|
||||
|
||||
|
||||
struct ReadBuf {
|
||||
|
||||
|
||||
ReadBuf (const uint8 *inData, int inLen) : mData (inData), mLen (inLen) {}
|
||||
|
||||
bool Read (uint8 *outBuffer, int inN) {
|
||||
|
||||
if (inN > mLen) {
|
||||
|
||||
memset (outBuffer, 0, inN);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
memcpy (outBuffer, mData, inN);
|
||||
mData += inN;
|
||||
mLen -= inN;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
const uint8 *mData;
|
||||
int mLen;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void user_error_fn (png_structp png_ptr, png_const_charp error_msg) {
|
||||
|
||||
longjmp (png_ptr->jmp_buf_local, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void user_warning_fn (png_structp png_ptr, png_const_charp warning_msg) {}
|
||||
|
||||
|
||||
static void user_read_data_fn (png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
|
||||
png_voidp buffer = png_get_io_ptr (png_ptr);
|
||||
((ReadBuf *)buffer)->Read (data, length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void user_write_data (png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
|
||||
QuickVec<unsigned char> *buffer = (QuickVec<unsigned char> *)png_get_io_ptr (png_ptr);
|
||||
buffer->append ((unsigned char *)data,(int)length);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void user_flush_data (png_structp png_ptr) {}
|
||||
|
||||
|
||||
bool PNG::Decode (Resource *resource, Image *image) {
|
||||
|
||||
unsigned char png_sig[PNG_SIG_SIZE];
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type;
|
||||
int bit_depth, color_type, interlace_type;
|
||||
|
||||
FILE *file = lime::fopen (resource->path, "rb");
|
||||
FILE *file = NULL;
|
||||
|
||||
if (resource->path) {
|
||||
|
||||
file = lime::fopen (resource->path, "rb");
|
||||
if (!file) return false;
|
||||
|
||||
// verify the PNG signature
|
||||
int read = lime::fread (png_sig, PNG_SIG_SIZE, 1, file);
|
||||
/*int read = lime::fread (png_sig, PNG_SIG_SIZE, 1, file);
|
||||
if (png_sig_cmp (png_sig, 0, PNG_SIG_SIZE)) {
|
||||
|
||||
lime::fclose (file);
|
||||
return false;
|
||||
|
||||
}*/
|
||||
|
||||
} else {
|
||||
|
||||
// TODO: optimize ByteArray Format check?
|
||||
|
||||
}
|
||||
|
||||
if ((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
|
||||
|
||||
lime::fclose (file);
|
||||
if (file) lime::fclose (file);
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -42,7 +112,7 @@ namespace lime {
|
||||
if ((info_ptr = png_create_info_struct (png_ptr)) == NULL) {
|
||||
|
||||
png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
lime::fclose (file);
|
||||
if (file) lime::fclose (file);
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -51,43 +121,59 @@ namespace lime {
|
||||
if (setjmp (png_jmpbuf (png_ptr))) {
|
||||
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
lime::fclose (file);
|
||||
if (file) lime::fclose (file);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
if (file) {
|
||||
|
||||
png_init_io (png_ptr, file);
|
||||
png_set_sig_bytes (png_ptr, PNG_SIG_SIZE);
|
||||
|
||||
} else {
|
||||
|
||||
ReadBuf buffer (resource->data->Bytes (), resource->data->Size ());
|
||||
png_set_read_fn (png_ptr, (void *)&buffer, user_read_data_fn);
|
||||
|
||||
}
|
||||
|
||||
png_read_info (png_ptr, info_ptr);
|
||||
|
||||
width = png_get_image_width (png_ptr, info_ptr);
|
||||
height = png_get_image_height (png_ptr, info_ptr);
|
||||
color_type = png_get_color_type (png_ptr, info_ptr);
|
||||
bit_depth = png_get_bit_depth (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 == 16)
|
||||
png_set_strip_16 (png_ptr);
|
||||
|
||||
//png_set_bgr (png_ptr);
|
||||
|
||||
int bpp = 4;
|
||||
const unsigned int stride = width * bpp;
|
||||
image->Resize(width, height, bpp);
|
||||
image->Resize (width, height, bpp);
|
||||
|
||||
png_bytepp row_ptrs = new png_bytep[height];
|
||||
unsigned char *bytes = image->data->Bytes ();
|
||||
|
||||
for (size_t i = 0; i < height; i++) {
|
||||
int number_of_passes = png_set_interlace_handling (png_ptr);
|
||||
|
||||
row_ptrs[i] = bytes + i * stride;
|
||||
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_image (png_ptr, row_ptrs);
|
||||
png_read_end (png_ptr, NULL);
|
||||
}
|
||||
|
||||
delete[] row_ptrs;
|
||||
png_read_end (png_ptr, info_ptr);
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user