Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitmapOffset - run only inside a given bitmap region #19

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions geometrize/Core.hx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class Core {
}
}
var result:Float = Math.sqrt(total / (width * height * 4.0)) / 255;
// trace('differenceFull: '+total+", "+width+", "+height+", "+result+", "+Math.isFinite(result));
Sure.sure(Math.isFinite(result));
return result;
}
Expand Down Expand Up @@ -144,6 +145,8 @@ class Core {
}
}
var result:Float = Math.sqrt(total / rgbaCount) / 255;
// trace('differencePartial: '+total+", "+rgbaCount+", "+result+", "+Math.isFinite(result));

Sure.sure(Math.isFinite(result));
return result;
}
Expand Down
54 changes: 42 additions & 12 deletions geometrize/Model.hx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import geometrize.rasterizer.Scanline;
import geometrize.shape.Shape;
import geometrize.shape.ShapeType;
import geometrize.rasterizer.Rasterizer;
import geometrize.Util;

/**
* Container for info about a shape added to the model.
Expand All @@ -27,45 +28,67 @@ class Model {
* Width of the target bitmap.
*/
public var width(default, null):Int;

/**
* Height of the target bitmap.
*/
public var height(default, null):Int;

/**
* The target bitmap, the bitmap we aim to approximate.
*/
public var target(default, null):Bitmap;

/**
* The current bitmap.
*/
public var current(default, null):Bitmap;

/**
* Buffer bitmap.
*/
public var buffer(default, null):Bitmap;

/**
* Score derived from calculating the difference between bitmaps.
*/
private var score(default, null):Float;

/**
* Creates a new model.
* @param target The target bitmap.
* @param backgroundColor The starting background color.
*/
public function new(target:Bitmap, backgroundColor:Rgba) {
Sure.sure(target != null);

this.width = target.width;
this.height = target.height;
this.target = target;
target.saveOffSet(true);
this.current = Bitmap.create(target.width, target.height, backgroundColor);
this.buffer = Bitmap.create(target.width, target.height, backgroundColor);

target.restoreOffset();
this.current.setOffset(target.getOffSet());
this.buffer.setOffset(target.getOffSet());

this.score = Core.differenceFull(target, current);
}

/**
* The algorithm will only consider a region of the entire bitmap.
* New shapes will be generated randombly but only inside this region.
* If null is passed it will reset the offset (default behaviour)
**/
public inline function setOffset(?offset:Util.Rect):Void {
this.current.setOffset(offset);
this.current.setOffset(offset);
this.target.setOffset(offset);
this.width = target.width;
this.height = target.height;
this.score = Core.differenceFull(target, current);
}

/**
* Steps the optimization/fitting algorithm.
* @param shapeType The shape types to use.
Expand All @@ -76,10 +99,10 @@ class Model {
*/
public function step(shapeTypes:Array<ShapeType>, alpha:Int, n:Int, age:Int):Array<ShapeResult> {
var state = Core.bestHillClimbState(shapeTypes, alpha, n, age, target, current, buffer, score);
var results:Array<ShapeResult> = [ addShape(state.shape, state.alpha) ];
var results:Array<ShapeResult> = [addShape(state.shape, state.alpha)];
return results;
}

