diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index ec779ce60..de0647cd5 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -2,6 +2,7 @@ package lime.graphics; import lime.utils.UInt8Array; +import lime.system.System; #if js import js.html.CanvasElement; @@ -46,6 +47,22 @@ class Image { } + public static function loadFromFile (path:String) { + + #if flash + + throw "Can not load image from file in Flash"; + + #elseif (cpp || neko) + + var imageData = lime_load_image (path); + + return (imageData == null ? null : new Image (new UInt8Array (imageData.data), imageData.width, imageData.height)); + + #end + + } + public function forcePowerOfTwo () { @@ -172,6 +189,13 @@ class Image { } + #if (cpp || neko) + + private static var lime_load_image = System.load("lime", "lime_load_image", 1); + + #end + + } diff --git a/project/Build.xml b/project/Build.xml index fbf8093e6..2dcea62a6 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -27,6 +27,7 @@ + @@ -63,6 +64,9 @@ + + + @@ -150,8 +154,11 @@ + + + diff --git a/project/include/graphics/ImageData.h b/project/include/graphics/ImageData.h index fd8f9d70e..638d3d38d 100644 --- a/project/include/graphics/ImageData.h +++ b/project/include/graphics/ImageData.h @@ -1,15 +1,28 @@ #ifndef LIME_GRAPHICS_IMAGE_DATA_H #define LIME_GRAPHICS_IMAGE_DATA_H +#include +#include + namespace lime { - struct ImageData { + class ImageData { + + public: int width; int height; - unsigned char data; + ByteArray *data; + + ImageData(); + ~ImageData(); + value Value(); + + private: + + value mValue; }; diff --git a/project/include/graphics/JPEG.h b/project/include/graphics/JPEG.h new file mode 100644 index 000000000..a5423ebfe --- /dev/null +++ b/project/include/graphics/JPEG.h @@ -0,0 +1,23 @@ +#ifndef LIME_GRAPHICS_JPEG_H +#define LIME_GRAPHICS_JPEG_H + + +namespace lime { + + class ImageData; + + class JPEG { + + + public: + + static bool Decode (const char *path, ImageData *imageData); + + + }; + + +} + + +#endif diff --git a/project/include/graphics/PNG.h b/project/include/graphics/PNG.h index ee9dd02df..63db9da1b 100644 --- a/project/include/graphics/PNG.h +++ b/project/include/graphics/PNG.h @@ -2,19 +2,16 @@ #define LIME_GRAPHICS_PNG_H -#include -#include - - namespace lime { + class ImageData; class PNG { public: - static void Decode (ByteArray bytes, value imageData); + static bool Decode (const char *path, ImageData *imageData); }; diff --git a/project/include/graphics/PVRTC.h b/project/include/graphics/PVRTC.h new file mode 100644 index 000000000..5b33184b6 --- /dev/null +++ b/project/include/graphics/PVRTC.h @@ -0,0 +1,23 @@ +#ifndef LIME_GRAPHICS_PVRTC_H +#define LIME_GRAPHICS_PVRTC_H + + +namespace lime { + + class ImageData; + + class PVRTC { + + + public: + + static bool Decode (const char *path, ImageData *imageData); + + + }; + + +} + + +#endif diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index e522672ef..bd0844878 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -49,13 +51,6 @@ namespace lime { } - value lime_jpg_decode (value bytes, value imageData) { - - return alloc_null (); - - } - - value lime_key_event_manager_register (value callback, value eventObject) { KeyEvent::callback = new AutoGCRoot (callback); @@ -110,10 +105,22 @@ namespace lime { } - value lime_png_decode (value bytes, value imageData) { + value lime_load_image (value path) { + + ImageData imageData; + const char *filePath = val_string (path); + + if (PNG::Decode (filePath, &imageData)) { + + return imageData.Value (); + + } + + if (JPEG::Decode(filePath, &imageData)) { + + return imageData.Value (); - ByteArray byteArray (bytes); - PNG::Decode (bytes, imageData); + } return alloc_null (); @@ -190,13 +197,12 @@ namespace lime { DEFINE_PRIM (lime_application_create, 1); DEFINE_PRIM (lime_application_exec, 1); DEFINE_PRIM (lime_application_get_ticks, 0); - DEFINE_PRIM (lime_jpg_decode, 2); + DEFINE_PRIM (lime_load_image, 1); DEFINE_PRIM (lime_key_event_manager_register, 2); DEFINE_PRIM (lime_lzma_encode, 1); DEFINE_PRIM (lime_lzma_decode, 1); DEFINE_PRIM (lime_mouse_event_manager_register, 2); DEFINE_PRIM (lime_neko_execute, 1); - DEFINE_PRIM (lime_png_decode, 2); DEFINE_PRIM (lime_renderer_create, 1); DEFINE_PRIM (lime_renderer_flip, 1); DEFINE_PRIM (lime_render_event_manager_register, 2); diff --git a/project/src/graphics/ImageData.cpp b/project/src/graphics/ImageData.cpp new file mode 100644 index 000000000..95ea16661 --- /dev/null +++ b/project/src/graphics/ImageData.cpp @@ -0,0 +1,38 @@ +#include + + +namespace lime { + + static int id_data; + static int id_height; + static int id_width; + static bool init = false; + + ImageData::ImageData():width(0), height(0), data(0) { } + + ImageData::~ImageData() { + + delete data; + + } + + value ImageData::Value() { + + if (!init) { + + id_width = val_id ("width"); + id_height = val_id ("height"); + id_data = val_id ("data"); + init = true; + + } + + mValue = alloc_empty_object (); + alloc_field (mValue, id_width, alloc_int (width)); + alloc_field (mValue, id_height, alloc_int (height)); + alloc_field (mValue, id_data, data->mValue); + return mValue; + + } + +} diff --git a/project/src/graphics/JPEG.cpp b/project/src/graphics/JPEG.cpp new file mode 100644 index 000000000..3ff8e3f3a --- /dev/null +++ b/project/src/graphics/JPEG.cpp @@ -0,0 +1,71 @@ +extern "C" { + + #include + #include + #include + +} + +#include +#include + + +namespace lime { + + + extern FILE *OpenRead (const char *); + + + bool JPEG::Decode (const char *path, ImageData *imageData) { + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + FILE *file = OpenRead (path); + + cinfo.err = jpeg_std_error (&jerr); + jpeg_create_decompress (&cinfo); + jpeg_stdio_src (&cinfo, file); + + if (jpeg_read_header (&cinfo, TRUE) == JPEG_HEADER_OK) { + + jpeg_start_decompress (&cinfo); + imageData->width = cinfo.output_width; + imageData->height = cinfo.output_height; + int components = cinfo.num_components; + imageData->data = new ByteArray (imageData->width * imageData->height * 4); + + unsigned char *bytes = imageData->data->Bytes(); + unsigned char *scanline = new unsigned char [imageData->width * imageData->height * components]; + + while (cinfo.output_scanline < cinfo.output_height) { + + jpeg_read_scanlines (&cinfo, &scanline, 1); + + // convert 24-bit scanline to 32-bit + const unsigned char *line = scanline; + const unsigned char *const end = line + imageData->width * components; + + while (line != end) { + + *bytes++ = *line++; + *bytes++ = *line++; + *bytes++ = *line++; + *bytes++ = 0xFF; + + } + + } + + delete[] scanline; + + jpeg_finish_decompress (&cinfo); + } + + fclose (file); + jpeg_destroy_decompress (&cinfo); + + return true; + } + +} diff --git a/project/src/graphics/PNG.cpp b/project/src/graphics/PNG.cpp index 0ecc3f2cf..982e2c38b 100644 --- a/project/src/graphics/PNG.cpp +++ b/project/src/graphics/PNG.cpp @@ -1,143 +1,100 @@ extern "C" { - //#include + #include + #define PNG_SIG_SIZE 8 } -#include +#include #include -#include namespace lime { - static int id_data; - static int id_height; - static int id_width; - static bool init = false; + extern FILE *OpenRead (const char *); - /*static void user_error_fn (png_structp png_ptr, png_const_charp error_msg) { - - longjmp (png_ptr->jmpbuf, 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 *buffer = (QuickVec *)png_get_io_ptr (png_ptr); - buffer->append ((unsigned char *)data, (int)length); - - } - - void user_flush_data (png_structp png_ptr) { }*/ - - - void PNG::Decode (ByteArray bytes, value imageData) { - - /*if (!init) { - - id_data = val_id ("data"); - id_height = val_id ("height"); - id_width = val_id ("width"); - init = true; - - } + bool PNG::Decode (const char *path, ImageData *imageData) { + 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, interlace_type; + int bit_depth, color_type; - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, user_error_fn, user_warning_fn); + FILE *file = OpenRead (path); + if (!file) return false; + + // verify the PNG signature + fread(png_sig, PNG_SIG_SIZE, 1, file); + if (png_sig_cmp (png_sig, 0, PNG_SIG_SIZE)) { - if (png_ptr == NULL) - return; + fclose (file); + return false; - info_ptr = png_create_info_struct (png_ptr); + } + + if ((png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) { + + fclose (file); + return false; + + } - if (info_ptr == NULL) { + if ((info_ptr = png_create_info_struct (png_ptr)) == NULL) { png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL); - return; + fclose (file); + return false; } - unsigned char* bytes[width * height * 4]; - RenderTarget target; - + // sets the point which libpng will jump back to in the case of an error if (setjmp (png_jmpbuf (png_ptr))) { - if (bytes) { - - delete bytes; - - } - png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); - return; + fclose (file); + return false; } - ReadBuf buffer (inData, inDataLen); - - //if (inFile) { - - //png_init_io (png_ptr, inFile); - - //} else { - - png_set_read_fn (png_ptr, (void *)&buffer, user_read_data_fn); - - //} - + png_init_io (png_ptr, file); + png_set_sig_bytes (png_ptr, PNG_SIG_SIZE); 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)); + 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_set_expand (png_ptr); png_set_filler (png_ptr, 0xff, PNG_FILLER_AFTER); - 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); + const unsigned int stride = width * 4; + imageData->width = width; + imageData->height = height; + imageData->data = new ByteArray (height * stride); - //result = new ImageData (); - //result.width = width; - //result.height = height; - //result.data = uint8[width * height * 4]; + png_bytepp row_ptrs = new png_bytep[height]; + unsigned char *bytes = imageData->data->Bytes(); - png_read_png (png_ptr, (png_bytepp)&bytes); + for (size_t i = 0; i < height; i++) { - png_read_end (png_ptr, info_ptr); + row_ptrs[i] = bytes + i * stride; + + } + + png_read_image (png_ptr, row_ptrs); + png_read_end (png_ptr, NULL); + + delete[] row_ptrs; png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); - - value object = (KeyEvent::eventObject ? KeyEvent::eventObject->get () : alloc_empty_object ()); - - alloc_field (object, id_code, alloc_int (event->code)); - alloc_field (object, id_type, alloc_int (event->type)); - - - alloc_field (imageData, id_width, alloc_int (width)); - alloc_field (imageData, id_height, alloc_int (height)); - alloc_field (imageData, id_data, alloc_int (bytes)); - - return result;*/ + return true; } diff --git a/project/src/graphics/PVRTC.cpp b/project/src/graphics/PVRTC.cpp new file mode 100644 index 000000000..fdae8b95e --- /dev/null +++ b/project/src/graphics/PVRTC.cpp @@ -0,0 +1,58 @@ +extern "C" { + + + +} + +#include +#include + + +typedef struct _PVRTexHeader { + + uint32_t headerLength; + uint32_t height; + uint32_t width; + uint32_t numMipmaps; + uint32_t flags; + uint32_t dataLength; + uint32_t bpp; + uint32_t bitmaskRed; + uint32_t bitmaskGreen; + uint32_t bitmaskBlue; + uint32_t bitmaskAlpha; + uint32_t pvrTag; + uint32_t numSurfs; + +} PVRTexHeader; + +static char gPVRTexIdentifier[5] = "PVR!"; + + +namespace lime { + + + extern FILE *OpenRead (const char *); + + + bool PVRTC::Decode (const char *path, ImageData *imageData) { + + PVRTexHeader header; + FILE *file = OpenRead (path); + + fread (&header, sizeof(header), 1, file); + + if (gPVRTexIdentifier[0] != ((header.pvrTag >> 0) & 0xFF) || + gPVRTexIdentifier[1] != ((header.pvrTag >> 8) & 0xFF) || + gPVRTexIdentifier[2] != ((header.pvrTag >> 16) & 0xFF) || + gPVRTexIdentifier[3] != ((header.pvrTag >> 24) & 0xFF)) { + + return false; + + } + + return false; + + } + +} diff --git a/project/src/utils/ByteArray.cpp b/project/src/utils/ByteArray.cpp index 7ffdc48a1..3235bd485 100644 --- a/project/src/utils/ByteArray.cpp +++ b/project/src/utils/ByteArray.cpp @@ -48,6 +48,9 @@ namespace lime { void ByteArray::Resize(int inSize) { + if (mValue == 0) + mValue = val_call1(gByteArrayCreate->get(), alloc_int(inSize) ); + else val_call2(gByteArrayResize->get(), mValue, alloc_int(inSize) ); } diff --git a/templates/haxe/DefaultAssetLibrary.hx b/templates/haxe/DefaultAssetLibrary.hx index 6b926d0cb..3a7a90c7b 100644 --- a/templates/haxe/DefaultAssetLibrary.hx +++ b/templates/haxe/DefaultAssetLibrary.hx @@ -70,7 +70,11 @@ class DefaultAssetLibrary extends AssetLibrary { if (Sys.args ().indexOf ("-livereload") > -1) { + #if mac + var path = FileSystem.fullPath ("../Resources/manifest"); + #else var path = FileSystem.fullPath ("manifest"); + #end lastModified = FileSystem.stat (path).mtime.getTime (); timer = new Timer (2000); @@ -211,39 +215,9 @@ class DefaultAssetLibrary extends AssetLibrary { #else - // TODO: Implement in native backend - - var bytes = getBytes (id); - var byteInput = new haxe.io.BytesInput (bytes, 0, bytes.length); - var png = new format.png.Reader (byteInput).read (); - var data = format.png.Tools.extract32 (png); - var header = format.png.Tools.getHeader (png); - - var imageWidth = header.width; - var imageHeight = header.height; - var imageData = new UInt8Array (ByteArray.fromBytes (data)); - - var imageLength = imageWidth * imageHeight; - var b, g, r, a; - - for (i in 0...imageLength) { - - b = imageData[i * 4]; - g = imageData[i * 4 + 1]; - r = imageData[i * 4 + 2]; - a = imageData[i * 4 + 3]; - - imageData[i * 4] = r; - imageData[i * 4 + 1] = g; - imageData[i * 4 + 2] = b; - imageData[i * 4 + 3] = a; - - } - - return new Image (imageData, imageWidth, imageHeight); - - //if (className.exists(id)) return cast (Type.createInstance (className.get (id), []), BitmapData); - //else return BitmapData.load (path.get (id)); + var image = Image.loadFromFile (path.get (id)); + if (image == null) return null; + return new Image(image.bytes, image.width, image.height); #end