From e2c235972670a48f80bfb0b859a98584be202f03 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 14 Apr 2015 14:26:57 -0700 Subject: [PATCH] Add floodFill in CFFI --- lime/graphics/utils/ImageDataUtil.hx | 17 +++-- .../include/graphics/utils/ImageDataUtil.h | 1 + project/src/ExternalInterface.cpp | 10 +++ project/src/graphics/Image.cpp | 2 +- project/src/graphics/utils/ImageDataUtil.cpp | 69 +++++++++++++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 8c8feef2a..7530101f7 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -347,16 +347,22 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; + 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 + var offset = (((y + image.offsetY) * (image.buffer.width * 4)) + ((x + image.offsetX) * 4)); var hitColorR = data[offset + 0]; var hitColorG = data[offset + 1]; var hitColorB = data[offset + 2]; var hitColorA = image.transparent ? data[offset + 3] : 0xFF; - var r = (color & 0xFF0000) >>> 16; - var g = (color & 0x00FF00) >>> 8; - var b = (color & 0x0000FF); - var a = image.transparent ? (color & 0xFF000000) >>> 24 : 0xFF; + var r = (color >> 24) & 0xFF; + var g = (color >> 16) & 0xFF; + var b = (color >> 8) & 0xFF; + var a = image.transparent ? color & 0xFF : 0xFF; if (hitColorR == r && hitColorG == g && hitColorB == b && hitColorA == a) return; @@ -406,6 +412,8 @@ class ImageDataUtil { } + #end + image.dirty = true; } @@ -900,6 +908,7 @@ class ImageDataUtil { private static var lime_image_data_util_copy_channel = System.load ("lime", "lime_image_data_util_copy_channel", -1); 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_multiply_alpha = System.load ("lime", "lime_image_data_util_multiply_alpha", 1); private static var lime_image_data_util_unmultiply_alpha = System.load ("lime", "lime_image_data_util_unmultiply_alpha", 1); #end diff --git a/project/include/graphics/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h index d1efd1d5c..1a6456865 100644 --- a/project/include/graphics/utils/ImageDataUtil.h +++ b/project/include/graphics/utils/ImageDataUtil.h @@ -22,6 +22,7 @@ namespace lime { 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); diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 76fcca2bb..9ffb46456 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -495,6 +495,15 @@ namespace lime { } + value lime_image_data_util_flood_fill (value image, value x, value y, value color) { + + Image _image = Image (image); + ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), val_number (color)); + return alloc_null (); + + } + + value lime_image_data_util_multiply_alpha (value image) { Image _image = Image (image); @@ -908,6 +917,7 @@ namespace lime { 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_flood_fill, 4); DEFINE_PRIM (lime_image_data_util_multiply_alpha, 1); DEFINE_PRIM (lime_image_data_util_unmultiply_alpha, 1); DEFINE_PRIM (lime_image_encode, 3); diff --git a/project/src/graphics/Image.cpp b/project/src/graphics/Image.cpp index 3ad8692db..4a84bffb4 100644 --- a/project/src/graphics/Image.cpp +++ b/project/src/graphics/Image.cpp @@ -44,7 +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)); + transparent = val_int (val_field (image, id_transparent)); } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index f3bbcf726..eb076b85b 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace lime { @@ -227,6 +228,74 @@ namespace lime { } + void ImageDataUtil::FloodFill (Image* image, int x, int y, int color) { + + uint8_t* data = (uint8_t*)image->buffer->data->Bytes (); + + int offset = (((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4)); + uint8_t hitColorR = data[offset + 0]; + uint8_t hitColorG = data[offset + 1]; + uint8_t hitColorB = data[offset + 2]; + uint8_t hitColorA = image->transparent ? data[offset + 3] : 0xFF; + + uint8_t r = (color >> 24) & 0xFF; + uint8_t g = (color >> 16) & 0xFF; + uint8_t b = (color >> 8) & 0xFF; + uint8_t a = image->transparent ? color & 0xFF : 0xFF; + + if (hitColorR == r && hitColorG == g && hitColorB == b && hitColorA == a) return; + + int dx[4] = { 0, -1, 1, 0 }; + int dy[4] = { -1, 0, 0, 1 }; + + int minX = -image->offsetX; + int minY = -image->offsetY; + int maxX = minX + image->width; + int maxY = minY + image->height; + + QuickVec queue = QuickVec (); + queue.push_back (x); + queue.push_back (y); + + int curPointX, curPointY, i, nextPointX, nextPointY, nextPointOffset; + + while (queue.size () > 0) { + + curPointY = queue.qpop (); + curPointX = queue.qpop (); + + for (i = 0; i < 4; i++) { + + nextPointX = curPointX + dx[i]; + nextPointY = curPointY + dy[i]; + + if (nextPointX < minX || nextPointY < minY || nextPointX >= maxX || nextPointY >= maxY) { + + continue; + + } + + nextPointOffset = (nextPointY * image->width + nextPointX) * 4; + + if (data[nextPointOffset + 0] == hitColorR && data[nextPointOffset + 1] == hitColorG && data[nextPointOffset + 2] == hitColorB && data[nextPointOffset + 3] == hitColorA) { + + data[nextPointOffset + 0] = r; + data[nextPointOffset + 1] = g; + data[nextPointOffset + 2] = b; + data[nextPointOffset + 3] = a; + + queue.push_back (nextPointX); + queue.push_back (nextPointY); + + } + + } + + } + + } + + void ImageDataUtil::MultiplyAlpha (Image* image) { int a16 = 0;