123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by the Free Pascal development team
- XPM reader class.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************}
- {$mode objfpc}{$h+}
- unit FPReadXPM;
- interface
- uses FPImage, classes, sysutils;
- type
- TFPReaderXPM = class (TFPCustomImageReader)
- private
- width, height, ncols, cpp, xhot, yhot : integer;
- xpmext : boolean;
- palette : TStringList;
- function HexToColor(s : string) : TFPColor;
- function NameToColor(s : string) : TFPColor;
- function DiminishWhiteSpace (s : string) : string;
- protected
- procedure InternalRead (Str:TStream; Img:TFPCustomImage); override;
- function InternalCheck (Str:TStream) : boolean; override;
- public
- constructor Create; override;
- destructor Destroy; override;
- end;
- implementation
- const
- WhiteSpace = ' '#8#10#13;
- constructor TFPReaderXPM.create;
- begin
- inherited create;
- palette := TStringList.Create;
- end;
- destructor TFPReaderXPM.Destroy;
- begin
- Palette.Free;
- inherited destroy;
- end;
- function TFPReaderXPM.HexToColor(s : string) : TFPColor;
- var l : integer;
- function CharConv (c : char) : longword;
- begin
- if (c >= 'A') and (c <= 'F') then
- result := ord (c) - ord('A') + 10
- else if (c >= '0') and (c <= '9') then
- result := ord (c) - ord('0')
- else
- raise exception.CreateFmt ('Wrong character (%s) in hexadecimal number', [c]);
- end;
- function convert (n : string) : word;
- var t,r: integer;
- begin
- result := 0;
- t := length(n);
- if t > 4 then
- raise exception.CreateFmt ('Too many bytes for color (%s)',[s]);
- for r := 1 to length(n) do
- result := (result shl 4) or CharConv(n[r]);
- // fill missing bits
- case t of
- 1: result:=result or (result shl 4) or (result shl 8) or (result shl 12);
- 2: result:=result or (result shl 8);
- 3: result:=result or (result shl 12);
- end;
- end;
- begin
- s := uppercase (s);
- l := length(s) div 3;
- result.red := (Convert(copy(s,1,l)));
- result.green := (Convert(copy(s,l+1,l)));
- result.blue := Convert(copy(s,l+l+1,l));
- result.alpha := AlphaOpaque;
- end;
- function TFPReaderXPM.NameToColor(s : string) : TFPColor;
- begin
- s := lowercase (s);
- if s = 'transparent' then
- result := colTransparent
- else if s = 'none' then
- result := colTransparent
- else if s = 'black' then
- result := colBlack
- else if s = 'blue' then
- result := colBlue
- else if s = 'green' then
- result := colGreen
- else if s = 'cyan' then
- result := colCyan
- else if s = 'red' then
- result := colRed
- else if s = 'magenta' then
- result := colMagenta
- else if s = 'yellow' then
- result := colYellow
- else if s = 'white' then
- result := colWhite
- else if s = 'gray' then
- result := colGray
- else if s = 'ltgray' then
- result := colLtGray
- else if s = 'dkblue' then
- result := colDkBlue
- else if s = 'dkgreen' then
- result := colDkGreen
- else if s = 'dkcyan' then
- result := colDkCyan
- else if s = 'dkred' then
- result := colDkRed
- else if s = 'dkmagenta' then
- result := colDkMagenta
- else if s = 'dkyellow' then
- result := colDkYellow
- else if s = 'maroon' then
- result := colMaroon
- else if s = 'ltgreen' then
- result := colLtGreen
- else if s = 'olive' then
- result := colOlive
- else if s = 'navy' then
- result := colNavy
- else if s = 'purple' then
- result := colPurple
- else if s = 'teal' then
- result := colTeal
- else if s = 'silver' then
- result := colSilver
- else if s = 'lime' then
- result := colLime
- else if s = 'fuchsia' then
- result := colFuchsia
- else if s = 'aqua' then
- result := colAqua
- else
- result := colTransparent;
- end;
- function TFPReaderXPM.DiminishWhiteSpace (s : string) : string;
- var r : integer;
- Doit : boolean;
- begin
- Doit := true;
- result := '';
- for r := 1 to length(s) do
- if pos(s[r],WhiteSpace)>0 then
- begin
- if DoIt then
- result := result + ' ';
- DoIt := false;
- end
- else
- begin
- DoIt := True;
- result := result + s[r];
- end;
- end;
- procedure TFPReaderXPM.InternalRead (Str:TStream; Img:TFPCustomImage);
- var l : TStringList;
- procedure TakeInteger (var s : string; var i : integer);
- var r : integer;
- begin
- r := pos (' ', s);
- if r = 0 then
- begin
- i := StrToInt(s);
- s := '';
- end
- else
- begin
- i := StrToInt(copy(s,1,r-1));
- delete (s, 1, r);
- end;
- end;
- procedure ParseFirstLine;
- var s : string;
- begin
- s := l[0];
- // diminish all whitespace to 1 blank
- s := DiminishWhiteSpace (trim(s));
- Takeinteger (s, width);
- Takeinteger (s, height);
- Takeinteger (s, ncols);
- Takeinteger (s, cpp);
- if s <> '' then
- begin
- Takeinteger (s, xhot);
- Takeinteger (s, yhot);
- xpmext := (comparetext(s, 'XPMEXT') = 0);
- if (s <> '') and not xpmext then
- Raise Exception.Create ('Wrong word for XPMEXT tag');
- end;
- end;
- procedure AddPalette (const code:string;const Acolor:TFPColor);
- var r : integer;
- begin
- r := Palette.Add(code);
- img.palette.Color[r] := Acolor;
- end;
- procedure AddToPalette(s : string);
- var code : string;
- c : TFPColor;
- p : integer;
- begin
- code := copy(s,1,cpp);
- s := trim(diminishWhiteSpace (copy(s,cpp+1,maxint)));
- // Search for c-key in the color values
- if s[1] = 'c' then
- delete (s, 1, 2)
- else
- begin
- p := pos (' c ',s);
- if p = 0 then
- s := ''
- else
- delete (s, 1, p+2);
- end;
- // c color value is first word, remove the rest of the line
- p := pos(' ', s);
- if p > 0 then
- delete (s, p, maxint);
- // check if exists
- if s = '' then
- raise exception.Create ('Only c-key is used for colors');
- // convert #hexadecimal value to integer and place in palette
- if s[1] = '#' then
- c := HexToColor(copy(s,2,maxint))
- else
- c := NameToColor(s);
- AddPalette(code,c);
- end;
- procedure ReadPalette;
- var r : integer;
- begin
- Palette.Clear;
- Img.Palette.Count := ncols;
- for r := 1 to ncols do
- AddToPalette (l[r]);
- end;
- procedure ReadLine (const s : string; imgindex : integer);
- var color, r, p : integer;
- code : string;
- begin
- p := 1;
- for r := 1 to width do
- begin
- code := copy(s, p, cpp);
- inc(p,cpp);
- for color := 0 to Palette.Count-1 do
- { Can't use indexof, as compare must be case sensitive }
- if code = Palette[color] then begin
- img.pixels[r-1,imgindex] := color;
- Break;
- end;
- end;
- end;
- procedure ReadData;
- var r : integer;
- begin
- for r := 1 to height do
- ReadLine (l[ncols+r], r-1);
- end;
- var p, r : integer;
- begin
- l := TStringList.Create;
- try
- l.LoadFromStream (Str);
- for r := l.count-1 downto 0 do
- begin
- p := pos ('"', l[r]);
- if p > 0 then
- l[r] := copy(l[r], p+1, lastdelimiter('"',l[r])-p-1)
- else
- l.delete(r);
- end;
- ParseFirstLine;
- Img.SetSize (width, height);
- ReadPalette;
- ReadData;
- finally
- l.Free;
- end;
- end;
- function TFPReaderXPM.InternalCheck (Str:TStream) : boolean;
- var s : string[9];
- l : integer;
- begin
- try
- l := str.Read (s[1],9);
- s[0] := char(l);
- if l <> 9 then
- result := False
- else
- result := (s = '/* XPM */');
- except
- result := false;
- end;
- end;
- initialization
- ImageHandlers.RegisterImageReader ('XPM Format', 'xpm', TFPReaderXPM);
- end.
|