Quellcode durchsuchen

Third approach.

Keep TBitmapImage using TBitmap only (so no use of pngimage or WIC stuff there) but convert any TPngImage to TBitmap when assigning it to the TBitmapImage using a single simple Assign call in TBitmapImageImplementation.SetGraphic.

Setup uses pngimage in Setup.MainFunc to load any PNG, but no WIC stuff. ISCmplr has no extra uses at all. So no extra run-time dependencies.

Also means run-time support for PNG. (Did not yet add stuff to make it visible to [Code].)

The builtin images are now PNG so Compil32 actually decreased in size.

The only downside is the extra size of pngimage code in Setup but thats only a few kb which is well worth having PNG support. Not only is PNG support by many more tools, also it has no annoying AlphaFormat to set.

Using TBitmapImage or TBitmapButton design-time doesnt really work for transparent images because both AlphaFormat and Graphic are missing in the list of published properties. Not sure how to fix, but also doesnt matter for us.
Martijn Laan vor 3 Wochen
Ursprung
Commit
4c783a234e

+ 9 - 0
Components/BitmapButton.pas

@@ -9,6 +9,8 @@ unit BitmapButton;
   A TImage-like component for bitmaps without the TPicture bloat and
   A TImage-like component for bitmaps without the TPicture bloat and
   which is actually a button with a focus rectangle when focused - in
   which is actually a button with a focus rectangle when focused - in
   other words: an accessible TImage
   other words: an accessible TImage
+
+  Also supports other TGraphic types which can be assigned to a TBitmap, like TPngImage
   
   
   Make sure to set the Caption property, even if it isn't visible
   Make sure to set the Caption property, even if it isn't visible
 
 
@@ -29,6 +31,7 @@ type
     procedure SetBackColor(Value: TColor);
     procedure SetBackColor(Value: TColor);
     procedure SetBitmap(Value: TBitmap);
     procedure SetBitmap(Value: TBitmap);
     procedure SetCenter(Value: Boolean);
     procedure SetCenter(Value: Boolean);
+    procedure SetGraphic(Value: TGraphic);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetStretch(Value: Boolean);
     procedure SetStretch(Value: Boolean);
@@ -44,6 +47,7 @@ type
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     destructor Destroy; override;
     function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
     function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
+    property Graphic: TGraphic write SetGraphic;
   published
   published
     property Align;
     property Align;
     property Anchors;
     property Anchors;
@@ -128,6 +132,11 @@ begin
   FImpl.SetCenter(Self, Value);
   FImpl.SetCenter(Self, Value);
 end;
 end;
 
 
+procedure TBitmapButton.SetGraphic(Value: TGraphic);
+begin
+  FImpl.SetGraphic(Value);
+end;
+
 procedure TBitmapButton.SetReplaceColor(Value: TColor);
 procedure TBitmapButton.SetReplaceColor(Value: TColor);
 begin
 begin
   FImpl.SetReplaceColor(Self, Value);
   FImpl.SetReplaceColor(Self, Value);

+ 16 - 1
Components/BitmapImage.pas

@@ -7,6 +7,8 @@ unit BitmapImage;
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
   A TImage-like component for bitmaps without the TPicture bloat
   A TImage-like component for bitmaps without the TPicture bloat
+  
+  Also supports other TGraphic types which can be assigned to a TBitmap, like TPngImage
 
 
   Also see TBitmapButton which is the TWinControl version
   Also see TBitmapButton which is the TWinControl version
 }
 }
@@ -43,6 +45,7 @@ type
     procedure SetBackColor(Sender: TObject; Value: TColor);
     procedure SetBackColor(Sender: TObject; Value: TColor);
     procedure SetBitmap(Value: TBitmap);
     procedure SetBitmap(Value: TBitmap);
     procedure SetCenter(Sender: TObject; Value: Boolean);
     procedure SetCenter(Sender: TObject; Value: Boolean);
+    procedure SetGraphic(Value: TGraphic);
     procedure SetReplaceColor(Sender: TObject; Value: TColor);
     procedure SetReplaceColor(Sender: TObject; Value: TColor);
     procedure SetReplaceWithColor(Sender: TObject; Value: TColor);
     procedure SetReplaceWithColor(Sender: TObject; Value: TColor);
     procedure SetStretch(Sender: TObject; Value: Boolean);
     procedure SetStretch(Sender: TObject; Value: Boolean);
@@ -56,6 +59,7 @@ type
     procedure SetBackColor(Value: TColor);
     procedure SetBackColor(Value: TColor);
     procedure SetBitmap(Value: TBitmap);
     procedure SetBitmap(Value: TBitmap);
     procedure SetCenter(Value: Boolean);
     procedure SetCenter(Value: Boolean);
+    procedure SetGraphic(Value: TGraphic);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetReplaceWithColor(Value: TColor);
     procedure SetStretch(Value: Boolean);
     procedure SetStretch(Value: Boolean);
@@ -67,17 +71,18 @@ type
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     destructor Destroy; override;
     function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
     function InitializeFromIcon(const Instance: HINST; const Name: PChar; const BkColor: TColor; const AscendingTrySizes: array of Integer): Boolean;
+    property Graphic: TGraphic write SetGraphic;
   published
   published
     property Align;
     property Align;
     property Anchors;
     property Anchors;
     property AutoSize: Boolean read FImpl.AutoSize write SetAutoSize default False;
     property AutoSize: Boolean read FImpl.AutoSize write SetAutoSize default False;
     property BackColor: TColor read FImpl.BackColor write SetBackColor default clBtnFace;
     property BackColor: TColor read FImpl.BackColor write SetBackColor default clBtnFace;
