ImagingCompare.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. {
  2. Vampyre Imaging Library
  3. by Marek Mauder
  4. http://imaginglib.sourceforge.net
  5. The contents of this file are used with permission, subject to the Mozilla
  6. Public License Version 1.1 (the "License"); you may not use this file except
  7. in compliance with the License. You may obtain a copy of the License at
  8. http://www.mozilla.org/MPL/MPL-1.1.html
  9. Software distributed under the License is distributed on an "AS IS" basis,
  10. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  11. the specific language governing rights and limitations under the License.
  12. Alternatively, the contents of this file may be used under the terms of the
  13. GNU Lesser General Public License (the "LGPL License"), in which case the
  14. provisions of the LGPL License are applicable instead of those above.
  15. If you wish to allow use of your version of this file only under the terms
  16. of the LGPL License and not to allow others to use your version of this file
  17. under the MPL, indicate your decision by deleting the provisions above and
  18. replace them with the notice and other provisions required by the LGPL
  19. License. If you do not delete the provisions above, a recipient may use
  20. your version of this file under either the MPL or the LGPL License.
  21. For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
  22. }
  23. {
  24. This unit contains various image comparing functions and image difference
  25. computations.
  26. }
  27. unit ImagingCompare;
  28. {$I ImagingOptions.inc}
  29. interface
  30. uses
  31. SysUtils, Classes, ImagingTypes, Imaging, ImagingFormats, ImagingUtility;
  32. { Computes various error metrics for two images. Images must have
  33. the same size and format. Only formats with 1, 2, and 4 byte samples are
  34. supported (no indexed, compressed, etc.).}
  35. procedure ComputeErrorMetrics(const Image1, Image2: TImageData;
  36. var PSNR, MSE, RMSE, PAE, MAE: Single);
  37. implementation
  38. procedure ComputeErrorMetrics(const Image1, Image2: TImageData;
  39. var PSNR, MSE, RMSE, PAE, MAE: Single);
  40. var
  41. I: Integer;
  42. Info: TImageFormatInfo;
  43. Samples, Bps: Integer;
  44. PixelPtr1, PixelPtr2: PByte;
  45. Diff, MaxSample: Single;
  46. begin
  47. GetImageFormatInfo(Image1.Format, Info);
  48. Bps := Info.ChannelCount div Info.BytesPerPixel;
  49. Assert((Image1.Width = Image2.Width) and (Image1.Height = Image2.Height) and
  50. (Image1.Format = Image2.Format));
  51. Assert(not Info.IsIndexed and not Info.IsSpecial and not Info.UsePixelFormat
  52. and (Bps in [1, 2, 4]));
  53. Diff := 0;
  54. PSNR := 0;
  55. MSE := 0;
  56. RMSE := 0;
  57. PAE := 0;
  58. MAE := 0;
  59. PixelPtr1 := Image1.Bits;
  60. PixelPtr2 := Image2.Bits;
  61. Samples := Image1.Width * Image1.Height * Info.ChannelCount;
  62. for I := 0 to Samples - 1 do
  63. begin
  64. // Compute difference betwen pixels
  65. case Bps of
  66. 1: Diff := Abs(PixelPtr2^ - PixelPtr1^);
  67. 2:
  68. begin
  69. if Info.IsFloatingPoint then
  70. Diff := Abs(HalfToFloat(PWord(PixelPtr2)^) - HalfToFloat(PWord(PixelPtr1)^))
  71. else
  72. Diff := Abs(PWord(PixelPtr2)^ - PWord(PixelPtr1)^);
  73. end;
  74. 4:
  75. begin
  76. if Info.IsFloatingPoint then
  77. Diff := Abs(PSingle(PixelPtr2)^ - PSingle(PixelPtr1)^)
  78. else
  79. Diff := Abs(PUInt32(PixelPtr2)^ - PUInt32(PixelPtr1)^);
  80. end;
  81. end;
  82. // Update metrics
  83. MAE := MAE + Diff;
  84. PAE := MaxFloat(PAE, Diff);
  85. MSE := MSE + Diff * Diff;
  86. Inc(PixelPtr1, Bps);
  87. Inc(PixelPtr2, Bps);
  88. end;
  89. if Info.IsFloatingPoint then
  90. MaxSample := 1.0
  91. else
  92. MaxSample := Pow2Int(Bps * 8) - 1;
  93. // Final metrics calculations
  94. MAE := MAE / Samples;
  95. MSE := MSE / Samples;
  96. RMSE := Sqrt(MSE);
  97. if RMSE < 0.0001 then
  98. PSNR := 1e06
  99. else
  100. PSNR := 20 * Log10(MaxSample / RMSE);
  101. end;
  102. {
  103. File Notes:
  104. -- TODOS ----------------------------------------------------
  105. - none
  106. -- 0.26.5 Changes/Bug Fixes -----------------------------------
  107. - Added ComputeErrorMetrics.
  108. - Unit created.
  109. }
  110. end.