ImagingSquishLib.pas 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. {
  2. $Id: ImagingSquishLib.pas 168 2009-08-22 18:50:21Z galfar $
  3. Vampyre Imaging Library
  4. by Marek Mauder
  5. http://imaginglib.sourceforge.net
  6. The contents of this file are used with permission, subject to the Mozilla
  7. Public License Version 1.1 (the "License"); you may not use this file except
  8. in compliance with the License. You may obtain a copy of the License at
  9. http://www.mozilla.org/MPL/MPL-1.1.html
  10. Software distributed under the License is distributed on an "AS IS" basis,
  11. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  12. the specific language governing rights and limitations under the License.
  13. Alternatively, the contents of this file may be used under the terms of the
  14. GNU Lesser General Public License (the "LGPL License"), in which case the
  15. provisions of the LGPL License are applicable instead of those above.
  16. If you wish to allow use of your version of this file only under the terms
  17. of the LGPL License and not to allow others to use your version of this file
  18. under the MPL, indicate your decision by deleting the provisions above and
  19. replace them with the notice and other provisions required by the LGPL
  20. License. If you do not delete the provisions above, a recipient may use
  21. your version of this file under either the MPL or the LGPL License.
  22. For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
  23. }
  24. { High quality DXTC compressor using Squish library (dynamicaly linked).}
  25. unit ImagingSquishLib;
  26. interface
  27. {$I ImagingOptions.inc}
  28. uses
  29. ImagingTypes, Imaging, ImagingFormats;
  30. type
  31. TDXTCompressor = (
  32. dcClusterFit, // Use a slow but high quality colour compressor (the default).
  33. dcRangeFit, // Use a fast but low quality colour compressor.
  34. dcClusterFitAlphaWeighted // Cluster fit that weights the colour by alpha.
  35. // For images that are rendered using alpha blending,
  36. // this can significantly increase the perceived quality.
  37. );
  38. TColorMetric = (
  39. cmPerceptual, // Use a perceptual metric for colour error (the default).
  40. cmUniform // Use a uniform metric for colour error.
  41. );
  42. { Compresses SrcImage using selected DXTn compression into DestImage.
  43. DestImage should be cleared before calling.}
  44. procedure DXTCompressImage(const SrcImage: TImageData; var DestImage: TImageData;
  45. DXTFormat: TImageFormat; Compressor: TDXTCompressor = dcClusterFit;
  46. Metric: TColorMetric = cmPerceptual);
  47. implementation
  48. const
  49. FlagDXT1 = 1 shl 0;
  50. FlagDXT3 = 1 shl 1;
  51. FlagDXT5 = 1 shl 2;
  52. FlagColourClusterFit = 1 shl 3;
  53. FlagColourRangeFit = 1 shl 4;
  54. FlagColourMetricPerceptual = 1 shl 5;
  55. FlagColourMetricUniform = 1 shl 6;
  56. FlagWeightColourByAlpha = 1 shl 7;
  57. (* @brief Compresses an image in memory.
  58. @param rgba The pixels of the source.
  59. @param width The width of the source image.
  60. @param height The height of the source image.
  61. @param blocks Storage for the compressed output.
  62. @param flags Compression flags.
  63. The source pixels should be presented as a contiguous array of width*height
  64. rgba values, with each component as 1 byte each. In memory this should be:
  65. { r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
  66. The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
  67. however, DXT1 will be used by default if none is specified. When using DXT1
  68. compression, 8 bytes of storage are required for each compressed DXT block.
  69. DXT3 and DXT5 compression require 16 bytes of storage per block.
  70. The flags parameter can also specify a preferred colour compressor and
  71. colour error metric to use when fitting the RGB components of the data.
  72. Possible colour compressors are: kColourClusterFit (the default) or
  73. kColourRangeFit. Possible colour error metrics are: kColourMetricPerceptual
  74. (the default) or kColourMetricUniform. If no flags are specified in any
  75. particular category then the default will be used. Unknown flags are
  76. ignored.
  77. When using kColourClusterFit, an additional flag can be specified to
  78. weight the colour of each pixel by its alpha value. For images that are
  79. rendered using alpha blending, this can significantly increase the
  80. perceived quality.
  81. Internally this function calls squish::Compress for each block. To see how
  82. much memory is required in the compressed image, use
  83. squish::GetStorageRequirements.
  84. *)
  85. procedure CompressImage(RGBA: PByte; Width, Height: Integer; Blocks: Pointer;
  86. Flags: Integer); cdecl; external 'libsquish.dll';
  87. procedure DXTCompressImage(const SrcImage: TImageData; var DestImage: TImageData;
  88. DXTFormat: TImageFormat; Compressor: TDXTCompressor = dcClusterFit;
  89. Metric: TColorMetric = cmPerceptual);
  90. var
  91. Width, Height: Integer;
  92. Info: TImageFormatInfo;
  93. TempImage: TImageData;
  94. Flags: Integer;
  95. function GetSquishFlags: Integer;
  96. begin
  97. Result := 0;
  98. case DXTFormat of
  99. ifDXT1: Result := FlagDXT1;
  100. ifDXT3: Result := FlagDXT3;
  101. ifDXT5: Result := FlagDXT5;
  102. end;
  103. case Compressor of
  104. dcClusterFit: Result := Result or FlagColourClusterFit;
  105. dcRangeFit: Result := Result or FlagColourRangeFit;
  106. dcClusterFitAlphaWeighted: Result := Result or FlagColourClusterFit or FlagWeightColourByAlpha;
  107. end;
  108. case Metric of
  109. cmPerceptual: Result := Result or FlagColourMetricPerceptual;
  110. cmUniform: Result := Result or FlagColourMetricUniform;
  111. end;
  112. end;
  113. begin
  114. Assert(DXTFormat in [ifDXT1, ifDXT3, ifDXT5]);
  115. Width := SrcImage.Width;
  116. Height := SrcImage.Height;
  117. Flags := GetSquishFlags;
  118. // Check if input has correct dimensions and change them if needed
  119. GetImageFormatInfo(DXTFormat, Info);
  120. Info.CheckDimensions(DXTFormat, Width, Height);
  121. try
  122. // Create temp image as input for squish (must be ABGR order with
  123. // dimensions being multiples of 4)
  124. NewImage(Width, Height, ifA8R8G8B8, TempImage);
  125. CopyRect(SrcImage, 0, 0, SrcImage.Width, SrcImage.Height, TempImage, 0, 0);
  126. SwapChannels(TempImage, ChannelRed, ChannelBlue);
  127. // Init and create out image
  128. InitImage(DestImage);
  129. NewImage(Width, Height, DXTFormat, DestImage);
  130. // Finally call Squish
  131. CompressImage(TempImage.Bits, Width, Height, DestImage.Bits, Flags);
  132. finally
  133. FreeImage(TempImage);
  134. end;
  135. end;
  136. end.