+    property Bitmap: TBitmap read FImpl.Bitmap write SetBitmap;
     property Center: Boolean read FImpl.Center write SetCenter default False;
     property Center: Boolean read FImpl.Center write SetCenter default False;
     property DragCursor;
     property DragCursor;
     property DragMode;
     property DragMode;
     property Enabled;
     property Enabled;
     property ParentShowHint;
     property ParentShowHint;
-    property Bitmap: TBitmap read FImpl.Bitmap write SetBitmap;
     property PopupMenu;
     property PopupMenu;
     property ShowHint;
     property ShowHint;
     property Stretch: Boolean read FImpl.Stretch write SetStretch default False;
     property Stretch: Boolean read FImpl.Stretch write SetStretch default False;
@@ -209,6 +214,11 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TBitmapImageImplementation.SetGraphic(Value: TGraphic);
+begin
+  Bitmap.Assign(Value);
+end;
+
 procedure TBitmapImageImplementation.SetReplaceColor(Sender: TObject; Value: TColor);
 procedure TBitmapImageImplementation.SetReplaceColor(Sender: TObject; Value: TColor);
 begin
 begin
   if ReplaceColor <> Value then begin
   if ReplaceColor <> Value then begin
@@ -351,6 +361,11 @@ begin
   FImpl.SetCenter(Self, Value);
   FImpl.SetCenter(Self, Value);
 end;
 end;
 
 
+procedure TBitmapImage.SetGraphic(Value: TGraphic);
+begin
+  FImpl.SetGraphic(Value);
+end;
+
 procedure TBitmapImage.SetReplaceColor(Value: TColor);
 procedure TBitmapImage.SetReplaceColor(Value: TColor);
 begin
 begin
   FImpl.SetReplaceColor(Self, Value);
   FImpl.SetReplaceColor(Self, Value);

+ 14 - 14
ISHelp/isetup.xml

@@ -5456,10 +5456,10 @@ DiskSliceSize=736000000
 <setuptopic directive="WizardImageFile">
 <setuptopic directive="WizardImageFile">
 <setupdefault><i>(blank)</i></setupdefault>
 <setupdefault><i>(blank)</i></setupdefault>
 <body>
 <body>
-<p>Specifies the name(s) of the bitmap file(s) to display on the left side of the <i>Welcome</i> and <i>Setup Completed</i> wizard pages. Wildcards are supported and the files(s) must be located in your installation's <link topic="sourcedirectorynotes">source directory</link> when running the compiler, unless a fully qualified pathname is specified or the pathname is prefixed by "compiler:", in which case it looks for the file in the compiler directory.</p>
-<p>Supports transparent bitmaps, see <link topic="setup_wizardimagealphaformat">WizardImageAlphaFormat</link> for more information.</p>
-<p>The size of the area in which the image is displayed depends on the system's DPI setting and whether the default <link topic="langoptionssection">font settings</link> are being used. At standard DPI with the default font settings, the size of the area is 164x314 pixels. At 200% DPI, the width and height will be roughly double that. In all cases, an aspect ratio of 164:314 is maintained. The specified bitmap should have the same aspect ratio.</p>
-<p>Any size of bitmap may be used; by default, bitmaps that are too small or too large to fit in the image area will be stretched or shrunk. Specifying a bitmap larger than 164x314 is recommended to avoid the image looking blurry on higher-DPI systems. The size of the default built-in image is 240x459.</p>
+<p>Specifies the name(s) of the image file(s) to display on the left side of the <i>Welcome</i> and <i>Setup Completed</i> wizard pages. Wildcards are supported and the files(s) must be located in your installation's <link topic="sourcedirectorynotes">source directory</link> when running the compiler, unless a fully qualified pathname is specified or the pathname is prefixed by "compiler:", in which case it looks for the file in the compiler directory.</p>
+<p>Supports .bmp and .png images, including those with transparency. Even transparent .bmp files are supported, see <link topic="setup_wizardimagealphaformat">WizardImageAlphaFormat</link> for more information.</p>
+<p>The size of the area in which the image is displayed depends on the system's DPI setting and whether the default <link topic="langoptionssection">font settings</link> are being used. At standard DPI with the default font settings, the size of the area is 164x314 pixels. At 200% DPI, the width and height will be roughly double that. In all cases, an aspect ratio of 164:314 is maintained. The specified image should have the same aspect ratio.</p>
+<p>Any size of image may be used; by default, images that are too small or too large to fit in the image area will be stretched or shrunk. Specifying an image larger than 164x314 is recommended to avoid the image looking blurry on higher-DPI systems. The size of the default built-in image is 240x459.</p>
 <p>If a single larger-sized image does not produce a satisfactory result across different DPI settings, multiple files may be specified, separated by commas. In that case, Setup will automatically select the one that best matches the size of the image area. Assuming the default font settings are being used, the size of the image area at various DPI settings is:</p>
 <p>If a single larger-sized image does not produce a satisfactory result across different DPI settings, multiple files may be specified, separated by commas. In that case, Setup will automatically select the one that best matches the size of the image area. Assuming the default font settings are being used, the size of the image area at various DPI settings is:</p>
 <table>
 <table>
 <tr><td>100%</td><td>164x314</td></tr>
 <tr><td>100%</td><td>164x314</td></tr>
@@ -5484,10 +5484,10 @@ DiskSliceSize=736000000
 <setuptopic directive="WizardSmallImageFile">
 <setuptopic directive="WizardSmallImageFile">
 <setupdefault><i>(blank)</i></setupdefault>
 <setupdefault><i>(blank)</i></setupdefault>
 <body>
 <body>
