Improve logic of Threshold

This commit is contained in:
Joshua Granick
2016-01-08 14:08:54 -08:00
parent 3e4bd31fc6
commit a06d18e461
2 changed files with 134 additions and 172 deletions

View File

@@ -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)

View File

@@ -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;
}