380 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			380 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
     Apophysis Copyright (C) 2001-2004 Mark Townsend
 | 
						|
 | 
						|
     This program is free software; you can redistribute it and/or modify
 | 
						|
     it under the terms of the GNU General Public License as published by
 | 
						|
     the Free Software Foundation; either version 2 of the License, or
 | 
						|
     (at your option) any later version.
 | 
						|
 | 
						|
     This program is distributed in the hope that it will be useful,
 | 
						|
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
     GNU General Public License for more details.
 | 
						|
 | 
						|
     You should have received a copy of the GNU General Public License
 | 
						|
     along with this program; if not, write to the Free Software
 | 
						|
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
}
 | 
						|
{$D-,L-,O+,Q-,R-,Y-,S-}
 | 
						|
unit Global;
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses SysUtils, Classes, SyncObjs, Controls, Graphics, Math, MyTypes, controlpoint;
 | 
						|
type
 | 
						|
  EFormatInvalid = class(Exception);
 | 
						|
 | 
						|
{ Weight manipulation }
 | 
						|
{ Triangle transformations }
 | 
						|
function triangle_area(t: TTriangle): double;
 | 
						|
function transform_affine(const t: TTriangle; const Triangles: TTriangles): boolean;
 | 
						|
function line_dist(x, y, x1, y1, x2, y2: double): double;
 | 
						|
function dist(x1, y1, x2, y2: double): double;
 | 
						|
{ Parsing functions }
 | 
						|
function GetVal(token: string): string;
 | 
						|
function ReplaceTabs(str: string): string;
 | 
						|
{ Palette and gradient functions }
 | 
						|
function GetGradient(FileName, Entry: string): string;
 | 
						|
{ Misc }
 | 
						|
function det(a, b, c, d: double): double;
 | 
						|
function solve3(x1, x2, x1h, y1, y2, y1h, z1, z2, z1h: double;
 | 
						|
  var a, b, e: double): double;
 | 
						|
 | 
						|
 | 
						|
const
 | 
						|
  APP_NAME: string = 'Apophysis 2.0';
 | 
						|
  prefilter_white: integer = 1024;
 | 
						|
  eps: double = 1E-10;
 | 
						|
  White_level = 200;
 | 
						|
  clyellow1 = TColor($17FCFF);
 | 
						|
  clplum2 = TColor($ECA9E6);
 | 
						|
  clSlateGray = TColor($837365);
 | 
						|
  FT_BMP = 1; FT_PNG = 2; FT_JPG = 3;
 | 
						|
 | 
						|
var
 | 
						|
  MainTriangles: TTriangles;
 | 
						|
  ConfirmDelete: boolean; // Flag confirmation of entry deletion
 | 
						|