-<p>Specifies the name(s) of the bitmap file(s) to display in the upper right corner of the wizard. Wildcards are supported and the file(s) must be located in your installation's <link topic="sourcedirectorynotes">source directory</link> when running the compiler, unless a fully qualified pathname is specified or the pathname is prefixed by "compiler:", in which case it looks for the file in the compiler directory.</p>
-<p>Supports transparent bitmaps, see <link topic="setup_wizardimagealphaformat">WizardImageAlphaFormat</link> for more information.</p>
-<p>The size of the area in which the image is displayed depends on the system's DPI setting and whether the default <link topic="langoptionssection">font settings</link> are being used. At standard DPI with the default font settings, the size of the area is 58x58 pixels. At 200% DPI, the width and height will be roughly double that. In all cases, the area is square; thus, the specified bitmap should be square as well.</p>
-<p>Any size of bitmap may be used; by default, bitmaps that are too small or too large to fit in the image area will be stretched or shrunk. Specifying a bitmap larger than 58x58 is recommended to avoid the image looking blurry on higher-DPI systems. The size of the default built-in image is 147x147.</p>
+<p>Specifies the name(s) of the image file(s) to display in the upper right corner of the wizard. Wildcards are supported and the file(s) must be located in your installation's <link topic="sourcedirectorynotes">source directory</link> when running the compiler, unless a fully qualified pathname is specified or the pathname is prefixed by "compiler:", in which case it looks for the file in the compiler directory.</p>
+<p>Supports .bmp and .png images, including those with transparency. Even transparent .bmp files are supported, see <link topic="setup_wizardimagealphaformat">WizardImageAlphaFormat</link> for more information.</p>
+<p>The size of the area in which the image is displayed depends on the system's DPI setting and whether the default <link topic="langoptionssection">font settings</link> are being used. At standard DPI with the default font settings, the size of the area is 58x58 pixels. At 200% DPI, the width and height will be roughly double that. In all cases, the area is square; thus, the specified image should be square as well.</p>
+<p>Any size of image may be used; by default, images that are too small or too large to fit in the image area will be stretched or shrunk. Specifying an image larger than 58x58 is recommended to avoid the image looking blurry on higher-DPI systems. The size of the default built-in image is 147x147.</p>
 <p>If a single larger-sized image does not produce a satisfactory result across different DPI settings, multiple files may be specified, separated by commas. In that case, Setup will automatically select the one that best matches the size of the image area. Assuming the default font settings are being used, the size of the image area at various DPI settings is:</p>
 <p>If a single larger-sized image does not produce a satisfactory result across different DPI settings, multiple files may be specified, separated by commas. In that case, Setup will automatically select the one that best matches the size of the image area. Assuming the default font settings are being used, the size of the image area at various DPI settings is:</p>
 <table>
 <table>
 <tr><td>100%</td><td>58x58</td></tr>
 <tr><td>100%</td><td>58x58</td></tr>
@@ -5499,7 +5499,7 @@ DiskSliceSize=736000000
 <tr><td>250%</td><td>147x147</td></tr>
 <tr><td>250%</td><td>147x147</td></tr>
 </table>
 </table>
 <p>(You may notice that the size at 200% is not exactly double the 100% size. This is because the scaling factor is based on the dimensions of the font that a DPI setting uses, not the DPI itself.)</p>
 <p>(You may notice that the size at 200% is not exactly double the 100% size. This is because the scaling factor is based on the dimensions of the font that a DPI setting uses, not the DPI itself.)</p>
-<p>Backward compatibility note: If a single bitmap smaller than 58x58 is specified, the bitmap will not be stretched to fill the entire image area; instead, it will be centered.</p>
+<p>Backward compatibility note: If a single image smaller than 58x58 is specified, the image will not be stretched to fill the entire image area; instead, it will be centered.</p>
 <p>If this directive is not specified or is blank, a single built-in 147x147 wizard image will be used, by default stretched or shrunk if the image is larger or smaller than required.</p>
 <p>If this directive is not specified or is blank, a single built-in 147x147 wizard image will be used, by default stretched or shrunk if the image is larger or smaller than required.</p>
 <p>To use the old default wizard images set this directive to <tt>compiler:WizClassicSmallImage.bmp</tt>.</p>
 <p>To use the old default wizard images set this directive to <tt>compiler:WizClassicSmallImage.bmp</tt>.</p>
 <example><pre>WizardSmallImageFile=mysmallimage.bmp,mysmallimage2.bmp</pre></example>
 <example><pre>WizardSmallImageFile=mysmallimage.bmp,mysmallimage2.bmp</pre></example>
@@ -5527,11 +5527,11 @@ DiskSliceSize=736000000
 <setupvalid><tt>none</tt>, <tt>defined</tt>, <tt>premultiplied</tt></setupvalid>
 <setupvalid><tt>none</tt>, <tt>defined</tt>, <tt>premultiplied</tt></setupvalid>
 <setupdefault><tt>none</tt></setupdefault>
 <setupdefault><tt>none</tt></setupdefault>
 <body>
 <body>