/**
* Adds a shape to the model.
* @param shape The shape to add.
Expand All @@ -88,17 +111,24 @@ class Model {
*/
public function addShape(shape:Shape, alpha:Int):ShapeResult {
Sure.sure(shape != null);

var before:Bitmap = current.clone();
var lines:Array<Scanline> = shape.rasterize();
var color:Rgba = Core.computeColor(target, current, lines, alpha);
Rasterizer.drawLines(current, color, lines);

score = Core.differencePartial(target, before, current, score, lines);


var currentOffset = current.getOffSet();
if (currentOffset != null) {
shape.translate(currentOffset);
}

var result:ShapeResult = {
score: score, color: color, shape: shape
score: score,
color: color,
shape: shape
};
return result;
}
}
}
2 changes: 2 additions & 0 deletions geometrize/State.hx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ class State {
* The geometric shape owned by the state.
*/
public var shape(default, null):Shape;

/**
* The alpha of the shape.
*/
public var alpha(default, null):Int;

/**
* The score of the state, a measure of the improvement applying the state to the current bitmap will have.
*/
Expand Down
48 changes: 29 additions & 19 deletions geometrize/Util.hx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ import geometrize.bitmap.Bitmap;
import geometrize.bitmap.Rgba;

/**
* Represents a point in 2D space.
* Represents a point or vector in 2D space.
* @author Sam Twidale (http://samcodes.co.uk/)
*/
typedef Point = {
var x:Int;
var y:Int;
}

/**
* Represents a rectangle in 2D space.
* @author Sam Twidale (http://samcodes.co.uk/)
*/
typedef Rect = {
> Point,
width:Int,
height:Int
}

/**
* Utility functions.
* @author Sam Twidale (http://samcodes.co.uk/)
Expand All @@ -25,11 +35,11 @@ class Util {
*/
public static function getAverageImageColor(image:Bitmap, alpha:Int = 255):Rgba {
Sure.sure(image != null);

var totalRed:Int = 0;
var totalGreen:Int = 0;
var totalBlue:Int = 0;

for (x in 0...image.width) {
for (y in 0...image.height) {
var pixel = image.getPixel(x, y);
Expand All @@ -38,11 +48,11 @@ class Util {
totalBlue += pixel.b;
}
}

var size:Int = image.width * image.height;
return Rgba.create(Std.int(totalRed / size), Std.int(totalGreen / size), Std.int(totalBlue / size), alpha);
}

/**
* Clamps a value within a range.
* @param value The value to clamp.
Expand All @@ -54,7 +64,7 @@ class Util {
Sure.sure(min <= max);
return value < min ? min : value > max ? max : value;
}

/**
* Compares two values and returns the smaller one.
* @param first The first value.
Expand All @@ -64,7 +74,7 @@ class Util {
public static inline function min(first:Int, second:Int):Int {
return first < second ? first : second;
}

/**
* Compare two values and returns the larger one.
* @param first The first value.
Expand All @@ -74,7 +84,7 @@ class Util {
public static inline function max(first:Int, second:Int):Int {
return first > second ? first : second;
}

/**
* Converts a value measured in degrees to radians.
* @param degrees Degrees value to convert to radians.
Expand All @@ -83,7 +93,7 @@ class Util {
public static inline function toRadians(degrees:Float):Float {
return degrees * Math.PI / 180;
}

/**
* Converts a value measured in radians to degrees.
* @param radians Radians value to convert to degrees.
Expand All @@ -92,7 +102,7 @@ class Util {
public static inline function toDegrees(radians:Float):Float {
return radians * 180 / Math.PI;
}

/**
* Returns a random integer in the range (inclusive).
* @param lower The lower bound.
Expand All @@ -103,7 +113,7 @@ class Util {
Sure.sure(lower <= upper);
return lower + Math.floor((upper - lower + 1) * Math.random());
}

/**
* Returns a random item from an array.
* @param a The array to pick a random item from.
Expand All @@ -113,20 +123,20 @@ class Util {
Sure.sure(a != null && a.length > 0);
return a[random(0, a.length - 1)];
}

/**
* Returns the smallest and largest items from an array of ints.
* @param a The array of ints.
* @return The smallest and largest items from the array.
*/
public static inline function minMaxElements(a:Array<Int>):Point {
if (a == null || a.length == 0) {
return { x : 0, y : 0 };
return {x: 0, y: 0};
}

var min:Int = a[0];
var max:Int = a[0];

for (value in a) {
if (min > value) {
min = value;
Expand All @@ -135,10 +145,10 @@ class Util {
max = value;
}
}
return { x: min, y: max };

return {x: min, y: max};
}

/**
* Returns the absolute value of the given value.
* @param value The value to abs.
Expand All @@ -150,4 +160,4 @@ class Util {
}
return value;
}
}
}
Loading