Some work on pixel formats

This commit is contained in:
Joshua Granick
2015-05-04 15:54:50 -07:00
parent ddd77134d2
commit 2b75564951
13 changed files with 270 additions and 8 deletions

View File

@@ -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));

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -1002,6 +1002,15 @@ class ByteArray #if !js extends Bytes implements ArrayAccess<Int> 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<Int> 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);

View File

@@ -3,6 +3,7 @@
#include <hx/CFFI.h>
#include <graphics/PixelFormat.h>
#include <utils/ByteArray.h>
@@ -24,6 +25,7 @@ namespace lime {
int bpp;
ByteArray *data;
PixelFormat format;
int height;
int width;
bool transparent;

View File

@@ -8,7 +8,8 @@ namespace lime {
enum PixelFormat {
RGBA,
ARGB
ARGB,
BGRA
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);