-<p>If set to <tt>none</tt>, the default, any wizard image which is a 32-bit bitmap file should not have an alpha channel.</p>
-<p>If set to <tt>premultiplied</tt>, any wizard image which is a 32-bit bitmap file should have its red, green and blue channel values premultiplied with the alpha channel value.</p>
-<p>If set to <tt>defined</tt>, any wizard image which is a 32-bit bitmap file should not have its red, green and blue channel values premultiplied with the alpha channel value.</p>
-<p>This directive has no effect for a wizard image which is not a 32-bit bitmap file.</p>
-<p>To create transparent 32-bit bitmaps compatible with Inno Setup, you can use Paint.NET, a free image editor. Open your transparent image in Paint.NET, save it as a 32-bit .bmp file, and then set this directive to <tt>defined</tt>. These files may appear large, but Inno Setup compresses them using LZMA, which typically achieves better compression ratios than, for example, PNG compression.</p>
+<p>If set to <tt>none</tt>, the default, any wizard image which is a 32-bit .bmp file should not have an alpha channel.</p>
+<p>If set to <tt>premultiplied</tt>, any wizard image which is a 32-bit .bmp file should have its red, green and blue channel values premultiplied with the alpha channel value.</p>
+<p>If set to <tt>defined</tt>, any wizard image which is a 32-bit .bmp file should not have its red, green and blue channel values premultiplied with the alpha channel value.</p>
+<p>This directive has no effect for a wizard image which is not a 32-bit .bmp file.</p>
+<p>To create transparent .bmp files compatible with Inno Setup, you can use Paint.NET, a free image editor. Open your transparent image in Paint.NET, save it as a 32-bit .bmp file, and then set this directive to <tt>defined</tt>. These files may appear large, but Inno Setup compresses them using LZMA, which typically achieves better compression ratios than, for example, PNG compression.</p>
 <p><b>See also:</b><br/>
 <p><b>See also:</b><br/>
 <link topic="setup_wizardimagefile">WizardImageFile</link><br/>
 <link topic="setup_wizardimagefile">WizardImageFile</link><br/>
 <link topic="setup_wizardsmallimagefile">WizardSmallImageFile</link></p>
 <link topic="setup_wizardsmallimagefile">WizardSmallImageFile</link></p>

BIN
Projects/Res/ISCmplr.images.res


+ 54 - 18
Projects/Src/Compiler.SetupCompiler.pas

@@ -65,6 +65,15 @@ type
   TPrecompiledFile = (pfSetupE32, pfSetupLdrE32, pfIs7zDll, pfIsbunzipDll, pfIsunzlibDll, pfIslzmaExe);
   TPrecompiledFile = (pfSetupE32, pfSetupLdrE32, pfIs7zDll, pfIsbunzipDll, pfIsunzlibDll, pfIslzmaExe);
   TPrecompiledFiles = set of TPrecompiledFile;
   TPrecompiledFiles = set of TPrecompiledFile;
 
 
+  TWizardImage = class
+    Stream: TCustomMemoryStream;
+    Format: TWizardImageGraphicFormat;
+    constructor Create(const AStream: TCustomMemoryStream; const AFormat: TWizardImageGraphicFormat);
+    destructor Destroy; override;
+  end;
+
+  TWizardImages = TObjectList<TWizardImage>;
+
   TSetupCompiler = class
   TSetupCompiler = class
   private
   private
     ScriptFiles: TStringList;
     ScriptFiles: TStringList;
@@ -261,8 +270,8 @@ type
     procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer; StepOutMarker: Boolean = False);
     procedure WriteDebugEntry(Kind: TDebugEntryKind; Index: Integer; StepOutMarker: Boolean = False);
     procedure WriteCompiledCodeText(const CompiledCodeText: Ansistring);
     procedure WriteCompiledCodeText(const CompiledCodeText: Ansistring);
     procedure WriteCompiledCodeDebugInfo(const CompiledCodeDebugInfo: AnsiString);
     procedure WriteCompiledCodeDebugInfo(const CompiledCodeDebugInfo: AnsiString);
-    function CreateMemoryStreamsFromFiles(const ADirectiveName, AFiles: String): TObjectList<TCustomMemoryStream>;
-    function CreateMemoryStreamsFromResources(const AResourceNamesPrefixes, AResourceNamesPostfixes: array of String): TObjectList<TCustomMemoryStream>;
+    function CreateWizardImagesFromFiles(const ADirectiveName, AFiles: String): TWizardImages;
+    function CreateWizardImagesFromResources(const AResourceNamesPrefixes, AResourceNamesPostfixes: array of String): TWizardImages;
     procedure VerificationError(const AError: TVerificationError;
     procedure VerificationError(const AError: TVerificationError;
       const AFilename: String; const ASigFilename: String = '');
       const AFilename: String; const ASigFilename: String = '');
   public
   public
@@ -378,6 +387,21 @@ begin
   Result := False;
   Result := False;
 end;
 end;
 
 
+{ TWizardImage }
+
+constructor TWizardImage.Create(const AStream: TCustomMemoryStream; const AFormat: TWizardImageGraphicFormat);
+begin
+  inherited Create;
+  Stream := AStream;
+  Format := AFormat;
+end;
+
+destructor TWizardImage.Destroy;
+begin
+  Stream.Free;
+  inherited;
+end;
+
 { TSetupCompiler }
 { TSetupCompiler }
 
 
 constructor TSetupCompiler.Create(AOwner: TComponent);
 constructor TSetupCompiler.Create(AOwner: TComponent);
@@ -475,12 +499,14 @@ begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
-function TSetupCompiler.CreateMemoryStreamsFromFiles(const ADirectiveName, AFiles: String): TObjectList<TCustomMemoryStream>;
+function TSetupCompiler.CreateWizardImagesFromFiles(const ADirectiveName, AFiles: String): TWizardImages;
 
 
   procedure AddFile(const Filename: String);
   procedure AddFile(const Filename: String);
+  const
+    Formats: array [Boolean] of TWizardImageGraphicFormat = (gfBitmap, gfPng);
   begin
   begin
     AddStatus(Format(SCompilerStatusReadingInFile, [FileName]));
     AddStatus(Format(SCompilerStatusReadingInFile, [FileName]));
-    Result.Add(CreateMemoryStreamFromFile(FileName));
+    Result.Add(TWizardImage.Create(CreateMemoryStreamFromFile(FileName),  Formats[SameText(PathExtractExt(Filename), '.png')]));
   end;
   end;
 
 
 var
 var
