diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index 86fb29bd6..93154d336 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -58,6 +58,7 @@ class Image { public var buffer:ImageBuffer; public var data (get, set):UInt8Array; public var dirty:Bool; + public var format (get, set):PixelFormat; public var height:Int; public var offsetX:Int; public var offsetY:Int; @@ -1172,6 +1173,34 @@ class Image { } + private function get_format ():PixelFormat { + + return buffer.format; + + } + + + private function set_format (value:PixelFormat):PixelFormat { + + if (buffer.format != value) { + + switch (type) { + + case DATA: + + ImageDataUtil.setFormat (this, value); + + default: + + } + + } + + return buffer.format = value; + + } + + private function get_powerOfTwo ():Bool { return ((buffer.width != 0) && ((buffer.width & (~buffer.width + 1)) == buffer.width)) && ((buffer.height != 0) && ((buffer.height & (~buffer.height + 1)) == buffer.height)); diff --git a/lime/graphics/ImageBuffer.hx b/lime/graphics/ImageBuffer.hx index 0bf554d33..36d276146 100644 --- a/lime/graphics/ImageBuffer.hx +++ b/lime/graphics/ImageBuffer.hx @@ -2,6 +2,7 @@ package lime.graphics; import haxe.io.Bytes; +import lime.graphics.cairo.CairoSurface; import lime.utils.ByteArray; import lime.utils.UInt8Array; @@ -24,9 +25,11 @@ class ImageBuffer { public var bitsPerPixel:Int; public var data:UInt8Array; + public var format:PixelFormat; public var height:Int; public var premultiplied:Bool; public var src (get, set):Dynamic; + public var stride (get, never):Int; public var transparent:Bool; public var width:Int; @@ -38,12 +41,13 @@ class ImageBuffer { @:noCompletion private var __srcImageData:#if (js && html5) ImageData #else Dynamic #end; - public function new (data:UInt8Array = null, width:Int = 0, height:Int = 0, bitsPerPixel:Int = 4) { + public function new (data:UInt8Array = null, width:Int = 0, height:Int = 0, bitsPerPixel:Int = 4, format:PixelFormat = null) { this.data = data; this.width = width; this.height = height; this.bitsPerPixel = bitsPerPixel; + this.format = (format == null ? RGBA : format); transparent = true; } @@ -169,4 +173,11 @@ class ImageBuffer { } + private function get_stride ():Int { + + return width * 4; + + } + + } \ No newline at end of file diff --git a/lime/graphics/PixelFormat.hx b/lime/graphics/PixelFormat.hx index 5981b014b..7b8106948 100644 --- a/lime/graphics/PixelFormat.hx +++ b/lime/graphics/PixelFormat.hx @@ -1,9 +1,10 @@ package lime.graphics; -enum PixelFormat { +@:enum abstract PixelFormat(Int) from Int to Int { - RGBA; - ARGB; + public var RGBA = 0; + public var ARGB = 1; + public var BGRA = 2; } \ No newline at end of file diff --git a/lime/graphics/cairo/CairoSurface.hx b/lime/graphics/cairo/CairoSurface.hx index e3609ae1a..90cf744a0 100644 --- a/lime/graphics/cairo/CairoSurface.hx +++ b/lime/graphics/cairo/CairoSurface.hx @@ -1,8 +1,11 @@ package lime.graphics.cairo; +import lime.graphics.Image; import lime.system.System; +@:access(haxe.io.Bytes) + abstract CairoSurface(Dynamic) { @@ -51,6 +54,17 @@ abstract CairoSurface(Dynamic) { } + public static function fromImage (image:Image):CairoSurface { + + #if lime_cairo + return createForData (image.data.buffer.__getNativePointer (), CairoFormat.ARGB32, image.width, image.height, image.buffer.stride); + #else + return null; + #end + + } + + // Get & Set Methods diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 94fffae68..f140c1338 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -4,6 +4,7 @@ package lime.graphics.utils; import haxe.ds.Vector; import lime.graphics.Image; import lime.graphics.ImageBuffer; +import lime.graphics.PixelFormat; import lime.math.ColorMatrix; import lime.math.Rectangle; import lime.math.Vector2; @@ -675,7 +676,7 @@ class ImageDataUtil { #end #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) byteArray = lime_image_data_util_get_pixels (image, rect, format == ARGB ? 1 : 0); else + if (!System.disableCFFI) byteArray = lime_image_data_util_get_pixels (image, rect, format); else #end { @@ -935,6 +936,95 @@ class ImageDataUtil { } + public static function setFormat (image:Image, format:PixelFormat):Void { + + var data = image.buffer.data; + if (data == null) return; + + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_set_format (image, format); else + #end + { + + var index, a16; + var length = Std.int (data.length / 4); + var r1, g1, b1, a1, r2, g2, b2, a2; + var r, g, b, a; + + switch (image.format) { + + case RGBA: + + r1 = 0; + g1 = 1; + b1 = 2; + a1 = 3; + + case ARGB: + + r1 = 1; + g1 = 2; + b1 = 3; + a1 = 0; + + case BGRA: + + r1 = 2; + g1 = 1; + b1 = 0; + a1 = 3; + + } + + switch (format) { + + case RGBA: + + r2 = 0; + g2 = 1; + b2 = 2; + a2 = 3; + + case ARGB: + + r2 = 1; + g2 = 2; + b2 = 3; + a2 = 0; + + case BGRA: + + r2 = 2; + g2 = 1; + b2 = 0; + a2 = 3; + + } + + for (i in 0...length) { + + index = i * 4; + + r = data[index + r1]; + g = data[index + g1]; + b = data[index + b1]; + a = data[index + a1]; + + data[index + r2] = r; + data[index + g2] = g; + data[index + b2] = b; + data[index + a2] = a; + + } + + } + + image.buffer.format = format; + image.dirty = true; + + } + + public static function setPixel (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void { var data = image.buffer.data; @@ -1000,7 +1090,7 @@ class ImageDataUtil { if (image.buffer.data == null) return; #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format == ARGB ? 1 : 0); else + if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format); else #end { @@ -1127,6 +1217,7 @@ class ImageDataUtil { private static var lime_image_data_util_merge = System.load ("lime", "lime_image_data_util_merge", -1); private static var lime_image_data_util_multiply_alpha = System.load ("lime", "lime_image_data_util_multiply_alpha", 1); private static var lime_image_data_util_resize = System.load ("lime", "lime_image_data_util_resize", 4); + private static var lime_image_data_util_set_format = System.load ("lime", "lime_image_data_util_set_format", 2); private static var lime_image_data_util_set_pixels = System.load ("lime", "lime_image_data_util_set_pixels", 4); private static var lime_image_data_util_unmultiply_alpha = System.load ("lime", "lime_image_data_util_unmultiply_alpha", 1); #end diff --git a/lime/utils/ByteArray.hx b/lime/utils/ByteArray.hx index 2910fa5b1..b5f2ea86c 100644 --- a/lime/utils/ByteArray.hx +++ b/lime/utils/ByteArray.hx @@ -1002,6 +1002,15 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa #end + #if (cpp || neko || nodejs) + public function __getNativePointer ():Dynamic { + + return lime_byte_array_get_native_pointer (this); + + } + #end + + #if js private function __getUTFBytesCount (value:String):Int { @@ -1154,6 +1163,7 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa + private static var lime_byte_array_get_native_pointer = System.load ("lime", "lime_byte_array_get_native_pointer", 1); private static var lime_byte_array_overwrite_file = System.load ("lime", "lime_byte_array_overwrite_file", 2); private static var lime_byte_array_read_file = System.load ("lime", "lime_byte_array_read_file", 1); private static var lime_lzma_decode = System.load ("lime", "lime_lzma_decode", 1); diff --git a/project/include/graphics/ImageBuffer.h b/project/include/graphics/ImageBuffer.h index 6e6e0ecfd..d092f9964 100644 --- a/project/include/graphics/ImageBuffer.h +++ b/project/include/graphics/ImageBuffer.h @@ -3,6 +3,7 @@ #include +#include #include @@ -24,6 +25,7 @@ namespace lime { int bpp; ByteArray *data; + PixelFormat format; int height; int width; bool transparent; diff --git a/project/include/graphics/PixelFormat.h b/project/include/graphics/PixelFormat.h index 101dcdab8..fb35c7cb1 100644 --- a/project/include/graphics/PixelFormat.h +++ b/project/include/graphics/PixelFormat.h @@ -8,7 +8,8 @@ namespace lime { enum PixelFormat { RGBA, - ARGB + ARGB, + BGRA }; diff --git a/project/include/graphics/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h index 77ddaac6e..1b06ef15b 100644 --- a/project/include/graphics/utils/ImageDataUtil.h +++ b/project/include/graphics/utils/ImageDataUtil.h @@ -29,6 +29,7 @@ namespace lime { static void Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier); static void MultiplyAlpha (Image* image); static void Resize (Image* image, ImageBuffer* buffer, int width, int height); + static void SetFormat (Image* image, PixelFormat format); static void SetPixels (Image* image, Rectangle* rect, ByteArray* bytes, PixelFormat format); static void UnmultiplyAlpha (Image* image); diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index d20b66d7c..913dd9f87 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -549,6 +549,16 @@ namespace lime { } + value lime_image_data_util_set_format (value image, value format) { + + Image _image = Image (image); + PixelFormat _format = (PixelFormat)val_int (format); + ImageDataUtil::SetFormat (&_image, _format); + return alloc_null (); + + } + + value lime_image_data_util_set_pixels (value image, value rect, value bytes, value format) { Image _image = Image (image); @@ -985,6 +995,7 @@ namespace lime { DEFINE_PRIM_MULT (lime_image_data_util_merge); DEFINE_PRIM (lime_image_data_util_multiply_alpha, 1); DEFINE_PRIM (lime_image_data_util_resize, 4); + DEFINE_PRIM (lime_image_data_util_set_format, 2); DEFINE_PRIM (lime_image_data_util_set_pixels, 4); DEFINE_PRIM (lime_image_data_util_unmultiply_alpha, 1); DEFINE_PRIM (lime_image_encode, 3); diff --git a/project/src/graphics/ImageBuffer.cpp b/project/src/graphics/ImageBuffer.cpp index 4f6c179ce..87fe3d9d5 100644 --- a/project/src/graphics/ImageBuffer.cpp +++ b/project/src/graphics/ImageBuffer.cpp @@ -8,6 +8,7 @@ namespace lime { static int id_bpp; static int id_buffer; static int id_data; + static int id_format; static int id_height; static int id_width; static int id_transparent; @@ -19,6 +20,7 @@ namespace lime { width = 0; height = 0; bpp = 4; + format = RGBA; data = 0; transparent = false; @@ -36,6 +38,7 @@ namespace lime { id_width = val_id ("width"); id_height = val_id ("height"); id_data = val_id ("data"); + id_format = val_id ("format"); init = true; } @@ -43,6 +46,7 @@ namespace lime { width = val_int (val_field (imageBuffer, id_width)); height = val_int (val_field (imageBuffer, id_height)); bpp = val_int (val_field (imageBuffer, id_bitsPerPixel)); + format = (PixelFormat)val_int (val_field (imageBuffer, id_format)); transparent = val_bool (val_field (imageBuffer, id_transparent)); value data_value = val_field (imageBuffer, id_data); value buffer_value = val_field (data_value, id_buffer); @@ -103,6 +107,7 @@ namespace lime { id_width = val_id ("width"); id_height = val_id ("height"); id_data = val_id ("data"); + id_format = val_id ("format"); init = true; } @@ -113,6 +118,7 @@ namespace lime { 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_format, alloc_int (format)); return mValue; } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 70863675a..1ced8f2bb 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -478,6 +478,90 @@ namespace lime { } + void ImageDataUtil::SetFormat (Image* image, PixelFormat format) { + + int index, a16; + int length = image->buffer->data->Size () / 4; + int r1, g1, b1, a1, r2, g2, b2, a2; + int r, g, b, a; + + switch (image->buffer->format) { + + case RGBA: + + r1 = 0; + g1 = 1; + b1 = 2; + a1 = 3; + break; + + case ARGB: + + r1 = 1; + g1 = 2; + b1 = 3; + a1 = 0; + break; + + case BGRA: + + r1 = 2; + g1 = 1; + b1 = 0; + a1 = 3; + break; + + } + + switch (format) { + + case RGBA: + + r2 = 0; + g2 = 1; + b2 = 2; + a2 = 3; + break; + + case ARGB: + + r2 = 1; + g2 = 2; + b2 = 3; + a2 = 0; + break; + + case BGRA: + + r2 = 2; + g2 = 1; + b2 = 0; + a2 = 3; + break; + + } + + unsigned char* data = image->buffer->data->Bytes (); + + for (int i = 0; i < length; i++) { + + index = i * 4; + + r = data[index + r1]; + g = data[index + g1]; + b = data[index + b1]; + a = data[index + a1]; + + data[index + r2] = r; + data[index + g2] = g; + data[index + b2] = b; + data[index + a2] = a; + + } + + } + + void ImageDataUtil::SetPixels (Image* image, Rectangle* rect, ByteArray* bytes, PixelFormat format) { if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { diff --git a/project/src/utils/ByteArray.cpp b/project/src/utils/ByteArray.cpp index 231fe27de..5bf21a040 100644 --- a/project/src/utils/ByteArray.cpp +++ b/project/src/utils/ByteArray.cpp @@ -138,7 +138,7 @@ namespace lime { if (!val_is_null (bytes.mValue)) { - return alloc_int ((intptr_t)bytes.Bytes ()); + return alloc_float ((intptr_t)bytes.Bytes ()); } @@ -146,6 +146,7 @@ namespace lime { } + value lime_byte_array_init (value inFactory, value inLen, value inResize, value inBytes) { gByteArrayCreate = new AutoGCRoot (inFactory);