FunctionImagingInPascal/src/function_imaging.pas

152 lines
4.0 KiB
ObjectPascal
Raw Normal View History

2020-05-12 13:52:09 +03:00
{$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.