@@ -490,7 +516,7 @@ var
   H: THandle;
   H: THandle;
   FindData: TWin32FindData;
   FindData: TWin32FindData;
 begin
 begin
-  Result := TObjectList<TCustomMemoryStream>.Create;
+  Result := TWizardImages.Create;
   try
   try
     { In older versions only one file could be listed and comma's could be used so
     { In older versions only one file could be listed and comma's could be used so
       before treating AFiles as a list, first check if it's actually a single file
       before treating AFiles as a list, first check if it's actually a single file
@@ -532,15 +558,15 @@ begin
   end;
   end;
 end;
 end;
 
 
-function TSetupCompiler.CreateMemoryStreamsFromResources(const AResourceNamesPrefixes, AResourceNamesPostfixes: array of String): TObjectList<TCustomMemoryStream>;
+function TSetupCompiler.CreateWizardImagesFromResources(const AResourceNamesPrefixes, AResourceNamesPostfixes: array of String): TWizardImages;
 var
 var
   I, J: Integer;
   I, J: Integer;
 begin
 begin
-  Result := TObjectList<TCustomMemoryStream>.Create;
+  Result := TWizardImages.Create;
   try
   try
     for I := 0 to Length(AResourceNamesPrefixes)-1 do
     for I := 0 to Length(AResourceNamesPrefixes)-1 do
       for J := 0 to Length(AResourceNamesPostfixes)-1 do
       for J := 0 to Length(AResourceNamesPostfixes)-1 do
-        Result.Add(TResourceStream.Create(HInstance, AResourceNamesPrefixes[I]+AResourceNamesPostfixes[J], RT_RCDATA));
+        Result.Add(TWizardImage.Create(TResourceStream.Create(HInstance, AResourceNamesPrefixes[I]+AResourceNamesPostfixes[J], RT_RCDATA), gfPng));
   except
   except
     Result.Free;
     Result.Free;
     raise;
     raise;
@@ -6860,14 +6886,14 @@ var
   SetupFile: TFile;
   SetupFile: TFile;
   ExeFile: TFile;
   ExeFile: TFile;
   LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
   LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
-  WizardImages, WizardSmallImages: TObjectList<TCustomMemoryStream>;
+  WizardImages, WizardSmallImages: TWizardImages;
   DecompressorDLL, SevenZipDLL: TMemoryStream;
   DecompressorDLL, SevenZipDLL: TMemoryStream;
 
 
   SizeOfExe, SizeOfHeaders: Int64;
   SizeOfExe, SizeOfHeaders: Int64;
 
 
   function WriteSetup0(const F: TFile): Int64;
   function WriteSetup0(const F: TFile): Int64;
 
 
-    procedure WriteStream(Stream: TCustomMemoryStream; W: TCompressedBlockWriter);
+    procedure WriteStream(const Stream: TCustomMemoryStream; const W: TCompressedBlockWriter);
     var
     var
       Size: Longint;
       Size: Longint;
     begin
     begin
@@ -6876,6 +6902,12 @@ var
       W.Write(Stream.Memory^, Size);
       W.Write(Stream.Memory^, Size);
     end;
     end;
 
 
+    procedure WriteWizardImage(const WizardImage: TWizardImage; const W: TCompressedBlockWriter);
+    begin
+      W.Write(WizardImage.Format, SizeOf(TWizardImageGraphicFormat));
+      WriteStream(WizardImage.Stream, W);
+    end;
+
   var
   var
     J: Integer;
     J: Integer;
     W: TCompressedBlockWriter;
     W: TCompressedBlockWriter;
@@ -6970,10 +7002,10 @@ var
 
 
       W.Write(WizardImages.Count, SizeOf(Integer));
       W.Write(WizardImages.Count, SizeOf(Integer));
       for J := 0 to WizardImages.Count-1 do
       for J := 0 to WizardImages.Count-1 do
-        WriteStream(WizardImages[J], W);
+        WriteWizardImage(WizardImages[J], W);
       W.Write(WizardSmallImages.Count, SizeOf(Integer));
       W.Write(WizardSmallImages.Count, SizeOf(Integer));
       for J := 0 to WizardSmallImages.Count-1 do
       for J := 0 to WizardSmallImages.Count-1 do
-        WriteStream(WizardSmallImages[J], W);
+        WriteWizardImage(WizardSmallImages[J], W);
       if SetupHeader.CompressMethod in [cmZip, cmBzip] then
       if SetupHeader.CompressMethod in [cmZip, cmBzip] then
         WriteStream(DecompressorDLL, W);
         WriteStream(DecompressorDLL, W);
       if SetupHeader.SevenZipLibraryName <> '' then
       if SetupHeader.SevenZipLibraryName <> '' then
@@ -7995,9 +8027,11 @@ begin
         WarningsList.Add(Format(SCompilerWizImageRenamed, [WizardImageFile, 'compiler:WizClassicImage.bmp']));
         WarningsList.Add(Format(SCompilerWizImageRenamed, [WizardImageFile, 'compiler:WizClassicImage.bmp']));
         WizardImageFile := 'compiler:WizClassicImage.bmp';
         WizardImageFile := 'compiler:WizClassicImage.bmp';
       end;
       end;
-      WizardImages := CreateMemoryStreamsFromFiles('WizardImageFile', WizardImageFile)
-    end else
-      WizardImages := CreateMemoryStreamsFromResources(['WizardImage'], ['150']);
+      WizardImages := CreateWizardImagesFromFiles('WizardImageFile', WizardImageFile)
+    end else begin
+      WizardImages := CreateWizardImagesFromResources(['WizardImage'], ['150']);
+      Include(SetupHeader.Options, shUsesBuiltinWizardImages);
+    end;
     LineNumber := SetupDirectiveLines[ssWizardSmallImageFile];
     LineNumber := SetupDirectiveLines[ssWizardSmallImageFile];
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardSmallImageFile']));
     AddStatus(Format(SCompilerStatusReadingFile, ['WizardSmallImageFile']));
     if WizardSmallImageFile <> '' then begin
     if WizardSmallImageFile <> '' then begin
@@ -8005,9 +8039,11 @@ begin
         WarningsList.Add(Format(SCompilerWizImageRenamed, [WizardSmallImageFile, 'compiler:WizClassicSmallImage.bmp']));
         WarningsList.Add(Format(SCompilerWizImageRenamed, [WizardSmallImageFile, 'compiler:WizClassicSmallImage.bmp']));
         WizardSmallImageFile := 'compiler:WizClassicSmallImage.bmp';
         WizardSmallImageFile := 'compiler:WizClassicSmallImage.bmp';
       end;
       end;
-      WizardSmallImages := CreateMemoryStreamsFromFiles('WizardSmallImage', WizardSmallImageFile)
-    end else
-      WizardSmallImages := CreateMemoryStreamsFromResources(['WizardSmallImage'], ['250']);
+      WizardSmallImages := CreateWizardImagesFromFiles('WizardSmallImage', WizardSmallImageFile)
+    end else begin
+      WizardSmallImages := CreateWizardImagesFromResources(['WizardSmallImage'], ['250']);
+      Include(SetupHeader.Options, shUsesBuiltinSmallWizardImages);
+    end;
     LineNumber := 0;
     LineNumber := 0;
 
 
     { Prepare Setup executable & signed uninstaller data }
     { Prepare Setup executable & signed uninstaller data }

+ 17 - 15
Projects/Src/Setup.MainFunc.pas

@@ -12,7 +12,7 @@ unit Setup.MainFunc;
 interface
 interface
 
 
 uses
 uses
-  Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs,
+  Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, Generics.Collections,
   StdCtrls, Shared.Struct, Shared.DebugStruct, Shared.CommonFunc.Vcl, Shared.CommonFunc,
   StdCtrls, Shared.Struct, Shared.DebugStruct, Shared.CommonFunc.Vcl, Shared.CommonFunc,
   Shared.SetupTypes, Setup.ScriptRunner, RestartManager;
   Shared.SetupTypes, Setup.ScriptRunner, RestartManager;
 
 
@@ -25,6 +25,8 @@ type
     sfFonts, sfAppData, sfDocs, sfTemplates,                                  //
     sfFonts, sfAppData, sfDocs, sfTemplates,                                  //
     sfFavorites, sfLocalAppData, sfUserProgramFiles, sfUserCommonFiles, sfUserSavedGames); //these only have user versions
     sfFavorites, sfLocalAppData, sfUserProgramFiles, sfUserCommonFiles, sfUserSavedGames); //these only have user versions
 
 
