소스 검색

review pixels access (using Bytes.get/setInt32) + added PixelsARGB for faster pixel access

ncannasse 9 년 전
부모
커밋
bf23209e65
1개의 변경된 파일102개의 추가작업 그리고 54개의 파일을 삭제
  1. 102 54
      hxd/Pixels.hx

+ 102 - 54
hxd/Pixels.hx

@@ -6,6 +6,26 @@ enum Flags {
 	FlipY;
 }
 
+@:forward(bytes, width, height, offset, flags, clear, dispose, toPNG, clone, toVector)
+abstract PixelsARGB(Pixels) to Pixels {
+
+
+	public inline function getPixel(x, y) {
+		return Pixels.switchEndian( this.bytes.getInt32(((x + y * this.width) << 2) + this.offset) );
+	}
+
+	public inline function setPixel(x, y, v) {
+		this.bytes.setInt32(((x + y * this.width) << 2) + this.offset, Pixels.switchEndian(v));
+	}
+
+	@:from public static function fromPixels(p:Pixels) : PixelsARGB {
+		p.convert(ARGB);
+		p.setFlip(false);
+		return cast p;
+	}
+}
+
+@:noDebug
 class Pixels {
 	public var bytes : haxe.io.Bytes;
 	public var format(default,set) : PixelFormat;
@@ -23,6 +43,14 @@ class Pixels {
 		this.offset = offset;
 	}
 
+	public static inline function switchEndian(v) {
+		return (v >>> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24);
+	}
+
+	public static inline function switchBR(v) {
+		return (v & 0xFF00FF00) | ((v << 16) & 0xFF0000) | ((v >> 16) & 0xFF);
+	}
+
 	function set_format(fmt) {
 		this.format = fmt;
 		bpp = bytesPerPixel(fmt);
@@ -34,38 +62,67 @@ class Pixels {
 	}
 
 	public function clear( color : Int ) {
-		var a, b, c, d;
+		if( color == 0 ) {
+			bytes.fill(offset, width * height * bytesPerPixel(format), 0);
+			return;
+		}
 		switch( format ) {
+		case BGRA:
 		case RGBA:
-			a = color >> 16;
-			b = color >> 8;
-			c = color;
-			d = color >>> 24;
+			color = switchBR(color);
 		case ARGB:
-			a = color >>> 24;
-			b = color >> 16;
-			c = color >> 8;
-			d = color;
-		case BGRA:
-			a = color;
-			b = color >> 8;
-			c = color >> 16;
-			d = color >>> 24;
+			color = switchEndian(color);
 		default:
 			invalidFormat();
-			a = b = c = d = 0;
 		}
-		a &= 0xFF;
-		b &= 0xFF;
-		c &= 0xFF;
-		d &= 0xFF;
-		var p = 0;
+		var p = offset;
 		for( i in 0...width * height ) {
-			bytes.set(p++, a);
-			bytes.set(p++, b);
-			bytes.set(p++, c);
-			bytes.set(p++, d);
+			bytes.setInt32(p, color);
+			p += 4;
+		}
+	}
+
+	public function toVector() : haxe.ds.Vector<Int> {
+		var vec = new haxe.ds.Vector<Int>(width * height);
+		var idx = 0;
+		var p = offset;
+		var dl = 0;
+		var bpp = bytesPerPixel(format);
+		if( flags.has(FlipY) ) {
+			p += ((height - 1) * width) * bpp;
+			dl = -width * 2 * bpp;
+		}
+		switch(format) {
+		case BGRA:
+			for( y in 0...height ) {
+				for( x in 0...width ) {
+					vec[idx++] = bytes.getInt32(p);
+					p += 4;
+				}
+				p += dl;
+			}
+		case RGBA:
+			for( y in 0...height ) {
+				for( x in 0...width ) {
+					var v = bytes.getInt32(p);
+					vec[idx++] = switchBR(v);
+					p += 4;
+				}
+				p += dl;
+			}
+		case ARGB:
+			for( y in 0...height ) {
+				for( x in 0...width ) {
+					var v = bytes.getInt32(p);
+					vec[idx++] = switchEndian(v);
+					p += 4;
+				}
+				p += dl;
+			}
+		default:
+			invalidFormat();
 		}
+		return vec;
 	}
 
 	public function makeSquare( ?copy : Bool ) {
@@ -80,11 +137,15 @@ class Pixels {
 			out.blit(p, bytes, b, w * 4);
 			p += w * 4;
 			b += w * 4;
-			for( i in 0...(tw - w) * 4 )
-				out.set(p++, 0);
+			for( i in 0...tw - w ) {
+				out.setInt32(p, 0);
+				p += 4;
+			}
+		}
+		for( i in 0...(th - h) * tw ) {
+			out.setInt32(p, 0);
+			p += 4;
 		}
-		for( i in 0...(th - h) * tw * 4 )
-			out.set(p++, 0);
 		if( copy )
 			return new Pixels(tw, th, out, format);
 		if( !flags.has(ReadOnly) ) hxd.impl.Tmp.saveBytes(bytes);
@@ -111,16 +172,17 @@ class Pixels {
 		for( y in 0...height >> 1 ) {
 			var p1 = y * stride;
 			var p2 = (height - 1 - y) * stride;
-			for( x in 0...stride ) {
-				var a = bytes.get(p1);
-				var b = bytes.get(p2);
-				bytes.set(p1++, b);
-				bytes.set(p2++, a);
+			for( x in 0...stride>>2 ) {
+				var a = bytes.getInt32(p1);
+				var b = bytes.getInt32(p2);
+				bytes.setInt32(p1, b);
+				bytes.setInt32(p2, a);
+				p1 += 4;
+				p2 += 4;
 			}
 		}
 	}
 
-	@:noDebug
 	public function convert( target : PixelFormat ) {
 		if( format == target )
 			return;
@@ -173,17 +235,16 @@ class Pixels {
 		format = target;
 	}
 
-	@:noDebug
 	public function getPixel(x, y) : Int {
 		if( flags.has(FlipY) ) y = height - 1 - y;
 		var p = ((x + y * width) * bpp) + offset;
 		switch(format) {
 		case BGRA:
-			return bytes.get(p) | (bytes.get( p+1 )<<8) | (bytes.get( p+2 )<<16) | (bytes.get( p+3 )<<24);
+			return bytes.getInt32(p);
 		case RGBA:
-			return (bytes.get(p)<<16) | (bytes.get( p+1 )<<8) | bytes.get( p+2 ) | (bytes.get( p+3 )<<24);
+			return switchBR(bytes.getInt32(p));
 		case ARGB:
-			return (bytes.get(p) << 24) | (bytes.get( p + 1 ) << 16) | (bytes.get( p + 2 ) << 8) | bytes.get( p + 3 );
+			return switchEndian(bytes.getInt32(p));
 		default:
 			invalidFormat();
 			return 0;
@@ -193,26 +254,13 @@ class Pixels {
 	public function setPixel(x, y, color) : Void {
 		if( flags.has(FlipY) ) y = height - 1 - y;
 		var p = ((x + y * width) * bpp) + offset;
-		var a = color >>> 24;
-		var r = (color >> 16) & 0xFF;
-		var g = (color >> 8) & 0xFF;
-		var b = color & 0xFF;
 		switch(format) {
 		case BGRA:
-			bytes.set(p++, b);
-			bytes.set(p++, g);
-			bytes.set(p++, r);
-			bytes.set(p++, a);
+			bytes.setInt32(p, color);
 		case RGBA:
-			bytes.set(p++, r);
-			bytes.set(p++, g);
-			bytes.set(p++, b);
-			bytes.set(p++, a);
+			bytes.setInt32(p, switchBR(color));
 		case ARGB:
-			bytes.set(p++, a);
-			bytes.set(p++, r);
-			bytes.set(p++, g);
-			bytes.set(p++, b);
+			bytes.setInt32(p, switchEndian(color));
 		default:
 			invalidFormat();
 		}