Tw1ddle / geometrize-haxe

:triangular_ruler: Geometrize is a Haxe port of primitive that geometrizes images into geometric primitives
https://www.geometrize.co.uk/
Other
348 stars 31 forks source link

docs : simple cpp example without libs #5

Closed mastef closed 5 years ago

mastef commented 6 years ago

It would be nice to have a simple haxe code example that doesn't rely on other libs. I tried at first with --interp but that just kept going and going. I've then managed to compile a cpp version, which was super-fast, but then it kept messing up the colors. I must be doing something wrong.

I'm trying to create more gifs like these so want to make some local code that tries that with different images and different strategies, instead of using the web-demo for every frame. Mainly from .png files.

This is how for I've come so far ( however colors in final image are skewed ) :

import geometrize.shape.ShapeType;
import geometrize.runner.ImageRunner;
import geometrize.runner.ImageRunnerOptions;
import geometrize.bitmap.Bitmap;
import geometrize.Util;
import haxe.Resource;
import haxe.io.Bytes;
import format.png.Reader;
import format.png.Tools;
import geometrize.Model.ShapeResult;
import geometrize.exporter.SvgExporter;

class ImageJob {
    public function new(sourceImagePath:String, imageRunnerOptions:ImageRunnerOptions) {
        this.sourceImagePath = sourceImagePath;
        this.imageRunnerOptions = imageRunnerOptions;
    }

    public var sourceImagePath:String;
    public var imageRunnerOptions:ImageRunnerOptions;
}

class Main {
    static public function main() {

        var opts:ImageRunnerOptions = {
            shapeTypes: [ ShapeType.CIRCLE, ShapeType.ELLIPSE, ShapeType.ROTATED_ELLIPSE ],
            alpha: 200,
            candidateShapesPerStep: 250,
            shapeMutationsPerStep: 20
        };
        var job = new ImageJob("images/input.png", opts);

        var bitmapData = readPixels(job.sourceImagePath);
        var sourceBitmap = Bitmap.createFromBytes (bitmapData.width, bitmapData.height, bitmapData.data);

        var backgroundColor = Util.getAverageImageColor(sourceBitmap);
        var runner = new ImageRunner(sourceBitmap, backgroundColor);

        var shapeData:Array<ShapeResult> = [];

        for (i in 0 ... 200) {
            var sData = runner.step(job.imageRunnerOptions);
            for (result in sData) shapeData.push(result);
        }

        var svgData = SvgExporter.export(shapeData,bitmapData.width,bitmapData.height);
        sys.io.File.saveContent("export/output.svg", svgData);
        sys.io.File.saveContent("export/output.png", runner.getImageData());
    }

    static function readPixels(file:String):{data:Bytes, width:Int, height:Int} {
        var handle = sys.io.File.read(file, true);
        var d = new format.png.Reader(handle).read();
        var hdr = format.png.Tools.getHeader(d);
        var ret = {
            data:format.png.Tools.extract32(d),
            width:hdr.width,
            height:hdr.height
        };
        handle.close();
        return ret;
    }

}
Tw1ddle commented 6 years ago

Cool project! Colors being wrong might be due to byte order/pixel format. I'll definitely take a look at getting a pure Haxe/cpp example working when I have time.

If you want something working real fast then you could probably strip the HaxeFlixel demo down, I think that was working on cpp: https://github.com/Tw1ddle/geometrize-haxe-demo

Tw1ddle commented 5 years ago

I think you issue you had with weird colours is that the PNG doesn't read/write RGBA8888 data. However that is what the Bitmap class in the library uses. I've started implementing this minimal example anyway, relevant lines are these:

https://github.com/Tw1ddle/geometrize-haxe-example/blob/master/Main.hx#L34 https://github.com/Tw1ddle/geometrize-haxe-example/blob/master/Main.hx#L45

cancerberoSgx commented 5 years ago

I've started implementing this minimal example anyway,

You should publish that as a library - when trying to make format for rgba pngs saw lots of people struggling with the same thing. I didn't found other libraries that didn't depend on lame or other big visual frameworks. I think several users will appreciate having it

Also I assume I can use it to build a simpler performance test suite or for documenting a getting started guide for this project, is that right ? Thanks!

Tw1ddle commented 5 years ago

Sure. All this uses is the Haxe https://github.com/HaxeFoundation/format library and this hackly code to flip the order of Bytes: https://github.com/Tw1ddle/geometrize-haxe-example/blob/master/PixelFormatHelpers.hx

cancerberoSgx commented 5 years ago

I'm trying to refactor your code as an API and base it on Bytes instead of file paths, so it supports all targets (didn't verified yet) and compatible with most use cases (string, buffer, stream, socket) also straight forward to covert to if needed.

User will be responsible of providing PNG image bytes (unparsed) which should be easy (read file, get canvas image , read a http request in servers, write http response on clients, streams, stdio, etc).

Do you know if Bytes is the right data type for flexibility or there is something more appropriate in haxe ? Unfortunately haxe API documentation doesn't describe any types and it names things with non POSIX / ANSI names so I cannot be not sureBTW do you know a better documentation for std api than the official one? particularly for core types?

If accomplished that could be a useful simple and portable companion library for geometrize-haxe, and perhaps in time we could support other formats, what do you think? (too bad format only support writing jpeg , not reading - would be awesome to also support jpeg input images).

This seems a good opportunity for me to keep learning/training with haxe and contribute to this project.

Pleas tell me if you are already working or planning to work on something similar and if it's OK that I PR something like this (and then discuss were maintain it)

Thanks

Tw1ddle commented 5 years ago

I'm not sure whether there is something more general than Bytes without getting into platform-specific types (but I'm not very experienced with writing code using these core types either).

I think the official Haxe docs is the best documentation you're going to get on the Haxe std types.

Your suggested approach for the companion library sounds fine to me. Feel free to open a PR and I'll work with you on that. The example I'm making was just a simple case to show to @mastef

cancerberoSgx commented 5 years ago

I think he and me tried to make it work and failed. so the demo as it is adds lots of value.

BytesData seems to be the representation of the native array although not 100% sinnce there is no description anywhere. For now I think Bytes is the safe decision.

About haxe docs I found a better documentation source and now I'm reading the haxe core classes directly :(