//  FlameTitle: string;
 | 
						|
  Transforms: integer; // Count of Tranforms
 | 
						|
  AppPath: string; // Path of applicatio file
 | 
						|
  OpenFile: string; // Name of currently open file
 | 
						|
  CanDrawOnResize: boolean;
 | 
						|
  PreserveWeights: boolean;
 | 
						|
  {UPR Options}
 | 
						|
  UPRSampleDensity: integer;
 | 
						|
  UPRFilterRadius: double;
 | 
						|
  UPROversample: integer;
 | 
						|
  UPRAdjustDensity: boolean;
 | 
						|
  UPRColoringIdent: string;
 | 
						|
  UPRColoringFile: string;
 | 
						|
  UPRFormulaIdent: string;
 | 
						|
  UPRFormulaFile: string;
 | 
						|
  UPRWidth: Integer;
 | 
						|
  UPRHeight: Integer;
 | 
						|
  ImageFolder: string;
 | 
						|
  UPRPath: string; // Name and folder of last UPR file
 | 
						|
  UpdateGradient: boolean;
 | 
						|
  cmap_index: integer; // Index to current gradient
 | 
						|
  Variation: TVariation; // Current variation
 | 
						|
  NumTries, TryLength: integer; // Settings for smooth palette
 | 
						|
  SmoothPaletteFile: string;
 | 
						|
{ Display }
 | 
						|
  defSampleDensity, defPreviewDensity: Double;
 | 
						|
  defGamma, defBrightness, defVibrancy, defFilterRadius: Double;
 | 
						|
  defOversample: integer;
 | 
						|
{ Render }
 | 
						|
  renderDensity, renderFilterRadius: double;
 | 
						|
  renderOversample, renderWidth, renderHeight: integer;
 | 
						|
  renderPath: string;
 | 
						|
  JPEGQuality: integer;
 | 
						|
  renderFileFormat: integer;
 | 
						|
{ Defaults }
 | 
						|
  SavePath, SmoothPalettePath: string;
 | 
						|
  RandomPrefix, RandomDate: string;
 | 
						|
  RandomIndex: integer;
 | 
						|
  FlameFile, GradientFile, GradientEntry, FlameEntry: string;
 | 
						|
  ParamFolder: string;
 | 
						|
  prevLowQuality, prevMediumQuality, prevHighQuality: double;
 | 
						|
  defSmoothPaletteFile: string;
 | 
						|
  BrowserPath: string; // Stored path of browser open dialog
 | 
						|
  EditPrevQual, MutatePrevQual, AdjustPrevQual: Integer;
 | 
						|
  randMinTransforms, randMaxTransforms: integer;
 | 
						|
  mutantMinTransforms, mutantMaxTransforms: integer;
 | 
						|
  KeepBackground: boolean;
 | 
						|
  randGradient: Integer;
 | 
						|
  defFlameFile: string;
 | 
						|
  SymmetryType: integer;
 | 
						|
  SymmetryOrder: integer;
 | 
						|
  Variations: array[0..NVARS - 1] of boolean;
 | 
						|
  VariationOptions: integer;
 | 
						|
  { For random gradients }
 | 
						|
  MinNodes, MaxNodes, MinHue, MaxHue, MinSat, MaxSat, MinLum, MaxLum: integer;
 | 
						|
  FixedReference: boolean;
 | 
						|
  BatchSize: Integer;
 | 
						|
  Compatibility: integer; //0 = original, 1 = Drave's
 | 
						|
  Favorites: TStringList;
 | 
						|
  Script: string;
 | 
						|
  ScriptPath: string;
 | 
						|
  SheepServer, SheepNick, SheepURL, SheepPW, HqiPath: string;
 | 
						|
  ExportBatches, ExportOversample, ExportWidth, ExportHeight, ExportFileFormat: Integer;
 | 
						|
  ExportFilter, ExportDensity: Double;
 | 
						|
  OpenFileType: TFileType;
 | 
						|
  ResizeOnLoad: Boolean;
 | 
						|
  ShowProgress: Boolean;
 | 
						|
  defLibrary: string;
 | 
						|
  LimitVibrancy: Boolean;
 | 
						|
implementation
 | 
						|
 | 
						|
uses dialogs, Main;
 | 
						|
 | 
						|
{ IFS }
 | 
						|
 | 
						|
function det(a, b, c, d: double): double;
 | 
						|
begin
 | 
						|
  Result := (a * d - b * c);
 | 
						|
end;
 | 
						|
 | 
						|
function solve3(x1, x2, x1h, y1, y2, y1h, z1, z2, z1h: double;
 | 
						|
  var a, b, e: double): double;
 | 
						|
var
 | 
						|
  det1: double;
 | 
						|
begin
 | 
						|
  det1 := x1 * det(y2, 1.0, z2, 1.0) - x2 * det(y1, 1.0, z1, 1.0)
 | 
						|
    + 1 * det(y1, y2, z1, z2);
 | 
						|
  if (det1 = 0.0) then
 | 
						|
  begin
 | 
						|
    Result := det1;
 | 
						|
    EXIT;
 | 
						|
  end
 | 
						|
  else
 | 
						|
  begin
 | 
						|
    a := (x1h * det(y2, 1.0, z2, 1.0) - x2 * det(y1h, 1.0, z1h, 1.0)
 | 
						|
      + 1 * det(y1h, y2, z1h, z2)) / det1;
 | 
						|
    b := (x1 * det(y1h, 1.0, z1h, 1.0) - x1h * det(y1, 1.0, z1, 1.0)
 | 
						|
      + 1 * det(y1, y1h, z1, z1h)) / det1;
 | 
						|
    e := (x1 * det(y2, y1h, z2, z1h) - x2 * det(y1, y1h, z1, z1h)
 | 
						|
      + x1h * det(y1, y2, z1, z2)) / det1;
 | 
						|
    a := Round6(a);
 | 
						|
    b := Round6(b);
 | 
						|
    e := Round6(e);
 | 
						|
    Result := det1;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function dist(x1, y1, x2, y2: double): double;
 | 
						|
var
 | 
						|
  d2: double;
 | 
						|