+  TWizardImages = TObjectList<TGraphic>;
+
 const
 const
   EntryStrings: array[TEntryType] of Integer = (SetupLanguageEntryStrings,
   EntryStrings: array[TEntryType] of Integer = (SetupLanguageEntryStrings,
     SetupCustomMessageEntryStrings, SetupPermissionEntryStrings,
     SetupCustomMessageEntryStrings, SetupPermissionEntryStrings,
@@ -109,8 +111,8 @@ var
   SetupHeader: TSetupHeader;
   SetupHeader: TSetupHeader;
   LangOptions: TSetupLanguageEntry;
   LangOptions: TSetupLanguageEntry;
   Entries: array[TEntryType] of TList;
   Entries: array[TEntryType] of TList;
-  WizardImages: TList;
-  WizardSmallImages: TList;
+  WizardImages: TWizardImages;
+  WizardSmallImages: TWizardImages;
   CloseApplicationsFilterList, CloseApplicationsFilterExcludesList: TStringList;
   CloseApplicationsFilterList, CloseApplicationsFilterExcludesList: TStringList;
   ISSigAvailableKeys: TArrayOfECDSAKey;
   ISSigAvailableKeys: TArrayOfECDSAKey;
 
 
@@ -238,7 +240,7 @@ function IsWindows11: Boolean;
 implementation
 implementation
 
 
 uses
 uses
-  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, ChaCha20, ECDSA, ISSigFunc,
+  ShellAPI, ShlObj, StrUtils, ActiveX, RegStr, Imaging.pngimage, ChaCha20, ECDSA, ISSigFunc,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.DownloadFileFunc, Setup.ExtractFileFunc,
   SetupLdrAndSetup.Messages, Shared.SetupMessageIDs, Setup.DownloadFileFunc, Setup.ExtractFileFunc,
   SetupLdrAndSetup.InstFunc, Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   SetupLdrAndSetup.InstFunc, Setup.InstFunc, SetupLdrAndSetup.RedirFunc, PathFunc,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
   Compression.Base, Compression.Zlib, Compression.bzlib, Compression.LZMADecompressor,
@@ -2636,14 +2638,20 @@ var
     end;
     end;
   end;
   end;
 
 
-  function ReadWizardImage(const Reader: TCompressedBlockReader): TBitmap;
+  function ReadWizardImage(const Reader: TCompressedBlockReader): TGraphic;
   begin
   begin
+    var Format: TWizardImageGraphicFormat;
+    Reader.Read(Format, SizeOf(TWizardImageGraphicFormat));
+
     const MemStream = TMemoryStream.Create;
     const MemStream = TMemoryStream.Create;
     try
     try
       ReadFileIntoStream(Reader, MemStream);
       ReadFileIntoStream(Reader, MemStream);
       MemStream.Seek(0, soFromBeginning);
       MemStream.Seek(0, soFromBeginning);
-      Result := TBitmap.Create;
-      Result.AlphaFormat := TAlphaFormat(SetupHeader.WizardImageAlphaFormat);
+      if Format = gfBitmap then begin
+        Result := TBitmap.Create;
+        TBitmap(Result).AlphaFormat := TAlphaFormat(SetupHeader.WizardImageAlphaFormat);
+      end else
+        Result := TPngImage.Create;
       Result.LoadFromStream(MemStream);
       Result.LoadFromStream(MemStream);
     finally
     finally
       MemStream.Free;
       MemStream.Free;
@@ -3966,14 +3974,8 @@ begin
 end;
 end;
 
 
 procedure FreeWizardImages;
 procedure FreeWizardImages;
-var
-  I: Integer;
 begin
 begin
-  for I := WizardImages.Count-1 downto 0 do
-    TBitmap(WizardImages[I]).Free;
   FreeAndNil(WizardImages);
   FreeAndNil(WizardImages);
-  for I := WizardSmallImages.Count-1 downto 0 do
-    TBitmap(WizardSmallImages[I]).Free;
   FreeAndNil(WizardSmallImages);
   FreeAndNil(WizardSmallImages);
 end;
 end;
 
 
@@ -3992,8 +3994,8 @@ initialization
   DeleteDirsAfterInstallList := TStringList.Create;
   DeleteDirsAfterInstallList := TStringList.Create;
   CloseApplicationsFilterList := TStringList.Create;
   CloseApplicationsFilterList := TStringList.Create;
   CloseApplicationsFilterExcludesList := TStringList.Create;
   CloseApplicationsFilterExcludesList := TStringList.Create;
-  WizardImages := TList.Create;
-  WizardSmallImages := TList.Create;
+  WizardImages := TWizardImages.Create;
+  WizardSmallImages := TWizardImages.Create;
   SHGetKnownFolderPathFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32,
   SHGetKnownFolderPathFunc := GetProcAddress(SafeLoadLibrary(AddBackslash(GetSystemDir) + shell32,
     SEM_NOOPENFILEERRORBOX), 'SHGetKnownFolderPath');
     SEM_NOOPENFILEERRORBOX), 'SHGetKnownFolderPath');
 
 

