Add support for PixelFormat (RGBA, ARGB) in Image, add more CFFI methods

This commit is contained in:
Joshua Granick
2015-04-14 13:49:58 -07:00
parent a6cb988d72
commit 560a78db62
14 changed files with 574 additions and 102 deletions

View File

@@ -459,6 +459,42 @@ namespace lime {
}
value lime_image_data_util_copy_channel (value *arg, int nargs) {
enum { image, sourceImage, sourceRect, destPoint, srcChannel, destChannel };
Image _image = Image (arg[image]);
Image _sourceImage = Image (arg[sourceImage]);
Rectangle _sourceRect = Rectangle (arg[sourceRect]);
Vector2 _destPoint = Vector2 (arg[destPoint]);
ImageDataUtil::CopyChannel (&_image, &_sourceImage, &_sourceRect, &_destPoint, val_int (arg[srcChannel]), val_int (arg[destChannel]));
return alloc_null ();
}
value lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value mergeAlpha) {
Image _image = Image (image);
Image _sourceImage = Image (sourceImage);
Rectangle _sourceRect = Rectangle (sourceRect);
Vector2 _destPoint = Vector2 (destPoint);
ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, val_bool (mergeAlpha));
return alloc_null ();
}
value lime_image_data_util_fill_rect (value image, value rect, value color) {
Image _image = Image (image);
Rectangle _rect = Rectangle (rect);
ImageDataUtil::FillRect (&_image, &_rect, val_number (color));
return alloc_null ();
}
value lime_image_data_util_multiply_alpha (value image) {
Image _image = Image (image);
@@ -869,6 +905,9 @@ namespace lime {
DEFINE_PRIM (lime_gamepad_get_device_guid, 1);
DEFINE_PRIM (lime_gamepad_get_device_name, 1);
DEFINE_PRIM (lime_image_data_util_color_transform, 3);
DEFINE_PRIM_MULT (lime_image_data_util_copy_channel);
DEFINE_PRIM (lime_image_data_util_copy_pixels, 5);
DEFINE_PRIM (lime_image_data_util_fill_rect, 3);
DEFINE_PRIM (lime_image_data_util_multiply_alpha, 1);
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_height;
static int id_offsetX;
static int id_offsetY;
static int id_transparent;
static int id_width;
static bool init = false;
@@ -18,6 +19,7 @@ namespace lime {
height = 0;
offsetX = 0;
offsetY = 0;
transparent = true;
width = 0;
}
@@ -31,6 +33,7 @@ namespace lime {
id_height = val_id ("height");
id_offsetX = val_id ("offsetX");
id_offsetY = val_id ("offsetY");
id_transparent = val_id ("transparent");
id_width = val_id ("width");
init = true;
@@ -41,6 +44,7 @@ namespace lime {
buffer = new ImageBuffer (val_field (image, id_buffer));
offsetX = val_int (val_field (image, id_offsetX));
offsetY = val_int (val_field (image, id_offsetY));
transparent = val_bool (val_field (image, id_transparent));
}

View File

@@ -84,6 +84,149 @@ namespace lime {
}
void ImageDataUtil::CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) {
int srcStride = sourceImage->buffer->width * 4;
int srcPosition = ((sourceRect->x + sourceImage->offsetX) * 4) + (srcStride * (sourceRect->y + sourceImage->offsetY)) + srcChannel;
int srcRowOffset = srcStride - int (4 * (sourceRect->width + sourceImage->offsetX));
int srcRowEnd = 4 * (sourceRect->x + sourceImage->offsetX + sourceRect->width);
uint8_t* srcData = (uint8_t*)sourceImage->buffer->data->Bytes ();
int destStride = image->buffer->width * 4;
int destPosition = ((destPoint->x + image->offsetX) * 4) + (destStride * (destPoint->y + image->offsetY)) + destChannel;
int destRowOffset = destStride - int (4 * (sourceRect->width + image->offsetX));
int destRowEnd = 4 * (destPoint->x + image->offsetX + sourceRect->width);
uint8_t* destData = (uint8_t*)image->buffer->data->Bytes ();
int length = sourceRect->width * sourceRect->height;
for (int i = 0; i < length; i++) {
destData[destPosition] = srcData[srcPosition];
srcPosition += 4;
destPosition += 4;
if ((srcPosition % srcStride) > srcRowEnd) {
srcPosition += srcRowOffset;
}
if ((destPosition % destStride) > destRowEnd) {
destPosition += destRowOffset;
}
}
}
void ImageDataUtil::CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha) {
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 rows = sourceRect->y + sourceRect->height + sourceImage->offsetY;
int columns = sourceRect->x + sourceRect->width + sourceImage->offsetX;
if (!mergeAlpha || !sourceImage->transparent) {
for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) {
for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
data[offset] = sourceData[sourceOffset];
data[offset + 1] = sourceData[sourceOffset + 1];
data[offset + 2] = sourceData[sourceOffset + 2];
data[offset + 3] = sourceData[sourceOffset + 3];
}
}
} else {
float sourceAlpha;
float oneMinusSourceAlpha;
for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) {
for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) {
sourceOffset = (row * sourceStride) + (column * 4);
offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
sourceAlpha = sourceData[sourceOffset + 3] / 255;
oneMinusSourceAlpha = (1 - sourceAlpha);
data[offset] = __clamp[int (sourceData[sourceOffset] + (data[offset] * oneMinusSourceAlpha))];
data[offset + 1] = __clamp[int (sourceData[sourceOffset + 1] + (data[offset + 1] * oneMinusSourceAlpha))];
data[offset + 2] = __clamp[int (sourceData[sourceOffset + 2] + (data[offset + 2] * oneMinusSourceAlpha))];
data[offset + 3] = __clamp[int (sourceData[sourceOffset + 3] + (data[offset + 3] * oneMinusSourceAlpha))];
}
}
}
}
void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int color) {
int* data = (int*)image->buffer->data->Bytes ();
if (rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0 && image->offsetX == 0 && image->offsetY == 0) {
int length = image->buffer->width * image->buffer->height;
for (int i = 0; i < length; i++) {
data[i] = color;
}
} else {
int stride = image->buffer->width;
int offset;
int rowStart = int (rect->y + image->offsetY);
int rowEnd = int (rect->y + rect->height + image->offsetY);
int columnStart = int (rect->x + image->offsetX);
int columnEnd = int (rect->x + rect->width + image->offsetX);
for (int row = rowStart; row < rowEnd; row++) {
for (int column = columnStart; column < columnEnd; column++) {
offset = (row * stride) + (column);
data[offset] = color;
}
}
}
}
void ImageDataUtil::MultiplyAlpha (Image* image) {
int a16 = 0;

View File

@@ -0,0 +1,36 @@
#include <math/Vector2.h>
namespace lime {
static int id_x;
static int id_y;
static bool init = false;
Vector2::Vector2 () {
x = 0;
y = 0;
}
Vector2::Vector2 (value vec) {
if (!init) {
id_x = val_id ("x");
id_y = val_id ("y");
init = true;
}
x = val_number (val_field (vec, id_x));
y = val_number (val_field (vec, id_y));
}
}