Last active
October 28, 2023 15:13
-
-
Save nanjizal/6a2b51bc755fae76843d49f3c3c2d4a0 to your computer and use it in GitHub Desktop.
Multitype image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//https://try.haxe.org/#d6768054 | |
enum abstract ImageType( Int ) { | |
var BYTES; | |
var ARRAY; | |
var UINT32ARRAY; | |
var VECTOR; | |
} | |
@:access( IDataImage ) | |
@:transitive | |
@:multiType | |
abstract HolderImage<T>( IDataImage ){ | |
public function new(); | |
@:to inline function toByteImage():ByteImage { | |
return if( this.imageType == ImageType.BYTES ) { | |
cast this; | |
} else { | |
var b = new ByteImage( this.width, this.height ); | |
for( i in 0...abstract.length ) b[i] = abstract[i]; | |
b; | |
} | |
} | |
@:to inline function holderByte():HolderImage<ByteImage> { | |
return if( this.imageType == ImageType.BYTES ) { | |
HolderImage.fromByteImage( cast this ); | |
} else { | |
var b = abstract.toByteImage(); | |
return ( b: HolderImage<ByteImage> ); | |
} | |
} | |
@:from static inline function fromByteImage<T>(b:ByteImage):HolderImage<T> { | |
return cast b; | |
} | |
@:to inline function toArrayImage():ArrayImage { | |
return if( this.imageType == ImageType.ARRAY ) { | |
cast this; | |
} else { | |
var a = new ArrayImage( this.width, this.height ); | |
for( i in 0...abstract.length ) a[i] = abstract[i]; | |
a; | |
} | |
} | |
@:from static inline function fromArrayImage<T>(a:ArrayImage):HolderImage<T>{ | |
return cast a; | |
} | |
@:to inline function holderArray():HolderImage<ArrayImage> { | |
return if( this.imageType == ImageType.ARRAY ) { | |
HolderImage.fromArrayImage( cast this ); | |
} else { | |
var a = abstract.toArrayImage(); | |
return ( a: HolderImage<ArrayImage> ); | |
} | |
} | |
@:to inline function toUInt32ArrayImage():UInt32ArrayImage { | |
return if( this.imageType == ImageType.UINT32ARRAY ) { | |
cast this; | |
} else { | |
var u = new UInt32ArrayImage( this.width, this.height ); | |
for( i in 0...abstract.length ) u[i] = abstract[i]; | |
u; | |
} | |
} | |
@:from static inline function fromUInt32ArrayImage<T>(u:UInt32ArrayImage):HolderImage<T> { | |
return cast u; | |
} | |
@:to inline function holderUnt32Array():HolderImage<UInt32ArrayImage> { | |
return if( this.imageType == ImageType.UINT32ARRAY ) { | |
HolderImage.fromUInt32ArrayImage( cast this ); | |
} else { | |
var u = abstract.toUInt32ArrayImage(); | |
return ( u: HolderImage<UInt32ArrayImage> ); | |
} | |
} | |
@:to inline function toVectorImage():VectorImage { | |
return if( this.imageType == ImageType.VECTOR ) { | |
cast this; | |
} else { | |
var v = new VectorImage( this.width, this.height ); | |
for( i in 0...abstract.length ) v[i] = abstract[i]; | |
v; | |
} | |
} | |
@:from static inline function fromVectorImage<T>(b:VectorImage):HolderImage<T> { | |
return cast b; | |
} | |
@:to inline function holderVector():HolderImage<VectorImage> { | |
return if( this.imageType == ImageType.VECTOR ) { | |
HolderImage.fromVectorImage( cast this ); | |
} else { | |
var v = abstract.toVectorImage(); | |
return ( v: HolderImage<VectorImage> ); | |
} | |
} | |
@:arrayAccess public inline function get(key:Int):UInt | |
return this.get(key); | |
@:arrayAccess public inline function set(key:Int, value:UInt): UInt | |
return this.set(key, value); | |
public var length( get, never ): Int; | |
inline function get_length(): Int { | |
return this.length; | |
} | |
public inline function toString(): String { | |
return this.toString(); | |
} | |
public inline function resetNext():Void { | |
return this.resetNext(); | |
} | |
public inline function hasNext():Bool { | |
return this.hasNext(); | |
} | |
public inline function next(): Int { | |
return this.next(); | |
} | |
public inline function position( px: Int, py: Int ): Int { | |
return this.position( px, py ); | |
} | |
public inline function zero(): Void { | |
return this.zero(); | |
} | |
public inline function getImageType():ImageType { | |
return this.imageType; | |
} | |
public inline function isImageType<U>( t: HolderImage<U> ){ | |
return this.imageType == t.getImageType(); | |
} | |
} | |
class Test { | |
static function main() { | |
var holderImage:HolderImage<ByteImage> = new ByteImage( 100, 100 ); | |
for( i in 0...holderImage.length ){ | |
holderImage[i] = Std.int(0xFF000000) + Std.random(0xFFFFFF); | |
} | |
var c: ByteImage = holderImage; | |
trace( c == holderImage ); | |
var a: ArrayImage = holderImage; | |
var d: HolderImage<ArrayImage> = holderImage; | |
trace( c == d ); | |
trace( a ); | |
/* | |
var b = new UInt32ArrayImage(100, 100); | |
for (i in 0...b.length )b[i] = Std.int(0xFF000000) + Std.random(0xFFFFFF); | |
var a = new ArrayImage(100, 100); | |
if (a.width != b.width && a.height != b.height ) return; | |
for( i in 0...a.length ) a[i] = b[i]; | |
trace( a ); | |
*/ | |
} | |
} | |
@:generic | |
@:structInit | |
class DataImage<T> { | |
public var width:Int; | |
public var height:Int; | |
var data:T; | |
public var imageType: ImageType; | |
public var count = 0; | |
public function new(width:Int, height:Int, data:T) { | |
this.width = width; | |
this.height = height; | |
this.data = data; | |
} | |
} | |
typedef TDataImage = { | |
public var width:Int; | |
public var height:Int; | |
public var count: Int; | |
public var length( get, never ):Int; | |
public function get_length():Int; | |
@:arrayAccess public function set( index: Int, value: UInt ): UInt; | |
@:arrayAccess public function get( index: Int ): UInt; | |
public function zero():Void; | |
public function position( px: Int, py: Int ) :Int; | |
public function toString():String; | |
public function next(): Int; | |
public function hasNext(): Bool; | |
public function resetNext():Void; | |
} | |
interface IDataImage { | |
public var width:Int; | |
public var height:Int; | |
public var count: Int; | |
public var length( get, never ):Int; | |
public function get_length():Int; | |
@:arrayAccess public function set( index: Int, value: UInt ): UInt; | |
@:arrayAccess public function get( index: Int ): UInt; | |
public function zero():Void; | |
public function position( px: Int, py: Int ) :Int; | |
public function toString():String; | |
public function next(): Int; | |
public function hasNext(): Bool; | |
public function resetNext():Void; | |
public var imageType: ImageType; | |
} | |
@:generic | |
@:structInit | |
abstract class ADataImage<T> extends DataImage<T> implements IDataImage { | |
public function new(width:Int, height:Int, data:T) { | |
super(width, height, data); | |
} | |
public var length(get, never):Int; | |
abstract public function get_length():Int; | |
@:arrayAccess | |
abstract public function set(index:Int, value:UInt):UInt; | |
@:arrayAccess | |
abstract public function get(index:Int):UInt; | |
abstract public function zero():Void; | |
abstract public function position(px:Int, py:Int):Int; | |
abstract public function toString():String; | |
public inline function resetNext(){ | |
count = 0; | |
} | |
abstract public function hasNext(): Bool; | |
abstract public function next(): Int; | |
} | |
@:forward | |
@:transient | |
abstract ArrayImage(ADataImage<Array<Int>>) from ADataImage<Array<Int>> to ADataImage<Array<Int>> { | |
public inline function new(w:Int, h:Int) { | |
this = {width: w, height: h, data: new Array<Int>()}; | |
this.imageType = ImageType.ARRAY; | |
zero(); | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function set(index:Int, value:UInt):UInt { | |
this.data[index] = value; | |
return value; | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function get(index:Int):UInt | |
return this.data[index]; | |
@:access( ADataImage ) | |
public inline function zero() { | |
for (i in 0...length) | |
this.data[i] = 0; | |
} | |
public inline function position(px:Float, py:Float):Int { | |
// key | |
return Std.int(py * this.width + px); | |
} | |
public var length(get, never):Int; | |
public inline | |
function get_length():Int { | |
return Std.int(this.width * this.height); | |
} | |
@:access( ADataImage ) | |
public inline | |
function toString() { | |
return this.data.toString(); | |
} | |
} | |
@:forward | |
@:transient | |
abstract ByteImage(ADataImage<haxe.io.Bytes>) from ADataImage<haxe.io.Bytes> to ADataImage<haxe.io.Bytes> { | |
public inline function new(w:Int, h:Int) { | |
this = {width: w, height: h, data: haxe.io.Bytes.alloc(w * h * 4)}; | |
this.imageType = ImageType.BYTES; | |
zero(); | |
} | |
@:access( ADataImage ) | |
public inline function zero() { | |
var w = 0; | |
for (y in 0...this.height) { | |
for (x in 0...this.width) { | |
this.data.set(w++, 0); | |
this.data.set(w++, 0); | |
this.data.set(w++, 0); | |
this.data.set(w++, 0); | |
} | |
} | |
} | |
public inline function position(px:Float, py:Float):Int { | |
// key | |
return Std.int(py * this.width + px); | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function get(key:Int):Int { | |
return (this.data.getInt32(Std.int(key * 4))); | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function set(key:Int, col:Int):Int { | |
this.data.setInt32(Std.int(key * 4), col); | |
return col; | |
} | |
public var length(get, never):Int; | |
inline function get_length():Int { | |
return Std.int(this.width * this.height); | |
} | |
public inline function toString() { | |
var str = ''; | |
for (i in 0...abstract.length) { | |
str += abstract.get(i); | |
str += ','; | |
} | |
return str.substr(0, str.length - 2); | |
} | |
public inline | |
function hasNext(): Bool { | |
return ( this.count < abstract.length ); | |
} | |
public inline | |
function next(){ | |
return get( this.count++ ); | |
} | |
} | |
@:forward | |
@:transient | |
abstract UInt32ArrayImage(ADataImage<haxe.io.UInt32Array>) from ADataImage<haxe.io.UInt32Array> to ADataImage<haxe.io.UInt32Array> { | |
public inline function new(w:Int, h:Int) { | |
this = { | |
width: w, | |
height: h, | |
data: new haxe.io.UInt32Array(Std.int(w * h)) | |
}; | |
this.imageType = ImageType.UINT32ARRAY; | |
zero(); | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function set(index:Int, value:UInt):UInt { | |
this.data[index] = value; | |
return value; | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function get(index:Int):UInt { | |
return this.data[index]; | |
} | |
@:access( ADataImage ) | |
public inline function zero() { | |
for (i in 0...length) | |
this.data[i] = 0; | |
} | |
public inline function position(px:Float, py:Float):Int { | |
// key | |
return Std.int(py * this.width + px); | |
} | |
public var length(get, never):Int; | |
inline function get_length():Int { | |
return Std.int(this.width * this.height); | |
} | |
public inline function toString() { | |
var str = ''; | |
for (i in 0...abstract.length) { | |
str += abstract.get(i); | |
str += ','; | |
} | |
return str.substr(0, str.length - 2); | |
} | |
public inline | |
function hasNext(): Bool { | |
return ( this.count < abstract.length ); | |
} | |
public inline | |
function next(){ | |
return get( this.count++ ); | |
} | |
} | |
@:forward | |
@:transient | |
abstract VectorImage(ADataImage<haxe.ds.Vector<Int>>) from ADataImage<haxe.ds.Vector<Int>> to ADataImage<haxe.ds.Vector<Int>> { | |
public inline function new(w:Int, h:Int) { | |
this = {width: w, height: h, data: new haxe.ds.Vector<Int>(Std.int(w * h))}; | |
this.imageType = ImageType.VECTOR; | |
zero(); | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline | |
function set(index:Int, value:UInt):UInt { | |
this.data[index] = value; | |
return value; | |
} | |
@:access( ADataImage ) | |
@:arrayAccess | |
public inline function get(index:Int):UInt | |
return this.data[index]; | |
@:access( ADataImage ) | |
public inline function zero() | |
for (i in 0...length) | |
this.data[i] = 0; | |
public var length(get, never):Int; | |
public inline function position(px:Float, py:Float):Int { | |
// key | |
return Std.int(py * this.width + px); | |
} | |
inline function get_length():Int { | |
return Std.int(this.width * this.height); | |
} | |
public inline function toString() { | |
var str = ''; | |
for (i in 0...abstract.length) { | |
str += abstract.get(i); | |
str += ','; | |
} | |
return str.substr(0, str.length - 2); | |
} | |
public inline | |
function hasNext(): Bool { | |
return ( this.count < abstract.length ); | |
} | |
public inline | |
function next(){ | |
return get( this.count++ ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment