
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5678 8e941d3f-bd1b-0410-a28a-d453659cc2b4
796 lines
20 KiB
ObjectPascal
796 lines
20 KiB
ObjectPascal
unit PalUtils;
|
||
|
||
interface
|
||
|
||
uses
|
||
LCLType, LCLIntf, SysUtils, Classes, Graphics,
|
||
//RGBHSVUtils, RGBHSLUtils,
|
||
RGBCIEUtils, RGBCMYKUtils,
|
||
HTMLColors;
|
||
|
||
const
|
||
clCustom = $2FFFFFFF;
|
||
clTransparent = $3FFFFFFF;
|
||
|
||
type
|
||
TSortOrder = (soAscending, soDescending);
|
||
TSortMode = (smRed, smGreen, smBlue, smHue, smSaturation, smLuminance, smValue, smNone, smCyan, smMagenta, smYellow, smBlacK, smCIEx, smCIEy, smCIEz, smCIEl, smCIEa, smCIEb);
|
||
|
||
AcoColors = record
|
||
Colors: array of TColor;
|
||
Names: array of WideString;
|
||
HasNames: boolean;
|
||
end;
|
||
|
||
//replaces passed strings with passed value
|
||
function ReplaceFlags(s: string; flags: array of string; value: integer): string;
|
||
|
||
//replaces the appropriate tags with values in a hint format string
|
||
function FormatHint(fmt: string; c: TColor): string;
|
||
|
||
//converts a string value to TColor including clCustom and clTransparent
|
||
function mbStringToColor(s: string): TColor;
|
||
|
||
//converts a TColor to a string value including clCustom and clTransparent
|
||
function mbColorToString(c: TColor): string;
|
||
|
||
//blends two colors together in proportion C1 : C2 = W1 : 100 - W1, where 0 <= W1 <= 100
|
||
function Blend(C1, C2: TColor; W1: Integer): TColor;
|
||
|
||
// Inverts a color
|
||
function InvertedColor(C: TColor): TColor;
|
||
|
||
//generates a white-color-black or a black-color-white gradient palette
|
||
function MakePalette(BaseColor: TColor; SortOrder: TSortOrder): string;
|
||
|
||
//generates a gradient palette from the given colors
|
||
function MakeGradientPalette(Colors: array of TColor): string;
|
||
|
||
//sorts colors in a string list
|
||
procedure SortPalColors(Colors: TStrings; SortMode: TSortMode; SortOrder: TSortOrder);
|
||
|
||
//reads JASC .pal file
|
||
function ReadJASCPal(PalFile: TFileName): string;
|
||
|
||
//saves a string list to a JASC .pal file
|
||
procedure SaveJASCPal(pal: TStrings; FileName: TFileName);
|
||
|
||
//reads Photoshop .aco file into an Aco record
|
||
function ReadPhotoshopAco(PalFile: TFileName): AcoColors;
|
||
|
||
//reads Photoshop .act file
|
||
function ReadPhotoshopAct(PalFile: TFileName): string;
|
||
|
||
|
||
implementation
|
||
|
||
uses
|
||
Math, mbColorConv;
|
||
|
||
function ReplaceFlags(s: string; flags: array of string; value: integer): string;
|
||
var
|
||
i, p: integer;
|
||
v: string;
|
||
begin
|
||
Result := s;
|
||
v := IntToStr(value);
|
||
for i := 0 to Length(flags) - 1 do
|
||
begin
|
||
p := Pos(flags[i], Result);
|
||
if p > 0 then
|
||
begin
|
||
Delete(Result, p, Length(flags[i]));
|
||
Insert(v, Result, p);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function AnsiReplaceText(const AText, AFromText, AToText: string): string;
|
||
begin
|
||
Result := StringReplace(AText, AFromText, AToText, [rfReplaceAll, rfIgnoreCase]);
|
||
end;
|
||
|
||
function FormatHint(fmt: string; c: TColor): string;
|
||
var
|
||
h: string;
|
||
hslH, hslS, hslL: Double;
|
||
hsvH, hsvS, hsvV: Double;
|
||
begin
|
||
ColorToHSL(c, hslH, hslS, hslL);
|
||
ColorToHSV(c, hsvH, hsvS, hsvV);
|
||
|
||
h := AnsiReplaceText(fmt, '%hex', '#' + ColorToHex(c));
|
||
h := AnsiReplaceText(h, '%cieL', IntToStr(Round(GetCIElValue(c))));
|
||
h := AnsiReplaceText(h, '%cieA', IntToStr(Round(GetCIEaValue(c))));
|
||
h := AnsiReplaceText(h, '%cieB', IntToStr(Round(GetCIEbValue(c))));
|
||
h := AnsiReplaceText(h, '%cieX', IntToStr(Round(GetCIExValue(c))));
|
||
h := AnsiReplaceText(h, '%cieY', IntToStr(Round(GetCIEyValue(c))));
|
||
h := AnsiReplaceText(h, '%cieZ', IntToStr(Round(GetCIEzValue(c))));
|
||
h := AnsiReplaceText(h, '%cieC', IntToStr(Round(GetCIEcValue(c))));
|
||
h := AnsiReplaceText(h, '%cieH', IntToStr(Round(GetCIEhValue(c))));
|
||
h := AnsiReplaceText(h, '%hslH', IntToStr(Round(hslH * 360))); //RGBHSLUtils.GetHValue(c)));
|
||
h := AnsiReplaceText(h, '%hslS', IntToStr(Round(hslS * 255))); //RGBHSLUtils.GetSValue(c)));
|
||
h := AnsiReplaceText(h, '%hslL', IntToStr(Round(hslL * 255))); //RGBHSLUtils.GetLValue(c)));
|
||
h := AnsiReplaceText(h, '%hsvH', IntToStr(round(hsvH * 360))); //RGBHSVUtils.GetHValue(c)));
|
||
h := AnsiReplaceText(h, '%hsvS', IntToStr(round(hsvS * 255))); //RGBHSVUtils.GetSValue(c)));
|
||
h := AnsiReplaceText(h, '%hsvV', IntToStr(round(hsvV * 255))); //RGBHSVUtils.GetVValue(c)));
|
||
h := AnsiReplaceText(h, '%r', IntToStr(GetRValue(c)));
|
||
h := AnsiReplaceText(h, '%g', IntToStr(GetGValue(c)));
|
||
h := AnsiReplaceText(h, '%b', IntToStr(GetBValue(c)));
|
||
h := AnsiReplaceText(h, '%c', IntToStr(GetCValue(c)));
|
||
h := AnsiReplaceText(h, '%m', IntToStr(GetMValue(c)));
|
||
h := AnsiReplaceText(h, '%y', IntToStr(GetYValue(c)));
|
||
h := AnsiReplaceText(h, '%k', IntToStr(GetKValue(c)));
|
||
h := AnsiReplaceText(h, '%h', IntToStr(round(hslH * 360))); //RGBHSLUtils.GetHValue(c)));
|
||
h := AnsiReplaceText(h, '%s', IntToStr(round(hslS * 255))); //RGBHSLUtils.GetSValue(c)));
|
||
h := AnsiReplaceText(h, '%l', IntToStr(round(hslL * 255))); //RGBHSLUtils.GetLValue(c)));
|
||
h := AnsiReplaceText(h, '%v', IntToStr(round(hsvV * 255))); //RGBHSVUtils.GetVValue(c)));
|
||
Result := h;
|
||
end;
|
||
|
||
function mbStringToColor(s: string): TColor;
|
||
begin
|
||
//remove spaces
|
||
s := AnsiReplaceText(s, ' ', '');
|
||
if SameText(s, 'clCustom') then
|
||
Result := clCustom
|
||
else
|
||
if SameText(s, 'clTransparent') then
|
||
Result := clTransparent
|
||
else
|
||
Result := StringToColor(s);
|
||
end;
|
||
|
||
function mbColorToString(c: TColor): string;
|
||
begin
|
||
if c = clCustom then
|
||
Result := 'clCustom'
|
||
else
|
||
if c = clTransparent then
|
||
Result := 'clTransparent'
|
||
else
|
||
Result := ColorToString(c);
|
||
end;
|
||
|
||
//taken from TBXUtils, TBX Package <20> Alex Denisov (www.g32.org)
|
||
function Blend(C1, C2: TColor; W1: Integer): TColor;
|
||
var
|
||
W2, A1, A2, D, F, G: Integer;
|
||
begin
|
||
if C1 < 0 then C1 := GetSysColor(C1 and $FF);
|
||
if C2 < 0 then C2 := GetSysColor(C2 and $FF);
|
||
|
||
if W1 >= 100 then D := 1000
|
||
else D := 100;
|
||
|
||
W2 := D - W1;
|
||
F := D div 2;
|
||
|
||
A2 := C2 shr 16 * W2;
|
||
A1 := C1 shr 16 * W1;
|
||
G := (A1 + A2 + F) div D and $FF;
|
||
Result := G shl 16;
|
||
|
||
A2 := (C2 shr 8 and $FF) * W2;
|
||
A1 := (C1 shr 8 and $FF) * W1;
|
||
G := (A1 + A2 + F) div D and $FF;
|
||
Result := Result or G shl 8;
|
||
|
||
A2 := (C2 and $FF) * W2;
|
||
A1 := (C1 and $FF) * W1;
|
||
G := (A1 + A2 + F) div D and $FF;
|
||
Result := Result or G;
|
||
end;
|
||
|
||
function InvertedColor(C: TColor): TColor;
|
||
begin
|
||
Result := RgbToColor(255 - GetRValue(c), 255 - GetGValue(c), 255 - GetBValue(c));
|
||
end;
|
||
|
||
function IsMember(sl: TStrings; s: string): boolean;
|
||
var
|
||
i: integer;
|
||
begin
|
||
for i := 0 to sl.count -1 do
|
||
if sl.Strings[i] = s then
|
||
begin
|
||
Result := true;
|
||
exit;
|
||
end;
|
||
Result := false;
|
||
end;
|
||
|
||
function MakePalette(BaseColor: TColor; SortOrder: TSortOrder): string;
|
||
const
|
||
maxL = 240;
|
||
var
|
||
i: integer;
|
||
s: TStrings;
|
||
hslH, hslS, hslL: Double;
|
||
begin
|
||
Result := '';
|
||
s := TStringList.Create;
|
||
try
|
||
ColorToHSL(BaseColor, hslH, hslS, hslL);
|
||
case SortOrder of
|
||
soAscending:
|
||
for i := maxL downto 0 do
|
||
s.Add(ColorToString(HSLToColor(hslH, hslS, 1 - i/maxL)));
|
||
// for i := 239 downto 0 do
|
||
// s.Add(ColorToString(HSLRangeToRGB(GetHValue(BaseColor), GetSValue(BaseColor), 240 - i)));
|
||
soDescending:
|
||
for i := 0 to maxL do
|
||
s.Add(ColorToString(HSLToColor(hslH, hslS, i/maxL)));
|
||
// for i := 0 to 239 do
|
||
// s.Add(ColorToString(HSLRangeToRGB(GetHValue(BaseColor), GetSValue(BaseColor), 240 - i)));
|
||
end;
|
||
Result := s.Text;
|
||
finally
|
||
s.Free;
|
||
end;
|
||
end;
|
||
|
||
function MakeGradientPalette(Colors: array of TColor): string;
|
||
type
|
||
RGBArray = array[0..2] of Byte;
|
||
var
|
||
i, j, k, Span: Integer;
|
||
s: TStringList;
|
||
Scolor: string;
|
||
Faktor: double;
|
||
a: RGBArray;
|
||
b: array of RGBArray;
|
||
begin
|
||
Result := '';
|
||
Span := 300;
|
||
s := TStringList.Create;
|
||
try
|
||
SetLength(b, High(Colors) + 1);
|
||
for i := 0 to High(Colors) do
|
||
begin
|
||
Colors[i] := ColorToRGB(Colors[i]);
|
||
b[i, 0] := GetRValue(Colors[i]);
|
||
b[i, 1] := GetGValue(Colors[i]);
|
||
b[i, 2] := GetBValue(Colors[i]);
|
||
end;
|
||
for i := 0 to High(Colors) - 1 do
|
||
for j := 0 to Span do
|
||
begin
|
||
Faktor := j / Span;
|
||
for k := 0 to 3 do
|
||
a[k] := Trunc(b[i, k] + ((b[i + 1, k] - b[i, k]) * Faktor));
|
||
Scolor := ColorToString(RGB(a[0], a[1], a[2]));
|
||
if not IsMember(s, Scolor) then
|
||
s.add(Scolor);
|
||
end;
|
||
Result := s.Text;
|
||
finally
|
||
s.Free;
|
||
end;
|
||
end;
|
||
|
||
procedure SortPalColors(Colors: TStrings; SortMode: TSortMode; SortOrder: TSortOrder);
|
||
|
||
function MaxPos(s: TStrings; sm: TSortMode): integer;
|
||
var
|
||
i: integer;
|
||
first: TColor;
|
||
c: TColor;
|
||
hc, sc, lc, vc: Double;
|
||
hf, sf, lf, vf: Double;
|
||
begin
|
||
Result := 0;
|
||
first := clBlack;
|
||
for i := 0 to s.Count - 1 do
|
||
begin
|
||
c := mbStringToColor(s.Strings[i]);
|
||
case sm of
|
||
smRed:
|
||
if GetRValue(first) < GetRValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smGreen:
|
||
if GetGValue(first) < GetGValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smBlue:
|
||
if GetBValue(first) < GetBValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smHue:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSL(first, hf, sf, lf);
|
||
if hf < hc then begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smSaturation:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSL(first, hf, sf, lf);
|
||
if sf < sc then begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smLuminance:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSL(first, hf, sc, lf);
|
||
if lf < lc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smValue:
|
||
begin
|
||
ColorToHSV(c, hc, sc, vc);
|
||
ColorToHSV(first, hf, sc, vf);
|
||
if vf < vc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smCyan:
|
||
if GetCValue(first) < GetCValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smMagenta:
|
||
if GetMValue(first) < GetMValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smYellow:
|
||
if GetYValue(first) < GetYValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smBlacK:
|
||
if GetKValue(first) < GetKValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEx:
|
||
if GetCIEXValue(first) < GetCIEXValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEy:
|
||
if GetCIEYValue(first) < GetCIEYValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEz:
|
||
if GetCIEZValue(first) < GetCIEZValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEl:
|
||
if GetCIELValue(first) < GetCIELValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEa:
|
||
if GetCIEAValue(first) < GetCIEAValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEb:
|
||
if GetCIEBValue(first) < GetCIEBValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function MinPos(s: TStrings; sm: TSortMode): integer;
|
||
var
|
||
i: integer;
|
||
first: TColor;
|
||
c: TColor;
|
||
hc, sc, lc, vc: Double;
|
||
hf, sf, lf, vf: Double;
|
||
begin
|
||
Result := 0;
|
||
first := clWhite;
|
||
for i := 0 to s.Count - 1 do
|
||
begin
|
||
c := mbStringToColor(s.Strings[i]);
|
||
case sm of
|
||
smRed:
|
||
if GetRValue(first) > GetRValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smGreen:
|
||
if GetGValue(first) > GetGValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smBlue:
|
||
if GetBValue(first) > GetBValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smHue:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSL(first, hf, sf, lf);
|
||
if hf > hc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smSaturation:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSV(first, hf, sf, vf);
|
||
if sf > sc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smLuminance:
|
||
begin
|
||
ColorToHSL(c, hc, sc, lc);
|
||
ColorToHSV(first, hf, sf, vf);
|
||
if lf > lc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smValue:
|
||
begin
|
||
ColorToHSV(c, hc, sc, vc);
|
||
ColorToHSV(first, hf, sf, vf);
|
||
if vf > vc then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
smCyan:
|
||
if GetCValue(first) > GetCValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smMagenta:
|
||
if GetMValue(first) > GetMValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smYellow:
|
||
if GetYValue(first) > GetYValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smBlacK:
|
||
if GetKValue(first) > GetKValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEx:
|
||
if GetCIEXValue(first) > GetCIEXValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEy:
|
||
if GetCIEYValue(first) > GetCIEYValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEz:
|
||
if GetCIEZValue(first) > GetCIEZValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEl:
|
||
if GetCIELValue(first) > GetCIELValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEa:
|
||
if GetCIEAValue(first) > GetCIEAValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
smCIEb:
|
||
if GetCIEBValue(first) > GetCIEBValue(c) then
|
||
begin
|
||
first := c;
|
||
Result := i;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
var
|
||
i, m: integer;
|
||
s: TStrings;
|
||
begin
|
||
if SortMode <> smNone then
|
||
begin
|
||
if Colors.Count = 0 then Exit;
|
||
m := 0;
|
||
s := TStringList.Create;
|
||
try
|
||
s.AddStrings(Colors);
|
||
Colors.Clear;
|
||
for i := s.Count - 1 downto 0 do
|
||
begin
|
||
case SortOrder of
|
||
soAscending : m := MinPos(s, SortMode);
|
||
soDescending : m := MaxPos(s, SortMode);
|
||
end;
|
||
Colors.Add(s.Strings[m]);
|
||
s.Delete(m);
|
||
end;
|
||
finally
|
||
s.Free;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function ReadJASCPal(PalFile: TFileName): string;
|
||
var
|
||
p, t, c: TStrings;
|
||
i: integer;
|
||
begin
|
||
if not FileExists(PalFile) then
|
||
raise Exception.Create('File not found');
|
||
|
||
p := TStringList.Create;
|
||
t := TStringList.Create;
|
||
c := TStringList.Create;
|
||
try
|
||
p.LoadFromFile(PalFile);
|
||
for i := 0 to p.Count - 1 do
|
||
if p.strings[i] <> '' then
|
||
begin
|
||
t.Clear;
|
||
ExtractStrings([' '], [], PChar(p.strings[i]), t);
|
||
if t.Count = 3 then
|
||
c.Add(ColorToString(RGB(StrToInt(t.strings[0]), StrToInt(t.strings[1]), StrToInt(t.strings[2]))));
|
||
end;
|
||
Result := c.Text;
|
||
finally
|
||
c.Free;
|
||
t.Free;
|
||
p.Free;
|
||
end;
|
||
end;
|
||
|
||
procedure SaveJASCPal(pal: TStrings; FileName: TFileName);
|
||
var
|
||
i: integer;
|
||
p: TStringList;
|
||
c: TColor;
|
||
begin
|
||
if not FileExists(FileName) then
|
||
raise Exception.Create('File not found');
|
||
|
||
p := TStringList.Create;
|
||
try
|
||
p.Add('JASC-PAL');
|
||
p.Add('0100');
|
||
p.Add('256');
|
||
for i := 0 to pal.Count - 1 do
|
||
if (pal.Strings[i] <> '') and not SameText(pal.Strings[i], 'clCustom') and not SameText(pal.Strings[i], 'clTransparent') then
|
||
begin
|
||
c := StringToColor(pal.Strings[i]);
|
||
p.Add(IntToStr(GetRValue(c)) + ' ' + IntToStr(GetGValue(c)) + ' ' + IntToStr(GetBValue(c)));
|
||
end;
|
||
p.SaveToFile(FileName);
|
||
finally
|
||
p.Free;
|
||
end;
|
||
end;
|
||
|
||
procedure ExchangeBytes(var w: Word);
|
||
type
|
||
TWordRec = packed record
|
||
a, b: byte;
|
||
end;
|
||
var
|
||
brec: TWordRec;
|
||
tmp: Byte;
|
||
begin
|
||
brec := TWordRec(w);
|
||
tmp := brec.a;
|
||
brec.a := brec.b;
|
||
brec.b := tmp;
|
||
w := word(brec);
|
||
|
||
// Swap(w);
|
||
{
|
||
asm
|
||
MOV DX,[w] //assign the word to the data register
|
||
XCHG DL,DH // exchange low and high data values
|
||
MOV [w],DX //assign the register data to the word
|
||
}
|
||
end;
|
||
|
||
procedure ExchangeChars(var s: WideString);
|
||
var
|
||
i: Integer;
|
||
w: Word;
|
||
begin
|
||
for i := 1 to Length(s) do
|
||
begin
|
||
w := Word(s[i]);
|
||
ExchangeBytes(w);
|
||
s[i] := WideChar(w);
|
||
end;
|
||
end;
|
||
|
||
function GetAcoColor(space,w,x,y,z: word): TColor;
|
||
begin
|
||
case space of
|
||
0: //RGB
|
||
Result := RGB(w div 256, x div 256, y div 256);
|
||
1: //HSB - HSV
|
||
Result := HSVToColor(Round(w/182.04), Round(x/655.35), Round(y/655.35));
|
||
2: //CMYK
|
||
Result := CMYKToColor(Round(100-w/55.35), Round(100-x/655.35), Round(100-y/655.35), Round(100-z/655.35));
|
||
7: //Lab
|
||
Result := LabToRGB(w/100, x/100, y/100);
|
||
8: //Grayscale
|
||
Result := RGB(Round(w/39.0625), Round(w/39.0625), Round(w/39.0625));
|
||
9: //Wide CMYK
|
||
Result := CMYKToColor(w div 100, x div 100, y div 100, z div 100)
|
||
else //unknown
|
||
Result := RGB(w div 256, x div 256, y div 256);
|
||
end;
|
||
end;
|
||
|
||
function ReadPhotoshopAco(PalFile: TFileName): AcoColors;
|
||
var
|
||
f: file;
|
||
ver, num, space, w, x, y, z, dummy: Word;
|
||
i: integer;
|
||
v0Length: byte;
|
||
v0Name: string;
|
||
v2Length: Word;
|
||
v2Name: WideString;
|
||
begin
|
||
if not FileExists(PalFile) then
|
||
begin
|
||
SetLength(Result.Colors, 0);
|
||
SetLength(Result.Names, 0);
|
||
Result.HasNames := false;
|
||
raise Exception.Create('File not found');
|
||
end;
|
||
|
||
AssignFile(f, PalFile);
|
||
Reset(f, 1);
|
||
//read version
|
||
BlockRead(f, ver, sizeof(ver));
|
||
ExchangeBytes(ver);
|
||
if not (ver in [0, 1, 2]) then
|
||
begin
|
||
CloseFile(f);
|
||
raise Exception.Create('The file you are trying to load is not (yet) supported.'#13'Please submit the file for testing to MXS so loading of this version will be supported too');
|
||
end;
|
||
|
||
//read number of colors
|
||
BlockRead(f, num, sizeof(num));
|
||
ExchangeBytes(num);
|
||
//read names
|
||
if (ver = 0) or (ver = 2) then
|
||
begin
|
||
SetLength(Result.Names, num);
|
||
Result.HasNames := true;
|
||
end
|
||
else
|
||
begin
|
||
SetLength(Result.Names, 0);
|
||
Result.HasNames := false;
|
||
end;
|
||
//read colors
|
||
SetLength(Result.Colors, num);
|
||
for i := 0 to num - 1 do
|
||
begin
|
||
BlockRead(f, space, sizeof(space));
|
||
ExchangeBytes(space);
|
||
BlockRead(f, w, sizeof(w));
|
||
ExchangeBytes(w);
|
||
BlockRead(f, x, sizeof(x));
|
||
ExchangeBytes(x);
|
||
BlockRead(f, y, sizeof(y));
|
||
ExchangeBytes(y);
|
||
BlockRead(f, z, sizeof(z));
|
||
ExchangeBytes(z);
|
||
Result.Colors[i] := GetAcoColor(space, w, x, y, z);
|
||
case ver of
|
||
0: begin
|
||
BlockRead(f, v0Length, SizeOf(v0Length));
|
||
SetLength(v0Name, v0Length);
|
||
if v0Length > 0 then
|
||
BlockRead(f, PChar(v0Name)^, v0Length);
|
||
Result.Names[i] := v0Name;
|
||
end;
|
||
2: begin
|
||
BlockRead(f, dummy, sizeof(dummy));
|
||
BlockRead(f, v2Length, SizeOf(v2Length));
|
||
ExchangeBytes(v2Length);
|
||
SetLength(v2Name, v2Length - 1);
|
||
if v2Length > 0 then
|
||
begin
|
||
BlockRead(f, PWideChar(v2Name)^, 2*(v2Length - 1));
|
||
ExchangeChars(v2Name);
|
||
end;
|
||
Result.Names[i] := v2Name;
|
||
BlockRead(f, dummy, sizeof(dummy));
|
||
end;
|
||
end;
|
||
end;
|
||
CloseFile(f);
|
||
end;
|
||
|
||
function ReadPhotoshopAct(PalFile: TFileName): string;
|
||
var
|
||
f: file;
|
||
r, g, b: byte;
|
||
s: TStringList;
|
||
i: integer;
|
||
begin
|
||
if not FileExists(PalFile) then
|
||
raise Exception.Create('File not found');
|
||
|
||
s := TStringList.Create;
|
||
try
|
||
AssignFile(f, PalFile);
|
||
Reset(f, 1);
|
||
for i := 0 to 255 do
|
||
begin
|
||
BlockRead(f, r, sizeof(r));
|
||
BlockRead(f, g, sizeof(g));
|
||
BlockRead(f, b, sizeof(b));
|
||
s.Add(ColorToString(RGB(r, g, b)));
|
||
end;
|
||
Result := s.Text;
|
||
finally
|
||
s.Free;
|
||
end;
|
||
CloseFile(f);
|
||
end;
|
||
|
||
end.
|