fpcolcnv.inc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. Some color conversion routines.
  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. {function FillOtherBits (initial:word;CorrectBits:byte):word;
  12. var r,c : byte;
  13. begin
  14. c := 16 div CorrectBits;
  15. result := initial;
  16. for r := 1 to c do
  17. result := (result shr CorrectBits) or result;
  18. end;
  19. function ShiftAndFill (initial:word; CorrectBits:byte):word;
  20. begin
  21. result := FillOtherBits (initial shl (16-correctbits), correctbits);
  22. end;
  23. }
  24. function CalculateGray (const from : TFPcolor) : word;
  25. var temp : longword;
  26. begin
  27. with GrayConvMatrix do
  28. temp := round(red*from.red + green*from.green + blue*from.blue);
  29. if temp > $ffff then
  30. result := $ffff
  31. else
  32. result := temp;
  33. end;
  34. (*
  35. type
  36. TColorBits = array [0..3] of TColorData;
  37. // 0:alpha, 1:red, 2:green, 3:blue
  38. TShiftBits = array [0..3] of shortint;
  39. const
  40. ColorBits : array[cfRGB15..cfABGR64] of TColorBits = (
  41. // alpha red green blue
  42. {cfRGB15} ($00000000, $00007C00, $000003E0, $0000001F),
  43. {cfRGB16} ($00000000, $00007C00, $000003E0, $0000001F),
  44. {cfRGB24} ($00000000, $00FF0000, $0000FF00, $000000FF),
  45. {cfRGB32} ($00000000, $00FF0000, $0000FF00, $000000FF),
  46. {cfRGB48} ($00000000, $FFFF0000, $FFFF0000, $0000FFFF),
  47. // shl 16
  48. {cfRGBA8} ($00000003, $000000C0, $00000030, $0000000C),
  49. {cfRGBA16}($0000000F, $0000F000, $00000F00, $000000F0),
  50. {cfRGBA32}($000000FF, $FF000000, $00FF0000, $0000FF00),
  51. {cfRGBA64}($0000FFFF, $FFFF0000, $FFFF0000, $FFFF0000),
  52. // shl 32 shl 16
  53. {cfBGR15} ($00000000, $0000001F, $000003E0, $00007C00),
  54. {cfBGR16} ($00000000, $0000001F, $000003E0, $00007C00),
  55. {cfBGR24} ($00000000, $000000FF, $0000FF00, $00FF0000),
  56. {cfBGR32} ($00000000, $000000FF, $0000FF00, $00FF0000),
  57. {cfBGR48} ($00000000, $0000FFFF, $FFFF0000, $FFFF0000),
  58. // shl 16
  59. {cfABGR8} ($000000C0, $00000003, $0000000C, $00000030),
  60. {cfABGR16}($0000F000, $0000000F, $000000F0, $00000F00),
  61. {cfABGR32}($FF000000, $000000FF, $0000FF00, $00FF0000),
  62. {cfABGR64}($FFFF0000, $0000FFFF, $FFFF0000, $FFFF0000)
  63. // shl 32 shl 16
  64. );
  65. ShiftBits : array[cfRGB15..cfABGR64] of TShiftBits = ( // <0:shl, >0:shr
  66. {cfRGB15} ( 0, -1, -6, -11),
  67. {cfRGB16} ( 0, -1, -6, -11),
  68. {cfRGB24} ( 0, 8, 0, -8),
  69. {cfRGB32} ( 0, 8, 0, -8),
  70. {cfRGB48} ( 0, 32, 16, 0),
  71. {cfRGBA8} (-14, -8, -10, -12),
  72. {cfRGBA16}(-12, 0, -4, -8),
  73. {cfRGBA32}( -8, 16, 8, 0),
  74. {cfRGBA64}( 0, 48, 32, 16),
  75. {cfBGR15} ( 0, -11, -6, -1),
  76. {cfBGR16} ( 0, -11, -6, -1),
  77. {cfBGR24} ( 0, -8, 0, 8),
  78. {cfBGR32} ( 0, -8, 0, 8),
  79. {cfBGR48} ( 0, 0, 16, 32),
  80. {cfBGRA8} ( -8, -14, -12, -10),
  81. {cfBGRA16}( 0, -12, -8, -4),
  82. {cfBGRA32}( 16, -8, 0, 8),
  83. {cfBGRA64}( 48, 0, 16, 32)
  84. );
  85. Bitdepths : array[cfRGB15..cfABGR64] of byte=
  86. (5,5,8,8,16, 2,4,8,16, 5,5,8,8,16, 2,4,8,16);
  87. function EnlargeColor (data:TColorData;CFmt:TColorFormat;component:byte):word;
  88. var w : word;
  89. i : TColorData;
  90. s : shortint;
  91. begin
  92. i := data and ColorBits[CFmt,component];
  93. s := ShiftBits[CFmt,component];
  94. if s = 0 then
  95. w := i
  96. else if s < 0 then
  97. w := i shl -s
  98. else
  99. w := i shr s;
  100. result := FillOtherBits (w ,BitDepths[CFmt]);
  101. end;
  102. function ConvertColor (const From : TColorData; FromFmt:TColorFormat) : TFPColor;
  103. function SetGrayScale (value : word) : TFPColor;
  104. begin
  105. with result do
  106. begin
  107. red := Value;
  108. green := value;
  109. blue := Value;
  110. end;
  111. end;
  112. function SetGrayScaleA (value : word) : TFPColor;
  113. begin
  114. result := SetGrayScale (value);
  115. result.alpha := alphaOpaque;
  116. end;
  117. var m : qword;
  118. begin
  119. case FromFmt of
  120. cfMono : result := SetGrayScaleA (ShiftAndFill(From,1));
  121. cfGray2 : result := SetGrayScaleA (ShiftAndFill(From,2));
  122. cfGray4 : result := SetGrayScaleA (ShiftAndFill(From,4));
  123. cfGray8 : result := SetGrayScaleA (ShiftAndFill(From,8));
  124. cfGray16 : result := SetGrayScaleA (From);
  125. cfGray24 : result := SetGrayScaleA ((From and $00FFFF00) shr 8);
  126. cfGrayA8 :
  127. begin
  128. result := SetGrayScale (FillOtherBits((From and $000000F0) shl 8,4));
  129. result.alpha := ShiftAndFill((From and $0000000F),4);
  130. end;
  131. cfGrayA16 :
  132. begin
  133. result := SetGrayScale (FillOtherBits((From and $0000FF00),8));
  134. result.alpha := ShiftAndFill((From and $000000FF),8);
  135. end;
  136. cfGrayA32 :
  137. begin
  138. result := SetGrayScale ((From and $FFFF0000) shr 16);
  139. result.alpha := (From and $0000FFFF);
  140. end;
  141. cfRGB15,cfRGB16,cfRGB24,cfRGB32,cfRGB48,
  142. cfBGR15,cfBGR16,cfBGR24,cfBGR32,cfBGR48 :
  143. begin
  144. result.alpha := AlphaOpaque;
  145. result.red := EnlargeColor(From, FromFmt, 1);
  146. result.green := EnlargeColor(From, FromFmt, 2);
  147. result.blue := EnlargeColor(From, FromFmt, 3);
  148. end;
  149. cfRGBA8,cfRGBA16,cfRGBA32,cfRGBA64,
  150. cfABGR8,cfABGR16,cfABGR32,cfABGR64 :
  151. begin
  152. result.alpha := EnlargeColor(From, FromFmt, 0);
  153. result.red := EnlargeColor(From, FromFmt, 1);
  154. result.green := EnlargeColor(From, FromFmt, 2);
  155. result.blue := EnlargeColor(From, FromFmt, 3);
  156. end;
  157. end;
  158. end;
  159. function ConvertColor (const From : TDeviceColor) : TFPColor;
  160. begin
  161. result := ConvertColor (From.data, From.Fmt)
  162. end;
  163. const BitMasks : array[1..32] of longword =
  164. ($8000000, $C000000, $E000000, $F000000,
  165. $F800000, $FC00000, $FE00000, $FF00000,
  166. $FF80000, $FFC0000, $FFE0000, $FFF0000,
  167. $FFF8000, $FFFC000, $FFFE000, $FFFF000,
  168. $FFFF800, $FFFFC00, $FFFFE00, $FFFFF00,
  169. $FFFFF80, $FFFFFC0, $FFFFFE0, $FFFFFF0,
  170. $FFFFFF8, $FFFFFFC, $FFFFFFE, $FFFFFFF,
  171. $FFFFFFF, $FFFFFFF, $FFFFFFF, $FFFFFFF);
  172. procedure PrepareBitMasks;
  173. { Putting the correct bits in the array (problem with constants in compiler 1.0)}
  174. var r : integer;
  175. begin
  176. for r := 1 to 32 do
  177. BitMasks[r] := BitMasks[r] shl 4;
  178. inc (BitMasks[29], $8);
  179. inc (BitMasks[30], $C);
  180. inc (BitMasks[31], $E);
  181. inc (BitMasks[32], $F);
  182. end;
  183. function CalculateGray (const c : TFPcolor; Bits:byte) : TColorData;
  184. var temp : longword;
  185. begin
  186. with GrayConvMatrix do
  187. temp := round(red*c.red + green*c.green + blue*c.blue);
  188. result := temp;
  189. //temp := temp + (result shl 16);
  190. //result := temp and BitMasks[Bits];
  191. {if not (c = colBlack) then
  192. with c do
  193. //writeln ('red:',red,' - green:',green,' - blue:',blue, ' : result=',result);
  194. writeln (format('red:%4x - green:%4x - blue:%4x => result:%4x',[integer(red),
  195. integer(green),integer(blue),integer(result)]));}
  196. end;
  197. function CalculateGrayA (const c : TFPcolor; Bits:byte) : TColorData;
  198. var r : longword;
  199. d : byte;
  200. begin
  201. d := bits div 2;
  202. r := CalculateGray (c, d);
  203. result := r shl d;
  204. r := c.alpha shr (16-d);
  205. result := result or r;
  206. end;
  207. function ConvertColorToData (const From : TFPColor; Fmt : TColorFormat) : TColorData;
  208. var sb : TShiftBits;
  209. cb : TColorBits;
  210. function MakeSample (Value:word; ToShift:shortint; ToUse:TColorData) : TColorData;
  211. var sh : word;
  212. begin
  213. result := Value;
  214. if ToShift >= 0 then
  215. begin
  216. sh := ToShift; // if not converting first to word, there will be a
  217. result := result shl Sh; // color shift
  218. end
  219. else
  220. begin
  221. sh := -ToShift;
  222. result := result shr Sh;
  223. end;
  224. result := result and ToUse;
  225. end;
  226. begin
  227. case Fmt of
  228. cfMono : result := CalculateGray (From,1);
  229. cfGray2 : result := CalculateGray (From,2);
  230. cfGray4 : result := CalculateGray (From,4);
  231. cfGray8 : result := CalculateGray (From,8);
  232. cfGray16 : result := CalculateGray (From,16);
  233. cfGray24 : result := CalculateGray (From,24);
  234. cfGrayA8 : result := CalculateGrayA (From, 8);
  235. cfGrayA16 : result := CalculateGrayA (From, 16);
  236. cfGrayA32 : result := CalculateGrayA (From, 32);
  237. cfRGB15,cfRGB16,cfRGB24,cfRGB32,cfRGB48,
  238. cfBGR15,cfBGR16,cfBGR24,cfBGR32,cfBGR48 :
  239. begin
  240. sb := ShiftBits[Fmt];
  241. cb := ColorBits[Fmt];
  242. result := MakeSample(From.blue, sb[3], cb[3]) or
  243. MakeSample(From.red, sb[1], cb[1]) or
  244. MakeSample(From.green, sb[2], cb[2]);
  245. with From do
  246. writeln (red,',',green,',',blue,',',result);
  247. end;
  248. cfRGBA8,cfRGBA16,cfRGBA32,cfRGBA64,
  249. cfABGR8,cfABGR16,cfABGR32,cfABGR64 :
  250. begin
  251. sb := ShiftBits[Fmt];
  252. cb := ColorBits[Fmt];
  253. result := MakeSample(From.alpha, sb[0], cb[0]) or
  254. MakeSample(From.red, sb[1], cb[1]) or
  255. MakeSample(From.green, sb[2], cb[2]) or
  256. MakeSample(From.blue, sb[3], cb[3]);
  257. end;
  258. end;
  259. end;
  260. function ConvertColor (const From : TFPColor; Fmt : TColorFormat) : TDeviceColor;
  261. begin
  262. result.Fmt := Fmt;
  263. result.data := convertColorToData(From, Fmt);
  264. end;
  265. function ConvertColorToData (const From : TDeviceColor; Fmt : TColorFormat) : TColorData;
  266. var c : TFPColor;
  267. begin
  268. c := ConvertColor (From);
  269. result := ConvertColorToData (c, Fmt);
  270. end;
  271. function ConvertColor (const From : TDeviceColor; Fmt : TColorFormat) : TDeviceColor;
  272. begin
  273. result.Fmt := Fmt;
  274. result.data := ConvertColorToData (From, Fmt);
  275. end;
  276. *)
  277. function CompareColors(const Color1, Color2: TFPColor): integer;
  278. begin
  279. Result:=integer(Color1.Red)-integer(Color2.Red);
  280. if Result<>0 then exit;
  281. Result:=integer(Color1.Green)-integer(Color2.Green);
  282. if Result<>0 then exit;
  283. Result:=integer(Color1.Blue)-integer(Color2.Blue);
  284. if Result<>0 then exit;
  285. Result:=integer(Color1.Alpha)-integer(Color2.Alpha);
  286. end;