Add more CFFI methods, improve use within the tools (force color order)

This commit is contained in:
Joshua Granick
2015-04-14 16:15:32 -07:00
parent e2c2359726
commit 8680d42d25
8 changed files with 607 additions and 354 deletions

View File

@@ -94,7 +94,7 @@ class BMP {
}
var pixels = image.getPixels (new Rectangle (0, 0, image.width, image.height));
var pixels = image.getPixels (new Rectangle (0, 0, image.width, image.height), ARGB);
var a, r, g, b;
switch (type) {

View File

@@ -52,8 +52,9 @@ class ImageDataUtil {
if (data == null) return;
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_color_transform (image, rect, colorMatrix);
#else
if (!System.disableCFFI) lime_image_data_util_color_transform (image, rect, colorMatrix); else
#end
{
var stride = image.buffer.width * 4;
var offset:Int;
@@ -88,7 +89,7 @@ class ImageDataUtil {
}
#end
}
image.dirty = true;
@@ -121,8 +122,9 @@ class ImageDataUtil {
if (srcData == null || destData == null) return;
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx);
#else
if (!System.disableCFFI) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else
#end
{
var srcStride = Std.int (sourceImage.buffer.width * 4);
var srcPosition = Std.int (((sourceRect.x + sourceImage.offsetX) * 4) + (srcStride * (sourceRect.y + sourceImage.offsetY)) + srcIdx);
@@ -159,7 +161,7 @@ class ImageDataUtil {
}
#end
}
image.dirty = true;
@@ -181,8 +183,9 @@ class ImageDataUtil {
}
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, mergeAlpha);
#else
if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, mergeAlpha); else
#end
{
var rowOffset = Std.int (destPoint.y + image.offsetY - sourceRect.y - sourceImage.offsetY);
var columnOffset = Std.int (destPoint.x + image.offsetX - sourceRect.x - sourceImage.offsetY);
@@ -248,7 +251,7 @@ class ImageDataUtil {
}
#end
}
image.dirty = true;
@@ -281,8 +284,9 @@ class ImageDataUtil {
if (data == null) return;
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_fill_rect (image, rect, rgba);
#else
if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, rgba); else
#end
{
if (rect.width == image.buffer.width && rect.height == image.buffer.height && rect.x == 0 && rect.y == 0 && image.offsetX == 0 && image.offsetY == 0) {
@@ -335,7 +339,7 @@ class ImageDataUtil {
}
#end
}
image.dirty = true;
@@ -350,8 +354,9 @@ class ImageDataUtil {
if (format == ARGB) color = ((color & 0xFFFFFF) << 8) | ((color >> 24) & 0xFF);
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_flood_fill (image, x, y, color);
#else
if (!System.disableCFFI) lime_image_data_util_flood_fill (image, x, y, color); else
#end
{
var offset = (((y + image.offsetY) * (image.buffer.width * 4)) + ((x + image.offsetX) * 4));
var hitColorR = data[offset + 0];
@@ -412,7 +417,7 @@ class ImageDataUtil {
}
#end
}
image.dirty = true;
@@ -486,6 +491,8 @@ class ImageDataUtil {
public static function getPixels (image:Image, rect:Rectangle, format:PixelFormat):ByteArray {
if (image.buffer.data == null) return null;
var length = Std.int (rect.width * rect.height);
#if flash
@@ -495,6 +502,14 @@ class ImageDataUtil {
byteArray.position = 0;
#end
Sys.println ("SDFKJ");
Sys.println (System.disableCFFI);
#if ((cpp || neko) && !disable_cffi)
if (!System.disableCFFI) lime_image_data_util_get_pixels (image, rect, format == ARGB ? 1 : 0); else
#end
{
//#if (!js && !flash)
//if (rect.width == image.width && rect.height == image.height && rect.x == 0 && rect.y == 0) {
//
@@ -567,6 +582,8 @@ class ImageDataUtil {
}
}
byteArray.position = 0;
return byteArray;
@@ -575,6 +592,13 @@ class ImageDataUtil {
public static function merge (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void {
if (image.buffer.data == null || sourceImage.buffer.data == null) return;
#if ((cpp || neko) && !disable_cffi)
if (!System.disableCFFI) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); else
#end
{
var rowOffset = Std.int (destPoint.y + image.offsetY - sourceRect.y - sourceImage.offsetY);
var columnOffset = Std.int (destPoint.x + image.offsetX - sourceRect.x - sourceImage.offsetY);
@@ -602,6 +626,8 @@ class ImageDataUtil {
}
}
image.dirty = true;
}
@@ -613,8 +639,9 @@ class ImageDataUtil {
if (data == null) return;
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_multiply_alpha (image);
#else
if (!System.disableCFFI) lime_image_data_util_multiply_alpha (image); else
#end
{
var index, a16;
var length = Std.int (data.length / 4);
@@ -630,7 +657,7 @@ class ImageDataUtil {
}
#end
}
image.buffer.premultiplied = true;
image.dirty = true;
@@ -641,8 +668,14 @@ class ImageDataUtil {
public static function resize (image:Image, newWidth:Int, newHeight:Int):Void {
var buffer = image.buffer;
if (buffer.width == newWidth && buffer.height == newHeight) return;
var newBuffer = new ImageBuffer (new UInt8Array (newWidth * newHeight * 4), newWidth, newHeight);
#if ((cpp || neko) && !disable_cffi)
if (!System.disableCFFI) lime_image_data_util_resize (image, newBuffer, newWidth, newHeight); else
#end
{
var imageWidth = image.width;
var imageHeight = image.height;
@@ -694,7 +727,9 @@ class ImageDataUtil {
}
buffer.data = newData;
}
buffer.data = newBuffer.data;
buffer.width = newWidth;
buffer.height = newHeight;
@@ -864,8 +899,9 @@ class ImageDataUtil {
if (data == null) return;
#if ((cpp || neko) && !disable_cffi)
lime_image_data_util_unmultiply_alpha (image);
#else
if (!System.disableCFFI) lime_image_data_util_unmultiply_alpha (image); else
#end
{
var index, a, unmultiply;
var length = Std.int (data.length / 4);
@@ -888,7 +924,7 @@ class ImageDataUtil {
}
#end
}
image.buffer.premultiplied = false;
image.dirty = true;
@@ -909,7 +945,10 @@ class ImageDataUtil {
private static var lime_image_data_util_copy_pixels = System.load ("lime", "lime_image_data_util_copy_pixels", 5);
private static var lime_image_data_util_fill_rect = System.load ("lime", "lime_image_data_util_fill_rect", 3);
private static var lime_image_data_util_flood_fill = System.load ("lime", "lime_image_data_util_flood_fill", 4);
private static var lime_image_data_util_get_pixels = System.load ("lime", "lime_image_data_util_get_pixels", 3);
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_unmultiply_alpha = System.load ("lime", "lime_image_data_util_unmultiply_alpha", 1);
#end

View File

@@ -29,7 +29,7 @@ class System {
public static var applicationDirectory (get, null):String;
public static var applicationStorageDirectory (get, null):String;
public static var desktopDirectory (get, null):String;
public static var disableCFFI:Bool;
public static var disableCFFI:Bool = #if (disable_cffi || macro || !cpp || !neko || !nodejs) true #else false #end;
public static var documentsDirectory (get, null):String;
public static var fontsDirectory (get, null):String;
public static var userDirectory (get, null):String;

View File

@@ -116,7 +116,7 @@ class IconHelper {
for (c in 0...4) out.writeByte (code.charCodeAt(c));
var n = s * s;
var pixels = image.getPixels (new Rectangle (0, 0, s, s));
var pixels = image.getPixels (new Rectangle (0, 0, s, s), ARGB);
var bytes_r = packBits (pixels, 1, s * s);
var bytes_g = packBits (pixels, 2, s * s);

View File

@@ -0,0 +1,19 @@
#ifndef LIME_GRAPHICS_PIXEL_FORMAT_H
#define LIME_GRAPHICS_PIXEL_FORMAT_H
namespace lime {
enum PixelFormat {
RGBA,
ARGB
};
}
#endif

View File

@@ -4,10 +4,12 @@
#include <hx/CFFI.h>
#include <graphics/Image.h>
#include <graphics/PixelFormat.h>
#include <math/ColorMatrix.h>
#include <math/Rectangle.h>
#include <math/Vector2.h>
#include <system/System.h>
#include <utils/ByteArray.h>
namespace lime {
@@ -23,7 +25,10 @@ namespace lime {
static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha);
static void FillRect (Image* image, Rectangle* rect, int color);
static void FloodFill (Image* image, int x, int y, int color);
static void GetPixels (Image* image, Rectangle* rect, PixelFormat format, ByteArray* pixels);
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 UnmultiplyAlpha (Image* image);

View File

@@ -504,6 +504,32 @@ namespace lime {
}
value lime_image_data_util_get_pixels (value image, value rect, value format) {
Image _image = Image (image);
Rectangle _rect = Rectangle (rect);
PixelFormat _format = (PixelFormat)val_int (format);
ByteArray pixels = ByteArray ();
ImageDataUtil::GetPixels (&_image, &_rect, _format, &pixels);
return pixels.mValue;
}
value lime_image_data_util_merge (value *arg, int nargs) {
enum { image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier };
Image _image = Image (arg[image]);
Image _sourceImage = Image (arg[sourceImage]);
Rectangle _sourceRect = Rectangle (arg[sourceRect]);
Vector2 _destPoint = Vector2 (arg[destPoint]);
ImageDataUtil::Merge (&_image, &_sourceImage, &_sourceRect, &_destPoint, val_int (arg[redMultiplier]), val_int (arg[greenMultiplier]), val_int (arg[blueMultiplier]), val_int (arg[alphaMultiplier]));
return alloc_null ();
}
value lime_image_data_util_multiply_alpha (value image) {
Image _image = Image (image);
@@ -513,6 +539,16 @@ namespace lime {
}
value lime_image_data_util_resize (value image, value buffer, value width, value height) {
Image _image = Image (image);
ImageBuffer _buffer = ImageBuffer (buffer);
ImageDataUtil::Resize (&_image, &_buffer, val_int (width), val_int (height));
return alloc_null ();
}
value lime_image_data_util_unmultiply_alpha (value image) {
Image _image = Image (image);
@@ -918,7 +954,10 @@ namespace lime {
DEFINE_PRIM (lime_image_data_util_copy_pixels, 5);
DEFINE_PRIM (lime_image_data_util_fill_rect, 3);
DEFINE_PRIM (lime_image_data_util_flood_fill, 4);
DEFINE_PRIM (lime_image_data_util_get_pixels, 3);
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_unmultiply_alpha, 1);
DEFINE_PRIM (lime_image_encode, 3);
DEFINE_PRIM (lime_image_load, 1);

View File

@@ -296,6 +296,100 @@ namespace lime {
}
void ImageDataUtil::GetPixels (Image* image, Rectangle* rect, PixelFormat format, ByteArray* pixels) {
int length = int (rect->width * rect->height);
pixels->Resize (length * 4);
if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) {
memcpy (pixels->Bytes (), image->buffer->data->Bytes (), image->buffer->data->Size ());
return;
}
uint8_t* data = (uint8_t*)pixels->Bytes ();
uint8_t* srcData = (uint8_t*)image->buffer->data->Bytes ();
int srcStride = int (image->buffer->width * 4);
int srcPosition = int ((rect->x * 4) + (srcStride * rect->y));
int srcRowOffset = srcStride - int (4 * rect->width);
int srcRowEnd = int (4 * (rect->x + rect->width));
if (format == ARGB) {
for (int i = 0; i < length; i++) {
data[i * 4 + 1] = srcData[srcPosition++];
data[i * 4 + 2] = srcData[srcPosition++];
data[i * 4 + 3] = srcData[srcPosition++];
data[i * 4] = srcData[srcPosition++];
if ((srcPosition % srcStride) > srcRowEnd) {
srcPosition += srcRowOffset;
}
}
} else {
for (int i = 0; i < length; i++) {
data[i * 4] = srcData[srcPosition++];
data[i * 4 + 1] = srcData[srcPosition++];
data[i * 4 + 2] = srcData[srcPosition++];
data[i * 4 + 3] = srcData[srcPosition++];
if ((srcPosition % srcStride) > srcRowEnd) {
srcPosition += srcRowOffset;
}
}
}
}
void ImageDataUtil::Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) {
int rowOffset = int (destPoint->y + image->offsetY - sourceRect->y - sourceImage->offsetY);
int columnOffset = int (destPoint->x + image->offsetX - sourceRect->x - sourceImage->offsetY);
uint8_t* sourceData = (uint8_t*)sourceImage->buffer->data->Bytes ();
int sourceStride = sourceImage->buffer->width * 4;
int sourceOffset = 0;
uint8_t* data = (uint8_t*)image->buffer->data->Bytes ();
int stride = image->buffer->width * 4;
int offset = 0;
int rowEnd = int (sourceRect->y + sourceRect->height + sourceImage->offsetY);
int columnEnd = int (sourceRect->x + sourceRect->width + sourceImage->offsetX);
for (int row = int (sourceRect->y + sourceImage->offsetY); row < rowEnd; row++) {
for (int column = int (sourceRect->x + sourceImage->offsetX); column < columnEnd; column++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
data[offset] = int (((sourceData[offset] * redMultiplier) + (data[offset] * (256 - redMultiplier))) / 256);
data[offset + 1] = int (((sourceData[offset + 1] * greenMultiplier) + (data[offset + 1] * (256 - greenMultiplier))) / 256);
data[offset + 2] = int (((sourceData[offset + 2] * blueMultiplier) + (data[offset + 2] * (256 - blueMultiplier))) / 256);
data[offset + 3] = int (((sourceData[offset + 3] * alphaMultiplier) + (data[offset + 3] * (256 - alphaMultiplier))) / 256);
}
}
}
void ImageDataUtil::MultiplyAlpha (Image* image) {
int a16 = 0;
@@ -315,6 +409,63 @@ namespace lime {
}
void ImageDataUtil::Resize (Image* image, ImageBuffer* buffer, int newWidth, int newHeight) {
int imageWidth = image->width;
int imageHeight = image->height;
uint8_t* data = (uint8_t*)image->buffer->data->Bytes ();
uint8_t* newData = (uint8_t*)buffer->data->Bytes ();
int sourceIndex, sourceIndexX, sourceIndexY, sourceIndexXY, index;
int sourceX, sourceY;
float u, v, uRatio, vRatio, uOpposite, vOpposite;
for (int y = 0; y < newHeight; y++) {
for (int x = 0; x < newWidth; x++) {
u = ((x + 0.5) / newWidth) * imageWidth - 0.5;
v = ((y + 0.5) / newHeight) * imageHeight - 0.5;
sourceX = int (u);
sourceY = int (v);
sourceIndex = (sourceY * imageWidth + sourceX) * 4;
sourceIndexX = (sourceX < imageWidth - 1) ? sourceIndex + 4 : sourceIndex;
sourceIndexY = (sourceY < imageHeight - 1) ? sourceIndex + (imageWidth * 4) : sourceIndex;
sourceIndexXY = (sourceIndexX != sourceIndex) ? sourceIndexY + 4 : sourceIndexY;
index = (y * newWidth + x) * 4;
uRatio = u - sourceX;
vRatio = v - sourceY;
uOpposite = 1 - uRatio;
vOpposite = 1 - vRatio;
newData[index] = int ((data[sourceIndex] * uOpposite + data[sourceIndexX] * uRatio) * vOpposite + (data[sourceIndexY] * uOpposite + data[sourceIndexXY] * uRatio) * vRatio);
newData[index + 1] = int ((data[sourceIndex + 1] * uOpposite + data[sourceIndexX + 1] * uRatio) * vOpposite + (data[sourceIndexY + 1] * uOpposite + data[sourceIndexXY + 1] * uRatio) * vRatio);
newData[index + 2] = int ((data[sourceIndex + 2] * uOpposite + data[sourceIndexX + 2] * uRatio) * vOpposite + (data[sourceIndexY + 2] * uOpposite + data[sourceIndexXY + 2] * uRatio) * vRatio);
// Maybe it would be better to not weigh colors with an alpha of zero, but the below should help prevent black fringes caused by transparent pixels made visible
if (data[sourceIndexX + 3] == 0 || data[sourceIndexY + 3] == 0 || data[sourceIndexXY + 3] == 0) {
newData[index + 3] = 0;
} else {
newData[index + 3] = data[sourceIndex + 3];
}
}
}
}
void ImageDataUtil::UnmultiplyAlpha (Image* image) {
int length = image->buffer->data->Size () / 4;