Feature: function images generator
This commit is contained in:
parent
88b94afb8e
commit
018f33ef55
|
@ -2,8 +2,8 @@ rm generator.exe
|
|||
rm gui.exe
|
||||
|
||||
cd src
|
||||
fpc main.pas
|
||||
mv main.exe ../generator.exe
|
||||
fpc mandelbrot_imaging.pas
|
||||
mv mandelbrot_imaging.exe ../generator.exe
|
||||
cd gui
|
||||
fpc gui.pas
|
||||
mv gui.exe ../../gui.exe
|
||||
|
|
|
@ -13,7 +13,7 @@ type
|
|||
procedure set_color(tr: byte; tg: byte; tb: byte);
|
||||
procedure reset();
|
||||
end;
|
||||
|
||||
|
||||
TPxData = array of array of TColor;
|
||||
|
||||
TBMPImage = object
|
||||
|
@ -37,6 +37,7 @@ type
|
|||
function get_height(): integer;
|
||||
|
||||
procedure open(path: string);
|
||||
procedure save(path: string);
|
||||
procedure save(path: string; monochrome: boolean);
|
||||
end;
|
||||
|
||||
|
@ -196,6 +197,11 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TBMPImage.save(path: string);
|
||||
begin
|
||||
save(path, false);
|
||||
end;
|
||||
|
||||
procedure TBMPImage.save(path: string; monochrome: boolean);
|
||||
var
|
||||
ostream: TFileStream;
|
||||
|
|
152
src/function_imaging.pas
Normal file
152
src/function_imaging.pas
Normal file
|
@ -0,0 +1,152 @@
|
|||
{$MODE OBJFPC}
|
||||
|
||||
uses fpexprpars, sysutils,
|
||||
BMPImage, utils;
|
||||
|
||||
type
|
||||
TArgs = record
|
||||
width: longint;
|
||||
height: longint;
|
||||
f: string;
|
||||
zoom: extended;
|
||||
centerX: extended;
|
||||
centerY: extended;
|
||||
outPath: string;
|
||||
end;
|
||||
|
||||
procedure setDefaultArgs(var args: TArgs);
|
||||
begin
|
||||
with args do begin
|
||||
width := 512;
|
||||
height := 512;
|
||||
f := 'sin(x) - y';
|
||||
zoom := 10;
|
||||
centerX := 0;
|
||||
centerY := 0;
|
||||
outPath := './function_images';
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure getArgs(var args: TArgs);
|
||||
var
|
||||
param: string;
|
||||
begin
|
||||
try
|
||||
args.width := strToInt(ParamStr(1));
|
||||
args.height := strToInt(ParamStr(2));
|
||||
args.f := ParamStr(3);
|
||||
args.zoom := StrToFloat(ParamStr(4)) * 10;
|
||||
args.centerX := StrToFloat(ParamStr(5));
|
||||
args.centerY := StrToFloat(ParamStr(6));
|
||||
|
||||
param := ParamStr(7);
|
||||
if (length(param) > 0) then begin
|
||||
args.outPath := param;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
function getFilename(args: TArgs): string;
|
||||
var
|
||||
fname: string;
|
||||
fn: string;
|
||||
begin
|
||||
fname := '{f}_(z={z},cx={cx},cy={cy},WxH={w}x{h}).bmp';
|
||||
|
||||
fn := stringReplace(args.f, ' ', '', [rfReplaceAll]);
|
||||
fname := StringReplace(fname, '{f}', fn, []);
|
||||
fname := StringReplace(fname, '{z}', floatToStr(args.zoom), []);
|
||||
fname := StringReplace(fname, '{cx}', floatToStr(args.centerX), []);
|
||||
fname := StringReplace(fname, '{cy}', floatToStr(args.centerY), []);
|
||||
fname := StringReplace(fname, '{w}', intToStr(args.width), []);
|
||||
fname := StringReplace(fname, '{h}', intToStr(args.height), []);
|
||||
|
||||
getFilename := fname;
|
||||
end;
|
||||
|
||||
function getPxData(args: TArgs): TPxData;
|
||||
var
|
||||
pxData: TPxData;
|
||||
fParser: TFPExpressionParser;
|
||||
argX, argY: TFPExprIdentifierDef;
|
||||
x, y, intense: integer;
|
||||
convX, convY, fRes: extended;
|
||||
ineq: boolean;
|
||||
begin
|
||||
setLength(pxData, args.width, args.height);
|
||||
fParser := TFPExpressionParser.create(nil);
|
||||
|
||||
try
|
||||
fParser.builtIns := [bcMath];
|
||||
argX := fParser.identifiers.addFloatVariable('x', 0.0);
|
||||
argY := fParser.identifiers.addFloatVariable('y', 0.0);
|
||||
//fParser.expression := 'sin(x*x*x * y*y) - cos(x*x * y*y*y)';
|
||||
fParser.expression := args.f;
|
||||
|
||||
ineq := (pos('>', fParser.expression) <> 0) or (pos('>=', fParser.expression) <> 0) or (pos('<', fParser.expression) <> 0) or (pos('<=', fParser.expression) <> 0);
|
||||
|
||||
for y := 0 to args.height - 1 do begin
|
||||
for x := 0 to args.width - 1 do begin
|
||||
convX := ((x - args.width / 2) / args.zoom) + args.centerX;
|
||||
convY := -(y - args.height / 2) / args.zoom + args.centerY;
|
||||
|
||||
if (abs(convX) < (1 / args.zoom)) or (abs(convY) < (1 / args.zoom)) then begin
|
||||
pxData[x][y].set_color(0, 255, 0);
|
||||
end else begin
|
||||
try
|
||||
argX.asFloat := convX;
|
||||
argY.asFloat := convY;
|
||||
if (ineq) then begin
|
||||
if (fParser.evaluate().resBoolean) then begin
|
||||
pxData[x][y].set_color(0, 0, 0);
|
||||
end else begin
|
||||
pxData[x][y].set_color(255, 255, 255);
|
||||
end;
|
||||
end else begin
|
||||
fRes := fParser.evaluate().resFloat;
|
||||
|
||||
if (abs(fRes) > (1 / args.zoom)) then begin
|
||||
pxData[x][y].set_color(255, 255, 255);
|
||||
end else begin
|
||||
intense := round(abs(fRes) / (1 / args.zoom));
|
||||
pxData[x][y].set_color(intense, intense, intense);
|
||||
end;
|
||||
end;
|
||||
except
|
||||
pxData[x][y].set_color(255, 255, 255);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
fParser.free();
|
||||
end;
|
||||
|
||||
getPxData := pxData;
|
||||
end;
|
||||
|
||||
var
|
||||
args: TArgs;
|
||||
outPath: string;
|
||||
filename: string;
|
||||
|
||||
img: TBMPImage;
|
||||
color: TColor;
|
||||
pxData: TPxData;
|
||||
begin
|
||||
setDefaultArgs(args);
|
||||
getArgs(args);
|
||||
|
||||
pxData := getPxData(args);
|
||||
|
||||
color.set_color(255, 255, 255);
|
||||
img.init(args.width, args.height, color);
|
||||
img.set_pixel_data(pxData);
|
||||
|
||||
filename := getFilename(args);
|
||||
outPath := args.outPath + '/' + filename;
|
||||
img.save(outPath);
|
||||
|
||||
writeln('Image generated and saved at ' + outPath);
|
||||
end.
|
|
@ -1,4 +1,4 @@
|
|||
uses sysutils, BMPImage, ucomplex;
|
||||
uses sysutils, BMPImage, ucomplex, utils;
|
||||
|
||||
type
|
||||
TArgs = record
|
||||
|
@ -10,35 +10,10 @@ type
|
|||
center_y: extended;
|
||||
out_path: string;
|
||||
end;
|
||||
TPxData = array of array of TColor;
|
||||
|
||||
const save_path = './images/generated/';
|
||||
const help_text = 'Usage: command <width = 512> <height = 512> <power = 2> <zoom = 1> <centerX = 0> <centerY = 0> <out_path = ./images>';
|
||||
|
||||
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
|
||||
var
|
||||
z, cx, cy: string;
|
||||
begin
|
||||
z := FloatToStr(zoom);
|
||||
cx := FloatToStr(center_x);
|
||||
cy := FloatToStr(center_y);
|
||||
|
||||
get_filename := base_name + '_(z=' + z + ';cx=' + cx + ';cy=' + cy + ').bmp'
|
||||
end;
|
||||
|
||||
type Point2D = object
|
||||
x: extended;
|
||||
y: extended;
|
||||
|
||||
procedure update(px: extended; py: extended);
|
||||
end;
|
||||
|
||||
procedure Point2D.update(px: extended; py: extended);
|
||||
begin
|
||||
x := px;
|
||||
y := py;
|
||||
end;
|
||||
|
||||
{function f(x: integer): integer;
|
||||
begin
|
||||
f := round(2 * sin(x) + 3);
|
37
src/utils.pas
Normal file
37
src/utils.pas
Normal file
|
@ -0,0 +1,37 @@
|
|||
unit utils;
|
||||
|
||||
interface
|
||||
|
||||
uses sysutils;
|
||||
|
||||
type
|
||||
Point2D = object
|
||||
x: extended;
|
||||
y: extended;
|
||||
|
||||
procedure update(px: extended; py: extended);
|
||||
end;
|
||||
|
||||
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
|
||||
|
||||
implementation
|
||||
|
||||
procedure Point2D.update(px: extended; py: extended);
|
||||
begin
|
||||
x := px;
|
||||
y := py;
|
||||
end;
|
||||
|
||||
function get_filename(base_name: string; zoom: extended; center_x: extended; center_y: extended): string;
|
||||
var
|
||||
z, cx, cy: string;
|
||||
begin
|
||||
z := FloatToStr(zoom);
|
||||
cx := FloatToStr(center_x);
|
||||
cy := FloatToStr(center_y);
|
||||
|
||||
get_filename := base_name + '_(z=' + z + ';cx=' + cx + ';cy=' + cy + ').bmp'
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
Loading…
Reference in New Issue
Block a user