+ 13 - 6
Projects/Src/Setup.WizardForm.pas

@@ -733,7 +733,7 @@ constructor TWizardForm.Create(AOwner: TComponent);
   using the FormCreate event, because if an exception is raised in FormCreate
   using the FormCreate event, because if an exception is raised in FormCreate
   it's not propagated out. }
   it's not propagated out. }
 
 
-  function SelectBestImage(WizardImages: TList; TargetWidth, TargetHeight: Integer): TBitmap;
+  function SelectBestImage(WizardImages: TWizardImages; TargetWidth, TargetHeight: Integer): TGraphic;
   var
   var
     TargetArea, Difference, SmallestDifference, I: Integer;
     TargetArea, Difference, SmallestDifference, I: Integer;
   begin
   begin
@@ -743,7 +743,7 @@ constructor TWizardForm.Create(AOwner: TComponent);
       SmallestDifference := -1;
       SmallestDifference := -1;
       Result := nil;
       Result := nil;
       for I := 0 to WizardImages.Count-1 do begin
       for I := 0 to WizardImages.Count-1 do begin
-        Difference := Abs(TargetArea-TBitmap(WizardImages[I]).Width*TBitmap(WizardImages[I]).Height);
+        Difference := Abs(TargetArea-WizardImages[I].Width*WizardImages[I].Height);
         if (SmallestDifference = -1) or (Difference < SmallestDifference) then begin
         if (SmallestDifference = -1) or (Difference < SmallestDifference) then begin
           Result := WizardImages[I];
           Result := WizardImages[I];
           SmallestDifference := Difference;
           SmallestDifference := Difference;
@@ -854,8 +854,8 @@ begin
         (such as 55x55 or 32x32) and WizardImageStretch=yes.
         (such as 55x55 or 32x32) and WizardImageStretch=yes.
       - Otherwise, it's unclear what size/shape the user prefers for the
       - Otherwise, it's unclear what size/shape the user prefers for the
         control. Keep the default control size. }
         control. Keep the default control size. }
-    var NewWidth := TBitmap(WizardSmallImages[0]).Width;
-    var NewHeight := TBitmap(WizardSmallImages[0]).Height;
+    var NewWidth := WizardSmallImages[0].Width;
+    var NewHeight := WizardSmallImages[0].Height;
     if (WizardSmallImages.Count > 1) or
     if (WizardSmallImages.Count > 1) or
        (NewWidth > 58) or
        (NewWidth > 58) or
        (NewHeight > 58) then begin
        (NewHeight > 58) then begin
@@ -880,18 +880,25 @@ begin
   end;
   end;
 
 
   { Initialize images }
   { Initialize images }
-  WizardBitmapImage.Bitmap := SelectBestImage(WizardImages, WizardBitmapImage.Width, WizardBitmapImage.Height);
+  WizardBitmapImage.Graphic := SelectBestImage(WizardImages, WizardBitmapImage.Width, WizardBitmapImage.Height);
   WizardBitmapImage.Center := True;
   WizardBitmapImage.Center := True;
   WizardBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardBitmapImage2.Bitmap := WizardBitmapImage.Bitmap;
   WizardBitmapImage2.Bitmap := WizardBitmapImage.Bitmap;
   WizardBitmapImage2.Center := True;
   WizardBitmapImage2.Center := True;
   WizardBitmapImage2.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardBitmapImage2.Stretch := (shWizardImageStretch in SetupHeader.Options);
