Add more CFFI methods, improve use within the tools (force color order)
This commit is contained in:
19
project/include/graphics/PixelFormat.h
Normal file
19
project/include/graphics/PixelFormat.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef LIME_GRAPHICS_PIXEL_FORMAT_H
|
||||
#define LIME_GRAPHICS_PIXEL_FORMAT_H
|
||||
|
||||
|
||||
namespace lime {
|
||||
|
||||
|
||||
enum PixelFormat {
|
||||
|
||||
RGBA,
|
||||
ARGB
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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 {
|
||||
@@ -18,13 +20,16 @@ namespace lime {
|
||||
|
||||
public:
|
||||
|
||||
static void ColorTransform (Image *image, Rectangle *rect, ColorMatrix *ColorMatrix);
|
||||
static void ColorTransform (Image* image, Rectangle* rect, ColorMatrix* ColorMatrix);
|
||||
static void CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel);
|
||||
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 MultiplyAlpha (Image *image);
|
||||
static void UnmultiplyAlpha (Image *image);
|
||||
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);
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user