365 lines
8.9 KiB
Haxe
365 lines
8.9 KiB
Haxe
package lime.graphics.utils;
|
|
|
|
|
|
import haxe.format.JsonParser;
|
|
import lime.graphics.Image;
|
|
import lime.graphics.ImageBuffer;
|
|
import lime.graphics.PixelFormat;
|
|
import lime.math.ColorMatrix;
|
|
import lime.math.Rectangle;
|
|
import lime.math.Vector2;
|
|
import lime.utils.ByteArray;
|
|
import lime.utils.UInt8Array;
|
|
|
|
#if (js && html5)
|
|
import js.Browser;
|
|
#end
|
|
|
|
@:access(lime.graphics.ImageBuffer)
|
|
|
|
|
|
class ImageCanvasUtil {
|
|
|
|
|
|
public static function colorTransform (image:Image, rect:Rectangle, colorMatrix:ColorMatrix):Void {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.colorTransform (image, rect, colorMatrix);
|
|
|
|
}
|
|
|
|
|
|
public static function convertToCanvas (image:Image):Void {
|
|
|
|
var buffer = image.buffer;
|
|
|
|
if (buffer.__srcImage != null) {
|
|
|
|
if (buffer.__srcCanvas == null) {
|
|
|
|
createCanvas (image, buffer.__srcImage.width, buffer.__srcImage.height);
|
|
buffer.__srcContext.drawImage (buffer.__srcImage, 0, 0);
|
|
|
|
}
|
|
|
|
buffer.__srcImage = null;
|
|
|
|
} else if (buffer.data != null && buffer.__srcCanvas == null) {
|
|
|
|
createCanvas (image, buffer.width, buffer.height);
|
|
createImageData (image);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static function convertToData (image:Image):Void {
|
|
|
|
#if (js && html5)
|
|
if (image.buffer.data == null) {
|
|
|
|
convertToCanvas (image);
|
|
sync (image);
|
|
createImageData (image);
|
|
|
|
image.buffer.__srcCanvas = null;
|
|
image.buffer.__srcContext = null;
|
|
|
|
}
|
|
#end
|
|
|
|
}
|
|
|
|
|
|
public static function copyChannel (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, sourceChannel:ImageChannel, destChannel:ImageChannel):Void {
|
|
|
|
convertToCanvas (sourceImage);
|
|
createImageData (sourceImage);
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.copyChannel (image, sourceImage, sourceRect, destPoint, sourceChannel, destChannel);
|
|
|
|
}
|
|
|
|
|
|
public static function copyPixels (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image = null, alphaPoint:Vector2 = null, mergeAlpha:Bool = false):Void {
|
|
|
|
if (destPoint == null || destPoint.x >= image.width || destPoint.y >= image.height || sourceRect == null || sourceRect.width <= 0 || sourceRect.height <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (alphaImage != null && alphaImage.transparent) {
|
|
|
|
if (alphaPoint == null) alphaPoint = new Vector2 ();
|
|
|
|
// TODO: use faster method
|
|
|
|
var tempData = image.clone ();
|
|
tempData.copyChannel (alphaImage, new Rectangle (alphaPoint.x, alphaPoint.y, sourceRect.width, sourceRect.height), new Vector2 (sourceRect.x, sourceRect.y), ImageChannel.ALPHA, ImageChannel.ALPHA);
|
|
sourceImage = tempData;
|
|
|
|
}
|
|
|
|
sync (image);
|
|
|
|
if (!mergeAlpha) {
|
|
|
|
if (image.transparent && sourceImage.transparent) {
|
|
|
|
image.buffer.__srcContext.clearRect (destPoint.x + image.offsetX, destPoint.y + image.offsetY, sourceRect.width + image.offsetX, sourceRect.height + image.offsetY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sync (sourceImage);
|
|
|
|
if (sourceImage.buffer.src != null) {
|
|
|
|
image.buffer.__srcContext.drawImage (sourceImage.buffer.src, Std.int (sourceRect.x + sourceImage.offsetX), Std.int (sourceRect.y + sourceImage.offsetY), Std.int (sourceRect.width), Std.int (sourceRect.height), Std.int (destPoint.x + image.offsetX), Std.int (destPoint.y + image.offsetY), Std.int (sourceRect.width), Std.int (sourceRect.height));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static function createCanvas (image:Image, width:Int, height:Int):Void {
|
|
|
|
#if (js && html5)
|
|
var buffer = image.buffer;
|
|
|
|
if (buffer.__srcCanvas == null) {
|
|
|
|
buffer.__srcCanvas = cast Browser.document.createElement ("canvas");
|
|
buffer.__srcCanvas.width = width;
|
|
buffer.__srcCanvas.height = height;
|
|
|
|
if (!image.transparent) {
|
|
|
|
if (!image.transparent) buffer.__srcCanvas.setAttribute ("moz-opaque", "true");
|
|
buffer.__srcContext = untyped __js__ ('buffer.__srcCanvas.getContext ("2d", { alpha: false })');
|
|
|
|
} else {
|
|
|
|
buffer.__srcContext = buffer.__srcCanvas.getContext ("2d");
|
|
|
|
}
|
|
|
|
untyped (buffer.__srcContext).mozImageSmoothingEnabled = false;
|
|
untyped (buffer.__srcContext).webkitImageSmoothingEnabled = false;
|
|
untyped (buffer.__srcContext).imageSmoothingEnabled = false;
|
|
|
|
}
|
|
#end
|
|
|
|
}
|
|
|
|
|
|
public static function createImageData (image:Image):Void {
|
|
|
|
#if (js && html5)
|
|
|
|
var buffer = image.buffer;
|
|
|
|
if (buffer.__srcImageData == null) {
|
|
|
|
if (buffer.data == null) {
|
|
|
|
buffer.__srcImageData = buffer.__srcContext.getImageData (0, 0, buffer.width, buffer.height);
|
|
|
|
} else {
|
|
|
|
buffer.__srcImageData = buffer.__srcContext.createImageData (buffer.width, buffer.height);
|
|
buffer.__srcImageData.data.set (cast buffer.data);
|
|
|
|
}
|
|
|
|
buffer.data = new UInt8Array (cast buffer.__srcImageData.data.buffer);
|
|
|
|
}
|
|
|
|
#end
|
|
|
|
}
|
|
|
|
|
|
public static function fillRect (image:Image, rect:Rectangle, color:Int, format:PixelFormat):Void {
|
|
|
|
convertToCanvas (image);
|
|
sync (image);
|
|
|
|
if (rect.x == 0 && rect.y == 0 && rect.width == image.width && rect.height == image.height) {
|
|
|
|
if (image.transparent && ((color & 0xFF) == 0)) {
|
|
|
|
image.buffer.__srcCanvas.width = image.buffer.width;
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var r, g, b, a;
|
|
|
|
if (format == ARGB32) {
|
|
|
|
r = (color >> 16) & 0xFF;
|
|
g = (color >> 8) & 0xFF;
|
|
b = color & 0xFF;
|
|
a = (image.transparent) ? (color >> 24) & 0xFF : 0xFF;
|
|
|
|
} else {
|
|
|
|
r = (color >> 24) & 0xFF;
|
|
g = (color >> 16) & 0xFF;
|
|
b = (color >> 8) & 0xFF;
|
|
a = (image.transparent) ? color & 0xFF : 0xFF;
|
|
|
|
}
|
|
|
|
image.buffer.__srcContext.fillStyle = 'rgba(' + r + ', ' + g + ', ' + b + ', ' + (a / 255) + ')';
|
|
image.buffer.__srcContext.fillRect (rect.x + image.offsetX, rect.y + image.offsetY, rect.width + image.offsetX, rect.height + image.offsetY);
|
|
|
|
}
|
|
|
|
|
|
public static function floodFill (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.floodFill (image, x, y, color, format);
|
|
|
|
}
|
|
|
|
|
|
public static function getPixel (image:Image, x:Int, y:Int, format:PixelFormat):Int {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
return ImageDataUtil.getPixel (image, x, y, format);
|
|
|
|
}
|
|
|
|
|
|
public static function getPixel32 (image:Image, x:Int, y:Int, format:PixelFormat):Int {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
return ImageDataUtil.getPixel32 (image, x, y, format);
|
|
|
|
}
|
|
|
|
|
|
public static function getPixels (image:Image, rect:Rectangle, format:PixelFormat):ByteArray {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
return ImageDataUtil.getPixels (image, rect, format);
|
|
|
|
}
|
|
|
|
|
|
public static function merge (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, redMultiplier:Int, greenMultiplier:Int, blueMultiplier:Int, alphaMultiplier:Int):Void {
|
|
|
|
convertToCanvas (sourceImage);
|
|
createImageData (sourceImage);
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier);
|
|
|
|
}
|
|
|
|
|
|
public static function resize (image:Image, newWidth:Int, newHeight:Int):Void {
|
|
|
|
var buffer = image.buffer;
|
|
|
|
if (buffer.__srcCanvas == null) {
|
|
|
|
createCanvas (image, newWidth, newHeight);
|
|
buffer.__srcContext.drawImage (buffer.src, 0, 0, newWidth, newHeight);
|
|
|
|
} else {
|
|
|
|
sync (image);
|
|
var sourceCanvas = buffer.__srcCanvas;
|
|
buffer.__srcCanvas = null;
|
|
createCanvas (image, newWidth, newHeight);
|
|
buffer.__srcContext.drawImage (sourceCanvas, 0, 0, newWidth, newHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static function scroll (image:Image, x:Int, y:Int):Void {
|
|
|
|
if ((x % image.width == 0) && (y % image.height == 0)) return;
|
|
|
|
convertToCanvas (image);
|
|
sync (image);
|
|
|
|
image.buffer.__srcContext.clearRect (x, y, image.width, image.height);
|
|
image.buffer.__srcContext.drawImage (image.buffer.__srcCanvas, x, y);
|
|
|
|
}
|
|
|
|
|
|
public static function setPixel (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.setPixel (image, x, y, color, format);
|
|
|
|
}
|
|
|
|
|
|
public static function setPixel32 (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.setPixel32 (image, x, y, color, format);
|
|
|
|
}
|
|
|
|
|
|
public static function setPixels (image:Image, rect:Rectangle, byteArray:ByteArray, format:PixelFormat):Void {
|
|
|
|
convertToCanvas (image);
|
|
createImageData (image);
|
|
|
|
ImageDataUtil.setPixels (image, rect, byteArray, format);
|
|
|
|
}
|
|
|
|
|
|
public static function sync (image:Image):Void {
|
|
|
|
#if (js && html5)
|
|
if (image.dirty && image.buffer.__srcImageData != null && image.type != DATA) {
|
|
|
|
image.buffer.__srcContext.putImageData (image.buffer.__srcImageData, 0, 0);
|
|
image.buffer.data = null;
|
|
image.dirty = false;
|
|
|
|
}
|
|
#end
|
|
|
|
}
|
|
|
|
|
|
}
|