GR32_Gamma.pas 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. unit GR32_Gamma;
  2. interface
  3. uses
  4. GR32;
  5. { Gamma bias for line/pixel antialiasing }
  6. type
  7. TGammaTable8Bit = array [Byte] of Byte;
  8. var
  9. GAMMA_VALUE: Double;
  10. GAMMA_ENCODING_TABLE: TGammaTable8Bit;
  11. GAMMA_DECODING_TABLE: TGammaTable8Bit;
  12. const
  13. DEFAULT_GAMMA: Double = 1.6;
  14. // set gamma
  15. procedure SetGamma; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  16. procedure SetGamma(Gamma: Double); overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  17. procedure SetGamma(Gamma: Double; var GammaTable: TGammaTable8Bit); overload;
  18. procedure Set_sRGB; overload;
  19. procedure Set_sRGB(var GammaTable: TGammaTable8Bit); overload;
  20. procedure SetInv_sRGB(var GammaTable: TGammaTable8Bit);
  21. // apply gamma
  22. function ApplyGamma(Color: TColor32): TColor32; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  23. function ApplyInvGamma(Color: TColor32): TColor32; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  24. function ApplyCustomGamma(Color: TColor32; GammaTable: TGammaTable8Bit): TColor32; overload; {$IFDEF USEINLINING} inline; {$ENDIF}
  25. procedure ApplyGamma(Color: PColor32Array; Length: Integer); overload;
  26. procedure ApplyInvGamma(Color: PColor32Array; Length: Integer); overload;
  27. procedure ApplyCustomGamma(Color: PColor32Array; Length: Integer; GammaTable: TGammaTable8Bit); overload;
  28. procedure ApplyGamma(Bitmap: TBitmap32); overload;
  29. procedure ApplyInvGamma(Bitmap: TBitmap32); overload;
  30. procedure ApplyCustomGamma(Bitmap: TBitmap32; GammaTable: TGammaTable8Bit); overload;
  31. procedure ApplyCustomGamma(Bitmap: TBitmap32; Gamma: Double); overload;
  32. implementation
  33. uses
  34. Math;
  35. function ApplyGamma(Color: TColor32): TColor32;
  36. begin
  37. TColor32Entry(Result).R := GAMMA_ENCODING_TABLE[TColor32Entry(Color).R];
  38. TColor32Entry(Result).G := GAMMA_ENCODING_TABLE[TColor32Entry(Color).G];
  39. TColor32Entry(Result).B := GAMMA_ENCODING_TABLE[TColor32Entry(Color).B];
  40. end;
  41. function ApplyInvGamma(Color: TColor32): TColor32;
  42. begin
  43. TColor32Entry(Result).R := GAMMA_DECODING_TABLE[TColor32Entry(Color).R];
  44. TColor32Entry(Result).G := GAMMA_DECODING_TABLE[TColor32Entry(Color).G];
  45. TColor32Entry(Result).B := GAMMA_DECODING_TABLE[TColor32Entry(Color).B];
  46. end;
  47. function ApplyCustomGamma(Color: TColor32; GammaTable: TGammaTable8Bit): TColor32;
  48. begin
  49. TColor32Entry(Result).R := GammaTable[TColor32Entry(Color).R];
  50. TColor32Entry(Result).G := GammaTable[TColor32Entry(Color).G];
  51. TColor32Entry(Result).B := GammaTable[TColor32Entry(Color).B];
  52. end;
  53. procedure ApplyGamma(Color: PColor32Array; Length: Integer);
  54. var
  55. Index: Integer;
  56. begin
  57. for Index := 0 to Length - 1 do
  58. begin
  59. PColor32Entry(Color)^.R := GAMMA_ENCODING_TABLE[PColor32Entry(Color)^.R];
  60. PColor32Entry(Color)^.G := GAMMA_ENCODING_TABLE[PColor32Entry(Color)^.G];
  61. PColor32Entry(Color)^.B := GAMMA_ENCODING_TABLE[PColor32Entry(Color)^.B];
  62. Inc(Color);
  63. end;
  64. end;
  65. procedure ApplyInvGamma(Color: PColor32Array; Length: Integer);
  66. var
  67. Index: Integer;
  68. begin
  69. for Index := 0 to Length - 1 do
  70. begin
  71. PColor32Entry(Color)^.R := GAMMA_DECODING_TABLE[PColor32Entry(Color)^.R];
  72. PColor32Entry(Color)^.G := GAMMA_DECODING_TABLE[PColor32Entry(Color)^.G];
  73. PColor32Entry(Color)^.B := GAMMA_DECODING_TABLE[PColor32Entry(Color)^.B];
  74. Inc(Color);
  75. end;
  76. end;
  77. procedure ApplyCustomGamma(Color: PColor32Array; Length: Integer; GammaTable: TGammaTable8Bit);
  78. var
  79. Index: Integer;
  80. begin
  81. for Index := 0 to Length - 1 do
  82. begin
  83. PColor32Entry(Color)^.R := GammaTable[PColor32Entry(Color)^.R];
  84. PColor32Entry(Color)^.G := GammaTable[PColor32Entry(Color)^.G];
  85. PColor32Entry(Color)^.B := GammaTable[PColor32Entry(Color)^.B];
  86. Inc(Color);
  87. end;
  88. end;
  89. procedure ApplyGamma(Bitmap: TBitmap32);
  90. begin
  91. ApplyGamma(Bitmap.Bits, Bitmap.Width * Bitmap.Height);
  92. end;
  93. procedure ApplyInvGamma(Bitmap: TBitmap32);
  94. begin
  95. ApplyInvGamma(Bitmap.Bits, Bitmap.Width * Bitmap.Height);
  96. end;
  97. procedure ApplyCustomGamma(Bitmap: TBitmap32; GammaTable: TGammaTable8Bit);
  98. begin
  99. ApplyCustomGamma(Bitmap.Bits, Bitmap.Width * Bitmap.Height, GammaTable);
  100. end;
  101. procedure ApplyCustomGamma(Bitmap: TBitmap32; Gamma: Double);
  102. var
  103. GammaTable: TGammaTable8Bit;
  104. begin
  105. if GAMMA_VALUE = Gamma then
  106. ApplyGamma(Bitmap.Bits, Bitmap.Width * Bitmap.Height)
  107. else
  108. begin
  109. SetGamma(Gamma, GammaTable);
  110. ApplyCustomGamma(Bitmap.Bits, Bitmap.Width * Bitmap.Height, GammaTable);
  111. end;
  112. end;
  113. { Gamma / Pixel Shape Correction table }
  114. procedure SetGamma;
  115. begin
  116. SetGamma(DEFAULT_GAMMA);
  117. end;
  118. procedure SetGamma(Gamma: Double);
  119. begin
  120. GAMMA_VALUE := Gamma;
  121. // calculate default gamma tables
  122. SetGamma(1 / Gamma, GAMMA_ENCODING_TABLE);
  123. SetGamma(Gamma, GAMMA_DECODING_TABLE);
  124. end;
  125. procedure SetGamma(Gamma: Double; var GammaTable: TGammaTable8Bit);
  126. var
  127. i: Integer;
  128. begin
  129. for i := 0 to $FF do
  130. GammaTable[i] := Round($FF * Power(i * COne255th, Gamma));
  131. end;
  132. procedure Set_sRGB;
  133. begin
  134. Set_sRGB(GAMMA_ENCODING_TABLE);
  135. SetInv_sRGB(GAMMA_DECODING_TABLE);
  136. end;
  137. procedure Set_sRGB(var GammaTable: TGammaTable8Bit);
  138. var
  139. i: Integer;
  140. Value: Double;
  141. const
  142. CExp = 1 / 2.4;
  143. begin
  144. for i := 0 to $FF do
  145. begin
  146. Value := i * COne255th;
  147. if (Value < 0.0031308) then
  148. GammaTable[i] := Round($FF * Value * 12.92)
  149. else
  150. GammaTable[i] := Round($FF * (1.055 * Power(Value, CExp) - 0.055));
  151. end;
  152. end;
  153. procedure SetInv_sRGB(var GammaTable: TGammaTable8Bit);
  154. var
  155. i: Integer;
  156. Value: Double;
  157. begin
  158. for i := 0 to $FF do
  159. begin
  160. Value := i * COne255th;
  161. if (Value < 0.004045) then
  162. GammaTable[i] := Round($FF * Value / 12.92)
  163. else
  164. GammaTable[i] := Round($FF * Power((Value + 0.055) / 1.055, 2.4));
  165. end;
  166. end;
  167. end.