-  WizardSmallBitmapImage.Bitmap := SelectBestImage(WizardSmallImages, WizardSmallBitmapImage.Width, WizardSmallBitmapImage.Height);
+  WizardSmallBitmapImage.Graphic := SelectBestImage(WizardSmallImages, WizardSmallBitmapImage.Width, WizardSmallBitmapImage.Height);
   WizardSmallBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   WizardSmallBitmapImage.Stretch := (shWizardImageStretch in SetupHeader.Options);
   SelectDirBitmapImage.InitializeFromIcon(HInstance, 'Z_DIRICON', SelectDirPage.Color, [32, 48, 64]); {don't localize}
   SelectDirBitmapImage.InitializeFromIcon(HInstance, 'Z_DIRICON', SelectDirPage.Color, [32, 48, 64]); {don't localize}
   SelectGroupBitmapImage.InitializeFromIcon(HInstance, 'Z_GROUPICON', SelectProgramGroupPage.Color, [32, 48, 64]); {don't localize}
   SelectGroupBitmapImage.InitializeFromIcon(HInstance, 'Z_GROUPICON', SelectProgramGroupPage.Color, [32, 48, 64]); {don't localize}
   PreparingErrorBitmapImage.InitializeFromIcon(HInstance, 'Z_STOPICON', PreparingPage.Color, [16, 24, 32]); {don't localize}
   PreparingErrorBitmapImage.InitializeFromIcon(HInstance, 'Z_STOPICON', PreparingPage.Color, [16, 24, 32]); {don't localize}
 
 
+  if shUsesBuiltinWizardImages in SetupHeader.Options then begin
+    WizardBitmapImage.BackColor := $F9F3E8; { Bluish Gray }
+    WizardBitmapImage2.BackColor := WizardBitmapImage.BackColor;
+  end;
+  if shUsesBuiltinSmallWizardImages in SetupHeader.Options then
+    WizardSmallBitmapImage.BackColor := clNone;
+
   { Initialize wpWelcome page }
   { Initialize wpWelcome page }
   RegisterExistingPage(wpWelcome, WelcomePage, nil, '', '');
   RegisterExistingPage(wpWelcome, WelcomePage, nil, '', '');
   WelcomeLabel1.Caption := ExpandSetupMessage(msgWelcomeLabel1) + SNewLine;
   WelcomeLabel1.Caption := ExpandSetupMessage(msgWelcomeLabel1) + SNewLine;

+ 3 - 1
Projects/Src/Shared.Struct.pas

@@ -64,7 +64,8 @@ type
     shSignedUninstaller, shUsePreviousLanguage, shDisableWelcomePage,
     shSignedUninstaller, shUsePreviousLanguage, shDisableWelcomePage,
     shCloseApplications, shRestartApplications, shAllowNetworkDrive,
     shCloseApplications, shRestartApplications, shAllowNetworkDrive,
     shForceCloseApplications, shAppNameHasConsts, shUsePreviousPrivileges,
     shForceCloseApplications, shAppNameHasConsts, shUsePreviousPrivileges,
-    shWizardResizable, shUninstallLogging);
+    shWizardResizable, shUninstallLogging, shUsesBuiltinWizardImages,
+    shUsesBuiltinSmallWizardImages);
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupLanguageDetectionMethod = (ldUILanguage, ldLocale, ldNone);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
   TSetupCompressMethod = (cmStored, cmZip, cmBzip, cmLZMA, cmLZMA2);
   TSetupKDFSalt = array[0..15] of Byte;
   TSetupKDFSalt = array[0..15] of Byte;
@@ -94,6 +95,7 @@ type
     BaseNonce: TSetupEncryptionNonce;
     BaseNonce: TSetupEncryptionNonce;
     PasswordTest: Integer;
     PasswordTest: Integer;
   end;
   end;
+  TWizardImageGraphicFormat = (gfBitmap, gfPng);
 
 
 const
 const
   SetupHeaderStrings = 34;
   SetupHeaderStrings = 34;

+ 2 - 1
whatsnew.htm

@@ -50,7 +50,8 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
     The default disk slice size is still <tt>2100000000</tt>, which is almost 2 GB. To update, you can simply set <tt>[Setup]</tt> section directive <tt>DiskSliceSize</tt> to <tt>max</tt>.</li>
     The default disk slice size is still <tt>2100000000</tt>, which is almost 2 GB. To update, you can simply set <tt>[Setup]</tt> section directive <tt>DiskSliceSize</tt> to <tt>max</tt>.</li>
 <li>All download functionality now supports TLS 1.3 when available. Support for TLS 1.0 and 1.1 has been removed on all versions of Windows.</li>
 <li>All download functionality now supports TLS 1.3 when available. Support for TLS 1.0 and 1.1 has been removed on all versions of Windows.</li>
 <li>Archive extraction now supports the RAR5 format.</li>
 <li>Archive extraction now supports the RAR5 format.</li>
-<li>Improved support for stretching 32-bit bitmaps with transparency.</li>
+<li>Added support for .png files to <tt>[Setup]</tt> section directives <tt>WizardImageFile</tt> and <tt>WizardSmallImageFile</tt>.</li>
+<li>Improved support for stretching 32-bit .bmp files with transparency.</li>
 <li>Compiler IDE: Added new <i>Automatically reload files</i> and <i>Allow Undo after reload</i> options. Both are enabled by default, consistent with most other modern editors, and improving integration with tools like Claude Code.</li>
 <li>Compiler IDE: Added new <i>Automatically reload files</i> and <i>Allow Undo after reload</i> options. Both are enabled by default, consistent with most other modern editors, and improving integration with tools like Claude Code.</li>
 <li>Pascal Scripting: Added new <tt>LogFmt</tt> support function.</li>
 <li>Pascal Scripting: Added new <tt>LogFmt</tt> support function.</li>
 </ul>
 </ul>