Skip to content

Instantly share code, notes, and snippets.

@nanjizal
Last active October 28, 2023 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nanjizal/6a2b51bc755fae76843d49f3c3c2d4a0 to your computer and use it in GitHub Desktop.
Save nanjizal/6a2b51bc755fae76843d49f3c3c2d4a0 to your computer and use it in GitHub Desktop.
Multitype image
//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