begin
 | 
						|
  { From FDesign source
 | 
						|
  { float pt_pt_distance(float x1, float y1, float x2, float y2) }
 | 
						|
  d2 := (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
 | 
						|
  if (d2 = 0.0) then
 | 
						|
  begin
 | 
						|
    Result := 0.0;
 | 
						|
    exit;
 | 
						|
  end
 | 
						|
  else
 | 
						|
    Result := sqrt(d2);
 | 
						|
end;
 | 
						|
 | 
						|
function line_dist(x, y, x1, y1, x2, y2: double): double;
 | 
						|
var
 | 
						|
  a, b, e, c: double;
 | 
						|
begin
 | 
						|
  if ((x = x1) and (y = y1)) then
 | 
						|
    a := 0.0
 | 
						|
  else
 | 
						|
    a := sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
 | 
						|
  if ((x = x2) and (y = y2)) then
 | 
						|
    b := 0.0
 | 
						|
  else
 | 
						|
    b := sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
 | 
						|
  if ((x1 = x2) and (y1 = y2)) then
 | 
						|
    e := 0.0
 | 
						|
  else
 | 
						|
    e := sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
 | 
						|
  if ((a * a + e * e) < (b * b)) then
 | 
						|
    Result := a
 | 
						|
  else if ((b * b + e * e) < (a * a)) then
 | 
						|
    Result := b
 | 
						|
  else if (e <> 0.0) then
 | 
						|
  begin
 | 
						|
    c := (b * b - a * a - e * e) / (-2 * e);
 | 
						|
    if ((a * a - c * c) < 0.0) then
 | 
						|
      Result := 0.0
 | 
						|
    else
 | 
						|
      Result := sqrt(a * a - c * c);
 | 
						|
  end
 | 
						|
  else
 | 
						|
    Result := a;
 | 
						|
end;
 | 
						|
 | 
						|
function transform_affine(const t: TTriangle; const Triangles: TTriangles): boolean;
 | 
						|
var
 | 
						|
  ra, rb, rc, a, b, c: double;
 | 
						|
begin
 | 
						|
  Result := True;
 | 
						|
  ra := dist(Triangles[-1].y[0], Triangles[-1].x[0],
 | 
						|
    Triangles[-1].y[1], Triangles[-1].x[1]);
 | 
						|
  rb := dist(Triangles[-1].y[1], Triangles[-1].x[1],
 | 
						|
    Triangles[-1].y[2], Triangles[-1].x[2]);
 | 
						|
  rc := dist(Triangles[-1].y[2], Triangles[-1].x[2],
 | 
						|
    Triangles[-1].y[0], Triangles[-1].x[0]);
 | 
						|
  a := dist(t.y[0], t.x[0], t.y[1], t.x[1]);
 | 
						|
  b := dist(t.y[1], t.x[1], t.y[2], t.x[2]);
 | 
						|
  c := dist(t.y[2], t.x[2], t.y[0], t.x[0]);
 | 
						|
  if (a > ra) then
 | 
						|
    Result := False
 | 
						|
  else if (b > rb) then
 | 
						|
    Result := False
 | 
						|
  else if (c > rc) then
 | 
						|
    Result := False
 | 
						|
  else if ((a = ra) and (b = rb) and (c = rc)) then
 | 
						|
    Result := False;
 | 
						|
end;
 | 
						|
 | 
						|
function triangle_area(t: TTriangle): double;
 | 
						|
var
 | 
						|
  base, height: double;
 | 
						|
begin
 | 
						|
  try
 | 
						|
    base := dist(t.x[0], t.y[0], t.x[1], t.y[1]);
 | 
						|
    height := line_dist(t.x[2], t.y[2], t.x[1], t.y[1],
 | 
						|
      t.x[0], t.y[0]);
 | 
						|
    if (base < 1.0) then
 | 
						|
      Result := height
 | 
						|
    else if (height < 1.0) then
 | 
						|
      Result := base
 | 
						|
    else
 | 
						|
      Result := 0.5 * base * height;
 | 
						|
  except on E: EMathError do
 | 
						|
      Result := 0;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
{ Weight manipulation }
 | 
						|
 | 
						|
 | 
						|
{ Parse }
 | 
						|
 | 
						|
function GetVal(token: string): string;
 | 
						|
var
 | 
						|
  p: integer;
 | 
						|
begin
 | 
						|
  p := Pos('=', token);
 | 
						|
  Delete(Token, 1, p);
 | 
						|
  Result := Token;
 | 
						|
end;
 | 
						|
 | 
						|
function ReplaceTabs(str: string): string;
 | 
						|
{Changes tab characters in a string to spaces}
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  for i := 1 to Length(str) do
 | 
						|
  begin
 | 
						|
    if str[i] = #9 then
 | 
						|
    begin
 | 
						|
      Delete(str, i, 1);
 | 
						|
      Insert(#32, str, i);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  Result := str;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{ Palette and gradient functions }
 | 
						|
 | 
						|
function RGBToColor(Pal: TMapPalette; index: integer): Tcolor;
 | 
						|
begin
 | 
						|
  { Converts the RGB values from a palette index to the TColor type ...
 | 
						|
    could maybe change it to SHLs }
 | 
						|
  Result := (Pal.Blue[index] * 65536) + (Pal.Green[index] * 256)
 | 
						|
    + Pal.Red[index];
 | 
						|
end;
 | 
						|
 | 
						|
procedure rgb2hsv(const rgb: array of double; out hsv: array of double);
 | 
						|
var
 | 
						|
  maxval, minval: double;
 | 
						|
  del: double;
 | 
						|
begin
 | 
						|
  Maxval := Max(rgb[0], Max(rgb[1], rgb[2]));
 | 
						|
  Minval := Min(rgb[0], Min(rgb[1], rgb[2]));
 | 
						|
 | 
						|
  hsv[2] := maxval; // v
 | 
						|
 | 
						|
  if (Maxval > 0) and (maxval <> minval) then begin
 | 
						|
    del := maxval - minval;
 | 
						|
    hsv[1] := del / Maxval; //s
 | 
						|
 | 
						|
    hsv[0] := 0;
 | 
						|
    if (rgb[0] > rgb[1]) and (rgb[0] > rgb[2]) then begin
 | 
						|
      hsv[0] := (rgb[1] - rgb[2]) / del;
 | 
						|
    end else if (rgb[1] > rgb[2]) then begin
 | 
						|
      hsv[0] := 2 + (rgb[2] - rgb[0]) / del;
 | 
						|
    end else begin
 | 
						|
      hsv[0] := 4 + (rgb[0] - rgb[1]) / del;
 | 
						|
    end;
 | 
						|
 | 
						|
    if hsv[0] < 0 then
 | 
						|
      hsv[0] := hsv[0] + 6;
 | 
						|
 | 
						|
  end else begin
 | 
						|
    hsv[0] := 0;
 | 
						|
    hsv[1] := 0;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure hsv2rgb(const hsv: array of double; out rgb: array of double);
 | 
						|
var
 | 
						|
  j: integer;
 | 
						|
  f, p, q, t, v: double;
 | 
						|
begin
 | 
						|
  j := floor(hsv[0]);
 | 
						|
  f := hsv[0] - j;
 | 
						|
  v := hsv[2];
 | 
						|
  p := hsv[2] * (1 - hsv[1]);
 | 
						|
  q := hsv[2] * (1 - hsv[1] * f);
 | 
						|
  t := hsv[2] * (1 - hsv[1] * (1 - f));
 | 
						|
 | 
						|
  case j of
 | 
						|
    0: begin rgb[0] := v; rgb[1] := t; rgb[2] := p; end;
 | 
						|
    1: begin rgb[0] := q; rgb[1] := v; rgb[2] := p; end;
 | 
						|
    2: begin rgb[0] := p; rgb[1] := v; rgb[2] := t; end;
 | 
						|
    3: begin rgb[0] := p; rgb[1] := q; rgb[2] := v; end;
 | 
						|
    4: begin rgb[0] := t; rgb[1] := p; rgb[2] := v; end;
 | 
						|
    5: begin rgb[0] := v; rgb[1] := p; rgb[2] := t; end;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function GetGradient(FileName, Entry: string): string;
 | 
						|
var
 | 
						|
  FileStrings: TStringList;
 | 
						|
  GradStrings: TStringList;
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  FileStrings := TStringList.Create;
 | 
						|
  GradStrings := TStringList.Create;
 | 
						|
  try
 | 
						|
    try
 | 
						|
      FileStrings.LoadFromFile(FileName);
 | 
						|
      for i := 0 to FileStrings.count - 1 do
 | 
						|
        if Pos(Entry + ' ', Trim(FileStrings[i])) = 1 then break;
 | 
						|
      GradStrings.Add(FileStrings[i]);
 | 
						|
      repeat
 | 
						|
        inc(i);
 | 
						|
        GradStrings.Add(FileStrings[i]);
 | 
						|
      until Pos('}', FileStrings[i]) <> 0;
 | 
						|
      GetGradient := GradStrings.Text;
 | 
						|
    except on exception do
 | 
						|
        Result := '';
 | 
						|
    end;
 | 
						|
  finally
 | 
						|
    GradStrings.Free;
 | 
						|
    FileStrings.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
end.
 | 
						|
 |