Improve logic of Threshold
This commit is contained in:
@@ -842,12 +842,6 @@ class Image {
|
||||
|
||||
}
|
||||
|
||||
public function threshold(sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, operation:String, threshold:Int, color:Int = 0x00000000, mask:Int = 0xFFFFFFFF, copySource:Bool = false):Int {
|
||||
|
||||
return ImageDataUtil.threshold(this, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function setPixel32 (x:Int, y:Int, color:Int, format:PixelFormat = null):Void {
|
||||
|
||||
@@ -968,6 +962,52 @@ class Image {
|
||||
}
|
||||
|
||||
|
||||
public function threshold (sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, operation:String, threshold:Int, color:Int = 0x00000000, mask:Int = 0xFFFFFFFF, copySource:Bool = false, format:PixelFormat = null):Int {
|
||||
|
||||
if (buffer == null || sourceImage == null || sourceRect == null) return 0;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case CANVAS, DATA:
|
||||
|
||||
#if (js && html5)
|
||||
ImageCanvasUtil.convertToData (this);
|
||||
#end
|
||||
|
||||
return ImageDataUtil.threshold (this, sourceImage, sourceRect, destPoint, operation, threshold, color, mask, copySource, format);
|
||||
|
||||
case FLASH:
|
||||
|
||||
var _color:ARGB = switch (format) {
|
||||
|
||||
case ARGB32: color;
|
||||
case BGRA32: (color:BGRA);
|
||||
default: (color:RGBA);
|
||||
|
||||
}
|
||||
|
||||
var _mask:ARGB = switch (format) {
|
||||
|
||||
case ARGB32: mask;
|
||||
case BGRA32: (mask:BGRA);
|
||||
default: (mask:RGBA);
|
||||
|
||||
}
|
||||
|
||||
sourceRect.offset (sourceImage.offsetX, sourceImage.offsetY);
|
||||
destPoint.offset (offsetX, offsetY);
|
||||
|
||||
return buffer.__srcBitmapData.threshold (sourceImage.buffer.src, sourceRect.__toFlashRectangle (), destPoint.__toFlashPoint (), operation, threshold, _color, _mask, copySource);
|
||||
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static function __base64Encode (bytes:Bytes):String {
|
||||
|
||||
#if (js && html5)
|
||||
|
||||
@@ -7,7 +7,6 @@ import haxe.io.Bytes;
|
||||
import lime.graphics.Image;
|
||||
import lime.graphics.ImageBuffer;
|
||||
import lime.graphics.PixelFormat;
|
||||
import lime.graphics.utils.ImageDataUtil.Operation;
|
||||
import lime.math.color.ARGB;
|
||||
import lime.math.color.BGRA;
|
||||
import lime.math.color.RGBA;
|
||||
@@ -1058,179 +1057,110 @@ class ImageDataUtil {
|
||||
}
|
||||
|
||||
|
||||
public static function threshold (destImage:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, operation:String, threshold:Int, color:Int = 0x00000000, mask:Int = 0xFFFFFFFF, copySource:Bool = false):Int {
|
||||
public static function threshold (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, operation:String, threshold:Int, color:Int, mask:Int, copySource:Bool, format:PixelFormat):Int {
|
||||
|
||||
var thresholdMask:Int = threshold & mask;
|
||||
var _color:RGBA, _mask:RGBA, _threshold:RGBA;
|
||||
|
||||
var a = (thresholdMask >> 24) & 0xFF;
|
||||
var r = (thresholdMask >> 16) & 0xFF;
|
||||
var g = (thresholdMask >> 8) & 0xFF;
|
||||
var b = (thresholdMask ) & 0xFF;
|
||||
switch (format) {
|
||||
|
||||
var thresholdRGBA:RGBA = RGBA.create(r, g, b, a);
|
||||
case ARGB32:
|
||||
|
||||
a = (color >> 24) & 0xFF;
|
||||
r = (color >> 16) & 0xFF;
|
||||
g = (color >> 8) & 0xFF;
|
||||
b = (color ) & 0xFF;
|
||||
_color = (color:ARGB);
|
||||
_mask = (mask:ARGB);
|
||||
_threshold = (threshold:ARGB);
|
||||
|
||||
var colorRGBA:RGBA = RGBA.create(r, g, b, a);
|
||||
case BGRA32:
|
||||
|
||||
var operationEnum:Operation = switch(operation) {
|
||||
_color = (color:BGRA);
|
||||
_mask = (mask:BGRA);
|
||||
_threshold = (threshold:BGRA);
|
||||
|
||||
case "==": EQUALS;
|
||||
case "<" : LESS_THAN;
|
||||
case ">" : GREATER_THAN;
|
||||
case "<=": LESS_THAN_OR_EQUAL_TO;
|
||||
case ">=": GREATER_THAN_OR_EQUAL_TO;
|
||||
case "!=": NOT_EQUALS;
|
||||
default : EQUALS;
|
||||
default:
|
||||
|
||||
_color = color;
|
||||
_mask = mask;
|
||||
_threshold = threshold;
|
||||
|
||||
}
|
||||
|
||||
var hits:Int = 0;
|
||||
|
||||
if (sourceImage == destImage && sourceRect.equals (destImage.rect) && destPoint.x == 0 && destPoint.y == 0) {
|
||||
|
||||
var pixelMask:Int, i, test;
|
||||
|
||||
#if ((cpp || neko) && !disable_cffi && !macro)
|
||||
if (CFFI.enabled) hits = lime_image_data_util_threshold_inner_loop (destImage, sourceImage, sourceRect, mask, thresholdRGBA, operationEnum, colorRGBA, new Rectangle(0, 0, sourceRect.width, sourceRect.height)); else
|
||||
#end
|
||||
{
|
||||
|
||||
hits = __threshold_inner_loop (destImage, sourceImage, sourceRect, mask, thresholdRGBA, operationEnum, colorRGBA, 0, 0, Std.int(sourceRect.width), Std.int(sourceRect.height));
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var destData = destImage.buffer.data;
|
||||
var destFormat = destImage.buffer.format;
|
||||
var destPremultiplied = destImage.buffer.premultiplied;
|
||||
|
||||
sourceRect = sourceRect.clone ();
|
||||
|
||||
if (sourceRect.right > sourceImage.width) {
|
||||
|
||||
sourceRect.width = sourceImage.width - sourceRect.x;
|
||||
|
||||
}
|
||||
|
||||
if (sourceRect.bottom > sourceImage.height) {
|
||||
|
||||
sourceRect.height = sourceImage.height - sourceRect.y;
|
||||
|
||||
}
|
||||
|
||||
var targetRect = sourceRect.clone ();
|
||||
targetRect.offsetPoint (destPoint);
|
||||
|
||||
if (targetRect.right > destImage.width) {
|
||||
|
||||
targetRect.width = destImage.width - targetRect.x;
|
||||
|
||||
}
|
||||
|
||||
if (targetRect.bottom > destImage.height) {
|
||||
|
||||
targetRect.height = destImage.height - targetRect.y;
|
||||
|
||||
}
|
||||
|
||||
sourceRect.width = Math.min (sourceRect.width, targetRect.width);
|
||||
sourceRect.height = Math.min (sourceRect.height, targetRect.height);
|
||||
|
||||
var sx = Std.int (sourceRect.x);
|
||||
var sy = Std.int (sourceRect.y);
|
||||
var sw = Std.int (sourceRect.width);
|
||||
var sh = Std.int (sourceRect.height);
|
||||
|
||||
var dx = Std.int (destPoint.x);
|
||||
var dy = Std.int (destPoint.y);
|
||||
|
||||
var bw:Int = destImage.width - sw - dx;
|
||||
var bh:Int = destImage.height - sh - dy;
|
||||
|
||||
var dw:Int = (bw < 0) ? sw + (destImage.width - sw - dx) : sw;
|
||||
var dh:Int = (bw < 0) ? sh + (destImage.height - sh - dy) : sh;
|
||||
|
||||
if (copySource) {
|
||||
|
||||
destImage.copyPixels(sourceImage, sourceRect, destPoint);
|
||||
|
||||
}
|
||||
|
||||
var pixelMask:Int, i, test;
|
||||
|
||||
#if ((cpp || neko) && !disable_cffi && !macro)
|
||||
if (CFFI.enabled) hits = lime_image_data_util_threshold_inner_loop (destImage, sourceImage, sourceRect, mask, thresholdRGBA, operationEnum, cast colorRGBA, new Rectangle(sx, sy, dw, dh)); else
|
||||
#end
|
||||
{
|
||||
|
||||
hits = __threshold_inner_loop (destImage, sourceImage, sourceRect, mask, thresholdRGBA, operationEnum, colorRGBA, sx, sy, dw, dh);
|
||||
|
||||
}
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static inline function __threshold_inner_loop (image:Image, sourceImage:Image, sourceRect:Rectangle, mask:Int, threshold:Int, operation:Operation, color:Int, startX:Int, startY:Int, destWidth:Int, destHeight:Int):Int {
|
||||
|
||||
var srcView = new ImageDataView(sourceImage, sourceRect);
|
||||
var srcPixel:RGBA = 0;
|
||||
var srcPosition:Int = 0;
|
||||
var srcFormat = sourceImage.buffer.format;
|
||||
var srcPremultiplied = sourceImage.buffer.premultiplied;
|
||||
var srcData = sourceImage.buffer.data;
|
||||
var destData = image.buffer.data;
|
||||
|
||||
var colorRGBA:RGBA = color;
|
||||
if (srcData == null || destData == null) return 0;
|
||||
|
||||
#if (false && (cpp || neko) && !disable_cffi && !macro)
|
||||
if (CFFI.enabled) return lime_image_data_util_threshold (image, sourceImage, sourceRect, destPoint, operation, threshold, color, mastk, copySource, format); else
|
||||
#end
|
||||
{
|
||||
|
||||
trace ("hi");
|
||||
trace (operation);
|
||||
trace (StringTools.hex (_mask));
|
||||
trace (StringTools.hex (_threshold));
|
||||
|
||||
var pixelMask:Int = 0;
|
||||
var i = 0;
|
||||
var test = false;
|
||||
var hits = 0;
|
||||
|
||||
for (yy in 0...destHeight) {
|
||||
var srcView = new ImageDataView (sourceImage, sourceRect);
|
||||
var destView = new ImageDataView (image, new Rectangle (destPoint.x, destPoint.y, srcView.width, srcView.height));
|
||||
|
||||
srcPosition = srcView.row (yy + startY);
|
||||
srcPosition += (4 * startX);
|
||||
var srcFormat = sourceImage.buffer.format;
|
||||
var destFormat = image.buffer.format;
|
||||
var srcPremultiplied = sourceImage.buffer.premultiplied;
|
||||
var destPremultiplied = image.buffer.premultiplied;
|
||||
|
||||
for (xx in 0...destWidth) {
|
||||
var srcPosition, destPosition, srcPixel:RGBA, destPixel:RGBA, pixelMask:Int, test:Bool, value:Int;
|
||||
|
||||
for (y in 0...destView.height) {
|
||||
|
||||
srcPosition = srcView.row (y);
|
||||
destPosition = destView.row (y);
|
||||
|
||||
for (x in 0...destView.width) {
|
||||
|
||||
srcPixel.readUInt8 (srcData, srcPosition, srcFormat, srcPremultiplied);
|
||||
pixelMask = srcPixel & mask;
|
||||
|
||||
i = __ucompare (pixelMask, threshold);
|
||||
pixelMask = srcPixel & _mask;
|
||||
|
||||
value = __ucompare (pixelMask, _threshold);
|
||||
|
||||
test = switch (operation) {
|
||||
|
||||
case EQUALS: (i == 0);
|
||||
case LESS_THAN: (i == -1);
|
||||
case GREATER_THAN: (i == 1);
|
||||
case NOT_EQUALS: (i != 0);
|
||||
case LESS_THAN_OR_EQUAL_TO: (i == 0 || i == -1);
|
||||
case GREATER_THAN_OR_EQUAL_TO: (i == 0 || i == 1);
|
||||
case "==": (value == 0);
|
||||
case "<": (value == -1);
|
||||
case ">": (value == 1);
|
||||
case "!=": (value != 0);
|
||||
case "<=": (value == 0 || value == -1);
|
||||
case ">=": (value == 0 || value == 1);
|
||||
default: false;
|
||||
|
||||
}
|
||||
|
||||
if (test) {
|
||||
|
||||
colorRGBA.writeUInt8(srcData, srcPosition, srcFormat, srcPremultiplied);
|
||||
|
||||
|
||||
_color.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
|
||||
hits++;
|
||||
|
||||
}
|
||||
|
||||
srcPosition += 4;
|
||||
destPosition += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hits > 0) {
|
||||
|
||||
image.dirty = true;
|
||||
|
||||
}
|
||||
|
||||
return hits;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1263,7 +1193,7 @@ class ImageDataUtil {
|
||||
}
|
||||
|
||||
|
||||
private static function __ucompare (n1:Int, n2:Int) : Int {
|
||||
private static inline function __ucompare (n1:Int, n2:Int):Int {
|
||||
|
||||
var tmp1:Int;
|
||||
var tmp2:Int;
|
||||
@@ -1317,6 +1247,8 @@ class ImageDataUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Native Methods
|
||||
|
||||
|
||||
@@ -1408,13 +1340,3 @@ private class ImageDataView {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@:enum abstract Operation(Int) from Int to Int{
|
||||
var EQUALS = 0;
|
||||
var LESS_THAN = 1;
|
||||
var GREATER_THAN = 2;
|
||||
var LESS_THAN_OR_EQUAL_TO = 3;
|
||||
var GREATER_THAN_OR_EQUAL_TO = 4;
|
||||
var NOT_EQUALS = 5;
|
||||
}
|
||||
Reference in New Issue
Block a user