Unit CastleImages

Description

Loading, saving, and processing of images (TEncodedImage, TCastleImage and other classes). This unit deals with images, stored in normal memory (not on GPU). Images can be loaded and saved from/to various formats and processed in a lot of ways. For example you can resize images, you can draw one image on another, convert to grayscale and so on.

The "image" as understood by this unit may have some interesting features useful with modern GPUs: image data may be compressed for GPU (TGPUCompressedImage), image data may be 3D (every image has Depth, in addition to Width and Height).

The most important class here is TCastleImage. It represents an image as a simple uncompressed array of pixels. Descendants of TCastleImage define what exactly is a "pixel". We have 8-bit color images (TRGBAlphaImage, TRGBImage, TGrayscaleAlphaImage and TGrayscaleImage). We also have an image with floating-point precision and range: TRGBFloatImage.

There is also a more abstract image class TEncodedImage, representing either uncompressed image (TCastleImage) or an image with data compressed for GPU (TGPUCompressedImage).

When reading and writing image files, we understand various image formats. See castle-view-image documentation ( https://castle-engine.io/castle-view-image.php ) for a current list of supported image formats.

The basic loading and saving procedures are LoadImage and SaveImage. Example usage:

var
  Image: TCastleImage;
begin
  Image := LoadImage('image.png');
  { scale the image to be 2x smaller }
  Image.Resize(Image.Width div 2, Image.Height div 2);
  SaveImage(Image, 'newimage.png');
end;

This unit is not dependent on OpenGL or any other rendering library. See CastleGLImages for OpenGL image operations (for textures and others).

Uses

Overview

Classes, Interfaces, Objects and Records

Name Description
Class EImagePosOutOfRange Raised by TCastleImage.MakeExtracted when coordinates on image are wrong.
Class EImageLerpError  
Class EImageLerpInvalidClasses  
Class EImageLerpDifferentSizes  
Class EImageAssignmentError  
Class EImageCannotConvertFpImage  
Class EImageDrawError  
Class TEncodedImage Abstract class for an image with unspecified, possibly compressed, memory format.
Class TCastleImage An abstract class representing image as a simple array of pixels.
Class TGPUCompressedImage Image compressed using one of the GPU texture compression algorithms.
Class ECannotDecompressTexture  
Class TRGBImage Image with pixel represented as a TVector3Byte (red, green, blue).
Class TRGBAlphaImage  
Class TRGBFloatImage Image with high-precision RGB colors encoded as 3 floats.
Class TGrayscaleImage Grayscale image.
Class TGrayscaleAlphaImage Grayscale image with an alpha channel.
Class EImageLoadError  
Class EInvalidImageFormat  
Class EUnableToLoadImage  
Class EImageFormatNotSupported  
Class EImageSaveError Raised by SaveImage when it's not possible to save image.
Object TTextureCompressionInfo  

Functions and Procedures

function EqualRGB(const Color1, Color2: TVector3Byte; Tolerance: Byte): boolean;
function InImageClasses(ImageClass: TEncodedImageClass; const ImageClasses: array of TEncodedImageClass): boolean; overload;
function InImageClasses(Image: TEncodedImage; const ImageClasses: array of TEncodedImageClass): boolean; overload;
function ImageClassesEqual(const Ar1, Ar2: array of TEncodedImageClass): boolean;
function Vector3ToRGBE(const v: TVector3): TVector4Byte; deprecated 'RGBE compression should be internal in CGE or Vampyre';
function VectorRGBETo3Single(const v: TVector4Byte): TVector3; deprecated 'RGBE compression should be internal in CGE or Vampyre';
function IsImageMimeType(const MimeType: string; const OnlyLoadable, OnlySaveable: boolean): boolean;
function ListImageExtsLong(OnlyLoadable, OnlySaveable: boolean; const LinePrefix: string): string;
function ListImageExtsShort(OnlyLoadable, OnlySaveable: boolean): string;
function ImageExtToMimeType(Ext: string): string; deprecated 'use URIMimeType';
function LoadImage(Stream: TStream; const MimeType: string; const AllowedImageClasses: array of TEncodedImageClass) :TCastleImage; overload;
function LoadImage(const URL: string): TCastleImage; overload;
function LoadImage(const URL: string; const AllowedImageClasses: array of TEncodedImageClass) :TCastleImage; overload;
function LoadImage(const URL: string; const AllowedImageClasses: array of TEncodedImageClass; const ResizeWidth, ResizeHeight: Cardinal; const Interpolation: TResizeInterpolation = riBilinear; const Options: TLoadImageOptions = []): TCastleImage; overload;
function LoadEncodedImage(Stream: TStream; const MimeType: string; const AllowedImageClasses: array of TEncodedImageClass; const Options: TLoadImageOptions = []) :TEncodedImage; overload;
function LoadEncodedImage(const URL: string; const Options: TLoadImageOptions = []): TEncodedImage; overload;
function LoadEncodedImage(URL: string; const AllowedImageClasses: array of TEncodedImageClass; const Options: TLoadImageOptions = []) :TEncodedImage; overload;
procedure SaveImage(const Img: TEncodedImage; const MimeType: string; Stream: TStream); overload;
procedure SaveImage(const Img: TEncodedImage; const URL: string); overload;
function ImageClassBestForSavingToFormat(const URL: string): TCastleImageClass; deprecated 'implement this logic yourself; the fact that this may return TRGBImage, disregarging possible alpha, is misleading';
procedure AlphaMaxVar(var A: TAlphaChannel; const B: TAlphaChannel);
function StringToAlpha(S: string; var WarningDone: boolean): TAutoAlphaChannel;
function TextureCompressionToString(const TextureCompression: TTextureCompression): string;
function StringToTextureCompression(const S: string): TTextureCompression;
procedure AddLoadImageListener(const Event: TLoadImageEvent);
procedure RemoveLoadImageListener(const Event: TLoadImageEvent);
function ProcessImageUrl(const URL: string): string;

Types

TAutoAlphaChannel = (...);
TAlphaChannel = acNone .. acBlending;
TResizeInterpolation = (...);
TResizeInterpolationInternal = Low(TResizeInterpolation) .. riBilinear;
TResizeInterpolationFpImage = Succ(riBilinear) .. High(TResizeInterpolation);
TDrawMode = (...);
TCastleImageList = specialize TObjectList<TCastleImage>;
TEncodedImageList = specialize TObjectList<TEncodedImage>;
TTextureCompression = (...);
TTextureCompressions = set of TTextureCompression;
TS3TCImage = TGPUCompressedImage deprecated;
TDecompressTextureFunction = function (Image: TGPUCompressedImage): TCastleImage;
TCastleImageClass = class of TCastleImage;
TEncodedImageClass = class of TEncodedImage;
TLoadImageOption = (...);
TLoadImageOptions = set of TLoadImageOption;
TLoadImageEvent = procedure (var ImageUrl: string) of object;

Constants

acSimpleYesNo = acBlending deprecated 'use acTest';
acFullRange = acBlending deprecated 'use acBlending';
DefaultAlphaTolerance = 5;
AlphaToString: array [TAutoAlphaChannel] of string = ('AUTO', 'NONE', 'TEST', 'BLENDING');
TextureCompressionInfo: array [TTextureCompression] of TTextureCompressionInfo = ( (Name: 'DXT1_RGB' ; RequiresPowerOf2: false; AlphaChannel: acNone ; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT1_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acTest ; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT3' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT5' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: false; FileExtension: '.dds'), (Name: 'PVRTC1_4bpp_RGB' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_2bpp_RGB' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_4bpp_RGBA' ; RequiresPowerOf2: true ; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_2bpp_RGBA' ; RequiresPowerOf2: true ; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC2_4bpp' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC2_2bpp' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGB' ; RequiresPowerOf2: false; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGBA_ExplicitAlpha' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGBA_InterpolatedAlpha'; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ETC1' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.ktx'), (Name: 'ASTC_4x4_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x4_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x8_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x8_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x10_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x10_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x12_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_4x4_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x4_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x8_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x8_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x10_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x10_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x12_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ) );

Variables

DecompressTexture: TDecompressTextureFunction;
LoadImage_FileFilters: TFileFilterList;
SaveImage_FileFilters: TFileFilterList;
SupportedTextureCompressionKnown: boolean;
SupportedTextureCompression: TTextureCompressions;

Description

Functions and Procedures

function EqualRGB(const Color1, Color2: TVector3Byte; Tolerance: Byte): boolean;

Check if the two RGB colors are equal, ignoring small differences. All three color components may differ by at most Tolerance. When Tolerance is 0, this is a normal (exact) comparison.

function InImageClasses(ImageClass: TEncodedImageClass; const ImageClasses: array of TEncodedImageClass): boolean; overload;

Check is ImageClass one of the items in the ImageClasses array, or a descendant of one of them.

function InImageClasses(Image: TEncodedImage; const ImageClasses: array of TEncodedImageClass): boolean; overload;

Check is Image class one of the items in the ImageClasses array, or a descendant of one of them. This is a shortcut for InImageClasses(Image.ClassType, ImageClasses).

function ImageClassesEqual(const Ar1, Ar2: array of TEncodedImageClass): boolean;

Check if both arrays contain exactly the same classes in the same order.

May be extended in the future to do better checks and return true also if both array contain the same classes but in different order, and one array may contain the same classes duplicated any times. So the intention is that you should treat both arrays as sets (i.e. order of elements is ignored).

The problem is that this function should be lighting fast. As the main purpose of it is to use it in constructions like setting property values, e.g.

if ImageClassesArraysEqual(Value, SomeProperty) then
begin
  SomeProperty := Value;
  { ... do some lengthy operations to update new value of SomeProperty ... }
end;

Doing smarter checks may cost us a little time.

So for now this function returns

  • True if for sure both arrays contain the same classes and

  • False if possibly they don't contain the same classes.

function Vector3ToRGBE(const v: TVector3): TVector4Byte; deprecated 'RGBE compression should be internal in CGE or Vampyre';

Warning: this symbol is deprecated: RGBE compression should be internal in CGE or Vampyre

Encode RGB color as Red + Green + Blue + Exponent format. This allows you to encode high-precision colors in 4 bytes, see ifRGBE image format for pointers why this is useful.

Each component of V (red, green, blue) must be from range [0, +infinity), not merely from [0, 1]. That is, V must have only nonnegative values.

function VectorRGBETo3Single(const v: TVector4Byte): TVector3; deprecated 'RGBE compression should be internal in CGE or Vampyre';

Warning: this symbol is deprecated: RGBE compression should be internal in CGE or Vampyre

Decode Red + Green + Blue + Exponent back into RGB (3 floats).

function IsImageMimeType(const MimeType: string; const OnlyLoadable, OnlySaveable: boolean): boolean;

Does this MIME type correspond to image.

function ListImageExtsLong(OnlyLoadable, OnlySaveable: boolean; const LinePrefix: string): string;

List available image file formats.

This is basically for debug/info purposes, you can show this to user to let him know which formats are supported (and by which extensions they are recognized). Although almost always a better way to show this to user is just to use SaveImage_FileFilters with a save dialog like TCastleWindow.FileDialog, this shows file types in the open/save dialog, so it's most natural and convenient to user.

ListImageExtsLong produces a multiline info (separated by NL, last line not terminated by NL), shows all extensions and FormatName for each file format. Each line starts with LinePrefix.

ListImageExtsShort writes all recognized extensions separated by comma (', ').

function ListImageExtsShort(OnlyLoadable, OnlySaveable: boolean): string;
 
function ImageExtToMimeType(Ext: string): string; deprecated 'use URIMimeType';

Warning: this symbol is deprecated: use URIMimeType

Guess MIME type from image extension. Empty string if cannot guess.

function LoadImage(Stream: TStream; const MimeType: string; const AllowedImageClasses: array of TEncodedImageClass) :TCastleImage; overload;

The ultimate procedure to load an image from a file or URL.

URL is downloaded using CastleDownload unit. As always, if you all you care about is loading normal files, then just pass a normal filename (absolute or relative to the current directory) as the URL parameter.

Simple examples:

{ When you don't care what TCastleImage descendant you get: }
Image := LoadImage('image.png');

{ When you insist on getting TRGBImage, that is 8-bit color image
  without an alpha channel. }
ImageRGB := LoadImage('image.png', [TRGBImage]) as TRGBImage;

Image file format may be given explicitly (overloaded version with Format parameter), or guessed based on URL extension (which can be given explicitly by TypeExt, or automatically calculated from full URL). For now, we cannot guess the file format based on file contents or MIME type (the latter case would be sensible for http URLs).

AllowedImageClasses says what image classes are allowed. As a special case, AllowedImageClasses = [] is equivalent to AllowedImageClasses = [TCastleImage] which says that all TCastleImage descendants are allowed. Then this function will do everything it can to load any image into the best subclass of TCastleImage, losing as little image information it can.

Example: consider you're loading a PNG file. Let's suppose you're loading it with AllowedImageClasses = []. Then you can get TGrayscaleImage, TGrayscaleAlphaImage, TRGBImage, TRGBAlphaImage, depending on whether PNG file is grayscale or not and has alpha or not. Now let's suppose you specified AllowedImageClasses = [TRGBImage]. If PNG file will not be grayscale and not have alpha channel, LoadImage will return TRGBImage descendant, as before. But if PNG fill *will* have alpha channel then LoadImage will simply ignore (strip) alpha channel and return you TRGBImage.

Similar thing for grayscale: if image file was grayscale but you requested only TRGBImage, then grayscale may be "expanded" into full three-channel RGB.

There can also happen reverse situation: you e.g. insist that AllowedImageClasses = [TRGBAlphaImage] but given PNG image does not have alpha channel. In this case LoadImage may add "dummy" alpha channel (everywhere equal to 1.0 or High(Byte)). Similar thing when you e.g. gave AllowedImageClasses = [TRGBFloatImage] but you're loading from PNG image. In this case you want float precision, but image file cannot offer it. So LoadImage can simply convert discreet values to appropriating floating point values.

If at any point LoadImage will find that it's unable to satisfy AllowedImageClasses, it will raise EUnableToLoadImage.

Exceptions raised
EUnableToLoadImage
If Image cannot be loaded into allowed AllowedImageClasses.
EImageFormatNotSupported
If image file format cannot be loaded at all. This can happen if format is totally unknown (not recognized MIME type, derived from file extension in case of local files) or if this image format cannot be loaded at all.
EImageLoadError
If the image file cannot be processed for some reason.
Exception
Various TStream instances (used internally by the Download function) may raise exceptions in case the stream cannot be created for reading. Right now, we simply let these exceptions to "pass through" from this function (instead of catching and re-raising). So be ready that this function may raise any Exception class. In case of local files (file:// URLs), the typical exceptions are EFOpenError and EReadError.
See also
LoadEncodedImage
function LoadImage(const URL: string): TCastleImage; overload;
 
function LoadImage(const URL: string; const AllowedImageClasses: array of TEncodedImageClass) :TCastleImage; overload;
 
function LoadImage(const URL: string; const AllowedImageClasses: array of TEncodedImageClass; const ResizeWidth, ResizeHeight: Cardinal; const Interpolation: TResizeInterpolation = riBilinear; const Options: TLoadImageOptions = []): TCastleImage; overload;
 
function LoadEncodedImage(Stream: TStream; const MimeType: string; const AllowedImageClasses: array of TEncodedImageClass; const Options: TLoadImageOptions = []) :TEncodedImage; overload;

Load image to TEncodedImage format. This allows loading image compressed with GPU, which is good for optimally loading it to GPU. However, the operations on GPU-compressed image are very limited, we generally cannot do much with GPU-compressed data except rendering it.

See also
LoadImage
function LoadEncodedImage(const URL: string; const Options: TLoadImageOptions = []): TEncodedImage; overload;
 
function LoadEncodedImage(URL: string; const AllowedImageClasses: array of TEncodedImageClass; const Options: TLoadImageOptions = []) :TEncodedImage; overload;
 
procedure SaveImage(const Img: TEncodedImage; const MimeType: string; Stream: TStream); overload;

Save image to a file. Takes URL as parameter, you can give file URL or just a normal filename.

File format is determined by looking at URL (guessing MIME type using URIMimeType), or given explicitly as MimeType, or just given explicitly as Format parameter.

Image class does not affect the created image file format, on the assumption that the "memory format" of the image (what TCastleImage descendant is used) can be orthogonal to the actual "file format" used to save this file.

Tries to write the image preserving it as closely as possible in this image format. When it's not possible, according conversions may be done: floating point precision of TRGBFloatImage may be lost (if saving to any file format besides RGBE file, although saving to OpenEXR may also preserve it once implemented), alpha channel may be lost, grayscale may be expanded and such.

Although not absolutely all conversions are implemented for now. You can be sure that all image formats (that allow any saving at all) can be saved from TRGBImage. Also TRGBFloatImage can be saved to RGBE file. Also PNG format supports full collection (grayscale/rgb, alpha/no alpha are all perfectly possible in PNG file; and TRGBFloatImage will be just converted to 8-bit RGB before saving to PNG).

Exceptions raised
EImageSaveError
When it's not possible to save image, because of Img class (memory format) and/or image file format.
procedure SaveImage(const Img: TEncodedImage; const URL: string); overload;
 
function ImageClassBestForSavingToFormat(const URL: string): TCastleImageClass; deprecated 'implement this logic yourself; the fact that this may return TRGBImage, disregarging possible alpha, is misleading';

Warning: this symbol is deprecated: implement this logic yourself; the fact that this may return TRGBImage, disregarging possible alpha, is misleading

Choose TCastleImage descendant best matching for this image file format. The only purpose of this for now is to pick TRGBFloatImage for RGBE files, chooses TRGBImage for anything else.

For the overloaded version with URL, file format is determined by guessing based on file extension.

procedure AlphaMaxVar(var A: TAlphaChannel; const B: TAlphaChannel);

Maximum alpha channel type. Chooses "full range" if anything is "full range", otherwise choose "simple yes/no" if anything is "simple yes/no", otherwise returns "no alpha channel".

function StringToAlpha(S: string; var WarningDone: boolean): TAutoAlphaChannel;
 
function TextureCompressionToString(const TextureCompression: TTextureCompression): string;

Convert TTextureCompression enum to string.

function StringToTextureCompression(const S: string): TTextureCompression;

Convert string to TTextureCompression enum. Possible values correspond to names listed in TextureCompressionInfo array, they are also equal to enum Pascal names without leading "tc". Compares given strig ignoring the case.

Exceptions raised
Exception
If the string value does not name any TTextureCompression value.
procedure AddLoadImageListener(const Event: TLoadImageEvent);

All image URLs are processed by this event before loading. This allows to globally modify / observe your images paths, e.g. to use GPU compressed alternative versions.

The URL processing is automatically used by all image loaders. This includes LoadImage, LoadEncodedImage and (internal) TCompositeImage.LoadFromFile.

The URL processing is automatically registered by MaterialProperties to automatically use GPU compressed textures. See https://castle-engine.io/creating_data_material_properties.php . You can also use it yourself, instead or in addition to MaterialProperties processing.

An example: To work on any GPU, you want to have various versions of your textures (uncompressed, and also compressed with various GPU algorithms) in your data. Use this procedure to redirect all image loading to use your compressed versions, when they are supported by the GPU. By doing it like this we capture all kinds of image loading — from TDrawableImage, from TCastleScene and so on.

uses ..., CastleURIUtils, CastleGLUtils, CastleLog, CastleStringUtils,
  CastleFilesUtils;

procedure TTextureUtils.GPUTextureAlternative(var ImageUrl: string);
begin
  if IsPrefix('castle-data:/animation/dragon/', ImageUrl) then
  begin
    if GLFeatures = nil then
      WritelnWarning('TextureCompression', 'Cannot determine whether to use GPU compressed version for ' + ImageUrl + ' because the image is loaded before GPU capabilities are known') else
    if tcPvrtc1_4bpp_RGBA in GLFeatures.TextureCompression then
    begin
      ImageUrl := ExtractURIPath(ImageUrl) + 'compressed/pvrtc1_4bpp_rgba/' +
        ExtractURIName(ImageUrl) + '.dds';
      WritelnLog('TextureCompression', 'Using compressed alternative ' + ImageUrl);
    end;
  end;
end;

initialization
  AddLoadImageListener(@TTextureUtils(nil).GPUTextureAlternative);
finalization
  RemoveLoadImageListener(@GPUTextureAlternative);
end.

procedure RemoveLoadImageListener(const Event: TLoadImageEvent);

Remove listener added by AddLoadImageListener.

function ProcessImageUrl(const URL: string): string;

Process URL through events registered by AddLoadImageListener. This is used internally by the engine.

Types

TAutoAlphaChannel = (...);

How is the alpha channel of an image treated.

Values
  • acAuto
  • acNone
  • acTest
  • acBlending
TAlphaChannel = acNone .. acBlending;

See TCastleImage.AlphaChannel.

TResizeInterpolation = (...);

Resize interpolation modes, see TCastleImage.Resize and TCastleImage.MakeResized.

Values
  • riNearest: Fastest interpolation mode.
  • riBilinear: Bilinear interpolation mode, quite fast.
  • riMitchel: Slower but prettier interpolation modes. All the following interpolation modes are slower, not only because their equations are more complicated (and using more inputs), but also because their current implementation involves round-trip to FpImage format. Use these if speed is not a concern, but quality is crucial.
  • riBlackman
  • riBlackmanSinc
  • riBlackmanBessel
  • riGaussian
  • riHermite
  • riLanczos
  • riQuadratic
  • riCubic
  • riCatrom
  • riHanning
  • riHamming
TResizeInterpolationInternal = Low(TResizeInterpolation) .. riBilinear;
 
TResizeInterpolationFpImage = Succ(riBilinear) .. High(TResizeInterpolation);
 
TDrawMode = (...);

Drawing mode used by image-on-image drawing methods (TCastleImage.DrawFrom and TCastleImage.DrawTo).

Values
  • dmBlend: Normal drawing mode, where the image contents are blended using the opacity (alpha) of the source image. That is,

    destination.rgb := destination.rgb * (1 - source.alpha) + source.rgb * source.alpha;
    destination.alpha := destination.alpha; // never changed by this drawing mode

    An image type without alpha (like TRGBImage or TGrayscaleImage) is always treated like it has alpha = 1.0 (fully opaque) everywhere. In particular, this means that when drawing an image without alpha over any other image, source RGB contents will simply replace the destination RGB contents.

  • dmBlendSmart: An advanced blending mode, capable of blending 2 images with alpha channel better than dmBlend. Based on https://en.wikipedia.org/wiki/Alpha_compositing formula for alpha-blending. This one is much less efficient than dmBlend and should be used only in case several layers of semi-transparent images should overlay one another and it matters to accurately account for both images alpha channel. Implemented for all TRGBAlphaImage and TGrayscaleAlphaImage combinations.
  • dmMultiply: Multiply two images. Simply multiply source with destination, channel by channel:

    destination.rgba := destination.rgba * source.rgba;

    The exception is when the source image has alpha channel, but destination does not. For example, when source is TRGBAlphaImage or TGrayscaleAlphaImage and destination is TRGBImage or TGrayscaleImage. In this case the multiplication is followed by a simple blending, to apply the effects of source alpha:

    destination.rgb :=
      source.rgb * destination.rgb * source.alpha +
                   destination.rgb * (1 - source.alpha);

    Note that if source.alpha = 1 (source is opaque) that this is equivalent to the previous simple multiply equation.

  • dmOverwrite: Overwrite drawing mode, where the image contents of destination image is replaced with contents of source image. That is,

    destination.rgba := source.rgba;

  • dmAdd: Additive drawing mode, where the image contents of source image are added to the existing destination image. That is,

    destination.rgb := destination.rgb + source.rgb * source.alpha;
    destination.alpha := destination.alpha; // never changed by this drawing mode

    So when drawing an image with alpha over an image without alpha, the colors will be added according to the above equation, only source is multiplied by alpha. To speed this operation, one can use TRGBAlphaImage.PremultiplyAlpha on the source image first, very useful if you plan to draw the same source image many times.

TCastleImageList = specialize TObjectList<TCastleImage>;
 
TEncodedImageList = specialize TObjectList<TEncodedImage>;
 
TTextureCompression = (...);

Possible compression of textures for GPU. The compressed texture formats may be automatically created for you by CGE, see https://castle-engine.io/creating_data_auto_generated_textures.php .

Values
  • tcDxt1_RGB: S3TC DXT1 compression, for opaque RGB images (no alpha channel). This compression format is often supported by desktop OpenGL implementations. See http://en.wikipedia.org/wiki/S3_Texture_Compression about S3TC. It is also supported by a small number of Android devices.

    Note that the tcDxt1_RGB and tcDxt1_RGBA are the same compression method. Their behavior only differs when rendering: in case of tcDxt1_RGB, the alpha information is not used, while in case of tcDxt1_RGBA, the renderer is using alpha-testing.

  • tcDxt1_RGBA: S3TC DXT1 compression, for RGBA images with simple yes/no alpha channel. The renderer will use alpha-testing when rendering such images. See above tcDxt1_RGB description for details.
  • tcDxt3: S3TC DXT3 compression, for RGBA images with full alpha channel, best for images with sharp alpha transitions. This compression format is often supported by desktop OpenGL implementations. See http://en.wikipedia.org/wiki/S3_Texture_Compression about S3TC.
  • tcDxt5: S3TC DXT5 compression, for RGBA images with full alpha channel, best for images with smooth alpha transitions. This compression format is often supported by desktop OpenGL implementations. See http://en.wikipedia.org/wiki/S3_Texture_Compression about S3TC.
  • tcPvrtc1_4bpp_RGB: PowerVR texture compression (PVRTC) format. Supported by some Android and iOS devices, using PowerVR GPU by Imagination Technologies. See http://en.wikipedia.org/wiki/PVRTC .
  • tcPvrtc1_2bpp_RGB
  • tcPvrtc1_4bpp_RGBA
  • tcPvrtc1_2bpp_RGBA
  • tcPvrtc2_4bpp
  • tcPvrtc2_2bpp
  • tcATITC_RGB: ATI texture compression format, for RGB images without alpha. Supported by some Android devices (Adreno GPU from Qualcomm).
  • tcATITC_RGBA_ExplicitAlpha: ATI texture compression format, with sharp alpha. Supported by some Android devices (Adreno GPU from Qualcomm).
  • tcATITC_RGBA_InterpolatedAlpha: ATI texture compression format, with smooth alpha. Supported by some Android devices (Adreno GPU from Qualcomm).
  • tcETC1: ETC texture compression, without alpha. See http://en.wikipedia.org/wiki/Ericsson_Texture_Compression . Available on almost all Android OpenGLES 2.0 devices, unfortunately it doesn't support alpha channel.
  • tcASTC_4x4_RGBA: ASTC compression with alpha - should be available on all modern mobile GPU. See https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_texture_compression_astc_hdr.txt
  • tcASTC_5x4_RGBA
  • tcASTC_5x5_RGBA
  • tcASTC_6x5_RGBA
  • tcASTC_6x6_RGBA
  • tcASTC_8x5_RGBA
  • tcASTC_8x6_RGBA
  • tcASTC_8x8_RGBA
  • tcASTC_10x5_RGBA
  • tcASTC_10x6_RGBA
  • tcASTC_10x8_RGBA
  • tcASTC_10x10_RGBA
  • tcASTC_12x10_RGBA
  • tcASTC_12x12_RGBA
  • tcASTC_4x4_SRGB8_ALPHA8
  • tcASTC_5x4_SRGB8_ALPHA8
  • tcASTC_5x5_SRGB8_ALPHA8
  • tcASTC_6x5_SRGB8_ALPHA8
  • tcASTC_6x6_SRGB8_ALPHA8
  • tcASTC_8x5_SRGB8_ALPHA8
  • tcASTC_8x6_SRGB8_ALPHA8
  • tcASTC_8x8_SRGB8_ALPHA8
  • tcASTC_10x5_SRGB8_ALPHA8
  • tcASTC_10x6_SRGB8_ALPHA8
  • tcASTC_10x8_SRGB8_ALPHA8
  • tcASTC_10x10_SRGB8_ALPHA8
  • tcASTC_12x10_SRGB8_ALPHA8
  • tcASTC_12x12_SRGB8_ALPHA8
TTextureCompressions = set of TTextureCompression;
 
TS3TCImage = TGPUCompressedImage deprecated;

Warning: this symbol is deprecated.

Deprecated alias for TGPUCompressedImage

TDecompressTextureFunction = function (Image: TGPUCompressedImage): TCastleImage;
 
TCastleImageClass = class of TCastleImage;
 
TEncodedImageClass = class of TEncodedImage;
 
TLoadImageOption = (...);
 
Values
  • liFlipVertically
TLoadImageOptions = set of TLoadImageOption;
 
TLoadImageEvent = procedure (var ImageUrl: string) of object;

Listener type for AddLoadImageListener.

Constants

acSimpleYesNo = acBlending deprecated 'use acTest';

Warning: this symbol is deprecated: use acTest

 
acFullRange = acBlending deprecated 'use acBlending';

Warning: this symbol is deprecated: use acBlending

 
DefaultAlphaTolerance = 5;

Default parameters for TEncodedImage.AlphaChannel, decide how to detect textures alpha channel.

AlphaToString: array [TAutoAlphaChannel] of string = ('AUTO', 'NONE', 'TEST', 'BLENDING');
 
TextureCompressionInfo: array [TTextureCompression] of TTextureCompressionInfo = ( (Name: 'DXT1_RGB' ; RequiresPowerOf2: false; AlphaChannel: acNone ; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT1_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acTest ; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT3' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: false; FileExtension: '.dds'), (Name: 'DXT5' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: false; FileExtension: '.dds'), (Name: 'PVRTC1_4bpp_RGB' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_2bpp_RGB' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_4bpp_RGBA' ; RequiresPowerOf2: true ; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC1_2bpp_RGBA' ; RequiresPowerOf2: true ; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC2_4bpp' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'PVRTC2_2bpp' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGB' ; RequiresPowerOf2: false; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGBA_ExplicitAlpha' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ATITC_RGBA_InterpolatedAlpha'; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.dds'), (Name: 'ETC1' ; RequiresPowerOf2: true ; AlphaChannel: acNone ; DDSFlipped: true; FileExtension: '.ktx'), (Name: 'ASTC_4x4_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x4_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x8_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x5_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x6_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x8_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x10_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x10_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x12_RGBA' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_4x4_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x4_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_5x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_6x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_8x8_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x5_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x6_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x8_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_10x10_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x10_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ), (Name: 'ASTC_12x12_SRGB8_ALPHA8' ; RequiresPowerOf2: false; AlphaChannel: acBlending; DDSFlipped: true; FileExtension: '.ktx' ) );
 

Variables

DecompressTexture: TDecompressTextureFunction;

Assign here texture decompression function that is available. This way the "decompressor" is pluggable, which means that you can even use OpenGL to decompress textures, if you're going to load images while some OpenGL context is active.

LoadImage_FileFilters: TFileFilterList;

File filters if you want to choose a file that can be loaded/saved by appropriate functions from Images unit.

These objects should be treated as read-only outside this unit. Initialization / finalization of this unit automatically take care of them.

SaveImage_FileFilters: TFileFilterList;
 
SupportedTextureCompressionKnown: boolean;

Is the value of SupportedTextureCompression determined by the renderer (like OpenGL context) parameters.

SupportedTextureCompression: TTextureCompressions;

Which texture compression values are supported by the renderer (like OpenGL context).


Generated by PasDoc 0.16.0.