fpwritexpm.pp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. XPM writer implementation.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}{$h+}
  12. unit FPWriteXPM;
  13. interface
  14. uses FPImage, classes, sysutils;
  15. type
  16. TFPWriterXPM = class (TFPCustomImageWriter)
  17. private
  18. FPalChars : string;
  19. FColorFormat : string;
  20. FColorShift : word;
  21. FColorSize : byte;
  22. procedure SetColorSize (AValue : byte);
  23. function ColorToHex (c:TFPColor) : string;
  24. protected
  25. procedure InternalWrite (Str:TStream; Img:TFPCustomImage); override;
  26. public
  27. constructor Create; override;
  28. property PalChars : string read FPalChars write FPalChars;
  29. property ColorCharSize : byte read FColorSize write SetColorSize;
  30. // number of characters to use for 1 colorcomponent
  31. end;
  32. implementation
  33. const
  34. DefPalChars = '.,-*abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#;:=+%$()[]';
  35. constructor TFPWriterXPM.create;
  36. begin
  37. inherited create;
  38. PalChars := DefPalChars;
  39. FColorSize := 4;
  40. end;
  41. procedure TFPWriterXPM.SetColorSize (AValue : byte);
  42. begin
  43. if AValue > 3 then
  44. FColorSize := 4
  45. else if AValue = 0 then
  46. FColorSize := 1
  47. else
  48. FColorSize := AValue;
  49. end;
  50. function TFPWriterXPM.ColorToHex (c:TFPColor) : string;
  51. var r,g,b : word;
  52. begin
  53. with c do
  54. begin
  55. r := red shr FColorShift;
  56. g := green shr FColorShift;
  57. b := blue shr FColorShift;
  58. end;
  59. result := format(FColorFormat,[r,g,b]);
  60. end;
  61. procedure TFPWriterXPM.InternalWrite (Str:TStream; Img:TFPCustomImage);
  62. var p, l : TStringList;
  63. c, len, r, t : integer;
  64. TmpPalette, Palette: TFPPalette;
  65. procedure BuildPaletteStrings;
  66. var r,c,e : integer;
  67. procedure MakeCodes (const head:string; charplace:integer);
  68. var r : integer;
  69. begin
  70. r := 1;
  71. dec (charplace);
  72. while (r <= e) and (c >= 0) do
  73. begin
  74. if Charplace > 0 then
  75. MakeCodes (head+PalChars[r],charplace)
  76. else begin
  77. p.Add (head+PalChars[r]);
  78. dec(c);
  79. end;
  80. inc (r);
  81. end;
  82. end;
  83. begin
  84. // Calculate length of codes
  85. len := 1;
  86. e := length(PalChars);
  87. r := e;
  88. c := Palette.count;
  89. while (r <= c) do
  90. begin
  91. inc (len);
  92. r := r * e;
  93. end;
  94. MakeCodes ('',len);
  95. end;
  96. procedure InitConsts;
  97. var fmt : string;
  98. begin
  99. fmt := inttostr(FColorSize);
  100. fmt := '%'+fmt+'.'+fmt+'x';
  101. FColorFormat := fmt+fmt+fmt;
  102. case FColorSize of
  103. 1 : FColorShift := 12;
  104. 2 : FColorShift := 8;
  105. 3 : FColorShift := 4;
  106. else FColorShift := 0;
  107. end;
  108. end;
  109. var s : string;
  110. begin
  111. l := TStringList.Create;
  112. p := TStringList.Create;
  113. TmpPalette := nil;
  114. try
  115. l.Add ('/* XPM */');
  116. l.Add ('static char *graphic[] = {');
  117. Palette := img.palette;
  118. if not Assigned(Palette) then begin
  119. TmpPalette := TFPPalette.Create(0);
  120. TmpPalette.Build(Img);
  121. Palette := TmpPalette;
  122. end;
  123. c := Palette.count;
  124. BuildPaletteStrings;
  125. l.add (format('"%d %d %d %d",',[img.width,img.height,c,len]));
  126. InitConsts;
  127. for r := 0 to c-1 do
  128. begin
  129. if Palette[r] <> colTransparent then
  130. l.Add (format('"%s c #%s",',[p[r],ColorToHex(Palette.color[r])]))
  131. else
  132. l.Add (format('"%s c None",',[p[r]]));
  133. end;
  134. for r := 0 to img.Height-1 do
  135. begin
  136. s := '';
  137. for t := 0 to img.Width-1 do
  138. if Assigned(TmpPalette) then
  139. s := s + p[TmpPalette.IndexOf(img.Colors[t,r])]
  140. else
  141. s := s + p[img.pixels[t,r]];
  142. s := '"'+s+'"';
  143. if r < img.Height-1 then
  144. s := s + ',';
  145. l.Add (s);
  146. end;
  147. l.Add ('};');
  148. finally
  149. TmpPalette.Free;
  150. l.SaveToStream (Str);
  151. p.Free;
  152. l.Free;
  153. end;
  154. end;
  155. initialization
  156. ImageHandlers.RegisterImageWriter ('XPM Format', 'xpm', TFPWriterXPM);
  157. end.