- Updated Vampyre Imaging Lib
- Added font rendering - Added height display in flat mode
This commit is contained in:
parent
a5128b0d05
commit
be3f8c05df
|
@ -56,7 +56,7 @@
|
||||||
<MinVersion Major="4" Minor="5" Release="1" Valid="True"/>
|
<MinVersion Major="4" Minor="5" Release="1" Valid="True"/>
|
||||||
</Item5>
|
</Item5>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="35">
|
<Units Count="36">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="CentrED.lpr"/>
|
<Filename Value="CentrED.lpr"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
|
@ -273,6 +273,11 @@
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<UnitName Value="UTiledata"/>
|
<UnitName Value="UTiledata"/>
|
||||||
</Unit34>
|
</Unit34>
|
||||||
|
<Unit35>
|
||||||
|
<Filename Value="UGLFont.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="UGLFont"/>
|
||||||
|
</Unit35>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -40,7 +40,7 @@ uses
|
||||||
UfrmLargeScaleCommand, UfrmVirtualLayer, UfrmFilter, UfrmTileInfo,
|
UfrmLargeScaleCommand, UfrmVirtualLayer, UfrmFilter, UfrmTileInfo,
|
||||||
UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets,
|
UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets,
|
||||||
UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow,
|
UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow,
|
||||||
Logging, UMap, UWorldItem, UStatics, UTiledata;
|
Logging, UMap, UWorldItem, UStatics, UTiledata, UGLFont;
|
||||||
|
|
||||||
{$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF}
|
{$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
|
@ -1,3 +1,5 @@
|
||||||
Overlay/LeftTopArrow.tga
|
Overlay/LeftTopArrow.tga
|
||||||
Overlay/TopArrow.tga
|
Overlay/TopArrow.tga
|
||||||
Overlay/VirtualLayer.tga
|
Overlay/VirtualLayer.tga
|
||||||
|
GLFont/DejaVu.png
|
||||||
|
GLFont/DejaVu.fnt
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
(*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at
|
||||||
|
* http://www.opensource.org/licenses/cddl1.php.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at
|
||||||
|
* http://www.opensource.org/licenses/cddl1.php. If applicable,
|
||||||
|
* add the following below this CDDL HEADER, with the fields enclosed
|
||||||
|
* by brackets "[]" replaced with your own identifying * information:
|
||||||
|
* Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Portions Copyright 2009 Andreas Schneider
|
||||||
|
*)
|
||||||
|
unit UGLFont;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, Math, ImagingClasses, ImagingTypes, ImagingOpenGL, GL;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TFontInfo = packed record
|
||||||
|
Character: Char;
|
||||||
|
LeftOffset: SmallInt;
|
||||||
|
CharWidth: Word;
|
||||||
|
Width: Word;
|
||||||
|
Height: Word;
|
||||||
|
X1: Single;
|
||||||
|
Y1: Single;
|
||||||
|
X2: Single;
|
||||||
|
Y2: Single;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TGLFont }
|
||||||
|
|
||||||
|
TGLFont = class
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy; override;
|
||||||
|
protected
|
||||||
|
FFontImage: TSingleImage;
|
||||||
|
FFontTexture: TGLuint;
|
||||||
|
FSpaceWidth: Word;
|
||||||
|
FFontInfo: array of TFontInfo;
|
||||||
|
function FindCharInfo(AChar: Char): Integer;
|
||||||
|
public
|
||||||
|
function GetTextHeight(AText: String): Integer;
|
||||||
|
function GetTextWidth(AText: String): Integer;
|
||||||
|
procedure DrawText(AX, AY: Integer; AText: String);
|
||||||
|
procedure LoadImage(AImage: TStream);
|
||||||
|
procedure LoadFontInfo(AFontInfo: TStream);
|
||||||
|
procedure UpdateTexture;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
Logging;
|
||||||
|
|
||||||
|
{ TGLFont }
|
||||||
|
|
||||||
|
|
||||||
|
constructor TGLFont.Create;
|
||||||
|
begin
|
||||||
|
FFontTexture := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TGLFont.Destroy;
|
||||||
|
begin
|
||||||
|
FreeAndNil(FFontImage);
|
||||||
|
if FFontTexture <> 0 then
|
||||||
|
glDeleteTextures(1, @FFontTexture);
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGLFont.FindCharInfo(AChar: Char): Integer;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := -1;
|
||||||
|
i := 0;
|
||||||
|
while (i < Length(FFontInfo)) and (Result = -1) do
|
||||||
|
begin
|
||||||
|
if FFontInfo[i].Character = AChar then
|
||||||
|
Result := i
|
||||||
|
else
|
||||||
|
Inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGLFont.GetTextHeight(AText: String): Integer;
|
||||||
|
var
|
||||||
|
i, charInfo: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
for i := 1 to Length(AText) do
|
||||||
|
begin
|
||||||
|
if AText[i] <> ' ' then
|
||||||
|
begin
|
||||||
|
charInfo := FindCharInfo(AText[i]);
|
||||||
|
if charInfo > -1 then
|
||||||
|
Result := Max(Result, FFontInfo[charInfo].Height);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGLFont.GetTextWidth(AText: String): Integer;
|
||||||
|
var
|
||||||
|
i, charInfo: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
for i := 1 to Length(AText) do
|
||||||
|
begin
|
||||||
|
if AText[i] = ' ' then
|
||||||
|
Inc(Result, FSpaceWidth)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
charInfo := FindCharInfo(AText[i]);
|
||||||
|
if charInfo > -1 then
|
||||||
|
Result := Result + FFontInfo[charInfo].LeftOffset +
|
||||||
|
FFontInfo[charInfo].CharWidth;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGLFont.DrawText(AX, AY: Integer; AText: String);
|
||||||
|
var
|
||||||
|
i, charInfo: Integer;
|
||||||
|
curX: Integer;
|
||||||
|
x1, y1, x2, y2: Single;
|
||||||
|
begin
|
||||||
|
if FFontTexture = 0 then UpdateTexture;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, FFontTexture);
|
||||||
|
|
||||||
|
curX := AX;
|
||||||
|
for i := 1 to Length(AText) do
|
||||||
|
begin
|
||||||
|
if AText[i] = ' ' then
|
||||||
|
Inc(curX, FSpaceWidth)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
charInfo := FindCharInfo(AText[i]);
|
||||||
|
if charInfo > -1 then
|
||||||
|
begin
|
||||||
|
x1 := FFontInfo[charInfo].X1;
|
||||||
|
y1 := FFontInfo[charInfo].Y1;
|
||||||
|
x2 := FFontInfo[charInfo].X2;
|
||||||
|
y2 := FFontInfo[charInfo].Y2;
|
||||||
|
|
||||||
|
Inc(curX, FFontInfo[charInfo].LeftOffset);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(x1, y1); glVertex2i(curX, AY);
|
||||||
|
glTexCoord2f(x2, y1); glVertex2i(curX + FFontInfo[charInfo].Width, AY);
|
||||||
|
glTexCoord2f(x2, y2); glVertex2i(curX + FFontInfo[charInfo].Width,
|
||||||
|
AY + FFontInfo[charInfo].Height);
|
||||||
|
glTexCoord2f(x1, y2); glVertex2i(curX, AY + FFontInfo[charInfo].Height);
|
||||||
|
glEnd;
|
||||||
|
Inc(curX, FFontInfo[charInfo].CharWidth);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGLFont.LoadImage(AImage: TStream);
|
||||||
|
begin
|
||||||
|
FFontImage := TSingleImage.CreateFromStream(AImage);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGLFont.LoadFontInfo(AFontInfo: TStream);
|
||||||
|
begin
|
||||||
|
AFontInfo.Read(FSpaceWidth, SizeOf(FSpaceWidth));
|
||||||
|
SetLength(FFontInfo, (AFontInfo.Size - AFontInfo.Position) div
|
||||||
|
SizeOf(TFontInfo));
|
||||||
|
AFontInfo.Read(FFontInfo[0], Length(FFontInfo) * SizeOf(TFontInfo));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGLFont.UpdateTexture;
|
||||||
|
begin
|
||||||
|
Logger.Send('UpdateTexture');
|
||||||
|
if FFontTexture <> 0 then glDeleteTextures(1, @FFontTexture);
|
||||||
|
|
||||||
|
FFontTexture := CreateGLTextureFromImage(FFontImage.ImageDataPointer^, 0, 0,
|
||||||
|
True, ifUnknown);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, FFontTexture);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
|
@ -30,11 +30,11 @@ unit ULandscape;
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Classes, math, LCLIntf, GL, GLU, ImagingOpenGL, Imaging,
|
SysUtils, Classes, math, LCLIntf, GL, GLu, ImagingOpenGL, Imaging,
|
||||||
ImagingClasses, ImagingTypes, ImagingUtility,
|
ImagingClasses, ImagingTypes, ImagingUtility,
|
||||||
UGenericIndex, UMap, UStatics, UArt, UTexture, UTiledata, UHue, UWorldItem,
|
UGenericIndex, UMap, UStatics, UArt, UTexture, UTiledata, UHue, UWorldItem,
|
||||||
UMulBlock,
|
UMulBlock,
|
||||||
UVector, UEnhancedMemoryStream,
|
UVector, UEnhancedMemoryStream, UGLFont,
|
||||||
UCacheManager;
|
UCacheManager;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -196,6 +196,19 @@ type
|
||||||
procedure UpdateWriteMap(AStream: TEnhancedMemoryStream);
|
procedure UpdateWriteMap(AStream: TEnhancedMemoryStream);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TGLText }
|
||||||
|
|
||||||
|
TGLText = class
|
||||||
|
constructor Create(AFont: TGLFont; AText: String);
|
||||||
|
protected
|
||||||
|
FFont: TGLFont;
|
||||||
|
FText: String;
|
||||||
|
FWidth: Integer;
|
||||||
|
FHeight: Integer;
|
||||||
|
public
|
||||||
|
procedure Render(AScreenRect: TRect);
|
||||||
|
end;
|
||||||
|
|
||||||
TScreenState = (ssNormal, ssFiltered, ssGhost);
|
TScreenState = (ssNormal, ssFiltered, ssGhost);
|
||||||
|
|
||||||
PBlockInfo = ^TBlockInfo;
|
PBlockInfo = ^TBlockInfo;
|
||||||
|
@ -212,6 +225,7 @@ type
|
||||||
HueOverride: Boolean;
|
HueOverride: Boolean;
|
||||||
CheckRealQuad: Boolean;
|
CheckRealQuad: Boolean;
|
||||||
Translucent: Boolean;
|
Translucent: Boolean;
|
||||||
|
Text: TGLText;
|
||||||
Next: PBlockInfo;
|
Next: PBlockInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1213,6 +1227,7 @@ begin
|
||||||
Result^.State := ssNormal;
|
Result^.State := ssNormal;
|
||||||
Result^.Highlighted := False;
|
Result^.Highlighted := False;
|
||||||
Result^.Translucent := False;
|
Result^.Translucent := False;
|
||||||
|
Result^.Text := nil;
|
||||||
Result^.Next := nil;
|
Result^.Next := nil;
|
||||||
|
|
||||||
if FShortCuts[0] = nil then //First element
|
if FShortCuts[0] = nil then //First element
|
||||||
|
@ -1239,6 +1254,7 @@ begin
|
||||||
current^.Item.Locked := False;
|
current^.Item.Locked := False;
|
||||||
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
||||||
if current^.Normals <> nil then Dispose(current^.Normals);
|
if current^.Normals <> nil then Dispose(current^.Normals);
|
||||||
|
current^.Text.Free;
|
||||||
Dispose(current);
|
Dispose(current);
|
||||||
current := next;
|
current := next;
|
||||||
end;
|
end;
|
||||||
|
@ -1266,6 +1282,7 @@ begin
|
||||||
if last <> nil then last^.Next := current^.Next;
|
if last <> nil then last^.Next := current^.Next;
|
||||||
|
|
||||||
if current^.Normals <> nil then Dispose(current^.Normals);
|
if current^.Normals <> nil then Dispose(current^.Normals);
|
||||||
|
current^.Text.Free;
|
||||||
|
|
||||||
Dispose(current);
|
Dispose(current);
|
||||||
Dec(FCount);
|
Dec(FCount);
|
||||||
|
@ -1356,6 +1373,7 @@ begin
|
||||||
Result^.State := ssNormal;
|
Result^.State := ssNormal;
|
||||||
Result^.Highlighted := False;
|
Result^.Highlighted := False;
|
||||||
Result^.Translucent := False;
|
Result^.Translucent := False;
|
||||||
|
Result^.Text := nil;
|
||||||
|
|
||||||
if (FShortCuts[0] = nil) or (CompareWorldItems(AItem, FShortCuts[0]^.Item) < 0) then
|
if (FShortCuts[0] = nil) or (CompareWorldItems(AItem, FShortCuts[0]^.Item) < 0) then
|
||||||
begin
|
begin
|
||||||
|
@ -1490,5 +1508,27 @@ begin
|
||||||
Delete(TWorldItem(ATile));
|
Delete(TWorldItem(ATile));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TGLText }
|
||||||
|
|
||||||
|
constructor TGLText.Create(AFont: TGLFont; AText: String);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
FFont := AFont;
|
||||||
|
FText := AText;
|
||||||
|
FWidth := FFont.GetTextWidth(AText);
|
||||||
|
FHeight := FFont.GetTextHeight('A');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGLText.Render(AScreenRect: TRect);
|
||||||
|
var
|
||||||
|
x, y: Integer;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
y := AScreenRect.Top + (AScreenRect.Bottom - AScreenRect.Top - FHeight) div 2;
|
||||||
|
x := AScreenRect.Left + (AScreenRect.Right - AScreenRect.Left - FWidth) div 2;
|
||||||
|
FFont.DrawText(x, y, FText);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright 2007 Andreas Schneider
|
* Portions Copyright 2009 Andreas Schneider
|
||||||
*)
|
*)
|
||||||
unit UResourceManager;
|
unit UResourceManager;
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ end;
|
||||||
|
|
||||||
destructor TResourceManager.Destroy;
|
destructor TResourceManager.Destroy;
|
||||||
begin
|
begin
|
||||||
if FFileStream <> nil then FreeAndNil(FFileStream);
|
FreeAndNil(FFileStream);
|
||||||
if FResourceStream <> nil then FreeAndNil(FResourceStream);
|
FreeAndNil(FResourceStream);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -81,7 +81,6 @@ begin
|
||||||
if AIndex <> FCurrentResource then
|
if AIndex <> FCurrentResource then
|
||||||
begin
|
begin
|
||||||
FFileStream.Position := FLookupTable[AIndex];
|
FFileStream.Position := FLookupTable[AIndex];
|
||||||
if FResourceStream <> nil then
|
|
||||||
FResourceStream.Free;
|
FResourceStream.Free;
|
||||||
FResourceStream := TMemoryStream.Create;
|
FResourceStream := TMemoryStream.Create;
|
||||||
FFileStream.Read(size, SizeOf(Cardinal));
|
FFileStream.Read(size, SizeOf(Cardinal));
|
||||||
|
|
|
@ -31,10 +31,10 @@ interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Menus,
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Menus,
|
||||||
ComCtrls, OpenGLContext, GL, GLU, UGameResources, ULandscape, ExtCtrls,
|
ComCtrls, OpenGLContext, GL, GLu, UGameResources, ULandscape, ExtCtrls,
|
||||||
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
|
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
|
||||||
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, fgl,
|
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, fgl,
|
||||||
ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket;
|
ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket, UGLFont;
|
||||||
|
|
||||||
type
|
type
|
||||||
TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object;
|
TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object;
|
||||||
|
@ -269,6 +269,7 @@ type
|
||||||
Node: PVirtualNode; Stream: TStream);
|
Node: PVirtualNode; Stream: TStream);
|
||||||
protected
|
protected
|
||||||
{ Members }
|
{ Members }
|
||||||
|
FAppDir: String;
|
||||||
FX: Integer;
|
FX: Integer;
|
||||||
FY: Integer;
|
FY: Integer;
|
||||||
FDrawDistance: Integer;
|
FDrawDistance: Integer;
|
||||||
|
@ -294,6 +295,7 @@ type
|
||||||
FRepaintNeeded: Boolean;
|
FRepaintNeeded: Boolean;
|
||||||
FSelection: TRect;
|
FSelection: TRect;
|
||||||
FUndoList: TPacketList;
|
FUndoList: TPacketList;
|
||||||
|
FGLFont: TGLFont;
|
||||||
{ Methods }
|
{ Methods }
|
||||||
procedure BuildTileList;
|
procedure BuildTileList;
|
||||||
function ConfirmAction: Boolean;
|
function ConfirmAction: Boolean;
|
||||||
|
@ -784,6 +786,8 @@ var
|
||||||
virtualLayerGraphic: TSingleImage;
|
virtualLayerGraphic: TSingleImage;
|
||||||
searchRec: TSearchRec;
|
searchRec: TSearchRec;
|
||||||
begin
|
begin
|
||||||
|
FAppDir := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
|
||||||
|
|
||||||
FLandscape := ResMan.Landscape;
|
FLandscape := ResMan.Landscape;
|
||||||
FLandscape.OnChange := @OnLandscapeChanged;
|
FLandscape.OnChange := @OnLandscapeChanged;
|
||||||
FLandscape.OnMapChanged := @OnMapChanged;
|
FLandscape.OnMapChanged := @OnMapChanged;
|
||||||
|
@ -812,8 +816,7 @@ begin
|
||||||
vstChat.NodeDataSize := SizeOf(TChatInfo);
|
vstChat.NodeDataSize := SizeOf(TChatInfo);
|
||||||
pnlChatHeader.AnchorSide[akBottom].Control := pnlBottom;
|
pnlChatHeader.AnchorSide[akBottom].Control := pnlBottom;
|
||||||
|
|
||||||
FLocationsFile := IncludeTrailingPathDelimiter(ExtractFilePath(
|
FLocationsFile := FAppDir + 'Locations.dat';
|
||||||
Application.ExeName)) + 'Locations.dat';
|
|
||||||
vstLocations.NodeDataSize := SizeOf(TLocationInfo);
|
vstLocations.NodeDataSize := SizeOf(TLocationInfo);
|
||||||
if FileExists(FLocationsFile) then vstLocations.LoadFromFile(FLocationsFile);
|
if FileExists(FLocationsFile) then vstLocations.LoadFromFile(FLocationsFile);
|
||||||
|
|
||||||
|
@ -824,11 +827,14 @@ begin
|
||||||
virtualLayerGraphic.Height, virtualLayerGraphic);
|
virtualLayerGraphic.Height, virtualLayerGraphic);
|
||||||
virtualLayerGraphic.Free;
|
virtualLayerGraphic.Free;
|
||||||
|
|
||||||
|
FGLFont := TGLFont.Create;
|
||||||
|
FGLFont.LoadImage(ResourceManager.GetResource(3));
|
||||||
|
FGLFont.LoadFontInfo(ResourceManager.GetResource(4));
|
||||||
|
|
||||||
FVirtualTiles := TWorldItemList.Create(True);
|
FVirtualTiles := TWorldItemList.Create(True);
|
||||||
FUndoList := TPacketList.Create(True);
|
FUndoList := TPacketList.Create(True);
|
||||||
|
|
||||||
FRandomPresetLocation := IncludeTrailingPathDelimiter(ExtractFilePath(
|
FRandomPresetLocation := FAppDir + 'RandomPresets' + PathDelim;
|
||||||
Application.ExeName)) + 'RandomPresets' + PathDelim;
|
|
||||||
if not DirectoryExists(FRandomPresetLocation) then
|
if not DirectoryExists(FRandomPresetLocation) then
|
||||||
CreateDir(FRandomPresetLocation);
|
CreateDir(FRandomPresetLocation);
|
||||||
|
|
||||||
|
@ -1116,6 +1122,7 @@ begin
|
||||||
FreeAndNil(FVLayerMaterial);
|
FreeAndNil(FVLayerMaterial);
|
||||||
FreeAndNil(FVirtualTiles);
|
FreeAndNil(FVirtualTiles);
|
||||||
FreeAndNil(FUndoList);
|
FreeAndNil(FUndoList);
|
||||||
|
FreeAndNil(FGLFont);
|
||||||
|
|
||||||
RegisterPacketHandler($0C, nil);
|
RegisterPacketHandler($0C, nil);
|
||||||
end;
|
end;
|
||||||
|
@ -1783,9 +1790,11 @@ procedure TfrmMain.InitSize;
|
||||||
begin
|
begin
|
||||||
glViewport(0, 0, oglGameWindow.Width, oglGameWindow.Height);
|
glViewport(0, 0, oglGameWindow.Width, oglGameWindow.Height);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix;
|
||||||
glLoadIdentity;
|
glLoadIdentity;
|
||||||
gluOrtho2D(0, oglGameWindow.Width, oglGameWindow.Height, 0);
|
gluOrtho2D(0, oglGameWindow.Width, oglGameWindow.Height, 0);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix;
|
||||||
glLoadIdentity;
|
glLoadIdentity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1923,6 +1932,10 @@ begin
|
||||||
CheckRealQuad := True;
|
CheckRealQuad := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
ABlockInfo^.Text.Free;
|
||||||
|
ABlockInfo^.Text := TGLText.Create(FGLFont, IntToStr(item.Z));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not ABlockInfo^.CheckRealQuad then
|
if not ABlockInfo^.CheckRealQuad then
|
||||||
|
@ -2082,6 +2095,9 @@ begin
|
||||||
|
|
||||||
if highlight then
|
if highlight then
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
|
||||||
|
if (blockInfo^.Text <> nil) then
|
||||||
|
blockInfo^.Text.Render(blockInfo^.ScreenRect);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
FOverlayUI.Draw(oglGameWindow);
|
FOverlayUI.Draw(oglGameWindow);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: Imaging.pas 124 2008-04-21 09:47:07Z galfar $
|
$Id: Imaging.pas 173 2009-09-04 17:05:52Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -203,9 +203,8 @@ function SplitImage(var Image: TImageData; var Chunks: TDynImageDataArray;
|
||||||
Pal must be allocated to have at least MaxColors entries.}
|
Pal must be allocated to have at least MaxColors entries.}
|
||||||
function MakePaletteForImages(var Images: TDynImageDataArray; Pal: PPalette32;
|
function MakePaletteForImages(var Images: TDynImageDataArray; Pal: PPalette32;
|
||||||
MaxColors: LongInt; ConvertImages: Boolean): Boolean;
|
MaxColors: LongInt; ConvertImages: Boolean): Boolean;
|
||||||
{ Rotates image by 90, 180, 270, -90, -180, or -270 degrees counterclockwise.
|
{ Rotates image by Angle degrees counterclockwise. All angles are allowed.}
|
||||||
Only multiples of 90 degrees are allowed.}
|
function RotateImage(var Image: TImageData; Angle: Single): Boolean;
|
||||||
function RotateImage(var Image: TImageData; Angle: LongInt): Boolean;
|
|
||||||
|
|
||||||
{ Drawing/Pixel functions }
|
{ Drawing/Pixel functions }
|
||||||
|
|
||||||
|
@ -303,7 +302,7 @@ function PopOptions: Boolean;
|
||||||
{ Image Format Functions }
|
{ Image Format Functions }
|
||||||
|
|
||||||
{ Returns short information about given image format.}
|
{ Returns short information about given image format.}
|
||||||
function GetImageFormatInfo(Format: TImageFormat; var Info: TImageFormatInfo): Boolean;
|
function GetImageFormatInfo(Format: TImageFormat; out Info: TImageFormatInfo): Boolean;
|
||||||
{ Returns size in bytes of Width x Height area of pixels. Works for all formats.}
|
{ Returns size in bytes of Width x Height area of pixels. Works for all formats.}
|
||||||
function GetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt;
|
function GetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt;
|
||||||
|
|
||||||
|
@ -534,28 +533,28 @@ procedure RaiseImaging(const Msg: string; const Args: array of const);
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
ImagingBitmap,
|
ImagingBitmap,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
ImagingJpeg,
|
ImagingJpeg,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IF Defined(LINK_PNG) or Defined(LINK_MNG) or Defined(LINK_JNG)}
|
{$IF not Defined(DONT_LINK_PNG) or not Defined(DONT_LINK_MNG) or not Defined(DONT_LINK_JNG)}
|
||||||
ImagingNetworkGraphics,
|
ImagingNetworkGraphics,
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
ImagingGif,
|
ImagingGif,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
ImagingDds,
|
ImagingDds,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
ImagingTarga,
|
ImagingTarga,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_PNM}
|
{$IFNDEF DONT_LINK_PNM}
|
||||||
ImagingPortableMaps,
|
ImagingPortableMaps,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_EXTRAS}
|
{$IFNDEF DONT_LINK_EXTRAS}
|
||||||
ImagingExtras,
|
ImagingExtras,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
ImagingFormats, ImagingUtility, ImagingIO;
|
ImagingFormats, ImagingUtility, ImagingIO;
|
||||||
|
@ -606,8 +605,9 @@ resourcestring
|
||||||
SErrorFreePalette = 'Error while freeing palette @%p';
|
SErrorFreePalette = 'Error while freeing palette @%p';
|
||||||
SErrorCopyPalette = 'Error while copying %d entries from palette @%p to @%p';
|
SErrorCopyPalette = 'Error while copying %d entries from palette @%p to @%p';
|
||||||
SErrorReplaceColor = 'Error while replacing colors in rectangle X:%d Y:%d W:%d H:%d of image %s';
|
SErrorReplaceColor = 'Error while replacing colors in rectangle X:%d Y:%d W:%d H:%d of image %s';
|
||||||
SErrorRotateImage = 'Error while rotating image %s by %d degrees';
|
SErrorRotateImage = 'Error while rotating image %s by %.2n degrees';
|
||||||
SErrorStretchRect = 'Error while stretching rect from image %s to image %s.';
|
SErrorStretchRect = 'Error while stretching rect from image %s to image %s.';
|
||||||
|
SErrorEmptyStream = 'Input stream has no data. Check Position property.';
|
||||||
|
|
||||||
const
|
const
|
||||||
// initial size of array with options information
|
// initial size of array with options information
|
||||||
|
@ -727,7 +727,7 @@ function NewImage(Width, Height: LongInt; Format: TImageFormat; var Image:
|
||||||
var
|
var
|
||||||
FInfo: PImageFormatInfo;
|
FInfo: PImageFormatInfo;
|
||||||
begin
|
begin
|
||||||
Assert((Width >= 0) and (Height >= 0));
|
Assert((Width > 0) and (Height >0));
|
||||||
Assert(IsImageFormatValid(Format));
|
Assert(IsImageFormatValid(Format));
|
||||||
Result := False;
|
Result := False;
|
||||||
FreeImage(Image);
|
FreeImage(Image);
|
||||||
|
@ -996,6 +996,8 @@ var
|
||||||
I: LongInt;
|
I: LongInt;
|
||||||
begin
|
begin
|
||||||
Assert(Stream <> nil);
|
Assert(Stream <> nil);
|
||||||
|
if Stream.Size - Stream.Position = 0 then
|
||||||
|
RaiseImaging(SErrorEmptyStream, []);
|
||||||
Result := False;
|
Result := False;
|
||||||
Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream));
|
Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream));
|
||||||
if Format <> nil then
|
if Format <> nil then
|
||||||
|
@ -1057,6 +1059,8 @@ var
|
||||||
Format: TImageFileFormat;
|
Format: TImageFileFormat;
|
||||||
begin
|
begin
|
||||||
Assert(Stream <> nil);
|
Assert(Stream <> nil);
|
||||||
|
if Stream.Size - Stream.Position = 0 then
|
||||||
|
RaiseImaging(SErrorEmptyStream, []);
|
||||||
Result := False;
|
Result := False;
|
||||||
Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream));
|
Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream));
|
||||||
if Format <> nil then
|
if Format <> nil then
|
||||||
|
@ -1416,7 +1420,10 @@ begin
|
||||||
// Free old image and assign new image to it
|
// Free old image and assign new image to it
|
||||||
FreeMemNil(Image.Bits);
|
FreeMemNil(Image.Bits);
|
||||||
if Image.Palette <> nil then
|
if Image.Palette <> nil then
|
||||||
|
begin
|
||||||
|
FreeMem(WorkImage.Palette);
|
||||||
WorkImage.Palette := Image.Palette;
|
WorkImage.Palette := Image.Palette;
|
||||||
|
end;
|
||||||
Image := WorkImage;
|
Image := WorkImage;
|
||||||
Result := True;
|
Result := True;
|
||||||
except
|
except
|
||||||
|
@ -1854,33 +1861,154 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RotateImage(var Image: TImageData; Angle: LongInt): Boolean;
|
function RotateImage(var Image: TImageData; Angle: Single): Boolean;
|
||||||
var
|
var
|
||||||
X, Y, BytesPerPixel: LongInt;
|
|
||||||
RotImage: TImageData;
|
|
||||||
Pix, RotPix: PByte;
|
|
||||||
OldFmt: TImageFormat;
|
OldFmt: TImageFormat;
|
||||||
begin
|
|
||||||
Assert(Angle mod 90 = 0);
|
|
||||||
Result := False;
|
|
||||||
|
|
||||||
if TestImage(Image) then
|
procedure XShear(var Src, Dst: TImageData; Row, Offset, Weight, Bpp: Integer);
|
||||||
try
|
var
|
||||||
if (Angle < -360) or (Angle > 360) then Angle := Angle mod 360;
|
I, J, XPos: Integer;
|
||||||
if (Angle = 0) or (Abs(Angle) = 360) then
|
PixSrc, PixLeft, PixOldLeft: TColor32Rec;
|
||||||
|
LineDst: PByteArray;
|
||||||
|
SrcPtr: PColor32;
|
||||||
begin
|
begin
|
||||||
Result := True;
|
SrcPtr := @PByteArray(Src.Bits)[Row * Src.Width * Bpp];
|
||||||
Exit;
|
LineDst := @PByteArray(Dst.Bits)[Row * Dst.Width * Bpp];
|
||||||
|
PixOldLeft.Color := 0;
|
||||||
|
|
||||||
|
for I := 0 to Src.Width - 1 do
|
||||||
|
begin
|
||||||
|
CopyPixel(SrcPtr, @PixSrc, Bpp);
|
||||||
|
for J := 0 to Bpp - 1 do
|
||||||
|
PixLeft.Channels[J] := MulDiv(PixSrc.Channels[J], Weight, 256);
|
||||||
|
|
||||||
|
XPos := I + Offset;
|
||||||
|
if (XPos >= 0) and (XPos < Dst.Width) then
|
||||||
|
begin
|
||||||
|
for J := 0 to Bpp - 1 do
|
||||||
|
PixSrc.Channels[J] := PixSrc.Channels[J] - (PixLeft.Channels[J] - PixOldLeft.Channels[J]);
|
||||||
|
CopyPixel(@PixSrc, @LineDst[XPos * Bpp], Bpp);
|
||||||
|
end;
|
||||||
|
PixOldLeft := PixLeft;
|
||||||
|
Inc(PByte(SrcPtr), Bpp);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Angle := Iff(Angle = -90, 270, Angle);
|
XPos := Src.Width + Offset;
|
||||||
Angle := Iff(Angle = -270, 90, Angle);
|
if XPos < Dst.Width then
|
||||||
Angle := Iff(Angle = -180, 180, Angle);
|
CopyPixel(@PixOldLeft, @LineDst[XPos * Bpp], Bpp);
|
||||||
|
end;
|
||||||
|
|
||||||
OldFmt := Image.Format;
|
procedure YShear(var Src, Dst: TImageData; Col, Offset, Weight, Bpp: Integer);
|
||||||
if ImageFormatInfos[Image.Format].IsSpecial then
|
var
|
||||||
ConvertImage(Image, ifDefault);
|
I, J, YPos: Integer;
|
||||||
|
PixSrc, PixLeft, PixOldLeft: TColor32Rec;
|
||||||
|
SrcPtr: PByte;
|
||||||
|
begin
|
||||||
|
SrcPtr := @PByteArray(Src.Bits)[Col * Bpp];
|
||||||
|
PixOldLeft.Color := 0;
|
||||||
|
|
||||||
|
for I := 0 to Src.Height - 1 do
|
||||||
|
begin
|
||||||
|
CopyPixel(SrcPtr, @PixSrc, Bpp);
|
||||||
|
for J := 0 to Bpp - 1 do
|
||||||
|
PixLeft.Channels[J] := MulDiv(PixSrc.Channels[J], Weight, 256);
|
||||||
|
|
||||||
|
YPos := I + Offset;
|
||||||
|
if (YPos >= 0) and (YPos < Dst.Height) then
|
||||||
|
begin
|
||||||
|
for J := 0 to Bpp - 1 do
|
||||||
|
PixSrc.Channels[J] := PixSrc.Channels[J] - (PixLeft.Channels[J] - PixOldLeft.Channels[J]);
|
||||||
|
CopyPixel(@PixSrc, @PByteArray(Dst.Bits)[(YPos * Dst.Width + Col) * Bpp], Bpp);
|
||||||
|
end;
|
||||||
|
PixOldLeft := PixLeft;
|
||||||
|
Inc(SrcPtr, Src.Width * Bpp);
|
||||||
|
end;
|
||||||
|
|
||||||
|
YPos := Src.Height + Offset;
|
||||||
|
if YPos < Dst.Height then
|
||||||
|
CopyPixel(@PixOldLeft, @PByteArray(Dst.Bits)[(YPos * Dst.Width + Col) * Bpp], Bpp);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Rotate45(var Image: TImageData; Angle: Single);
|
||||||
|
var
|
||||||
|
TempImage1, TempImage2: TImageData;
|
||||||
|
AngleRad, AngleTan, AngleSin, AngleCos, Shear: Single;
|
||||||
|
I, DstWidth, DstHeight, SrcWidth, SrcHeight, Bpp: Integer;
|
||||||
|
SrcFmt, TempFormat: TImageFormat;
|
||||||
|
Info: TImageFormatInfo;
|
||||||
|
begin
|
||||||
|
AngleRad := Angle * Pi / 180;
|
||||||
|
AngleSin := Sin(AngleRad);
|
||||||
|
AngleCos := Cos(AngleRad);
|
||||||
|
AngleTan := Sin(AngleRad / 2) / Cos(AngleRad / 2);
|
||||||
|
SrcWidth := Image.Width;
|
||||||
|
SrcHeight := Image.Height;
|
||||||
|
SrcFmt := Image.Format;
|
||||||
|
|
||||||
|
if not (SrcFmt in [ifR8G8B8..ifX8R8G8B8, ifGray8..ifGray32, ifA16Gray16]) then
|
||||||
|
ConvertImage(Image, ifA8R8G8B8);
|
||||||
|
|
||||||
|
TempFormat := Image.Format;
|
||||||
|
GetImageFormatInfo(TempFormat, Info);
|
||||||
|
Bpp := Info.BytesPerPixel;
|
||||||
|
|
||||||
|
// 1st shear (horizontal)
|
||||||
|
DstWidth := Trunc(SrcWidth + SrcHeight * Abs(AngleTan) + 0.5);
|
||||||
|
DstHeight := SrcHeight;
|
||||||
|
NewImage(DstWidth, DstHeight, TempFormat, TempImage1);
|
||||||
|
|
||||||
|
for I := 0 to DstHeight - 1 do
|
||||||
|
begin
|
||||||
|
if AngleTan >= 0 then
|
||||||
|
Shear := (I + 0.5) * AngleTan
|
||||||
|
else
|
||||||
|
Shear := (I - DstHeight + 0.5) * AngleTan;
|
||||||
|
XShear(Image, TempImage1, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 2nd shear (vertical)
|
||||||
|
FreeImage(Image);
|
||||||
|
DstHeight := Trunc(SrcWidth * Abs(AngleSin) + SrcHeight * AngleCos + 0.5) + 1;
|
||||||
|
NewImage(DstWidth, DstHeight, TempFormat, TempImage2);
|
||||||
|
|
||||||
|
if AngleSin >= 0 then
|
||||||
|
Shear := (SrcWidth - 1) * AngleSin
|
||||||
|
else
|
||||||
|
Shear := (SrcWidth - DstWidth) * -AngleSin;
|
||||||
|
|
||||||
|
for I := 0 to DstWidth - 1 do
|
||||||
|
begin
|
||||||
|
YShear(TempImage1, TempImage2, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp);
|
||||||
|
Shear := Shear - AngleSin;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 3rd shear (horizontal)
|
||||||
|
FreeImage(TempImage1);
|
||||||
|
DstWidth := Trunc(SrcHeight * Abs(AngleSin) + SrcWidth * AngleCos + 0.5) + 1;
|
||||||
|
NewImage(DstWidth, DstHeight, TempFormat, Image);
|
||||||
|
|
||||||
|
if AngleSin >= 0 then
|
||||||
|
Shear := (SrcWidth - 1) * AngleSin * -AngleTan
|
||||||
|
else
|
||||||
|
Shear := ((SrcWidth - 1) * -AngleSin + (1 - DstHeight)) * AngleTan;
|
||||||
|
|
||||||
|
for I := 0 to DstHeight - 1 do
|
||||||
|
begin
|
||||||
|
XShear(TempImage2, Image, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp);
|
||||||
|
Shear := Shear + AngleTan;
|
||||||
|
end;
|
||||||
|
|
||||||
|
FreeImage(TempImage2);
|
||||||
|
if Image.Format <> SrcFmt then
|
||||||
|
ConvertImage(Image, SrcFmt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure RotateMul90(var Image: TImageData; Angle: Integer);
|
||||||
|
var
|
||||||
|
RotImage: TImageData;
|
||||||
|
X, Y, BytesPerPixel: Integer;
|
||||||
|
RotPix, Pix: PByte;
|
||||||
|
begin
|
||||||
InitImage(RotImage);
|
InitImage(RotImage);
|
||||||
BytesPerPixel := ImageFormatInfos[Image.Format].BytesPerPixel;
|
BytesPerPixel := ImageFormatInfos[Image.Format].BytesPerPixel;
|
||||||
|
|
||||||
|
@ -1920,8 +2048,7 @@ begin
|
||||||
begin
|
begin
|
||||||
for Y := 0 to RotImage.Height - 1 do
|
for Y := 0 to RotImage.Height - 1 do
|
||||||
begin
|
begin
|
||||||
Pix := @PByteArray(Image.Bits)[((Image.Height - 1) * Image.Width +
|
Pix := @PByteArray(Image.Bits)[((Image.Height - 1) * Image.Width + Y) * BytesPerPixel];
|
||||||
Y) * BytesPerPixel];
|
|
||||||
for X := 0 to RotImage.Width - 1 do
|
for X := 0 to RotImage.Width - 1 do
|
||||||
begin
|
begin
|
||||||
CopyPixel(Pix, RotPix, BytesPerPixel);
|
CopyPixel(Pix, RotPix, BytesPerPixel);
|
||||||
|
@ -1935,6 +2062,46 @@ begin
|
||||||
FreeMemNil(Image.Bits);
|
FreeMemNil(Image.Bits);
|
||||||
RotImage.Palette := Image.Palette;
|
RotImage.Palette := Image.Palette;
|
||||||
Image := RotImage;
|
Image := RotImage;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
|
||||||
|
if TestImage(Image) then
|
||||||
|
try
|
||||||
|
while Angle >= 360 do
|
||||||
|
Angle := Angle - 360;
|
||||||
|
while Angle < 0 do
|
||||||
|
Angle := Angle + 360;
|
||||||
|
|
||||||
|
if (Angle = 0) or (Abs(Angle) = 360) then
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
OldFmt := Image.Format;
|
||||||
|
if ImageFormatInfos[Image.Format].IsSpecial then
|
||||||
|
ConvertImage(Image, ifDefault);
|
||||||
|
|
||||||
|
if (Angle > 45) and (Angle <= 135) then
|
||||||
|
begin
|
||||||
|
RotateMul90(Image, 90);
|
||||||
|
Angle := Angle - 90;
|
||||||
|
end
|
||||||
|
else if (Angle > 135) and (Angle <= 225) then
|
||||||
|
begin
|
||||||
|
RotateMul90(Image, 180);
|
||||||
|
Angle := Angle - 180;
|
||||||
|
end
|
||||||
|
else if (Angle > 225) and (Angle <= 315) then
|
||||||
|
begin
|
||||||
|
RotateMul90(Image, 270);
|
||||||
|
Angle := Angle - 270;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Angle <> 0 then
|
||||||
|
Rotate45(Image, Angle);
|
||||||
|
|
||||||
if OldFmt <> Image.Format then
|
if OldFmt <> Image.Format then
|
||||||
ConvertImage(Image, OldFmt);
|
ConvertImage(Image, OldFmt);
|
||||||
|
@ -2421,7 +2588,7 @@ end;
|
||||||
|
|
||||||
{ Image Format Functions }
|
{ Image Format Functions }
|
||||||
|
|
||||||
function GetImageFormatInfo(Format: TImageFormat; var Info: TImageFormatInfo): Boolean;
|
function GetImageFormatInfo(Format: TImageFormat; out Info: TImageFormatInfo): Boolean;
|
||||||
begin
|
begin
|
||||||
FillChar(Info, SizeOf(Info), 0);
|
FillChar(Info, SizeOf(Info), 0);
|
||||||
if ImageFormatInfos[Format] <> nil then
|
if ImageFormatInfos[Format] <> nil then
|
||||||
|
@ -2527,7 +2694,7 @@ begin
|
||||||
|
|
||||||
if OptionId >= Length(Options) then
|
if OptionId >= Length(Options) then
|
||||||
SetLength(Options, OptionId + InitialOptions);
|
SetLength(Options, OptionId + InitialOptions);
|
||||||
if (OptionId >= 0) and (OptionId < Length(Options)) and (Options[OptionId] = nil) then
|
if (OptionId >= 0) and (OptionId < Length(Options)) {and (Options[OptionId] = nil) - must be able to override existing } then
|
||||||
begin
|
begin
|
||||||
Options[OptionId] := Variable;
|
Options[OptionId] := Variable;
|
||||||
Result := True;
|
Result := True;
|
||||||
|
@ -2539,7 +2706,7 @@ var
|
||||||
I: LongInt;
|
I: LongInt;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
for I := 0 to ImageFileFormats.Count - 1 do
|
for I := ImageFileFormats.Count - 1 downto 0 do
|
||||||
if TImageFileFormat(ImageFileFormats[I]).Extensions.IndexOf(Ext) >= 0 then
|
if TImageFileFormat(ImageFileFormats[I]).Extensions.IndexOf(Ext) >= 0 then
|
||||||
begin
|
begin
|
||||||
Result := TImageFileFormat(ImageFileFormats[I]);
|
Result := TImageFileFormat(ImageFileFormats[I]);
|
||||||
|
@ -2552,7 +2719,7 @@ var
|
||||||
I: LongInt;
|
I: LongInt;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
for I := 0 to ImageFileFormats.Count - 1 do
|
for I := ImageFileFormats.Count - 1 downto 0 do
|
||||||
if TImageFileFormat(ImageFileFormats[I]).TestFileName(FileName) then
|
if TImageFileFormat(ImageFileFormats[I]).TestFileName(FileName) then
|
||||||
begin
|
begin
|
||||||
Result := TImageFileFormat(ImageFileFormats[I]);
|
Result := TImageFileFormat(ImageFileFormats[I]);
|
||||||
|
@ -3289,6 +3456,19 @@ finalization
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Extended RotateImage to allow arbitrary angle rotations.
|
||||||
|
- Reversed the order file formats list is searched so
|
||||||
|
if you register a new one it will be found sooner than
|
||||||
|
built in formats.
|
||||||
|
- Fixed memory leak in ResizeImage ocurring when resizing
|
||||||
|
indexed images.
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added position/size checks to LoadFromStream functions.
|
||||||
|
- Changed conditional compilation in impl. uses section to reflect changes
|
||||||
|
in LINK symbols.
|
||||||
|
|
||||||
-- 0.24.3 Changes/Bug Fixes ---------------------------------
|
-- 0.24.3 Changes/Bug Fixes ---------------------------------
|
||||||
- GenerateMipMaps now generates all smaller levels from
|
- GenerateMipMaps now generates all smaller levels from
|
||||||
original big image (better results when using more advanced filters).
|
original big image (better results when using more advanced filters).
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingCanvases.pas 131 2008-08-14 15:14:24Z galfar $
|
$Id: ImagingCanvases.pas 174 2009-09-08 09:37:59Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -118,6 +118,8 @@ type
|
||||||
|
|
||||||
TDynFPPixelArray = array of TColorFPRec;
|
TDynFPPixelArray = array of TColorFPRec;
|
||||||
|
|
||||||
|
THistogramArray = array[Byte] of Integer;
|
||||||
|
|
||||||
TSelectPixelFunction = function(var Pixels: TDynFPPixelArray): TColorFPRec;
|
TSelectPixelFunction = function(var Pixels: TDynFPPixelArray): TColorFPRec;
|
||||||
|
|
||||||
{ Base canvas class for drawing objects, applying effects, and other.
|
{ Base canvas class for drawing objects, applying effects, and other.
|
||||||
|
@ -128,7 +130,7 @@ type
|
||||||
recompute some data size related stuff).
|
recompute some data size related stuff).
|
||||||
|
|
||||||
TImagingCanvas works for all image data formats except special ones
|
TImagingCanvas works for all image data formats except special ones
|
||||||
(compressed). Because of this its methods are quite slow (they work
|
(compressed). Because of this its methods are quite slow (they usually work
|
||||||
with colors in ifA32R32G32B32F format). If you want fast drawing you
|
with colors in ifA32R32G32B32F format). If you want fast drawing you
|
||||||
can use one of fast canvas clases. These descendants of TImagingCanvas
|
can use one of fast canvas clases. These descendants of TImagingCanvas
|
||||||
work only for few select formats (or only one) but they are optimized thus
|
work only for few select formats (or only one) but they are optimized thus
|
||||||
|
@ -216,6 +218,12 @@ type
|
||||||
filled by using the current fill settings. Rect specifies bounding rectangle
|
filled by using the current fill settings. Rect specifies bounding rectangle
|
||||||
of ellipse to be drawn.}
|
of ellipse to be drawn.}
|
||||||
procedure Ellipse(const Rect: TRect);
|
procedure Ellipse(const Rect: TRect);
|
||||||
|
{ Fills area of canvas with current fill color starting at point [X, Y] and
|
||||||
|
coloring its neighbors. Default flood fill mode changes color of all
|
||||||
|
neighbors with the same color as pixel [X, Y]. With BoundaryFillMode
|
||||||
|
set to True neighbors are recolored regardless of their old color,
|
||||||
|
but area which will be recolored has boundary (specified by current pen color).}
|
||||||
|
procedure FloodFill(X, Y: Integer; BoundaryFillMode: Boolean = False);
|
||||||
|
|
||||||
{ Draws contents of this canvas onto another canvas with pixel blending.
|
{ Draws contents of this canvas onto another canvas with pixel blending.
|
||||||
Blending factors are chosen using TBlendingFactor parameters.
|
Blending factors are chosen using TBlendingFactor parameters.
|
||||||
|
@ -225,7 +233,7 @@ type
|
||||||
DestX, DestY: Integer; SrcFactor, DestFactor: TBlendingFactor);
|
DestX, DestY: Integer; SrcFactor, DestFactor: TBlendingFactor);
|
||||||
{ Draws contents of this canvas onto another one with typical alpha
|
{ Draws contents of this canvas onto another one with typical alpha
|
||||||
blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)}
|
blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)}
|
||||||
procedure DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer);
|
procedure DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer); virtual;
|
||||||
{ Draws contents of this canvas onto another one using additive blending
|
{ Draws contents of this canvas onto another one using additive blending
|
||||||
(source and dest factors are bfOne).}
|
(source and dest factors are bfOne).}
|
||||||
procedure DrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer);
|
procedure DrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer);
|
||||||
|
@ -239,7 +247,7 @@ type
|
||||||
{ Draws contents of this canvas onto another one with typical alpha
|
{ Draws contents of this canvas onto another one with typical alpha
|
||||||
blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)}
|
blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)}
|
||||||
procedure StretchDrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas;
|
procedure StretchDrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas;
|
||||||
const DestRect: TRect; Filter: TResizeFilter = rfBilinear);
|
const DestRect: TRect; Filter: TResizeFilter = rfBilinear); virtual;
|
||||||
{ Draws contents of this canvas onto another one using additive blending
|
{ Draws contents of this canvas onto another one using additive blending
|
||||||
(source and dest factors are bfOne).}
|
(source and dest factors are bfOne).}
|
||||||
procedure StretchDrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas;
|
procedure StretchDrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas;
|
||||||
|
@ -286,10 +294,36 @@ type
|
||||||
{ Gamma correction of individual color channels. Range is (0, +inf),
|
{ Gamma correction of individual color channels. Range is (0, +inf),
|
||||||
1.0 means no change.}
|
1.0 means no change.}
|
||||||
procedure GammaCorection(Red, Green, Blue: Single);
|
procedure GammaCorection(Red, Green, Blue: Single);
|
||||||
{ Inverts colors of all image pixels, makes negative image.}
|
{ Inverts colors of all image pixels, makes negative image. Ignores alpha channel.}
|
||||||
procedure InvertColors;
|
procedure InvertColors; virtual;
|
||||||
{ Simple single level thresholding with threshold level for each color channel.}
|
{ Simple single level thresholding with threshold level (in range [0, 1])
|
||||||
|
for each color channel.}
|
||||||
procedure Threshold(Red, Green, Blue: Single);
|
procedure Threshold(Red, Green, Blue: Single);
|
||||||
|
{ Adjusts the color levels of the image by scaling the
|
||||||
|
colors falling between specified white and black points to full [0, 1] range.
|
||||||
|
The black point specifies the darkest color in the image, white point
|
||||||
|
specifies the lightest color, and mid point is gamma aplied to image.
|
||||||
|
Black and white point must be in range [0, 1].}
|
||||||
|
procedure AdjustColorLevels(BlackPoint, WhitePoint: Single; MidPoint: Single = 1.0);
|
||||||
|
{ Premultiplies color channel values by alpha. Needed for some platforms/APIs
|
||||||
|
to display images with alpha properly.}
|
||||||
|
procedure PremultiplyAlpha;
|
||||||
|
{ Reverses PremultiplyAlpha operation.}
|
||||||
|
procedure UnPremultiplyAlpha;
|
||||||
|
|
||||||
|
{ Calculates image histogram for each channel and also gray values. Each
|
||||||
|
channel has 256 values available. Channel values of data formats with higher
|
||||||
|
precision are scaled and rounded. Example: Red[126] specifies number of pixels
|
||||||
|
in image with red channel = 126.}
|
||||||
|
procedure GetHistogram(out Red, Green, Blue, Alpha, Gray: THistogramArray);
|
||||||
|
{ Fills image channel with given value leaving other channels intact.
|
||||||
|
Use ChannelAlpha, ChannelRed, etc. constants from ImagingTypes as
|
||||||
|
channel identifier.}
|
||||||
|
procedure FillChannel(ChannelId: Integer; NewChannelValue: Byte); overload;
|
||||||
|
{ Fills image channel with given value leaving other channels intact.
|
||||||
|
Use ChannelAlpha, ChannelRed, etc. constants from ImagingTypes as
|
||||||
|
channel identifier.}
|
||||||
|
procedure FillChannelFP(ChannelId: Integer; NewChannelValue: Single); overload;
|
||||||
|
|
||||||
{ Color used when drawing lines, frames, and outlines of objects.}
|
{ Color used when drawing lines, frames, and outlines of objects.}
|
||||||
property PenColor32: TColor32 read FPenColor32 write SetPenColor32;
|
property PenColor32: TColor32 read FPenColor32 write SetPenColor32;
|
||||||
|
@ -337,6 +371,7 @@ type
|
||||||
TFastARGB32Canvas = class(TImagingCanvas)
|
TFastARGB32Canvas = class(TImagingCanvas)
|
||||||
protected
|
protected
|
||||||
FScanlines: PScanlineArray;
|
FScanlines: PScanlineArray;
|
||||||
|
procedure AlphaBlendPixels(SrcPix, DestPix: PColor32Rec); {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
function GetPixel32(X, Y: LongInt): TColor32; override;
|
function GetPixel32(X, Y: LongInt): TColor32; override;
|
||||||
procedure SetPixel32(X, Y: LongInt; const Value: TColor32); override;
|
procedure SetPixel32(X, Y: LongInt; const Value: TColor32); override;
|
||||||
public
|
public
|
||||||
|
@ -344,6 +379,11 @@ type
|
||||||
|
|
||||||
procedure UpdateCanvasState; override;
|
procedure UpdateCanvasState; override;
|
||||||
|
|
||||||
|
procedure DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer); override;
|
||||||
|
procedure StretchDrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas;
|
||||||
|
const DestRect: TRect; Filter: TResizeFilter = rfBilinear); override;
|
||||||
|
procedure InvertColors; override;
|
||||||
|
|
||||||
property Scanlines: PScanlineArray read FScanlines;
|
property Scanlines: PScanlineArray read FScanlines;
|
||||||
|
|
||||||
class function GetSupportedFormats: TImageFormats; override;
|
class function GetSupportedFormats: TImageFormats; override;
|
||||||
|
@ -600,13 +640,16 @@ procedure PixelAlphaProc(const SrcPix: TColorFPRec; DestPtr: PByte;
|
||||||
DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor);
|
DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor);
|
||||||
var
|
var
|
||||||
DestPix: TColorFPRec;
|
DestPix: TColorFPRec;
|
||||||
|
SrcAlpha, DestAlpha: Single;
|
||||||
begin
|
begin
|
||||||
DestPix := DestInfo.GetPixelFP(DestPtr, DestInfo, nil);
|
DestPix := DestInfo.GetPixelFP(DestPtr, DestInfo, nil);
|
||||||
// Blend the two pixels (Src 'over' Dest alpha composition operation)
|
// Blend the two pixels (Src 'over' Dest alpha composition operation)
|
||||||
DestPix.R := SrcPix.R * SrcPix.A + DestPix.R * DestPix.A * (1.0 - SrcPix.A);
|
DestPix.A := SrcPix.A + DestPix.A - SrcPix.A * DestPix.A;
|
||||||
DestPix.G := SrcPix.G * SrcPix.A + DestPix.G * DestPix.A * (1.0 - SrcPix.A);
|
SrcAlpha := IffFloat(DestPix.A = 0, 0, SrcPix.A / DestPix.A);
|
||||||
DestPix.B := SrcPix.B * SrcPix.A + DestPix.B * DestPix.A * (1.0 - SrcPix.A);
|
DestAlpha := 1.0 - SrcAlpha;
|
||||||
DestPix.A := SrcPix.A + DestPix.A * (1.0 - SrcPix.A);
|
DestPix.R := SrcPix.R * SrcAlpha + DestPix.R * DestAlpha;
|
||||||
|
DestPix.G := SrcPix.G * SrcAlpha + DestPix.G * DestAlpha;
|
||||||
|
DestPix.B := SrcPix.B * SrcAlpha + DestPix.B * DestAlpha;
|
||||||
// Write blended pixel
|
// Write blended pixel
|
||||||
DestInfo.SetPixelFP(DestPtr, DestInfo, nil, DestPix);
|
DestInfo.SetPixelFP(DestPtr, DestInfo, nil, DestPix);
|
||||||
end;
|
end;
|
||||||
|
@ -691,7 +734,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TransformContrastBrightness(const Pixel: TColorFPRec; C, B, Ignore: Single): TColorFPRec;
|
function TransformContrastBrightness(const Pixel: TColorFPRec; C, B, P3: Single): TColorFPRec;
|
||||||
begin
|
begin
|
||||||
Result.A := Pixel.A;
|
Result.A := Pixel.A;
|
||||||
Result.R := Pixel.R * C + B;
|
Result.R := Pixel.R * C + B;
|
||||||
|
@ -707,7 +750,7 @@ begin
|
||||||
Result.B := Power(Pixel.B, 1.0 / B);
|
Result.B := Power(Pixel.B, 1.0 / B);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TransformInvert(const Pixel: TColorFPRec; A, B, C: Single): TColorFPRec;
|
function TransformInvert(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
|
||||||
begin
|
begin
|
||||||
Result.A := Pixel.A;
|
Result.A := Pixel.A;
|
||||||
Result.R := 1.0 - Pixel.R;
|
Result.R := 1.0 - Pixel.R;
|
||||||
|
@ -723,6 +766,49 @@ begin
|
||||||
Result.B := IffFloat(Pixel.B >= B, 1.0, 0.0);
|
Result.B := IffFloat(Pixel.B >= B, 1.0, 0.0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TransformLevels(const Pixel: TColorFPRec; BlackPoint, WhitePoint, Exp: Single): TColorFPRec;
|
||||||
|
begin
|
||||||
|
Result.A := Pixel.A;
|
||||||
|
if Pixel.R > BlackPoint then
|
||||||
|
Result.R := Power((Pixel.R - BlackPoint) / (WhitePoint - BlackPoint), Exp)
|
||||||
|
else
|
||||||
|
Result.R := 0.0;
|
||||||
|
if Pixel.G > BlackPoint then
|
||||||
|
Result.G := Power((Pixel.G - BlackPoint) / (WhitePoint - BlackPoint), Exp)
|
||||||
|
else
|
||||||
|
Result.G := 0.0;
|
||||||
|
if Pixel.B > BlackPoint then
|
||||||
|
Result.B := Power((Pixel.B - BlackPoint) / (WhitePoint - BlackPoint), Exp)
|
||||||
|
else
|
||||||
|
Result.B := 0.0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TransformPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
|
||||||
|
begin
|
||||||
|
Result.A := Pixel.A;
|
||||||
|
Result.R := Result.R * Pixel.A;
|
||||||
|
Result.G := Result.G * Pixel.A;
|
||||||
|
Result.B := Result.B * Pixel.A;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TransformUnPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
|
||||||
|
begin
|
||||||
|
Result.A := Pixel.A;
|
||||||
|
if Pixel.A <> 0.0 then
|
||||||
|
begin
|
||||||
|
Result.R := Result.R / Pixel.A;
|
||||||
|
Result.G := Result.G / Pixel.A;
|
||||||
|
Result.B := Result.B / Pixel.A;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result.R := 0;
|
||||||
|
Result.G := 0;
|
||||||
|
Result.B := 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TImagingCanvas class implementation }
|
{ TImagingCanvas class implementation }
|
||||||
|
|
||||||
constructor TImagingCanvas.CreateForData(ImageDataPointer: PImageData);
|
constructor TImagingCanvas.CreateForData(ImageDataPointer: PImageData);
|
||||||
|
@ -1175,6 +1261,98 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.FloodFill(X, Y: Integer; BoundaryFillMode: Boolean);
|
||||||
|
var
|
||||||
|
Stack: array of TPoint;
|
||||||
|
StackPos, Y1: Integer;
|
||||||
|
OldColor: TColor32;
|
||||||
|
SpanLeft, SpanRight: Boolean;
|
||||||
|
|
||||||
|
procedure Push(AX, AY: Integer);
|
||||||
|
begin
|
||||||
|
if StackPos < High(Stack) then
|
||||||
|
begin
|
||||||
|
Inc(StackPos);
|
||||||
|
Stack[StackPos].X := AX;
|
||||||
|
Stack[StackPos].Y := AY;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
SetLength(Stack, Length(Stack) + FPData.Width);
|
||||||
|
Push(AX, AY);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Pop(out AX, AY: Integer): Boolean;
|
||||||
|
begin
|
||||||
|
if StackPos > 0 then
|
||||||
|
begin
|
||||||
|
AX := Stack[StackPos].X;
|
||||||
|
AY := Stack[StackPos].Y;
|
||||||
|
Dec(StackPos);
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Compare(AX, AY: Integer): Boolean;
|
||||||
|
var
|
||||||
|
Color: TColor32;
|
||||||
|
begin
|
||||||
|
Color := GetPixel32(AX, AY);
|
||||||
|
if BoundaryFillMode then
|
||||||
|
Result := (Color <> FFillColor32) and (Color <> FPenColor32)
|
||||||
|
else
|
||||||
|
Result := Color = OldColor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Scanline Floodfill Algorithm With Stack
|
||||||
|
// http://student.kuleuven.be/~m0216922/CG/floodfill.html
|
||||||
|
|
||||||
|
if not PtInRect(FClipRect, Point(X, Y)) then Exit;
|
||||||
|
|
||||||
|
SetLength(Stack, FPData.Width * 4);
|
||||||
|
StackPos := 0;
|
||||||
|
|
||||||
|
OldColor := GetPixel32(X, Y);
|
||||||
|
|
||||||
|
Push(X, Y);
|
||||||
|
|
||||||
|
while Pop(X, Y) do
|
||||||
|
begin
|
||||||
|
Y1 := Y;
|
||||||
|
while (Y1 >= FClipRect.Top) and Compare(X, Y1) do
|
||||||
|
Dec(Y1);
|
||||||
|
|
||||||
|
Inc(Y1);
|
||||||
|
SpanLeft := False;
|
||||||
|
SpanRight := False;
|
||||||
|
|
||||||
|
while (Y1 < FClipRect.Bottom) and Compare(X, Y1) do
|
||||||
|
begin
|
||||||
|
SetPixel32(X, Y1, FFillColor32);
|
||||||
|
if not SpanLeft and (X > FClipRect.Left) and Compare(X - 1, Y1) then
|
||||||
|
begin
|
||||||
|
Push(X - 1, Y1);
|
||||||
|
SpanLeft := True;
|
||||||
|
end
|
||||||
|
else if SpanLeft and (X > FClipRect.Left) and not Compare(X - 1, Y1) then
|
||||||
|
SpanLeft := False
|
||||||
|
else if not SpanRight and (X < FClipRect.Right - 1) and Compare(X + 1, Y1)then
|
||||||
|
begin
|
||||||
|
Push(X + 1, Y1);
|
||||||
|
SpanRight := True;
|
||||||
|
end
|
||||||
|
else if SpanRight and (X < FClipRect.Right - 1) and not Compare(X + 1, Y1) then
|
||||||
|
SpanRight := False;
|
||||||
|
|
||||||
|
Inc(Y1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TImagingCanvas.DrawInternal(const SrcRect: TRect;
|
procedure TImagingCanvas.DrawInternal(const SrcRect: TRect;
|
||||||
DestCanvas: TImagingCanvas; DestX, DestY: Integer; SrcFactor,
|
DestCanvas: TImagingCanvas; DestX, DestY: Integer; SrcFactor,
|
||||||
DestFactor: TBlendingFactor; PixelWriteProc: TPixelWriteProc);
|
DestFactor: TBlendingFactor; PixelWriteProc: TPixelWriteProc);
|
||||||
|
@ -1533,7 +1711,7 @@ end;
|
||||||
procedure TImagingCanvas.ModifyContrastBrightness(Contrast, Brightness: Single);
|
procedure TImagingCanvas.ModifyContrastBrightness(Contrast, Brightness: Single);
|
||||||
begin
|
begin
|
||||||
PointTransform(TransformContrastBrightness, 1.0 + Contrast / 100,
|
PointTransform(TransformContrastBrightness, 1.0 + Contrast / 100,
|
||||||
Brightness / 100, 0.0);
|
Brightness / 100, 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TImagingCanvas.GammaCorection(Red, Green, Blue: Single);
|
procedure TImagingCanvas.GammaCorection(Red, Green, Blue: Single);
|
||||||
|
@ -1551,6 +1729,98 @@ begin
|
||||||
PointTransform(TransformThreshold, Red, Green, Blue);
|
PointTransform(TransformThreshold, Red, Green, Blue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.AdjustColorLevels(BlackPoint, WhitePoint, MidPoint: Single);
|
||||||
|
begin
|
||||||
|
PointTransform(TransformLevels, BlackPoint, WhitePoint, 1.0 / MidPoint);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.PremultiplyAlpha;
|
||||||
|
begin
|
||||||
|
PointTransform(TransformPremultiplyAlpha, 0, 0, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.UnPremultiplyAlpha;
|
||||||
|
begin
|
||||||
|
PointTransform(TransformUnPremultiplyAlpha, 0, 0, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.GetHistogram(out Red, Green, Blue, Alpha,
|
||||||
|
Gray: THistogramArray);
|
||||||
|
var
|
||||||
|
X, Y, Bpp: Integer;
|
||||||
|
PixPointer: PByte;
|
||||||
|
Color32: TColor32Rec;
|
||||||
|
begin
|
||||||
|
FillChar(Red, SizeOf(Red), 0);
|
||||||
|
FillChar(Green, SizeOf(Green), 0);
|
||||||
|
FillChar(Blue, SizeOf(Blue), 0);
|
||||||
|
FillChar(Alpha, SizeOf(Alpha), 0);
|
||||||
|
FillChar(Gray, SizeOf(Gray), 0);
|
||||||
|
|
||||||
|
Bpp := FFormatInfo.BytesPerPixel;
|
||||||
|
|
||||||
|
for Y := FClipRect.Top to FClipRect.Bottom - 1 do
|
||||||
|
begin
|
||||||
|
PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp];
|
||||||
|
for X := FClipRect.Left to FClipRect.Right - 1 do
|
||||||
|
begin
|
||||||
|
Color32 := FFormatInfo.GetPixel32(PixPointer, @FFormatInfo, FPData.Palette);
|
||||||
|
|
||||||
|
Inc(Red[Color32.R]);
|
||||||
|
Inc(Green[Color32.G]);
|
||||||
|
Inc(Blue[Color32.B]);
|
||||||
|
Inc(Alpha[Color32.A]);
|
||||||
|
Inc(Gray[Round(GrayConv.R * Color32.R + GrayConv.G * Color32.G + GrayConv.B * Color32.B)]);
|
||||||
|
|
||||||
|
Inc(PixPointer, Bpp);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.FillChannel(ChannelId: Integer; NewChannelValue: Byte);
|
||||||
|
var
|
||||||
|
X, Y, Bpp: Integer;
|
||||||
|
PixPointer: PByte;
|
||||||
|
Color32: TColor32Rec;
|
||||||
|
begin
|
||||||
|
Bpp := FFormatInfo.BytesPerPixel;
|
||||||
|
|
||||||
|
for Y := FClipRect.Top to FClipRect.Bottom - 1 do
|
||||||
|
begin
|
||||||
|
PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp];
|
||||||
|
for X := FClipRect.Left to FClipRect.Right - 1 do
|
||||||
|
begin
|
||||||
|
Color32 := FFormatInfo.GetPixel32(PixPointer, @FFormatInfo, FPData.Palette);
|
||||||
|
Color32.Channels[ChannelId] := NewChannelValue;
|
||||||
|
FFormatInfo.SetPixel32(PixPointer, @FFormatInfo, FPData.Palette, Color32);
|
||||||
|
|
||||||
|
Inc(PixPointer, Bpp);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TImagingCanvas.FillChannelFP(ChannelId: Integer; NewChannelValue: Single);
|
||||||
|
var
|
||||||
|
X, Y, Bpp: Integer;
|
||||||
|
PixPointer: PByte;
|
||||||
|
ColorFP: TColorFPRec;
|
||||||
|
begin
|
||||||
|
Bpp := FFormatInfo.BytesPerPixel;
|
||||||
|
|
||||||
|
for Y := FClipRect.Top to FClipRect.Bottom - 1 do
|
||||||
|
begin
|
||||||
|
PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp];
|
||||||
|
for X := FClipRect.Left to FClipRect.Right - 1 do
|
||||||
|
begin
|
||||||
|
ColorFP := FFormatInfo.GetPixelFP(PixPointer, @FFormatInfo, FPData.Palette);
|
||||||
|
ColorFP.Channels[ChannelId] := NewChannelValue;
|
||||||
|
FFormatInfo.SetPixelFP(PixPointer, @FFormatInfo, FPData.Palette, ColorFP);
|
||||||
|
|
||||||
|
Inc(PixPointer, Bpp);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
class function TImagingCanvas.GetSupportedFormats: TImageFormats;
|
class function TImagingCanvas.GetSupportedFormats: TImageFormats;
|
||||||
begin
|
begin
|
||||||
Result := [ifIndex8..Pred(ifDXT1)];
|
Result := [ifIndex8..Pred(ifDXT1)];
|
||||||
|
@ -1564,6 +1834,55 @@ begin
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFastARGB32Canvas.AlphaBlendPixels(SrcPix, DestPix: PColor32Rec);
|
||||||
|
var
|
||||||
|
SrcAlpha, DestAlpha, FinalAlpha: Integer;
|
||||||
|
begin
|
||||||
|
FinalAlpha := SrcPix.A + 1 + (DestPix.A * (256 - SrcPix.A)) shr 8;
|
||||||
|
if FinalAlpha = 0 then
|
||||||
|
SrcAlpha := 0
|
||||||
|
else
|
||||||
|
SrcAlpha := (SrcPix.A shl 8) div FinalAlpha;
|
||||||
|
DestAlpha := 256 - SrcAlpha;
|
||||||
|
|
||||||
|
DestPix.A := ClampToByte(FinalAlpha);
|
||||||
|
DestPix.R := (SrcPix.R * SrcAlpha + DestPix.R * DestAlpha) shr 8;
|
||||||
|
DestPix.G := (SrcPix.G * SrcAlpha + DestPix.G * DestAlpha) shr 8;
|
||||||
|
DestPix.B := (SrcPix.B * SrcAlpha + DestPix.B * DestAlpha) shr 8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFastARGB32Canvas.DrawAlpha(const SrcRect: TRect;
|
||||||
|
DestCanvas: TImagingCanvas; DestX, DestY: Integer);
|
||||||
|
var
|
||||||
|
X, Y, SrcX, SrcY, Width, Height: Integer;
|
||||||
|
SrcPix, DestPix: PColor32Rec;
|
||||||
|
begin
|
||||||
|
if DestCanvas.ClassType <> Self.ClassType then
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
SrcX := SrcRect.Left;
|
||||||
|
SrcY := SrcRect.Top;
|
||||||
|
Width := SrcRect.Right - SrcRect.Left;
|
||||||
|
Height := SrcRect.Bottom - SrcRect.Top;
|
||||||
|
ClipCopyBounds(SrcX, SrcY, Width, Height, DestX, DestY,
|
||||||
|
FPData.Width, FPData.Height, DestCanvas.ClipRect);
|
||||||
|
|
||||||
|
for Y := 0 to Height - 1 do
|
||||||
|
begin
|
||||||
|
SrcPix := @FScanlines[SrcY + Y, SrcX];
|
||||||
|
DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[DestY + Y, DestX];
|
||||||
|
for X := 0 to Width - 1 do
|
||||||
|
begin
|
||||||
|
AlphaBlendPixels(SrcPix, DestPix);
|
||||||
|
Inc(SrcPix);
|
||||||
|
Inc(DestPix);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFastARGB32Canvas.GetPixel32(X, Y: LongInt): TColor32;
|
function TFastARGB32Canvas.GetPixel32(X, Y: LongInt): TColor32;
|
||||||
begin
|
begin
|
||||||
Result := FScanlines[Y, X].Color;
|
Result := FScanlines[Y, X].Color;
|
||||||
|
@ -1578,6 +1897,189 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFastARGB32Canvas.StretchDrawAlpha(const SrcRect: TRect;
|
||||||
|
DestCanvas: TImagingCanvas; const DestRect: TRect; Filter: TResizeFilter);
|
||||||
|
var
|
||||||
|
X, Y, ScaleX, ScaleY, Yp, Xp, Weight1, Weight2, Weight3, Weight4,
|
||||||
|
FracX, FracY, InvFracY, T1, T2: Integer;
|
||||||
|
SrcX, SrcY, SrcWidth, SrcHeight: Integer;
|
||||||
|
DestX, DestY, DestWidth, DestHeight: Integer;
|
||||||
|
SrcLine, SrcLine2: PColor32RecArray;
|
||||||
|
DestPix: PColor32Rec;
|
||||||
|
Accum: TColor32Rec;
|
||||||
|
begin
|
||||||
|
if (Filter = rfBicubic) or (DestCanvas.ClassType <> Self.ClassType) then
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
SrcX := SrcRect.Left;
|
||||||
|
SrcY := SrcRect.Top;
|
||||||
|
SrcWidth := SrcRect.Right - SrcRect.Left;
|
||||||
|
SrcHeight := SrcRect.Bottom - SrcRect.Top;
|
||||||
|
DestX := DestRect.Left;
|
||||||
|
DestY := DestRect.Top;
|
||||||
|
DestWidth := DestRect.Right - DestRect.Left;
|
||||||
|
DestHeight := DestRect.Bottom - DestRect.Top;
|
||||||
|
// Clip src and dst rects
|
||||||
|
ClipStretchBounds(SrcX, SrcY, SrcWidth, SrcHeight, DestX, DestY, DestWidth, DestHeight,
|
||||||
|
FPData.Width, FPData.Height, DestCanvas.ClipRect);
|
||||||
|
ScaleX := (SrcWidth shl 16) div DestWidth;
|
||||||
|
ScaleY := (SrcHeight shl 16) div DestHeight;
|
||||||
|
|
||||||
|
// Nearest and linear filtering using fixed point math
|
||||||
|
|
||||||
|
if Filter = rfNearest then
|
||||||
|
begin
|
||||||
|
Yp := 0;
|
||||||
|
for Y := DestY to DestY + DestHeight - 1 do
|
||||||
|
begin
|
||||||
|
Xp := 0;
|
||||||
|
SrcLine := @FScanlines[SrcY + Yp shr 16, SrcX];
|
||||||
|
DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[Y, DestX];
|
||||||
|
for X := 0 to DestWidth - 1 do
|
||||||
|
begin
|
||||||
|
AlphaBlendPixels(@SrcLine[Xp shr 16], DestPix);
|
||||||
|
Inc(DestPix);
|
||||||
|
Inc(Xp, ScaleX);
|
||||||
|
end;
|
||||||
|
Inc(Yp, ScaleY);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Yp := (ScaleY shr 1) - $8000;
|
||||||
|
for Y := DestY to DestY + DestHeight - 1 do
|
||||||
|
begin
|
||||||
|
DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[Y, DestX];
|
||||||
|
if Yp < 0 then
|
||||||
|
begin
|
||||||
|
T1 := 0;
|
||||||
|
FracY := 0;
|
||||||
|
InvFracY := $10000;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
T1 := Yp shr 16;
|
||||||
|
FracY := Yp and $FFFF;
|
||||||
|
InvFracY := (not Yp and $FFFF) + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
T2 := Iff(T1 < SrcHeight - 1, T1 + 1, T1);
|
||||||
|
SrcLine := @Scanlines[T1 + SrcY, SrcX];
|
||||||
|
SrcLine2 := @Scanlines[T2 + SrcY, SrcX];
|
||||||
|
Xp := (ScaleX shr 1) - $8000;
|
||||||
|
|
||||||
|
for X := 0 to DestWidth - 1 do
|
||||||
|
begin
|
||||||
|
if Xp < 0 then
|
||||||
|
begin
|
||||||
|
T1 := 0;
|
||||||
|
FracX := 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
T1 := Xp shr 16;
|
||||||
|
FracX := Xp and $FFFF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
T2 := Iff(T1 < SrcWidth - 1, T1 + 1, T1);
|
||||||
|
Weight2:= (Cardinal(InvFracY) * FracX) shr 16; // cast to Card, Int can overflow gere
|
||||||
|
Weight1:= InvFracY - Weight2;
|
||||||
|
Weight4:= (Cardinal(FracY) * FracX) shr 16;
|
||||||
|
Weight3:= FracY - Weight4;
|
||||||
|
|
||||||
|
Accum.B := (SrcLine[T1].B * Weight1 + SrcLine[T2].B * Weight2 +
|
||||||
|
SrcLine2[T1].B * Weight3 + SrcLine2[T2].B * Weight4 + $8000) shr 16;
|
||||||
|
Accum.G := (SrcLine[T1].G * Weight1 + SrcLine[T2].G * Weight2 +
|
||||||
|
SrcLine2[T1].G * Weight3 + SrcLine2[T2].G * Weight4 + $8000) shr 16;
|
||||||
|
Accum.R := (SrcLine[T1].R * Weight1 + SrcLine[T2].R * Weight2 +
|
||||||
|
SrcLine2[T1].R * Weight3 + SrcLine2[T2].R * Weight4 + $8000) shr 16;
|
||||||
|
Accum.A := (SrcLine[T1].A * Weight1 + SrcLine[T2].A * Weight2 +
|
||||||
|
SrcLine2[T1].A * Weight3 + SrcLine2[T2].A * Weight4 + $8000) shr 16;
|
||||||
|
|
||||||
|
AlphaBlendPixels(@Accum, DestPix);
|
||||||
|
|
||||||
|
Inc(Xp, ScaleX);
|
||||||
|
Inc(DestPix);
|
||||||
|
end;
|
||||||
|
Inc(Yp, ScaleY);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{
|
||||||
|
|
||||||
|
// Generate mapping tables
|
||||||
|
MapX := BuildMappingTable(DestX, DestX + DestWidth, SrcX, SrcX + SrcWidth,
|
||||||
|
FPData.Width, FilterFunction, Radius, False);
|
||||||
|
MapY := BuildMappingTable(DestY, DestY + DestHeight, SrcY, SrcY + SrcHeight,
|
||||||
|
FPData.Height, FilterFunction, Radius, False);
|
||||||
|
FindExtremes(MapX, XMinimum, XMaximum);
|
||||||
|
SetLength(LineBuffer, XMaximum - XMinimum + 1);
|
||||||
|
|
||||||
|
for J := 0 to DestHeight - 1 do
|
||||||
|
begin
|
||||||
|
ClusterY := MapY[J];
|
||||||
|
for X := XMinimum to XMaximum do
|
||||||
|
begin
|
||||||
|
AccumA := 0;
|
||||||
|
AccumR := 0;
|
||||||
|
AccumG := 0;
|
||||||
|
AccumB := 0;
|
||||||
|
for Y := 0 to Length(ClusterY) - 1 do
|
||||||
|
begin
|
||||||
|
Weight := Round(ClusterY[Y].Weight * 256);
|
||||||
|
SrcColor := FScanlines[ClusterY[Y].Pos, X];
|
||||||
|
|
||||||
|
AccumB := AccumB + SrcColor.B * Weight;
|
||||||
|
AccumG := AccumG + SrcColor.G * Weight;
|
||||||
|
AccumR := AccumR + SrcColor.R * Weight;
|
||||||
|
AccumA := AccumA + SrcColor.A * Weight;
|
||||||
|
end;
|
||||||
|
with LineBuffer[X - XMinimum] do
|
||||||
|
begin
|
||||||
|
A := AccumA;
|
||||||
|
R := AccumR;
|
||||||
|
G := AccumG;
|
||||||
|
B := AccumB;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
DestPtr := @TFastARGB32Canvas(DestCanvas).FScanlines[DestY + J, DestX];
|
||||||
|
|
||||||
|
for I := 0 to DestWidth - 1 do
|
||||||
|
begin
|
||||||
|
ClusterX := MapX[I];
|
||||||
|
AccumA := 0;
|
||||||
|
AccumR := 0;
|
||||||
|
AccumG := 0;
|
||||||
|
AccumB := 0;
|
||||||
|
for X := 0 to Length(ClusterX) - 1 do
|
||||||
|
begin
|
||||||
|
Weight := Round(ClusterX[X].Weight * 256);
|
||||||
|
with LineBuffer[ClusterX[X].Pos - XMinimum] do
|
||||||
|
begin
|
||||||
|
AccumB := AccumB + B * Weight;
|
||||||
|
AccumG := AccumG + G * Weight;
|
||||||
|
AccumR := AccumR + R * Weight;
|
||||||
|
AccumA := AccumA + A * Weight;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
AccumA := ClampInt(AccumA, 0, $00FF0000);
|
||||||
|
AccumR := ClampInt(AccumR, 0, $00FF0000);
|
||||||
|
AccumG := ClampInt(AccumG, 0, $00FF0000);
|
||||||
|
AccumB := ClampInt(AccumB, 0, $00FF0000);
|
||||||
|
SrcColor.Color := (Cardinal(AccumA and $00FF0000) shl 8) or
|
||||||
|
(AccumR and $00FF0000) or ((AccumG and $00FF0000) shr 8) or ((AccumB and $00FF0000) shr 16);
|
||||||
|
|
||||||
|
AlphaBlendPixels(@SrcColor, DestPtr);
|
||||||
|
|
||||||
|
Inc(DestPtr);
|
||||||
|
end;
|
||||||
|
end; }
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TFastARGB32Canvas.UpdateCanvasState;
|
procedure TFastARGB32Canvas.UpdateCanvasState;
|
||||||
var
|
var
|
||||||
I: LongInt;
|
I: LongInt;
|
||||||
|
@ -1601,6 +2103,24 @@ begin
|
||||||
Result := [ifA8R8G8B8];
|
Result := [ifA8R8G8B8];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFastARGB32Canvas.InvertColors;
|
||||||
|
var
|
||||||
|
X, Y: Integer;
|
||||||
|
PixPtr: PColor32Rec;
|
||||||
|
begin
|
||||||
|
for Y := FClipRect.Top to FClipRect.Bottom - 1 do
|
||||||
|
begin
|
||||||
|
PixPtr := @FScanlines[Y, FClipRect.Left];
|
||||||
|
for X := FClipRect.Left to FClipRect.Right - 1 do
|
||||||
|
begin
|
||||||
|
PixPtr.R := not PixPtr.R;
|
||||||
|
PixPtr.G := not PixPtr.G;
|
||||||
|
PixPtr.B := not PixPtr.B;
|
||||||
|
Inc(PixPtr);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterCanvas(TFastARGB32Canvas);
|
RegisterCanvas(TFastARGB32Canvas);
|
||||||
|
|
||||||
|
@ -1616,6 +2136,19 @@ finalization
|
||||||
- add blending (*image and object drawing)
|
- add blending (*image and object drawing)
|
||||||
- more objects (arc, polygon)
|
- more objects (arc, polygon)
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added some methods to TFastARGB32Canvas (InvertColors, DrawAlpha/StretchDrawAlpha)
|
||||||
|
- Fixed DrawAlpha/StretchDrawAlpha destination alpha calculation.
|
||||||
|
- Added PremultiplyAlpha and UnPremultiplyAlpha methods.
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added FillChannel methods.
|
||||||
|
- Added FloodFill method.
|
||||||
|
- Added GetHistogram method.
|
||||||
|
- Fixed "Invalid FP operation" in AdjustColorLevels in FPC compiled exes
|
||||||
|
(thanks to Carlos González).
|
||||||
|
- Added TImagingCanvas.AdjustColorLevels method.
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
||||||
- Fixed error that could cause AV in linear and nonlinear filters.
|
- Fixed error that could cause AV in linear and nonlinear filters.
|
||||||
- Added blended rect filling function FillRectBlend.
|
- Added blended rect filling function FillRectBlend.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingClasses.pas 124 2008-04-21 09:47:07Z galfar $
|
$Id: ImagingClasses.pas 173 2009-09-04 17:05:52Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -68,7 +68,7 @@ type
|
||||||
constructor CreateFromImage(AImage: TBaseImage);
|
constructor CreateFromImage(AImage: TBaseImage);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
{ Returns info about current image.}
|
{ Returns info about current image.}
|
||||||
function ToString: string;
|
function ToString: string; {$IF Defined(DCC) and (CompilerVersion >= 20.0)}override;{$IFEND}
|
||||||
|
|
||||||
{ Creates a new image data with the given size and format. Old image
|
{ Creates a new image data with the given size and format. Old image
|
||||||
data is lost. Works only for the current image of TMultiImage.}
|
data is lost. Works only for the current image of TMultiImage.}
|
||||||
|
@ -81,8 +81,8 @@ type
|
||||||
{ Mirrors current image. Reverses the image along its vertical axis the left
|
{ Mirrors current image. Reverses the image along its vertical axis the left
|
||||||
side becomes the right and vice versa.}
|
side becomes the right and vice versa.}
|
||||||
procedure Mirror;
|
procedure Mirror;
|
||||||
{ Rotates image by 90, 180, 270, -90, -180, or -270 degrees counterclockwise.}
|
{ Rotates image by Angle degrees counterclockwise.}
|
||||||
procedure Rotate(Angle: LongInt);
|
procedure Rotate(Angle: Single);
|
||||||
{ Copies rectangular part of SrcImage to DstImage. No blending is performed -
|
{ Copies rectangular part of SrcImage to DstImage. No blending is performed -
|
||||||
alpha is simply copied to destination image. Operates also with
|
alpha is simply copied to destination image. Operates also with
|
||||||
negative X and Y coordinates.
|
negative X and Y coordinates.
|
||||||
|
@ -451,7 +451,7 @@ begin
|
||||||
DoPixelsChanged;
|
DoPixelsChanged;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TBaseImage.Rotate(Angle: LongInt);
|
procedure TBaseImage.Rotate(Angle: Single);
|
||||||
begin
|
begin
|
||||||
if Valid and Imaging.RotateImage(FPData^, Angle) then
|
if Valid and Imaging.RotateImage(FPData^, Angle) then
|
||||||
DoPixelsChanged;
|
DoPixelsChanged;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingColors.pas 74 2007-03-12 15:04:04Z galfar $
|
$Id: ImagingColors.pas 173 2009-09-04 17:05:52Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -68,6 +68,12 @@ procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||||
{ Converts CMYK to RGB color.}
|
{ Converts CMYK to RGB color.}
|
||||||
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word);
|
||||||
|
|
||||||
|
{ Converts RGB color to YCoCg.}
|
||||||
|
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||||
|
{ Converts YCoCg to RGB color.}
|
||||||
|
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte);
|
||||||
|
@ -149,11 +155,17 @@ procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte);
|
||||||
begin
|
begin
|
||||||
RGBToCMY(R, G, B, C, M, Y);
|
RGBToCMY(R, G, B, C, M, Y);
|
||||||
K := Min(C, Min(M, Y));
|
K := Min(C, Min(M, Y));
|
||||||
if K > 0 then
|
if K = 255 then
|
||||||
begin
|
begin
|
||||||
C := C - K;
|
C := 0;
|
||||||
M := M - K;
|
M := 0;
|
||||||
Y := Y - K;
|
Y := 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
C := ClampToByte(Round((C - K) / (255 - K) * 255));
|
||||||
|
M := ClampToByte(Round((M - K) / (255 - K) * 255));
|
||||||
|
Y := ClampToByte(Round((Y - K) / (255 - K) * 255));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -168,11 +180,17 @@ procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word);
|
||||||
begin
|
begin
|
||||||
RGBToCMY16(R, G, B, C, M, Y);
|
RGBToCMY16(R, G, B, C, M, Y);
|
||||||
K := Min(C, Min(M, Y));
|
K := Min(C, Min(M, Y));
|
||||||
if K > 0 then
|
if K = 65535 then
|
||||||
begin
|
begin
|
||||||
C := C - K;
|
C := 0;
|
||||||
M := M - K;
|
M := 0;
|
||||||
Y := Y - K;
|
Y := 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
C := ClampToWord(Round((C - K) / (65535 - K) * 65535));
|
||||||
|
M := ClampToWord(Round((M - K) / (65535 - K) * 65535));
|
||||||
|
Y := ClampToWord(Round((Y - K) / (65535 - K) * 65535));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -183,12 +201,35 @@ begin
|
||||||
B := 65535 - (Y - MulDiv(Y, K, 65535) + K);
|
B := 65535 - (Y - MulDiv(Y, K, 65535) + K);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte);
|
||||||
|
begin
|
||||||
|
// C and Delphi's SHR behaviour differs for negative numbers, use div instead.
|
||||||
|
Y := ClampToByte(( R + G shl 1 + B + 2) div 4);
|
||||||
|
Co := ClampToByte(( R shl 1 - B shl 1 + 2) div 4 + 128);
|
||||||
|
Cg := ClampToByte((-R + G shl 1 - B + 2) div 4 + 128);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte);
|
||||||
|
var
|
||||||
|
CoInt, CgInt: Integer;
|
||||||
|
begin
|
||||||
|
CoInt := Co - 128;
|
||||||
|
CgInt := Cg - 128;
|
||||||
|
R := ClampToByte(Y + CoInt - CgInt);
|
||||||
|
G := ClampToByte(Y + CgInt);
|
||||||
|
B := ClampToByte(Y - CoInt - CgInt);
|
||||||
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
File Notes:
|
File Notes:
|
||||||
|
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added RGB<>YCoCg conversion functions.
|
||||||
|
- Fixed RGB>>CMYK conversions.
|
||||||
|
|
||||||
-- 0.23 Changes/Bug Fixes -----------------------------------
|
-- 0.23 Changes/Bug Fixes -----------------------------------
|
||||||
- Added RGB<>CMY(K) converion functions for 16 bit channels
|
- Added RGB<>CMY(K) converion functions for 16 bit channels
|
||||||
(needed by PSD loading code).
|
(needed by PSD loading code).
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingComponents.pas 132 2008-08-27 20:37:38Z galfar $
|
$Id: ImagingComponents.pas 171 2009-09-02 01:34:19Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
|
For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
|
||||||
}
|
}
|
||||||
|
|
||||||
{ This unit contains VCL/CLX/LCL TGraphic descendant which uses Imaging library
|
{ This unit contains VCL/LCL TGraphic descendant which uses Imaging library
|
||||||
for saving and loading.}
|
for saving and loading.}
|
||||||
unit ImagingComponents;
|
unit ImagingComponents;
|
||||||
|
|
||||||
|
@ -34,6 +34,17 @@ unit ImagingComponents;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
{$IFDEF LCL}
|
||||||
|
{$DEFINE COMPONENT_SET_LCL}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{$IF not Defined(COMPONENT_SET_LCL) and not Defined(COMPONENT_SET_VCL)}
|
||||||
|
// If no component sets should be used just include empty unit.
|
||||||
|
//DOC-IGNORE-BEGIN
|
||||||
|
implementation
|
||||||
|
//DOC-IGNORE-END
|
||||||
|
{$ELSE}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Types, Classes,
|
SysUtils, Types, Classes,
|
||||||
{$IFDEF MSWINDOWS}
|
{$IFDEF MSWINDOWS}
|
||||||
|
@ -42,10 +53,6 @@ uses
|
||||||
{$IFDEF COMPONENT_SET_VCL}
|
{$IFDEF COMPONENT_SET_VCL}
|
||||||
Graphics,
|
Graphics,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
Qt,
|
|
||||||
QGraphics,
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
InterfaceBase,
|
InterfaceBase,
|
||||||
GraphType,
|
GraphType,
|
||||||
|
@ -71,6 +78,8 @@ type
|
||||||
procedure ReadDataFromStream(Stream: TStream); virtual;
|
procedure ReadDataFromStream(Stream: TStream); virtual;
|
||||||
procedure AssignTo(Dest: TPersistent); override;
|
procedure AssignTo(Dest: TPersistent); override;
|
||||||
public
|
public
|
||||||
|
constructor Create; override;
|
||||||
|
|
||||||
{ Loads new image from the stream. It can load all image
|
{ Loads new image from the stream. It can load all image
|
||||||
file formats supported by Imaging (and enabled of course)
|
file formats supported by Imaging (and enabled of course)
|
||||||
even though it is called by descendant class capable of
|
even though it is called by descendant class capable of
|
||||||
|
@ -114,8 +123,7 @@ type
|
||||||
{ Returns file extensions of this graphic class.}
|
{ Returns file extensions of this graphic class.}
|
||||||
class function GetFileExtensions: string; override;
|
class function GetFileExtensions: string; override;
|
||||||
{ Returns default MIME type of this graphic class.}
|
{ Returns default MIME type of this graphic class.}
|
||||||
function GetMimeType: string; override; // uncomment for Laz 0.9.25 if you get error here
|
function GetMimeType: string; override;
|
||||||
//function GetDefaultMimeType: string; override;
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{ Default (the most common) file extension of this graphic class.}
|
{ Default (the most common) file extension of this graphic class.}
|
||||||
property DefaultFileExt: string read FDefaultFileExt;
|
property DefaultFileExt: string read FDefaultFileExt;
|
||||||
|
@ -123,7 +131,7 @@ type
|
||||||
|
|
||||||
TImagingGraphicForSaveClass = class of TImagingGraphicForSave;
|
TImagingGraphicForSaveClass = class of TImagingGraphicForSave;
|
||||||
|
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
{ TImagingGraphic descendant for loading/saving Windows bitmaps.
|
{ TImagingGraphic descendant for loading/saving Windows bitmaps.
|
||||||
VCL/CLX/LCL all have native support for bitmaps so you might
|
VCL/CLX/LCL all have native support for bitmaps so you might
|
||||||
want to disable this class (although you can save bitmaps with
|
want to disable this class (although you can save bitmaps with
|
||||||
|
@ -140,7 +148,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
{ TImagingGraphic descendant for loading/saving JPEG images.}
|
{ TImagingGraphic descendant for loading/saving JPEG images.}
|
||||||
TImagingJpeg = class(TImagingGraphicForSave)
|
TImagingJpeg = class(TImagingGraphicForSave)
|
||||||
protected
|
protected
|
||||||
|
@ -151,8 +159,7 @@ type
|
||||||
procedure SaveToStream(Stream: TStream); override;
|
procedure SaveToStream(Stream: TStream); override;
|
||||||
class function GetFileFormat: TImageFileFormat; override;
|
class function GetFileFormat: TImageFileFormat; override;
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
//function GetMimeType: string; override; // uncomment for Laz 0.9.25 if you get error here
|
function GetMimeType: string; override;
|
||||||
function GetDefaultMimeType: string; override;
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{ See ImagingJpegQuality option for details.}
|
{ See ImagingJpegQuality option for details.}
|
||||||
property Quality: LongInt read FQuality write FQuality;
|
property Quality: LongInt read FQuality write FQuality;
|
||||||
|
@ -161,7 +168,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_PNG}
|
{$IFNDEF DONT_LINK_PNG}
|
||||||
{ TImagingGraphic descendant for loading/saving PNG images.}
|
{ TImagingGraphic descendant for loading/saving PNG images.}
|
||||||
TImagingPNG = class(TImagingGraphicForSave)
|
TImagingPNG = class(TImagingGraphicForSave)
|
||||||
protected
|
protected
|
||||||
|
@ -178,7 +185,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
{ TImagingGraphic descendant for loading/saving GIF images.}
|
{ TImagingGraphic descendant for loading/saving GIF images.}
|
||||||
TImagingGIF = class(TImagingGraphicForSave)
|
TImagingGIF = class(TImagingGraphicForSave)
|
||||||
public
|
public
|
||||||
|
@ -186,7 +193,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
{ TImagingGraphic descendant for loading/saving Targa images.}
|
{ TImagingGraphic descendant for loading/saving Targa images.}
|
||||||
TImagingTarga = class(TImagingGraphicForSave)
|
TImagingTarga = class(TImagingGraphicForSave)
|
||||||
protected
|
protected
|
||||||
|
@ -200,7 +207,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
{ Compresssion type used when saving DDS files by TImagingDds.}
|
{ Compresssion type used when saving DDS files by TImagingDds.}
|
||||||
TDDSCompresion = (dcNone, dcDXT1, dcDXT3, dcDXT5);
|
TDDSCompresion = (dcNone, dcDXT1, dcDXT3, dcDXT5);
|
||||||
|
|
||||||
|
@ -218,7 +225,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_MNG}
|
{$IFNDEF DONT_LINK_MNG}
|
||||||
{ TImagingGraphic descendant for loading/saving MNG images.}
|
{ TImagingGraphic descendant for loading/saving MNG images.}
|
||||||
TImagingMNG = class(TImagingGraphicForSave)
|
TImagingMNG = class(TImagingGraphicForSave)
|
||||||
protected
|
protected
|
||||||
|
@ -233,8 +240,7 @@ type
|
||||||
procedure SaveToStream(Stream: TStream); override;
|
procedure SaveToStream(Stream: TStream); override;
|
||||||
class function GetFileFormat: TImageFileFormat; override;
|
class function GetFileFormat: TImageFileFormat; override;
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
//function GetMimeType: string; override; // uncomment for Laz 0.9.25 if you get error here
|
function GetMimeType: string; override;
|
||||||
function GetDefaultMimeType: string; override;
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{ See ImagingMNGLossyCompression option for details.}
|
{ See ImagingMNGLossyCompression option for details.}
|
||||||
property LossyCompression: Boolean read FLossyCompression write FLossyCompression;
|
property LossyCompression: Boolean read FLossyCompression write FLossyCompression;
|
||||||
|
@ -251,7 +257,7 @@ type
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_JNG}
|
{$IFNDEF DONT_LINK_JNG}
|
||||||
{ TImagingGraphic descendant for loading/saving JNG images.}
|
{ TImagingGraphic descendant for loading/saving JNG images.}
|
||||||
TImagingJNG = class(TImagingGraphicForSave)
|
TImagingJNG = class(TImagingGraphicForSave)
|
||||||
protected
|
protected
|
||||||
|
@ -328,29 +334,29 @@ procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: T
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IF Defined(UNIX) and Defined(COMPONENT_SET_LCL)}
|
{$IF Defined(LCL)}
|
||||||
{$IFDEF LCLGTK2}
|
{$IF Defined(LCLGTK2)}
|
||||||
GLib2, GDK2, GTK2, GTKDef, GTKProc,
|
GLib2, GDK2, GTK2, GTKDef, GTKProc,
|
||||||
{$ELSE}
|
{$ELSEIF Defined(LCLGTK)}
|
||||||
GDK, GTK, GTKDef, GTKProc,
|
GDK, GTK, GTKDef, GTKProc,
|
||||||
{$ENDIF}
|
{$IFEND}
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
ImagingBitmap,
|
ImagingBitmap,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
ImagingJpeg,
|
ImagingJpeg,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
ImagingGif,
|
ImagingGif,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
ImagingTarga,
|
ImagingTarga,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
ImagingDds,
|
ImagingDds,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IF Defined(LINK_PNG) or Defined(LINK_MNG) or Defined(LINK_JNG)}
|
{$IF not Defined(DONT_LINK_PNG) or not Defined(DONT_LINK_MNG) or not Defined(DONT_LINK_JNG)}
|
||||||
ImagingNetworkGraphics,
|
ImagingNetworkGraphics,
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
ImagingUtility;
|
ImagingUtility;
|
||||||
|
@ -359,9 +365,10 @@ resourcestring
|
||||||
SBadFormatDataToBitmap = 'Cannot find compatible bitmap format for image %s';
|
SBadFormatDataToBitmap = 'Cannot find compatible bitmap format for image %s';
|
||||||
SBadFormatBitmapToData = 'Cannot find compatible data format for bitmap %p';
|
SBadFormatBitmapToData = 'Cannot find compatible data format for bitmap %p';
|
||||||
SBadFormatDisplay = 'Unsupported image format passed';
|
SBadFormatDisplay = 'Unsupported image format passed';
|
||||||
|
SUnsupportedLCLWidgetSet = 'This function is not implemented for current LCL widget set';
|
||||||
SImagingGraphicName = 'Imaging Graphic AllInOne';
|
SImagingGraphicName = 'Imaging Graphic AllInOne';
|
||||||
|
|
||||||
{ Registers types to VCL/CLX/LCL.}
|
{ Registers types to VCL/LCL.}
|
||||||
procedure RegisterTypes;
|
procedure RegisterTypes;
|
||||||
var
|
var
|
||||||
I: LongInt;
|
I: LongInt;
|
||||||
|
@ -387,87 +394,85 @@ var
|
||||||
begin
|
begin
|
||||||
for I := Imaging.GetFileFormatCount - 1 downto 0 do
|
for I := Imaging.GetFileFormatCount - 1 downto 0 do
|
||||||
RegisterFileFormatAllInOne(Imaging.GetFileFormatAtIndex(I));
|
RegisterFileFormatAllInOne(Imaging.GetFileFormatAtIndex(I));
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingGraphic);{$ENDIF}
|
Classes.RegisterClass(TImagingGraphic);
|
||||||
|
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
RegisterFileFormat(TImagingTarga);
|
RegisterFileFormat(TImagingTarga);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingTarga);{$ENDIF}
|
Classes.RegisterClass(TImagingTarga);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
RegisterFileFormat(TImagingDDS);
|
RegisterFileFormat(TImagingDDS);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingDDS);{$ENDIF}
|
Classes.RegisterClass(TImagingDDS);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_JNG}
|
{$IFNDEF DONT_LINK_JNG}
|
||||||
RegisterFileFormat(TImagingJNG);
|
RegisterFileFormat(TImagingJNG);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingJNG);{$ENDIF}
|
Classes.RegisterClass(TImagingJNG);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_MNG}
|
{$IFNDEF DONT_LINK_MNG}
|
||||||
RegisterFileFormat(TImagingMNG);
|
RegisterFileFormat(TImagingMNG);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingMNG);{$ENDIF}
|
Classes.RegisterClass(TImagingMNG);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
RegisterFileFormat(TImagingGIF);
|
RegisterFileFormat(TImagingGIF);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingGIF);{$ENDIF}
|
Classes.RegisterClass(TImagingGIF);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_PNG}
|
{$IFNDEF DONT_LINK_PNG}
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
// Unregister Lazarus´ default PNG loader which crashes on some PNG files
|
// Unregister Lazarus´ default PNG loader which crashes on some PNG files
|
||||||
TPicture.UnregisterGraphicClass(TPortableNetworkGraphic);
|
TPicture.UnregisterGraphicClass(TPortableNetworkGraphic);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
RegisterFileFormat(TImagingPNG);
|
RegisterFileFormat(TImagingPNG);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingPNG);{$ENDIF}
|
Classes.RegisterClass(TImagingPNG);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
RegisterFileFormat(TImagingJpeg);
|
RegisterFileFormat(TImagingJpeg);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingJpeg);{$ENDIF}
|
Classes.RegisterClass(TImagingJpeg);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
RegisterFileFormat(TImagingBitmap);
|
RegisterFileFormat(TImagingBitmap);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingBitmap);{$ENDIF}
|
Classes.RegisterClass(TImagingBitmap);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Unregisters types from VCL/CLX/LCL.}
|
{ Unregisters types from VCL/LCL.}
|
||||||
procedure UnRegisterTypes;
|
procedure UnRegisterTypes;
|
||||||
begin
|
begin
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
TPicture.UnregisterGraphicClass(TImagingBitmap);
|
TPicture.UnregisterGraphicClass(TImagingBitmap);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingBitmap);{$ENDIF}
|
Classes.UnRegisterClass(TImagingBitmap);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
TPicture.UnregisterGraphicClass(TImagingJpeg);
|
TPicture.UnregisterGraphicClass(TImagingJpeg);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingJpeg);{$ENDIF}
|
Classes.UnRegisterClass(TImagingJpeg);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_PNG}
|
{$IFNDEF DONT_LINK_PNG}
|
||||||
TPicture.UnregisterGraphicClass(TImagingPNG);
|
TPicture.UnregisterGraphicClass(TImagingPNG);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingPNG);{$ENDIF}
|
Classes.UnRegisterClass(TImagingPNG);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
TPicture.UnregisterGraphicClass(TImagingGIF);
|
TPicture.UnregisterGraphicClass(TImagingGIF);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingGIF);{$ENDIF}
|
Classes.UnRegisterClass(TImagingGIF);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
TPicture.UnregisterGraphicClass(TImagingTarga);
|
TPicture.UnregisterGraphicClass(TImagingTarga);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingTarga);{$ENDIF}
|
Classes.UnRegisterClass(TImagingTarga);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
TPicture.UnregisterGraphicClass(TImagingDDS);
|
TPicture.UnregisterGraphicClass(TImagingDDS);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingDDS);{$ENDIF}
|
Classes.UnRegisterClass(TImagingDDS);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
TPicture.UnregisterGraphicClass(TImagingGraphic);
|
TPicture.UnregisterGraphicClass(TImagingGraphic);
|
||||||
{$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingGraphic);{$ENDIF}
|
Classes.UnRegisterClass(TImagingGraphic);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat;
|
function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat;
|
||||||
begin
|
begin
|
||||||
case Format of
|
case Format of
|
||||||
{$IFNDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_VCL}
|
||||||
ifIndex8: Result := pf8bit;
|
ifIndex8: Result := pf8bit;
|
||||||
{$ENDIF}
|
|
||||||
{$IF (not Defined(COMPONENT_SET_CLX)) and (not Defined(COMPONENT_SET_LCL))}
|
|
||||||
ifR5G6B5: Result := pf16bit;
|
ifR5G6B5: Result := pf16bit;
|
||||||
ifR8G8B8: Result := pf24bit;
|
ifR8G8B8: Result := pf24bit;
|
||||||
{$IFEND}
|
{$ENDIF}
|
||||||
ifA8R8G8B8,
|
ifA8R8G8B8,
|
||||||
ifX8R8G8B8: Result := pf32bit;
|
ifX8R8G8B8: Result := pf32bit;
|
||||||
else
|
else
|
||||||
|
@ -479,11 +484,9 @@ function PixelFormatToDataFormat(Format: TPixelFormat): TImageFormat;
|
||||||
begin
|
begin
|
||||||
case Format of
|
case Format of
|
||||||
pf8bit: Result := ifIndex8;
|
pf8bit: Result := ifIndex8;
|
||||||
{$IFNDEF COMPONENT_SET_CLX}
|
|
||||||
pf15bit: Result := ifA1R5G5B5;
|
pf15bit: Result := ifA1R5G5B5;
|
||||||
pf16bit: Result := ifR5G6B5;
|
pf16bit: Result := ifR5G6B5;
|
||||||
pf24bit: Result := ifR8G8B8;
|
pf24bit: Result := ifR8G8B8;
|
||||||
{$ENDIF}
|
|
||||||
pf32bit: Result := ifA8R8G8B8;
|
pf32bit: Result := ifA8R8G8B8;
|
||||||
else
|
else
|
||||||
Result := ifUnknown;
|
Result := ifUnknown;
|
||||||
|
@ -499,9 +502,6 @@ var
|
||||||
{$IFDEF COMPONENT_SET_VCL}
|
{$IFDEF COMPONENT_SET_VCL}
|
||||||
LogPalette: TMaxLogPalette;
|
LogPalette: TMaxLogPalette;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
ColorTable: PPalette32;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
RawImage: TRawImage;
|
RawImage: TRawImage;
|
||||||
ImgHandle, ImgMaskHandle: HBitmap;
|
ImgHandle, ImgMaskHandle: HBitmap;
|
||||||
|
@ -517,19 +517,16 @@ begin
|
||||||
if Info.IsFloatingPoint or Info.HasAlphaChannel or Info.IsSpecial then
|
if Info.IsFloatingPoint or Info.HasAlphaChannel or Info.IsSpecial then
|
||||||
Imaging.ConvertImage(WorkData, ifA8R8G8B8)
|
Imaging.ConvertImage(WorkData, ifA8R8G8B8)
|
||||||
else
|
else
|
||||||
{$IFNDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_VCL}
|
||||||
if Info.IsIndexed or Info.HasGrayChannel then
|
if Info.IsIndexed or Info.HasGrayChannel then
|
||||||
Imaging.ConvertImage(WorkData, ifIndex8)
|
Imaging.ConvertImage(WorkData, ifIndex8)
|
||||||
else
|
else if Info.UsePixelFormat then
|
||||||
{$ENDIF}
|
|
||||||
{$IF (not Defined(COMPONENT_SET_CLX)) and (not Defined(COMPONENT_SET_LCL))}
|
|
||||||
if Info.UsePixelFormat then
|
|
||||||
Imaging.ConvertImage(WorkData, ifR5G6B5)
|
Imaging.ConvertImage(WorkData, ifR5G6B5)
|
||||||
else
|
else
|
||||||
Imaging.ConvertImage(WorkData, ifR8G8B8);
|
Imaging.ConvertImage(WorkData, ifR8G8B8);
|
||||||
{$ELSE}
|
{$ELSE}
|
||||||
Imaging.ConvertImage(WorkData, ifA8R8G8B8);
|
Imaging.ConvertImage(WorkData, ifA8R8G8B8);
|
||||||
{$IFEND}
|
{$ENDIF}
|
||||||
|
|
||||||
PF := DataFormatToPixelFormat(WorkData.Format);
|
PF := DataFormatToPixelFormat(WorkData.Format);
|
||||||
GetImageFormatInfo(WorkData.Format, Info);
|
GetImageFormatInfo(WorkData.Format, Info);
|
||||||
|
@ -565,27 +562,13 @@ begin
|
||||||
// Copy scanlines
|
// Copy scanlines
|
||||||
for I := 0 to WorkData.Height - 1 do
|
for I := 0 to WorkData.Height - 1 do
|
||||||
Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes);
|
Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes);
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
Bitmap.Width := WorkData.Width;
|
|
||||||
Bitmap.Height := WorkData.Height;
|
|
||||||
Bitmap.PixelFormat := PF;
|
|
||||||
|
|
||||||
if (PF = pf8bit) and (WorkData.Palette <> nil) then
|
// Delphi 2009 and newer support alpha transparency fro TBitmap
|
||||||
begin
|
{$IF Defined(DELPHI) and (CompilerVersion >= 20.0)}
|
||||||
// Copy palette
|
if Bitmap.PixelFormat = pf32bit then
|
||||||
ColorTable := Bitmap.ColorTable;
|
Bitmap.AlphaFormat := afDefined;
|
||||||
for I := 0 to Info.PaletteEntries - 1 do
|
{$IFEND}
|
||||||
with ColorTable[I] do
|
|
||||||
begin
|
|
||||||
R := WorkData.Palette[I].R;
|
|
||||||
G := WorkData.Palette[I].G;
|
|
||||||
B := WorkData.Palette[I].B;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
// Copy scanlines
|
|
||||||
for I := 0 to WorkData.Height - 1 do
|
|
||||||
Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes);
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
// Create 32bit raw image from image data
|
// Create 32bit raw image from image data
|
||||||
|
@ -594,9 +577,9 @@ begin
|
||||||
begin
|
begin
|
||||||
Width := WorkData.Width;
|
Width := WorkData.Width;
|
||||||
Height := WorkData.Height;
|
Height := WorkData.Height;
|
||||||
BitsPerPixel := Info.BytesPerPixel * 8;
|
BitsPerPixel := 32;
|
||||||
Format := ricfRGBA;
|
Format := ricfRGBA;
|
||||||
LineEnd := rileByteBoundary;
|
LineEnd := rileDWordBoundary;
|
||||||
BitOrder := riboBitsInOrder;
|
BitOrder := riboBitsInOrder;
|
||||||
ByteOrder := riboLSBFirst;
|
ByteOrder := riboLSBFirst;
|
||||||
LineOrder := riloTopToBottom;
|
LineOrder := riloTopToBottom;
|
||||||
|
@ -608,14 +591,13 @@ begin
|
||||||
RedShift := 16;
|
RedShift := 16;
|
||||||
GreenShift := 8;
|
GreenShift := 8;
|
||||||
BlueShift := 0;
|
BlueShift := 0;
|
||||||
Depth := 24;
|
Depth := 32; // Must be 32 for alpha blending (and for working in MacOSX Carbon)
|
||||||
end;
|
end;
|
||||||
RawImage.Data := WorkData.Bits;
|
RawImage.Data := WorkData.Bits;
|
||||||
RawImage.DataSize := WorkData.Size;
|
RawImage.DataSize := WorkData.Size;
|
||||||
|
|
||||||
// Create bitmap from raw image
|
// Create bitmap from raw image
|
||||||
{ If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
if RawImage_CreateBitmaps(RawImage, ImgHandle, ImgMaskHandle) then
|
||||||
if RawImage_CreateBitmaps(RawImage, ImgHandle, ImgMaskHandle, False) then
|
|
||||||
begin
|
begin
|
||||||
Bitmap.Handle := ImgHandle;
|
Bitmap.Handle := ImgHandle;
|
||||||
Bitmap.MaskHandle := ImgMaskHandle;
|
Bitmap.MaskHandle := ImgMaskHandle;
|
||||||
|
@ -634,9 +616,6 @@ var
|
||||||
Colors: Word;
|
Colors: Word;
|
||||||
LogPalette: TMaxLogPalette;
|
LogPalette: TMaxLogPalette;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
ColorTable: PPalette32;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
RawImage: TRawImage;
|
RawImage: TRawImage;
|
||||||
LineLazBytes: LongInt;
|
LineLazBytes: LongInt;
|
||||||
|
@ -650,7 +629,6 @@ begin
|
||||||
// trough RawImage api and cannot be changed to mirror some Imaging format
|
// trough RawImage api and cannot be changed to mirror some Imaging format
|
||||||
// (so formats with no coresponding Imaging format cannot be saved now).
|
// (so formats with no coresponding Imaging format cannot be saved now).
|
||||||
|
|
||||||
{ If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
|
||||||
if RawImage_DescriptionFromBitmap(Bitmap.Handle, RawImage.Description) then
|
if RawImage_DescriptionFromBitmap(Bitmap.Handle, RawImage.Description) then
|
||||||
case RawImage.Description.BitsPerPixel of
|
case RawImage.Description.BitsPerPixel of
|
||||||
8: Format := ifIndex8;
|
8: Format := ifIndex8;
|
||||||
|
@ -707,28 +685,9 @@ begin
|
||||||
for I := 0 to Data.Height - 1 do
|
for I := 0 to Data.Height - 1 do
|
||||||
Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes);
|
Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
if Format = ifIndex8 then
|
|
||||||
begin
|
|
||||||
// Copy palette
|
|
||||||
ColorTable := Bitmap.ColorTable;
|
|
||||||
for I := 0 to Info.PaletteEntries - 1 do
|
|
||||||
with ColorTable[I] do
|
|
||||||
begin
|
|
||||||
Data.Palette[I].A := $FF;
|
|
||||||
Data.Palette[I].R := R;
|
|
||||||
Data.Palette[I].G := G;
|
|
||||||
Data.Palette[I].B := B;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
// Copy scanlines
|
|
||||||
for I := 0 to Data.Height - 1 do
|
|
||||||
Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes);
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
// Get raw image from bitmap (mask handle must be 0 or expect violations)
|
// Get raw image from bitmap (mask handle must be 0 or expect violations)
|
||||||
if RawImage_FromBitmap(RawImage, Bitmap.Handle, 0, nil) then // uncommnet for Laz 0.9.25 if you get error here
|
if RawImage_FromBitmap(RawImage, Bitmap.Handle, 0, nil) then
|
||||||
//if RawImage_FromBitmap(RawImage, Bitmap.Handle, 0, Classes.Rect(0, 0, Data.Width, Data.Height)) then
|
|
||||||
begin
|
begin
|
||||||
LineLazBytes := GetBytesPerLine(Data.Width, RawImage.Description.BitsPerPixel,
|
LineLazBytes := GetBytesPerLine(Data.Width, RawImage.Description.BitsPerPixel,
|
||||||
RawImage.Description.LineEnd);
|
RawImage.Description.LineEnd);
|
||||||
|
@ -757,6 +716,7 @@ procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: T
|
||||||
var
|
var
|
||||||
OldMode: Integer;
|
OldMode: Integer;
|
||||||
BitmapInfo: Windows.TBitmapInfo;
|
BitmapInfo: Windows.TBitmapInfo;
|
||||||
|
Bmp: TBitmap;
|
||||||
begin
|
begin
|
||||||
if TestImage(ImageData) then
|
if TestImage(ImageData) then
|
||||||
begin
|
begin
|
||||||
|
@ -781,9 +741,21 @@ begin
|
||||||
|
|
||||||
try
|
try
|
||||||
with SrcRect, ImageData do
|
with SrcRect, ImageData do
|
||||||
Windows.StretchDIBits(DC, DstRect.Left, DstRect.Top,
|
if Windows.StretchDIBits(DC, DstRect.Left, DstRect.Top,
|
||||||
DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, Left,
|
DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, Left,
|
||||||
Top, Right - Left, Bottom - Top, Bits, BitmapInfo, DIB_RGB_COLORS, SRCCOPY);
|
Top, Right - Left, Bottom - Top, Bits, BitmapInfo, DIB_RGB_COLORS, SRCCOPY) <> Height then
|
||||||
|
begin
|
||||||
|
// StretchDIBits may fail on some ocassions (error 487, http://support.microsoft.com/kb/269585).
|
||||||
|
// This fallback is slow but works every time. Thanks to Sergey Galezdinov for the fix.
|
||||||
|
Bmp := TBitmap.Create;
|
||||||
|
try
|
||||||
|
ConvertDataToBitmap(ImageData, Bmp);
|
||||||
|
StretchBlt(DC, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top,
|
||||||
|
Bmp.Canvas.Handle, 0, 0, Width, Height, SRCCOPY);
|
||||||
|
finally
|
||||||
|
Bmp.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
finally
|
finally
|
||||||
Windows.SetStretchBltMode(DC, OldMode);
|
Windows.SetStretchBltMode(DC, OldMode);
|
||||||
end;
|
end;
|
||||||
|
@ -792,50 +764,21 @@ end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect);
|
procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect);
|
||||||
{$IF Defined(MSWINDOWS) and not Defined(COMPONENT_SET_CLX)}
|
{$IF Defined(DCC) or Defined(LCLWIN32)} // Delphi or LCL Win32
|
||||||
begin
|
begin
|
||||||
DisplayImageDataOnDC(DstCanvas.Handle, DstRect, ImageData, SrcRect);
|
DisplayImageDataOnDC(DstCanvas.Handle, DstRect, ImageData, SrcRect);
|
||||||
end;
|
end;
|
||||||
{$ELSEIF Defined(COMPONENT_SET_CLX)}
|
{$ELSEIF Defined(LCLGTK) or Defined(LCLGTK2)}
|
||||||
var
|
|
||||||
Bitmap: TBitmap;
|
|
||||||
//Handle: LongWord;
|
|
||||||
begin
|
|
||||||
(*
|
|
||||||
// It would be nice if this worked:
|
|
||||||
DstCanvas.Start;
|
|
||||||
Handle := QPainter_handle(DstCanvas.Handle);
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
DisplayImageDataOnDC(Handle, DstRect, ImageData, SrcRect);
|
|
||||||
{$ELSE}
|
|
||||||
DisplayImageDataOnX(Handle, DstRect, ImageData, SrcRect);
|
|
||||||
{$ENDIF}
|
|
||||||
DstCanvas.Stop;
|
|
||||||
*)
|
|
||||||
Bitmap := TBitmap.Create;
|
|
||||||
try
|
|
||||||
ConvertDataToBitmap(ImageData, Bitmap);
|
|
||||||
DstCanvas.CopyRect(DstRect, Bitmap.Canvas, SrcRect);
|
|
||||||
finally
|
|
||||||
Bitmap.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{$ELSEIF Defined(UNIX) and Defined(COMPONENT_SET_LCL)}
|
|
||||||
|
|
||||||
procedure GDKDrawBitmap(Dest: HDC; DstX, DstY: Integer; SrcX, SrcY,
|
procedure GDKDrawBitmap(Dest: HDC; DstX, DstY: Integer; SrcX, SrcY,
|
||||||
SrcWidth, SrcHeight: Integer; ImageData: TImageData);
|
SrcWidth, SrcHeight: Integer; ImageData: TImageData);
|
||||||
var
|
var
|
||||||
P: TPoint;
|
P: TPoint;
|
||||||
begin
|
begin
|
||||||
// If you get compilation errors here with new Lazarus (rev 14368+)
|
|
||||||
// uncomment commented code and comment the active code below:
|
|
||||||
|
|
||||||
P := TGtkDeviceContext(Dest).Offset;
|
P := TGtkDeviceContext(Dest).Offset;
|
||||||
//P := GetDCOffset(TDeviceContext(Dest));
|
|
||||||
Inc(DstX, P.X);
|
Inc(DstX, P.X);
|
||||||
Inc(DstY, P.Y);
|
Inc(DstY, P.Y);
|
||||||
gdk_draw_rgb_32_image(TGtkDeviceContext(Dest).Drawable, TGtkDeviceContext(Dest).GC,
|
gdk_draw_rgb_32_image(TGtkDeviceContext(Dest).Drawable, TGtkDeviceContext(Dest).GC,
|
||||||
//gdk_draw_rgb_32_image(TDeviceContext(Dest).Drawable, TDeviceContext(Dest).GC,
|
|
||||||
DstX, DstY, SrcWidth, SrcHeight, GDK_RGB_DITHER_NONE,
|
DstX, DstY, SrcWidth, SrcHeight, GDK_RGB_DITHER_NONE,
|
||||||
@PLongWordArray(ImageData.Bits)[SrcY * ImageData.Width + SrcX], ImageData.Width * 4);
|
@PLongWordArray(ImageData.Bits)[SrcY * ImageData.Width + SrcX], ImageData.Width * 4);
|
||||||
end;
|
end;
|
||||||
|
@ -890,6 +833,10 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$ELSE}
|
||||||
|
begin
|
||||||
|
raise Exception.Create(SUnsupportedLCLWidgetSet);
|
||||||
|
end;
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
|
|
||||||
procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage);
|
procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage);
|
||||||
|
@ -911,6 +858,12 @@ end;
|
||||||
|
|
||||||
{ TImagingGraphic class implementation }
|
{ TImagingGraphic class implementation }
|
||||||
|
|
||||||
|
constructor TImagingGraphic.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
PixelFormat := pf24Bit;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TImagingGraphic.LoadFromStream(Stream: TStream);
|
procedure TImagingGraphic.LoadFromStream(Stream: TStream);
|
||||||
begin
|
begin
|
||||||
ReadDataFromStream(Stream);
|
ReadDataFromStream(Stream);
|
||||||
|
@ -1020,14 +973,13 @@ begin
|
||||||
Result := StringReplace(GetFileFormat.Extensions.CommaText, ',', ';', [rfReplaceAll]);
|
Result := StringReplace(GetFileFormat.Extensions.CommaText, ',', ';', [rfReplaceAll]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TImagingGraphicForSave.GetMimeType: string; // uncomment for Laz 0.9.25 if you get error here
|
function TImagingGraphicForSave.GetMimeType: string;
|
||||||
//function TImagingGraphicForSave.GetDefaultMimeType: string;
|
|
||||||
begin
|
begin
|
||||||
Result := 'image/' + FDefaultFileExt;
|
Result := 'image/' + FDefaultFileExt;
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_BITMAP}
|
{$IFNDEF DONT_LINK_BITMAP}
|
||||||
|
|
||||||
{ TImagingBitmap class implementation }
|
{ TImagingBitmap class implementation }
|
||||||
|
|
||||||
|
@ -1051,7 +1003,7 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_JPEG}
|
{$IFNDEF DONT_LINK_JPEG}
|
||||||
|
|
||||||
{ TImagingJpeg class implementation }
|
{ TImagingJpeg class implementation }
|
||||||
|
|
||||||
|
@ -1068,8 +1020,7 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
//function TImagingJpeg.GetMimeType: string; // uncomment for Laz 0.9.25 if you get error here
|
function TImagingJpeg.GetMimeType: string;
|
||||||
function TImagingJpeg.GetDefaultMimeType: string;
|
|
||||||
begin
|
begin
|
||||||
Result := 'image/jpeg';
|
Result := 'image/jpeg';
|
||||||
end;
|
end;
|
||||||
|
@ -1086,7 +1037,7 @@ end;
|
||||||
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_PNG}
|
{$IFNDEF DONT_LINK_PNG}
|
||||||
|
|
||||||
{ TImagingPNG class implementation }
|
{ TImagingPNG class implementation }
|
||||||
|
|
||||||
|
@ -1112,7 +1063,7 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_GIF}
|
{$IFNDEF DONT_LINK_GIF}
|
||||||
|
|
||||||
{ TImagingGIF class implementation}
|
{ TImagingGIF class implementation}
|
||||||
|
|
||||||
|
@ -1123,7 +1074,7 @@ end;
|
||||||
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_TARGA}
|
{$IFNDEF DONT_LINK_TARGA}
|
||||||
|
|
||||||
{ TImagingTarga class implementation }
|
{ TImagingTarga class implementation }
|
||||||
|
|
||||||
|
@ -1147,7 +1098,7 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_DDS}
|
{$IFNDEF DONT_LINK_DDS}
|
||||||
|
|
||||||
{ TImagingDDS class implementation }
|
{ TImagingDDS class implementation }
|
||||||
|
|
||||||
|
@ -1180,7 +1131,7 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_MNG}
|
{$IFNDEF DONT_LINK_MNG}
|
||||||
|
|
||||||
{ TImagingMNG class implementation }
|
{ TImagingMNG class implementation }
|
||||||
|
|
||||||
|
@ -1201,8 +1152,7 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
{$IFDEF COMPONENT_SET_LCL}
|
||||||
//function TImagingMNG.GetMimeType: string; // uncomment for Laz 0.9.25 if you get error here
|
function TImagingMNG.GetMimeType: string;
|
||||||
function TImagingMNG.GetDefaultMimeType: string;
|
|
||||||
begin
|
begin
|
||||||
Result := 'video/mng';
|
Result := 'video/mng';
|
||||||
end;
|
end;
|
||||||
|
@ -1222,7 +1172,7 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF LINK_JNG}
|
{$IFNDEF DONT_LINK_JNG}
|
||||||
|
|
||||||
{ TImagingJNG class implementation }
|
{ TImagingJNG class implementation }
|
||||||
|
|
||||||
|
@ -1259,12 +1209,30 @@ initialization
|
||||||
finalization
|
finalization
|
||||||
UnRegisterTypes;
|
UnRegisterTypes;
|
||||||
|
|
||||||
|
{$IFEND} // {$IF not Defined(COMPONENT_SET_LCL) and not Defined(COMPONENT_SET_VCL)}
|
||||||
|
|
||||||
{
|
{
|
||||||
File Notes:
|
File Notes:
|
||||||
|
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Setting AlphaFormat property of TBitmap in ConvertDataToBitmap
|
||||||
|
when using Delphi 2009+.
|
||||||
|
- Fixed garbled LCL TBitmaps created by ConvertDataToBitmap
|
||||||
|
in Mac OS X (Carbon).
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added some more IFDEFs for Lazarus widget sets.
|
||||||
|
- Removed CLX code.
|
||||||
|
- GTK version of Unix DisplayImageData only used with LCL GTK so the
|
||||||
|
the rest of the unit can be used with Qt or other LCL interfaces.
|
||||||
|
- Fallback mechanism for DisplayImageDataOnDC, it may fail on occasions.
|
||||||
|
- Changed file format conditional compilation to reflect changes
|
||||||
|
in LINK symbols.
|
||||||
|
- Lazarus 0.9.26 compatibility changes.
|
||||||
|
|
||||||
-- 0.24.1 Changes/Bug Fixes ---------------------------------
|
-- 0.24.1 Changes/Bug Fixes ---------------------------------
|
||||||
- Fixed wrong IFDEF causing that Imaging wouldn't compile in Lazarus
|
- Fixed wrong IFDEF causing that Imaging wouldn't compile in Lazarus
|
||||||
with GTK2 target.
|
with GTK2 target.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingExport.pas 71 2007-03-08 00:10:10Z galfar $
|
$Id: ImagingExport.pas 173 2009-09-04 17:05:52Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -52,14 +52,14 @@ function ImTestImage(var Image: TImageData): Boolean; cdecl;
|
||||||
function ImFreeImage(var Image: TImageData): Boolean; cdecl;
|
function ImFreeImage(var Image: TImageData): Boolean; cdecl;
|
||||||
{ Look at DetermineFileFormat for details. Ext should have enough space for
|
{ Look at DetermineFileFormat for details. Ext should have enough space for
|
||||||
result file extension.}
|
result file extension.}
|
||||||
function ImDetermineFileFormat(FileName, Ext: PChar): Boolean; cdecl;
|
function ImDetermineFileFormat(FileName, Ext: PAnsiChar): Boolean; cdecl;
|
||||||
{ Look at DetermineMemoryFormat for details. Ext should have enough space for
|
{ Look at DetermineMemoryFormat for details. Ext should have enough space for
|
||||||
result file extension.}
|
result file extension.}
|
||||||
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PChar): Boolean; cdecl;
|
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PAnsiChar): Boolean; cdecl;
|
||||||
{ Look at IsFileFormatSupported for details.}
|
{ Look at IsFileFormatSupported for details.}
|
||||||
function ImIsFileFormatSupported(FileName: PChar): Boolean; cdecl;
|
function ImIsFileFormatSupported(FileName: PAnsiChar): Boolean; cdecl;
|
||||||
{ Look at EnumFileFormats for details.}
|
{ Look at EnumFileFormats for details.}
|
||||||
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PChar;
|
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PAnsiChar;
|
||||||
var CanSave, IsMultiImageFormat: Boolean): Boolean; cdecl;
|
var CanSave, IsMultiImageFormat: Boolean): Boolean; cdecl;
|
||||||
|
|
||||||
{ Inits image list.}
|
{ Inits image list.}
|
||||||
|
@ -82,24 +82,24 @@ function ImTestImagesInList(ImageList: TImageDataList): Boolean; cdecl;
|
||||||
function ImFreeImageList(var ImageList: TImageDataList): Boolean; cdecl;
|
function ImFreeImageList(var ImageList: TImageDataList): Boolean; cdecl;
|
||||||
|
|
||||||
{ Look at LoadImageFromFile for details.}
|
{ Look at LoadImageFromFile for details.}
|
||||||
function ImLoadImageFromFile(FileName: PChar; var Image: TImageData): Boolean; cdecl;
|
function ImLoadImageFromFile(FileName: PAnsiChar; var Image: TImageData): Boolean; cdecl;
|
||||||
{ Look at LoadImageFromMemory for details.}
|
{ Look at LoadImageFromMemory for details.}
|
||||||
function ImLoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean; cdecl;
|
function ImLoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean; cdecl;
|
||||||
{ Look at LoadMultiImageFromFile for details.}
|
{ Look at LoadMultiImageFromFile for details.}
|
||||||
function ImLoadMultiImageFromFile(FileName: PChar; var ImageList: TImageDataList): Boolean; cdecl;
|
function ImLoadMultiImageFromFile(FileName: PAnsiChar; var ImageList: TImageDataList): Boolean; cdecl;
|
||||||
{ Look at LoadMultiImageFromMemory for details.}
|
{ Look at LoadMultiImageFromMemory for details.}
|
||||||
function ImLoadMultiImageFromMemory(Data: Pointer; Size: LongInt;
|
function ImLoadMultiImageFromMemory(Data: Pointer; Size: LongInt;
|
||||||
var ImageList: TImageDataList): Boolean; cdecl;
|
var ImageList: TImageDataList): Boolean; cdecl;
|
||||||
|
|
||||||
{ Look at SaveImageToFile for details.}
|
{ Look at SaveImageToFile for details.}
|
||||||
function ImSaveImageToFile(FileName: PChar; const Image: TImageData): Boolean; cdecl;
|
function ImSaveImageToFile(FileName: PAnsiChar; const Image: TImageData): Boolean; cdecl;
|
||||||
{ Look at SaveImageToMemory for details.}
|
{ Look at SaveImageToMemory for details.}
|
||||||
function ImSaveImageToMemory(Ext: PChar; Data: Pointer; var Size: LongInt;
|
function ImSaveImageToMemory(Ext: PAnsiChar; Data: Pointer; var Size: LongInt;
|
||||||
const Image: TImageData): Boolean; cdecl;
|
const Image: TImageData): Boolean; cdecl;
|
||||||
{ Look at SaveMultiImageToFile for details.}
|
{ Look at SaveMultiImageToFile for details.}
|
||||||
function ImSaveMultiImageToFile(FileName: PChar; ImageList: TImageDataList): Boolean; cdecl;
|
function ImSaveMultiImageToFile(FileName: PAnsiChar; ImageList: TImageDataList): Boolean; cdecl;
|
||||||
{ Look at SaveMultiImageToMemory for details.}
|
{ Look at SaveMultiImageToMemory for details.}
|
||||||
function ImSaveMultiImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
|
function ImSaveMultiImageToMemory(Ext: PAnsiChar; Data: Pointer; Size: PLongInt;
|
||||||
ImageList: TImageDataList): Boolean; cdecl;
|
ImageList: TImageDataList): Boolean; cdecl;
|
||||||
|
|
||||||
{ Look at CloneImage for details.}
|
{ Look at CloneImage for details.}
|
||||||
|
@ -131,7 +131,7 @@ function ImSplitImage(var Image: TImageData; var Chunks: TImageDataList;
|
||||||
function ImMakePaletteForImages(Images: TImageDataList; Pal: PPalette32;
|
function ImMakePaletteForImages(Images: TImageDataList; Pal: PPalette32;
|
||||||
MaxColors: LongInt; ConvertImages: Boolean): Boolean; cdecl;
|
MaxColors: LongInt; ConvertImages: Boolean): Boolean; cdecl;
|
||||||
{ Look at RotateImage for details.}
|
{ Look at RotateImage for details.}
|
||||||
function ImRotateImage(var Image: TImageData; Angle: LongInt): Boolean; cdecl;
|
function ImRotateImage(var Image: TImageData; Angle: Single): Boolean; cdecl;
|
||||||
|
|
||||||
{ Look at CopyRect for details.}
|
{ Look at CopyRect for details.}
|
||||||
function ImCopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt;
|
function ImCopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt;
|
||||||
|
@ -262,33 +262,33 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImDetermineFileFormat(FileName, Ext: PChar): Boolean;
|
function ImDetermineFileFormat(FileName, Ext: PAnsiChar): Boolean;
|
||||||
var
|
var
|
||||||
S: string;
|
S: string;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
S := Imaging.DetermineFileFormat(FileName);
|
S := Imaging.DetermineFileFormat(FileName);
|
||||||
Result := S <> '';
|
Result := S <> '';
|
||||||
StrCopy(Ext, PChar(S));
|
StrCopy(Ext, PAnsiChar(AnsiString(S)));
|
||||||
except
|
except
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PChar): Boolean;
|
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PAnsiChar): Boolean;
|
||||||
var
|
var
|
||||||
S: string;
|
S: string;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
S := Imaging.DetermineMemoryFormat(Data, Size);
|
S := Imaging.DetermineMemoryFormat(Data, Size);
|
||||||
Result := S <> '';
|
Result := S <> '';
|
||||||
StrCopy(Ext, PChar(S));
|
StrCopy(Ext, PAnsiChar(AnsiString(S)));
|
||||||
except
|
except
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImIsFileFormatSupported(FileName: PChar): Boolean;
|
function ImIsFileFormatSupported(FileName: PAnsiChar): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := Imaging.IsFileFormatSupported(FileName);
|
Result := Imaging.IsFileFormatSupported(FileName);
|
||||||
|
@ -297,7 +297,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PChar;
|
function ImEnumFileFormats(var Index: LongInt; Name, DefaultExt, Masks: PAnsiChar;
|
||||||
var CanSave, IsMultiImageFormat: Boolean): Boolean;
|
var CanSave, IsMultiImageFormat: Boolean): Boolean;
|
||||||
var
|
var
|
||||||
StrName, StrDefaultExt, StrMasks: string;
|
StrName, StrDefaultExt, StrMasks: string;
|
||||||
|
@ -305,9 +305,9 @@ begin
|
||||||
try
|
try
|
||||||
Result := Imaging.EnumFileFormats(Index, StrName, StrDefaultExt, StrMasks, CanSave,
|
Result := Imaging.EnumFileFormats(Index, StrName, StrDefaultExt, StrMasks, CanSave,
|
||||||
IsMultiImageFormat);
|
IsMultiImageFormat);
|
||||||
StrCopy(Name, PChar(StrName));
|
StrCopy(Name, PAnsiChar(AnsiString(StrName)));
|
||||||
StrCopy(DefaultExt, PChar(StrDefaultExt));
|
StrCopy(DefaultExt, PAnsiChar(AnsiString(StrDefaultExt)));
|
||||||
StrCopy(Masks, PChar(StrMasks));
|
StrCopy(Masks, PAnsiChar(AnsiString(StrMasks)));
|
||||||
except
|
except
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
@ -419,7 +419,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImLoadImageFromFile(FileName: PChar; var Image: TImageData): Boolean;
|
function ImLoadImageFromFile(FileName: PAnsiChar; var Image: TImageData): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := Imaging.LoadImageFromFile(FileName, Image);
|
Result := Imaging.LoadImageFromFile(FileName, Image);
|
||||||
|
@ -437,7 +437,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImLoadMultiImageFromFile(FileName: PChar; var ImageList: TImageDataList):
|
function ImLoadMultiImageFromFile(FileName: PAnsiChar; var ImageList: TImageDataList):
|
||||||
Boolean;
|
Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
|
@ -460,7 +460,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImSaveImageToFile(FileName: PChar; const Image: TImageData): Boolean;
|
function ImSaveImageToFile(FileName: PAnsiChar; const Image: TImageData): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := Imaging.SaveImageToFile(FileName, Image);
|
Result := Imaging.SaveImageToFile(FileName, Image);
|
||||||
|
@ -469,7 +469,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImSaveImageToMemory(Ext: PChar; Data: Pointer; var Size: LongInt;
|
function ImSaveImageToMemory(Ext: PAnsiChar; Data: Pointer; var Size: LongInt;
|
||||||
const Image: TImageData): Boolean;
|
const Image: TImageData): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
|
@ -479,7 +479,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImSaveMultiImageToFile(FileName: PChar;
|
function ImSaveMultiImageToFile(FileName: PAnsiChar;
|
||||||
ImageList: TImageDataList): Boolean;
|
ImageList: TImageDataList): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
|
@ -490,7 +490,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImSaveMultiImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
|
function ImSaveMultiImageToMemory(Ext: PAnsiChar; Data: Pointer; Size: PLongInt;
|
||||||
ImageList: TImageDataList): Boolean;
|
ImageList: TImageDataList): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
|
@ -612,7 +612,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ImRotateImage(var Image: TImageData; Angle: LongInt): Boolean;
|
function ImRotateImage(var Image: TImageData; Angle: Single): Boolean;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := Imaging.RotateImage(Image, Angle);
|
Result := Imaging.RotateImage(Image, Angle);
|
||||||
|
@ -864,6 +864,10 @@ end;
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 ---------------------------------------------------
|
||||||
|
- changed PChars to PAnsiChars and some more D2009 friendly
|
||||||
|
casts.
|
||||||
|
|
||||||
-- 0.19 -----------------------------------------------------
|
-- 0.19 -----------------------------------------------------
|
||||||
- updated to reflect changes in low level interface (added pixel set/get, ...)
|
- updated to reflect changes in low level interface (added pixel set/get, ...)
|
||||||
- changed ImInitImage to procedure to reflect change in Imaging.pas
|
- changed ImInitImage to procedure to reflect change in Imaging.pas
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingFormats.pas 129 2008-08-06 20:01:30Z galfar $
|
$Id: ImagingFormats.pas 176 2009-10-12 10:53:17Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -388,6 +388,7 @@ var
|
||||||
BytesPerPixel: 1;
|
BytesPerPixel: 1;
|
||||||
ChannelCount: 1;
|
ChannelCount: 1;
|
||||||
PaletteEntries: 256;
|
PaletteEntries: 256;
|
||||||
|
HasAlphaChannel: True;
|
||||||
IsIndexed: True;
|
IsIndexed: True;
|
||||||
GetPixelsSize: GetStdPixelsSize;
|
GetPixelsSize: GetStdPixelsSize;
|
||||||
CheckDimensions: CheckStdDimensions;
|
CheckDimensions: CheckStdDimensions;
|
||||||
|
@ -1617,8 +1618,7 @@ begin
|
||||||
Result[0][0].Pos := (SrcLow + SrcHigh) div 2;
|
Result[0][0].Pos := (SrcLow + SrcHigh) div 2;
|
||||||
Result[0][0].Weight := 1.0;
|
Result[0][0].Weight := 1.0;
|
||||||
end
|
end
|
||||||
else
|
else if Scale < 1.0 then
|
||||||
if Scale < 1.0 then
|
|
||||||
begin
|
begin
|
||||||
// Sub-sampling - scales from bigger to smaller
|
// Sub-sampling - scales from bigger to smaller
|
||||||
Radius := Radius / Scale;
|
Radius := Radius / Scale;
|
||||||
|
@ -1649,8 +1649,7 @@ begin
|
||||||
Result[I][0].Pos := Floor(Center);
|
Result[I][0].Pos := Floor(Center);
|
||||||
Result[I][0].Weight := 1.0;
|
Result[I][0].Weight := 1.0;
|
||||||
end
|
end
|
||||||
else
|
else if Count <> 0.0 then
|
||||||
if Count <> 0.0 then
|
|
||||||
Result[I][K div 2].Weight := Result[I][K div 2].Weight - Count;
|
Result[I][K div 2].Weight := Result[I][K div 2].Weight - Count;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
@ -1680,8 +1679,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if J < 0 then
|
if J < 0 then
|
||||||
N := SrcImageWidth + J
|
N := SrcImageWidth + J
|
||||||
else
|
else if J >= SrcImageWidth then
|
||||||
if J >= SrcImageWidth then
|
|
||||||
N := J - SrcImageWidth
|
N := J - SrcImageWidth
|
||||||
else
|
else
|
||||||
N := ClampInt(J, SrcLow, SrcHigh - 1);
|
N := ClampInt(J, SrcLow, SrcHigh - 1);
|
||||||
|
@ -1723,13 +1721,19 @@ procedure StretchResample(const SrcImage: TImageData; SrcX, SrcY, SrcWidth,
|
||||||
DstHeight: LongInt; Filter: TFilterFunction; Radius: Single; WrapEdges: Boolean);
|
DstHeight: LongInt; Filter: TFilterFunction; Radius: Single; WrapEdges: Boolean);
|
||||||
const
|
const
|
||||||
Channel8BitMax: Single = 255.0;
|
Channel8BitMax: Single = 255.0;
|
||||||
|
type
|
||||||
|
TBufferItem = record
|
||||||
|
A, R, G, B: Integer;
|
||||||
|
end;
|
||||||
var
|
var
|
||||||
MapX, MapY: TMappingTable;
|
MapX, MapY: TMappingTable;
|
||||||
I, J, X, Y: LongInt;
|
I, J, X, Y: LongInt;
|
||||||
XMinimum, XMaximum: LongInt;
|
XMinimum, XMaximum: LongInt;
|
||||||
LineBuffer: array of TColorFPRec;
|
LineBufferFP: array of TColorFPRec;
|
||||||
|
LineBufferInt: array of TBufferItem;
|
||||||
ClusterX, ClusterY: TCluster;
|
ClusterX, ClusterY: TCluster;
|
||||||
Weight, AccumA, AccumR, AccumG, AccumB: Single;
|
Weight, AccumA, AccumR, AccumG, AccumB: Single;
|
||||||
|
IWeight, IAccumA, IAccumR, IAccumG, IAccumB: Integer;
|
||||||
DstLine: PByte;
|
DstLine: PByte;
|
||||||
SrcColor: TColor32Rec;
|
SrcColor: TColor32Rec;
|
||||||
SrcFloat: TColorFPRec;
|
SrcFloat: TColorFPRec;
|
||||||
|
@ -1759,10 +1763,10 @@ begin
|
||||||
try
|
try
|
||||||
// Find min and max X coords of pixels that will contribute to target image
|
// Find min and max X coords of pixels that will contribute to target image
|
||||||
FindExtremes(MapX, XMinimum, XMaximum);
|
FindExtremes(MapX, XMinimum, XMaximum);
|
||||||
SetLength(LineBuffer, XMaximum - XMinimum + 1);
|
|
||||||
|
|
||||||
if not UseOptimizedVersion then
|
if not UseOptimizedVersion then
|
||||||
begin
|
begin
|
||||||
|
SetLength(LineBufferFP, XMaximum - XMinimum + 1);
|
||||||
// Following code works for the rest of data formats
|
// Following code works for the rest of data formats
|
||||||
for J := 0 to DstHeight - 1 do
|
for J := 0 to DstHeight - 1 do
|
||||||
begin
|
begin
|
||||||
|
@ -1773,10 +1777,10 @@ begin
|
||||||
for X := XMinimum to XMaximum do
|
for X := XMinimum to XMaximum do
|
||||||
begin
|
begin
|
||||||
// Clear accumulators
|
// Clear accumulators
|
||||||
AccumA := 0.0;
|
AccumA := 0;
|
||||||
AccumR := 0.0;
|
AccumR := 0;
|
||||||
AccumG := 0.0;
|
AccumG := 0;
|
||||||
AccumB := 0.0;
|
AccumB := 0;
|
||||||
// For each pixel in line compute weighted sum of pixels
|
// For each pixel in line compute weighted sum of pixels
|
||||||
// in source column that will contribute to this pixel
|
// in source column that will contribute to this pixel
|
||||||
for Y := 0 to Length(ClusterY) - 1 do
|
for Y := 0 to Length(ClusterY) - 1 do
|
||||||
|
@ -1790,7 +1794,7 @@ begin
|
||||||
AccumA := AccumA + SrcFloat.A * Weight;
|
AccumA := AccumA + SrcFloat.A * Weight;
|
||||||
end;
|
end;
|
||||||
// Store accumulated value for this pixel in buffer
|
// Store accumulated value for this pixel in buffer
|
||||||
with LineBuffer[X - XMinimum] do
|
with LineBufferFP[X - XMinimum] do
|
||||||
begin
|
begin
|
||||||
A := AccumA;
|
A := AccumA;
|
||||||
R := AccumR;
|
R := AccumR;
|
||||||
|
@ -1806,17 +1810,17 @@ begin
|
||||||
begin
|
begin
|
||||||
ClusterX := MapX[I];
|
ClusterX := MapX[I];
|
||||||
// Clear accumulator
|
// Clear accumulator
|
||||||
AccumA := 0.0;
|
AccumA := 0;
|
||||||
AccumR := 0.0;
|
AccumR := 0;
|
||||||
AccumG := 0.0;
|
AccumG := 0;
|
||||||
AccumB := 0.0;
|
AccumB := 0;
|
||||||
// Compute weighted sum of values (which are already
|
// Compute weighted sum of values (which are already
|
||||||
// computed weighted sums of pixels in source columns stored in LineBuffer)
|
// computed weighted sums of pixels in source columns stored in LineBuffer)
|
||||||
// that will contribute to the current target pixel
|
// that will contribute to the current target pixel
|
||||||
for X := 0 to Length(ClusterX) - 1 do
|
for X := 0 to Length(ClusterX) - 1 do
|
||||||
begin
|
begin
|
||||||
Weight := ClusterX[X].Weight;
|
Weight := ClusterX[X].Weight;
|
||||||
with LineBuffer[ClusterX[X].Pos - XMinimum] do
|
with LineBufferFP[ClusterX[X].Pos - XMinimum] do
|
||||||
begin
|
begin
|
||||||
AccumB := AccumB + B * Weight;
|
AccumB := AccumB + B * Weight;
|
||||||
AccumG := AccumG + G * Weight;
|
AccumG := AccumG + G * Weight;
|
||||||
|
@ -1838,37 +1842,35 @@ begin
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
SetLength(LineBufferInt, XMaximum - XMinimum + 1);
|
||||||
// Following code is optimized for images with 8 bit channels
|
// Following code is optimized for images with 8 bit channels
|
||||||
for J := 0 to DstHeight - 1 do
|
for J := 0 to DstHeight - 1 do
|
||||||
begin
|
begin
|
||||||
ClusterY := MapY[J];
|
ClusterY := MapY[J];
|
||||||
for X := XMinimum to XMaximum do
|
for X := XMinimum to XMaximum do
|
||||||
begin
|
begin
|
||||||
AccumA := 0.0;
|
IAccumA := 0;
|
||||||
AccumR := 0.0;
|
IAccumR := 0;
|
||||||
AccumG := 0.0;
|
IAccumG := 0;
|
||||||
AccumB := 0.0;
|
IAccumB := 0;
|
||||||
for Y := 0 to Length(ClusterY) - 1 do
|
for Y := 0 to Length(ClusterY) - 1 do
|
||||||
begin
|
begin
|
||||||
Weight := ClusterY[Y].Weight;
|
IWeight := Round(256 * ClusterY[Y].Weight);
|
||||||
CopyPixel(
|
CopyPixel(
|
||||||
@PByteArray(SrcImage.Bits)[(ClusterY[Y].Pos * SrcImage.Width + X) * Info.BytesPerPixel],
|
@PByteArray(SrcImage.Bits)[(ClusterY[Y].Pos * SrcImage.Width + X) * Info.BytesPerPixel],
|
||||||
@SrcColor, Info.BytesPerPixel);
|
@SrcColor, Info.BytesPerPixel);
|
||||||
|
|
||||||
AccumB := AccumB + SrcColor.B * Weight;
|
IAccumB := IAccumB + SrcColor.B * IWeight;
|
||||||
if Info.ChannelCount > 1 then
|
IAccumG := IAccumG + SrcColor.G * IWeight;
|
||||||
AccumG := AccumG + SrcColor.G * Weight;
|
IAccumR := IAccumR + SrcColor.R * IWeight;
|
||||||
if Info.ChannelCount > 2 then
|
IAccumA := IAccumA + SrcColor.A * IWeight;
|
||||||
AccumR := AccumR + SrcColor.R * Weight;
|
|
||||||
if Info.ChannelCount > 3 then
|
|
||||||
AccumA := AccumA + SrcColor.A * Weight;
|
|
||||||
end;
|
end;
|
||||||
with LineBuffer[X - XMinimum] do
|
with LineBufferInt[X - XMinimum] do
|
||||||
begin
|
begin
|
||||||
A := AccumA;
|
A := IAccumA;
|
||||||
R := AccumR;
|
R := IAccumR;
|
||||||
G := AccumG;
|
G := IAccumG;
|
||||||
B := AccumB;
|
B := IAccumB;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1877,31 +1879,26 @@ begin
|
||||||
for I := 0 to DstWidth - 1 do
|
for I := 0 to DstWidth - 1 do
|
||||||
begin
|
begin
|
||||||
ClusterX := MapX[I];
|
ClusterX := MapX[I];
|
||||||
AccumA := 0.0;
|
IAccumA := 0;
|
||||||
AccumR := 0.0;
|
IAccumR := 0;
|
||||||
AccumG := 0.0;
|
IAccumG := 0;
|
||||||
AccumB := 0.0;
|
IAccumB := 0;
|
||||||
for X := 0 to Length(ClusterX) - 1 do
|
for X := 0 to Length(ClusterX) - 1 do
|
||||||
begin
|
begin
|
||||||
Weight := ClusterX[X].Weight;
|
IWeight := Round(256 * ClusterX[X].Weight);
|
||||||
with LineBuffer[ClusterX[X].Pos - XMinimum] do
|
with LineBufferInt[ClusterX[X].Pos - XMinimum] do
|
||||||
begin
|
begin
|
||||||
AccumB := AccumB + B * Weight;
|
IAccumB := IAccumB + B * IWeight;
|
||||||
if Info.ChannelCount > 1 then
|
IAccumG := IAccumG + G * IWeight;
|
||||||
AccumG := AccumG + G * Weight;
|
IAccumR := IAccumR + R * IWeight;
|
||||||
if Info.ChannelCount > 2 then
|
IAccumA := IAccumA + A * IWeight;
|
||||||
AccumR := AccumR + R * Weight;
|
|
||||||
if Info.ChannelCount > 3 then
|
|
||||||
AccumA := AccumA + A * Weight;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
SrcColor.B := ClampToByte(Round(AccumB));
|
|
||||||
if Info.ChannelCount > 1 then
|
SrcColor.B := ClampInt(IAccumB, 0, $00FF0000) shr 16;
|
||||||
SrcColor.G := ClampToByte(Round(AccumG));
|
SrcColor.G := ClampInt(IAccumG, 0, $00FF0000) shr 16;
|
||||||
if Info.ChannelCount > 2 then
|
SrcColor.R := ClampInt(IAccumR, 0, $00FF0000) shr 16;
|
||||||
SrcColor.R := ClampToByte(Round(AccumR));
|
SrcColor.A := ClampInt(IAccumA, 0, $00FF0000) shr 16;
|
||||||
if Info.ChannelCount > 3 then
|
|
||||||
SrcColor.A := ClampToByte(Round(AccumA));
|
|
||||||
|
|
||||||
CopyPixel(@SrcColor, DstLine, Info.BytesPerPixel);
|
CopyPixel(@SrcColor, DstLine, Info.BytesPerPixel);
|
||||||
Inc(DstLine, Info.BytesPerPixel);
|
Inc(DstLine, Info.BytesPerPixel);
|
||||||
|
@ -3234,11 +3231,11 @@ type
|
||||||
|
|
||||||
TPixelBlock = array[0..15] of TPixelInfo;
|
TPixelBlock = array[0..15] of TPixelInfo;
|
||||||
|
|
||||||
function DecodeCol(Color : Word): TColor32Rec;
|
function DecodeCol(Color: Word): TColor32Rec;
|
||||||
{$IFDEF USE_INLINE} inline; {$ENDIF}
|
{$IFDEF USE_INLINE} inline; {$ENDIF}
|
||||||
begin
|
begin
|
||||||
Result.A := $FF;
|
Result.A := $FF;
|
||||||
{Result.R := ((Color and $F800) shr 11) shl 3;
|
{ Result.R := ((Color and $F800) shr 11) shl 3;
|
||||||
Result.G := ((Color and $07E0) shr 5) shl 2;
|
Result.G := ((Color and $07E0) shr 5) shl 2;
|
||||||
Result.B := (Color and $001F) shl 3;}
|
Result.B := (Color and $001F) shl 3;}
|
||||||
// this color expansion is slower but gives better results
|
// this color expansion is slower but gives better results
|
||||||
|
@ -3663,7 +3660,7 @@ begin
|
||||||
GetBlock(Pixels, SrcBits, X, Y, Width, Height);
|
GetBlock(Pixels, SrcBits, X, Y, Width, Height);
|
||||||
for I := 0 to 7 do
|
for I := 0 to 7 do
|
||||||
PByteArray(@AlphaBlock.Alphas)[I] :=
|
PByteArray(@AlphaBlock.Alphas)[I] :=
|
||||||
((Pixels[I shl 1].Alpha shr 4) shl 4) or (Pixels[I shl 1 + 1].Alpha shr 4);
|
(Pixels[I shl 1].Alpha shr 4) or ((Pixels[I shl 1 + 1].Alpha shr 4) shl 4);
|
||||||
GetEndpoints(Pixels, Block.Color0, Block.Color1);
|
GetEndpoints(Pixels, Block.Color0, Block.Color1);
|
||||||
FixEndpoints(Block.Color0, Block.Color1, False);
|
FixEndpoints(Block.Color0, Block.Color1, False);
|
||||||
Block.Mask := GetColorMask(Block.Color0, Block.Color1, 4, Pixels);
|
Block.Mask := GetColorMask(Block.Color0, Block.Color1, 4, Pixels);
|
||||||
|
@ -4222,7 +4219,11 @@ initialization
|
||||||
|
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
- rewrite StretchRect for 8bit channels to use integer math?
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes -----------------------------------
|
||||||
|
- Filtered resampling ~10% faster now.
|
||||||
|
- Fixed DXT3 alpha encoding.
|
||||||
|
- ifIndex8 format now has HasAlphaChannel=True.
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes -----------------------------------
|
-- 0.25.0 Changes/Bug Fixes -----------------------------------
|
||||||
- Made some resampling stuff public so that it can be used in canvas class.
|
- Made some resampling stuff public so that it can be used in canvas class.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingGif.pas 132 2008-08-27 20:37:38Z galfar $
|
$Id: ImagingGif.pas 157 2009-02-15 14:24:58Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -44,9 +44,11 @@ type
|
||||||
its own color palette. GIF uses lossless LZW compression
|
its own color palette. GIF uses lossless LZW compression
|
||||||
(patent expired few years ago).
|
(patent expired few years ago).
|
||||||
Imaging can load and save all GIFs with all frames and supports
|
Imaging can load and save all GIFs with all frames and supports
|
||||||
transparency.}
|
transparency. Imaging can load just raw ifIndex8 frames or
|
||||||
|
also animate them in ifA8R8G8B8 format. See ImagingGIFLoadAnimated option.}
|
||||||
TGIFFileFormat = class(TImageFileFormat)
|
TGIFFileFormat = class(TImageFileFormat)
|
||||||
private
|
private
|
||||||
|
FLoadAnimated: LongBool;
|
||||||
function InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer;
|
function InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer;
|
||||||
procedure LZWDecompress(Stream: TStream; Handle: TImagingHandle;
|
procedure LZWDecompress(Stream: TStream; Handle: TImagingHandle;
|
||||||
Width, Height: Integer; Interlaced: Boolean; Data: Pointer);
|
Width, Height: Integer; Interlaced: Boolean; Data: Pointer);
|
||||||
|
@ -62,6 +64,8 @@ type
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
function TestFormat(Handle: TImagingHandle): Boolean; override;
|
function TestFormat(Handle: TImagingHandle): Boolean; override;
|
||||||
|
published
|
||||||
|
property LoadAnimated: LongBool read FLoadAnimated write FLoadAnimated;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
@ -70,10 +74,11 @@ const
|
||||||
SGIFFormatName = 'Graphics Interchange Format';
|
SGIFFormatName = 'Graphics Interchange Format';
|
||||||
SGIFMasks = '*.gif';
|
SGIFMasks = '*.gif';
|
||||||
GIFSupportedFormats: TImageFormats = [ifIndex8];
|
GIFSupportedFormats: TImageFormats = [ifIndex8];
|
||||||
|
GIFDefaultLoadAnimated = True;
|
||||||
|
|
||||||
type
|
type
|
||||||
TGIFVersion = (gv87, gv89);
|
TGIFVersion = (gv87, gv89);
|
||||||
TDisposalMethod = (dmUndefined, dmLeave, dmRestoreBackground,
|
TDisposalMethod = (dmNoRemoval, dmLeave, dmRestoreBackground,
|
||||||
dmRestorePrevious, dmReserved4, dmReserved5, dmReserved6, dmReserved7);
|
dmRestorePrevious, dmReserved4, dmReserved5, dmReserved6, dmReserved7);
|
||||||
|
|
||||||
const
|
const
|
||||||
|
@ -144,6 +149,19 @@ type
|
||||||
Terminator: Byte;
|
Terminator: Byte;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
// Netscape sub block types
|
||||||
|
GIFAppLoopExtension = 1;
|
||||||
|
GIFAppBufferExtension = 2;
|
||||||
|
|
||||||
|
type
|
||||||
|
TGIFIdentifierCode = array[0..7] of AnsiChar;
|
||||||
|
TGIFAuthenticationCode = array[0..2] of AnsiChar;
|
||||||
|
TGIFApplicationRec = packed record
|
||||||
|
Identifier: TGIFIdentifierCode;
|
||||||
|
Authentication: TGIFAuthenticationCode;
|
||||||
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
CodeTableSize = 4096;
|
CodeTableSize = 4096;
|
||||||
HashTableSize = 17777;
|
HashTableSize = 17777;
|
||||||
|
@ -206,8 +224,10 @@ begin
|
||||||
FCanSave := True;
|
FCanSave := True;
|
||||||
FIsMultiImageFormat := True;
|
FIsMultiImageFormat := True;
|
||||||
FSupportedFormats := GIFSupportedFormats;
|
FSupportedFormats := GIFSupportedFormats;
|
||||||
|
FLoadAnimated := GIFDefaultLoadAnimated;
|
||||||
|
|
||||||
AddMasks(SGIFMasks);
|
AddMasks(SGIFMasks);
|
||||||
|
RegisterOption(ImagingGIFLoadAnimated, @FLoadAnimated);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGIFFileFormat.InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer;
|
function TGIFFileFormat.InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer;
|
||||||
|
@ -644,28 +664,56 @@ end;
|
||||||
|
|
||||||
function TGIFFileFormat.LoadData(Handle: TImagingHandle;
|
function TGIFFileFormat.LoadData(Handle: TImagingHandle;
|
||||||
var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean;
|
var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean;
|
||||||
|
type
|
||||||
|
TFrameInfo = record
|
||||||
|
Left, Top: Integer;
|
||||||
|
Width, Height: Integer;
|
||||||
|
Disposal: TDisposalMethod;
|
||||||
|
HasTransparency: Boolean;
|
||||||
|
HasLocalPal: Boolean;
|
||||||
|
TransIndex: Integer;
|
||||||
|
BackIndex: Integer;
|
||||||
|
end;
|
||||||
var
|
var
|
||||||
Header: TGIFHeader;
|
Header: TGIFHeader;
|
||||||
HasGlobalPal: Boolean;
|
HasGlobalPal: Boolean;
|
||||||
GlobalPalLength: Integer;
|
GlobalPalLength: Integer;
|
||||||
GlobalPal: TPalette32Size256;
|
GlobalPal: TPalette32Size256;
|
||||||
I: Integer;
|
ScreenWidth, ScreenHeight, I, CachedIndex: Integer;
|
||||||
BlockID: Byte;
|
BlockID: Byte;
|
||||||
HasGraphicExt: Boolean;
|
HasGraphicExt: Boolean;
|
||||||
GraphicExt: TGraphicControlExtension;
|
GraphicExt: TGraphicControlExtension;
|
||||||
Disposals: array of TDisposalMethod;
|
FrameInfos: array of TFrameInfo;
|
||||||
|
AppRead: Boolean;
|
||||||
|
CachedFrame: TImageData;
|
||||||
|
AnimFrames: TDynImageDataArray;
|
||||||
|
|
||||||
function ReadBlockID: Byte;
|
function ReadBlockID: Byte;
|
||||||
begin
|
begin
|
||||||
Result := GIFTrailer;
|
Result := GIFTrailer;
|
||||||
GetIO.Read(Handle, @Result, SizeOf(Result));
|
if GetIO.Read(Handle, @Result, SizeOf(Result)) < SizeOf(Result) then
|
||||||
|
Result := GIFTrailer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ReadExtensions;
|
procedure ReadExtensions;
|
||||||
var
|
var
|
||||||
BlockSize, ExtType: Byte;
|
BlockSize, BlockType, ExtType: Byte;
|
||||||
|
AppRec: TGIFApplicationRec;
|
||||||
|
LoopCount: SmallInt;
|
||||||
|
|
||||||
|
procedure SkipBytes;
|
||||||
|
begin
|
||||||
|
with GetIO do
|
||||||
|
repeat
|
||||||
|
// Read block sizes and skip them
|
||||||
|
Read(Handle, @BlockSize, SizeOf(BlockSize));
|
||||||
|
Seek(Handle, BlockSize, smFromCurrent);
|
||||||
|
until BlockSize = 0;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
HasGraphicExt := False;
|
HasGraphicExt := False;
|
||||||
|
AppRead := False;
|
||||||
|
|
||||||
// Read extensions until image descriptor is found. Only graphic extension
|
// Read extensions until image descriptor is found. Only graphic extension
|
||||||
// is stored now (for transparency), others are skipped.
|
// is stored now (for transparency), others are skipped.
|
||||||
|
@ -674,11 +722,58 @@ var
|
||||||
begin
|
begin
|
||||||
Read(Handle, @ExtType, SizeOf(ExtType));
|
Read(Handle, @ExtType, SizeOf(ExtType));
|
||||||
|
|
||||||
|
while ExtType in [GIFGraphicControlExtension, GIFCommentExtension, GIFApplicationExtension, GIFPlainText] do
|
||||||
|
begin
|
||||||
if ExtType = GIFGraphicControlExtension then
|
if ExtType = GIFGraphicControlExtension then
|
||||||
begin
|
begin
|
||||||
HasGraphicExt := True;
|
HasGraphicExt := True;
|
||||||
Read(Handle, @GraphicExt, SizeOf(GraphicExt));
|
Read(Handle, @GraphicExt, SizeOf(GraphicExt));
|
||||||
end
|
end
|
||||||
|
else if (ExtType = GIFApplicationExtension) and not AppRead then
|
||||||
|
begin
|
||||||
|
Read(Handle, @BlockSize, SizeOf(BlockSize));
|
||||||
|
if BlockSize >= SizeOf(AppRec) then
|
||||||
|
begin
|
||||||
|
Read(Handle, @AppRec, SizeOf(AppRec));
|
||||||
|
if (AppRec.Identifier = 'NETSCAPE') and (AppRec.Authentication = '2.0') then
|
||||||
|
begin
|
||||||
|
Read(Handle, @BlockSize, SizeOf(BlockSize));
|
||||||
|
while BlockSize <> 0 do
|
||||||
|
begin
|
||||||
|
BlockType := ReadBlockID;
|
||||||
|
Dec(BlockSize);
|
||||||
|
|
||||||
|
case BlockType of
|
||||||
|
GIFAppLoopExtension:
|
||||||
|
if (BlockSize >= SizeOf(LoopCount)) then
|
||||||
|
begin
|
||||||
|
// Read loop count
|
||||||
|
Read(Handle, @LoopCount, SizeOf(LoopCount));
|
||||||
|
Dec(BlockSize, SizeOf(LoopCount));
|
||||||
|
end;
|
||||||
|
GIFAppBufferExtension:
|
||||||
|
begin
|
||||||
|
Dec(BlockSize, SizeOf(Word));
|
||||||
|
Seek(Handle, SizeOf(Word), smFromCurrent);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SkipBytes;
|
||||||
|
AppRead := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Revert all bytes reading
|
||||||
|
Seek(Handle, - SizeOf(AppRec) - SizeOf(BlockSize), smFromCurrent);
|
||||||
|
SkipBytes;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Seek(Handle, - BlockSize - SizeOf(BlockSize), smFromCurrent);
|
||||||
|
SkipBytes;
|
||||||
|
end;
|
||||||
|
end
|
||||||
else if ExtType in [GIFCommentExtension, GIFApplicationExtension, GIFPlainText] then
|
else if ExtType in [GIFCommentExtension, GIFApplicationExtension, GIFPlainText] then
|
||||||
repeat
|
repeat
|
||||||
// Read block sizes and skip them
|
// Read block sizes and skip them
|
||||||
|
@ -688,33 +783,8 @@ var
|
||||||
|
|
||||||
// Read ID of following block
|
// Read ID of following block
|
||||||
BlockID := ReadBlockID;
|
BlockID := ReadBlockID;
|
||||||
end;
|
ExtType := BlockID;
|
||||||
end;
|
end
|
||||||
|
|
||||||
procedure CopyFrameTransparent(const Image, Frame: TImageData; Left, Top,
|
|
||||||
TransIndex: Integer; Disposal: TDisposalMethod);
|
|
||||||
var
|
|
||||||
X, Y: Integer;
|
|
||||||
Src, Dst: PByte;
|
|
||||||
begin
|
|
||||||
Src := Frame.Bits;
|
|
||||||
|
|
||||||
// Copy all pixels from frame to log screen but ignore the transparent ones
|
|
||||||
for Y := 0 to Frame.Height - 1 do
|
|
||||||
begin
|
|
||||||
Dst := @PByteArray(Image.Bits)[(Top + Y) * Image.Width + Left];
|
|
||||||
for X := 0 to Frame.Width - 1 do
|
|
||||||
begin
|
|
||||||
// If disposal methos is undefined copy all pixels regardless of
|
|
||||||
// transparency (transparency of whole image will be determined by TranspIndex
|
|
||||||
// in image palette) - same effect as filling the image with trasp color
|
|
||||||
// instead of backround color beforehand.
|
|
||||||
// For other methods don't copy transparent pixels from frame to image.
|
|
||||||
if (Src^ <> TransIndex) or (Disposal = dmUndefined) then
|
|
||||||
Dst^ := Src^;
|
|
||||||
Inc(Src);
|
|
||||||
Inc(Dst);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -743,33 +813,49 @@ var
|
||||||
procedure ReadFrame;
|
procedure ReadFrame;
|
||||||
var
|
var
|
||||||
ImageDesc: TImageDescriptor;
|
ImageDesc: TImageDescriptor;
|
||||||
HasLocalPal, Interlaced, HasTransparency: Boolean;
|
Interlaced: Boolean;
|
||||||
I, Idx, LocalPalLength, TransIndex: Integer;
|
I, Idx, LocalPalLength: Integer;
|
||||||
LocalPal: TPalette32Size256;
|
LocalPal: TPalette32Size256;
|
||||||
BlockTerm: Byte;
|
|
||||||
Frame: TImageData;
|
|
||||||
LZWStream: TMemoryStream;
|
LZWStream: TMemoryStream;
|
||||||
|
|
||||||
|
procedure RemoveBadFrame;
|
||||||
|
begin
|
||||||
|
FreeImage(Images[Idx]);
|
||||||
|
SetLength(Images, Length(Images) - 1);
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Idx := Length(Images);
|
Idx := Length(Images);
|
||||||
SetLength(Images, Idx + 1);
|
SetLength(Images, Idx + 1);
|
||||||
|
SetLength(FrameInfos, Idx + 1);
|
||||||
FillChar(LocalPal, SizeOf(LocalPal), 0);
|
FillChar(LocalPal, SizeOf(LocalPal), 0);
|
||||||
|
|
||||||
with GetIO do
|
with GetIO do
|
||||||
begin
|
begin
|
||||||
// Read and parse image descriptor
|
// Read and parse image descriptor
|
||||||
Read(Handle, @ImageDesc, SizeOf(ImageDesc));
|
Read(Handle, @ImageDesc, SizeOf(ImageDesc));
|
||||||
HasLocalPal := (ImageDesc.PackedFields and GIFLocalColorTable) = GIFLocalColorTable;
|
FrameInfos[Idx].HasLocalPal := (ImageDesc.PackedFields and GIFLocalColorTable) = GIFLocalColorTable;
|
||||||
Interlaced := (ImageDesc.PackedFields and GIFInterlaced) = GIFInterlaced;
|
Interlaced := (ImageDesc.PackedFields and GIFInterlaced) = GIFInterlaced;
|
||||||
LocalPalLength := ImageDesc.PackedFields and GIFColorTableSize;
|
LocalPalLength := ImageDesc.PackedFields and GIFColorTableSize;
|
||||||
LocalPalLength := 1 shl (LocalPalLength + 1); // Total pal length is 2^(n+1)
|
LocalPalLength := 1 shl (LocalPalLength + 1); // Total pal length is 2^(n+1)
|
||||||
|
|
||||||
// Create new logical screen
|
// From Mozilla source
|
||||||
NewImage(Header.ScreenWidth, Header.ScreenHeight, ifIndex8, Images[Idx]);
|
if (ImageDesc.Width = 0) or (ImageDesc.Width > Header.ScreenWidth) then
|
||||||
|
ImageDesc.Width := Header.ScreenWidth;
|
||||||
|
if (ImageDesc.Height = 0) or (ImageDesc.Height > Header.ScreenHeight) then
|
||||||
|
ImageDesc.Height := Header.ScreenHeight;
|
||||||
|
|
||||||
|
FrameInfos[Idx].Left := ImageDesc.Left;
|
||||||
|
FrameInfos[Idx].Top := ImageDesc.Top;
|
||||||
|
FrameInfos[Idx].Width := ImageDesc.Width;
|
||||||
|
FrameInfos[Idx].Height := ImageDesc.Height;
|
||||||
|
FrameInfos[Idx].BackIndex := Header.BackgroundColorIndex;
|
||||||
|
|
||||||
// Create new image for this frame which would be later pasted onto logical screen
|
// Create new image for this frame which would be later pasted onto logical screen
|
||||||
InitImage(Frame);
|
NewImage(ImageDesc.Width, ImageDesc.Height, ifIndex8, Images[Idx]);
|
||||||
NewImage(ImageDesc.Width, ImageDesc.Height, ifIndex8, Frame);
|
|
||||||
|
|
||||||
// Load local palette if there is any
|
// Load local palette if there is any
|
||||||
if HasLocalPal then
|
if FrameInfos[Idx].HasLocalPal then
|
||||||
for I := 0 to LocalPalLength - 1 do
|
for I := 0 to LocalPalLength - 1 do
|
||||||
begin
|
begin
|
||||||
LocalPal[I].A := 255;
|
LocalPal[I].A := 255;
|
||||||
|
@ -780,87 +866,174 @@ var
|
||||||
|
|
||||||
// Use local pal if present or global pal if present or create
|
// Use local pal if present or global pal if present or create
|
||||||
// default pal if neither of them is present
|
// default pal if neither of them is present
|
||||||
if HasLocalPal then
|
if FrameInfos[Idx].HasLocalPal then
|
||||||
Move(LocalPal, Images[Idx].Palette^, SizeOf(LocalPal))
|
Move(LocalPal, Images[Idx].Palette^, SizeOf(LocalPal))
|
||||||
else if HasGlobalPal then
|
else if HasGlobalPal then
|
||||||
Move(GlobalPal, Images[Idx].Palette^, SizeOf(GlobalPal))
|
Move(GlobalPal, Images[Idx].Palette^, SizeOf(GlobalPal))
|
||||||
else
|
else
|
||||||
FillCustomPalette(Images[Idx].Palette, GlobalPalLength, 3, 3, 2);
|
FillCustomPalette(Images[Idx].Palette, GlobalPalLength, 3, 3, 2);
|
||||||
|
|
||||||
// Add default disposal method for this frame
|
if (ImageDesc.Left <= Header.ScreenWidth + 1) and (ImageDesc.Top <= Header.ScreenHeight + 1) then
|
||||||
SetLength(Disposals, Length(Disposals) + 1);
|
begin
|
||||||
Disposals[High(Disposals)] := dmUndefined;
|
// Resize the screen if needed to fit the frame
|
||||||
|
ScreenWidth := Max(ScreenWidth, ImageDesc.Width + ImageDesc.Left);
|
||||||
|
ScreenHeight := Max(ScreenHeight, ImageDesc.Height + ImageDesc.Top);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Remove frame outside logical screen
|
||||||
|
RemoveBadFrame;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// If Grahic Control Extension is present make use of it
|
// If Grahic Control Extension is present make use of it
|
||||||
if HasGraphicExt then
|
if HasGraphicExt then
|
||||||
begin
|
begin
|
||||||
HasTransparency := (GraphicExt.PackedFields and GIFTransparent) = GIFTransparent;
|
FrameInfos[Idx].HasTransparency := (GraphicExt.PackedFields and GIFTransparent) = GIFTransparent;
|
||||||
Disposals[High(Disposals)] := TDisposalMethod((GraphicExt.PackedFields and GIFDisposalMethod) shr 2);
|
FrameInfos[Idx].Disposal := TDisposalMethod((GraphicExt.PackedFields and GIFDisposalMethod) shr 2);
|
||||||
if HasTransparency then
|
if FrameInfos[Idx].HasTransparency then
|
||||||
Images[Idx].Palette[GraphicExt.TransparentColorIndex].A := 0;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
HasTransparency := False;
|
|
||||||
|
|
||||||
if Idx >= 1 then
|
|
||||||
begin
|
begin
|
||||||
// If previous frame had some special disposal method we take it into
|
FrameInfos[Idx].TransIndex := GraphicExt.TransparentColorIndex;
|
||||||
// account now
|
Images[Idx].Palette[FrameInfos[Idx].TransIndex].A := 0;
|
||||||
case Disposals[Idx - 1] of
|
|
||||||
dmUndefined: ; // Do nothing
|
|
||||||
dmLeave:
|
|
||||||
begin
|
|
||||||
// Leave previous frame on log screen
|
|
||||||
CopyRect(Images[Idx - 1], 0, 0, Images[Idx].Width,
|
|
||||||
Images[Idx].Height, Images[Idx], 0, 0);
|
|
||||||
end;
|
|
||||||
dmRestoreBackground:
|
|
||||||
begin
|
|
||||||
// Clear log screen with background color
|
|
||||||
FillRect(Images[Idx], 0, 0, Images[Idx].Width, Images[Idx].Height,
|
|
||||||
@Header.BackgroundColorIndex);
|
|
||||||
end;
|
|
||||||
dmRestorePrevious:
|
|
||||||
if Idx >= 2 then
|
|
||||||
begin
|
|
||||||
// Set log screen to "previous of previous" frame
|
|
||||||
CopyRect(Images[Idx - 2], 0, 0, Images[Idx].Width,
|
|
||||||
Images[Idx].Height, Images[Idx], 0, 0);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
FrameInfos[Idx].HasTransparency := False;
|
||||||
// First frame - just fill with background color
|
|
||||||
FillRect(Images[Idx], 0, 0, Images[Idx].Width, Images[Idx].Height,
|
|
||||||
@Header.BackgroundColorIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
LZWStream := TMemoryStream.Create;
|
LZWStream := TMemoryStream.Create;
|
||||||
|
try
|
||||||
try
|
try
|
||||||
// Copy LZW data to temp stream, needed for correct decompression
|
// Copy LZW data to temp stream, needed for correct decompression
|
||||||
CopyLZWData(LZWStream);
|
CopyLZWData(LZWStream);
|
||||||
LZWStream.Position := 0;
|
LZWStream.Position := 0;
|
||||||
// Data decompression finally
|
// Data decompression finally
|
||||||
LZWDecompress(LZWStream, Handle, ImageDesc.Width, ImageDesc.Height, Interlaced, Frame.Bits);
|
LZWDecompress(LZWStream, Handle, ImageDesc.Width, ImageDesc.Height, Interlaced, Images[Idx].Bits);
|
||||||
// Now copy frame to logical screen with skipping of transparent pixels (if enabled)
|
except
|
||||||
TransIndex := Iff(HasTransparency, GraphicExt.TransparentColorIndex, MaxInt);
|
RemoveBadFrame;
|
||||||
CopyFrameTransparent(Images[Idx], Frame, ImageDesc.Left, ImageDesc.Top,
|
Exit;
|
||||||
TransIndex, Disposals[Idx]);
|
end;
|
||||||
finally
|
finally
|
||||||
FreeImage(Frame);
|
|
||||||
LZWStream.Free;
|
LZWStream.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure CopyFrameTransparent32(const Image, Frame: TImageData; Left, Top: Integer);
|
||||||
|
var
|
||||||
|
X, Y: Integer;
|
||||||
|
Src: PByte;
|
||||||
|
Dst: PColor32;
|
||||||
|
begin
|
||||||
|
Src := Frame.Bits;
|
||||||
|
|
||||||
|
// Copy all pixels from frame to log screen but ignore the transparent ones
|
||||||
|
for Y := 0 to Frame.Height - 1 do
|
||||||
|
begin
|
||||||
|
Dst := @PColor32RecArray(Image.Bits)[(Top + Y) * Image.Width + Left];
|
||||||
|
for X := 0 to Frame.Width - 1 do
|
||||||
|
begin
|
||||||
|
if (Frame.Palette[Src^].A <> 0) then
|
||||||
|
Dst^ := Frame.Palette[Src^].Color;
|
||||||
|
Inc(Src);
|
||||||
|
Inc(Dst);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AnimateFrame(Index: Integer; var AnimFrame: TImageData);
|
||||||
|
var
|
||||||
|
I, First, Last: Integer;
|
||||||
|
UseCache: Boolean;
|
||||||
|
BGColor: TColor32;
|
||||||
|
begin
|
||||||
|
// We may need to use raw frame 0 to n to correctly animate n-th frame
|
||||||
|
Last := Index;
|
||||||
|
First := Max(0, Last);
|
||||||
|
// See if we can use last animate frame as a basis for this one
|
||||||
|
// (so we don't have to use previous raw frames).
|
||||||
|
UseCache := TestImage(CachedFrame) and (CachedIndex = Index - 1) and (CachedIndex >= 0) and
|
||||||
|
(FrameInfos[CachedIndex].Disposal <> dmRestorePrevious);
|
||||||
|
|
||||||
|
// Reuse or release cache
|
||||||
|
if UseCache then
|
||||||
|
CloneImage(CachedFrame, AnimFrame)
|
||||||
|
else
|
||||||
|
FreeImage(CachedFrame);
|
||||||
|
|
||||||
|
// Default color for clearing of the screen
|
||||||
|
BGColor := Images[Index].Palette[FrameInfos[Index].BackIndex].Color;
|
||||||
|
|
||||||
|
// Now prepare logical screen for drawing of raw frame at Index.
|
||||||
|
// We may need to use all previous raw frames to get the screen
|
||||||
|
// to proper state (according to their disposal methods).
|
||||||
|
|
||||||
|
if not UseCache then
|
||||||
|
begin
|
||||||
|
if FrameInfos[Index].HasTransparency then
|
||||||
|
BGColor := Images[Index].Palette[FrameInfos[Index].TransIndex].Color;
|
||||||
|
// Clear whole screen
|
||||||
|
FillMemoryLongWord(AnimFrame.Bits, AnimFrame.Size, BGColor);
|
||||||
|
|
||||||
|
// Try to maximize First so we don't have to use all 0 to n raw frames
|
||||||
|
while First > 0 do
|
||||||
|
begin
|
||||||
|
if (ScreenWidth = Images[First].Width) and (ScreenHeight = Images[First].Height) then
|
||||||
|
begin
|
||||||
|
if (FrameInfos[First].Disposal = dmRestoreBackground) and (First < Last) then
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
Dec(First);
|
||||||
|
end;
|
||||||
|
|
||||||
|
for I := First to Last - 1 do
|
||||||
|
begin
|
||||||
|
case FrameInfos[I].Disposal of
|
||||||
|
dmNoRemoval, dmLeave:
|
||||||
|
begin
|
||||||
|
// Copy previous raw frame onto screen
|
||||||
|
CopyFrameTransparent32(AnimFrame, Images[I], FrameInfos[I].Left, FrameInfos[I].Top);
|
||||||
|
end;
|
||||||
|
dmRestoreBackground:
|
||||||
|
if (I > First) then
|
||||||
|
begin
|
||||||
|
// Restore background color
|
||||||
|
FillRect(AnimFrame, FrameInfos[I].Left, FrameInfos[I].Top,
|
||||||
|
FrameInfos[I].Width, FrameInfos[I].Height, @BGColor);
|
||||||
|
end;
|
||||||
|
dmRestorePrevious: ; // Do nothing - previous state is already on screen
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if FrameInfos[CachedIndex].Disposal = dmRestoreBackground then
|
||||||
|
begin
|
||||||
|
// We have our cached result but also need to restore
|
||||||
|
// background in a place of cached frame
|
||||||
|
if FrameInfos[CachedIndex].HasTransparency then
|
||||||
|
BGColor := Images[CachedIndex].Palette[FrameInfos[CachedIndex].TransIndex].Color;
|
||||||
|
FillRect(AnimFrame, FrameInfos[CachedIndex].Left, FrameInfos[CachedIndex].Top,
|
||||||
|
FrameInfos[CachedIndex].Width, FrameInfos[CachedIndex].Height, @BGColor);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Copy current raw frame to prepared screen
|
||||||
|
CopyFrameTransparent32(AnimFrame, Images[Index], FrameInfos[Index].Left, FrameInfos[Index].Top);
|
||||||
|
|
||||||
|
// Cache animated result
|
||||||
|
CloneImage(AnimFrame, CachedFrame);
|
||||||
|
CachedIndex := Index;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
AppRead := False;
|
||||||
|
|
||||||
SetLength(Images, 0);
|
SetLength(Images, 0);
|
||||||
FillChar(GlobalPal, SizeOf(GlobalPal), 0);
|
FillChar(GlobalPal, SizeOf(GlobalPal), 0);
|
||||||
|
|
||||||
with GetIO do
|
with GetIO do
|
||||||
begin
|
begin
|
||||||
// Read GIF header
|
// Read GIF header
|
||||||
Read(Handle, @Header, SizeOf(Header));
|
Read(Handle, @Header, SizeOf(Header));
|
||||||
|
ScreenWidth := Header.ScreenWidth;
|
||||||
|
ScreenHeight := Header.ScreenHeight;
|
||||||
HasGlobalPal := Header.PackedFields and GIFGlobalColorTable = GIFGlobalColorTable; // Bit 7
|
HasGlobalPal := Header.PackedFields and GIFGlobalColorTable = GIFGlobalColorTable; // Bit 7
|
||||||
GlobalPalLength := Header.PackedFields and GIFColorTableSize; // Bits 0-2
|
GlobalPalLength := Header.PackedFields and GIFColorTableSize; // Bits 0-2
|
||||||
GlobalPalLength := 1 shl (GlobalPalLength + 1); // Total pal length is 2^(n+1)
|
GlobalPalLength := 1 shl (GlobalPalLength + 1); // Total pal length is 2^(n+1)
|
||||||
|
@ -883,6 +1056,9 @@ begin
|
||||||
// Now read all data blocks in the file until file trailer is reached
|
// Now read all data blocks in the file until file trailer is reached
|
||||||
while BlockID <> GIFTrailer do
|
while BlockID <> GIFTrailer do
|
||||||
begin
|
begin
|
||||||
|
// Read blocks until we find the one of known type
|
||||||
|
while not (BlockID in [GIFTrailer, GIFExtensionIntroducer, GIFImageDescriptor]) do
|
||||||
|
BlockID := ReadBlockID;
|
||||||
// Read supported and skip unsupported extensions
|
// Read supported and skip unsupported extensions
|
||||||
ReadExtensions;
|
ReadExtensions;
|
||||||
// If image frame is found read it
|
// If image frame is found read it
|
||||||
|
@ -895,6 +1071,31 @@ begin
|
||||||
BlockID := GIFTrailer;
|
BlockID := GIFTrailer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if FLoadAnimated then
|
||||||
|
begin
|
||||||
|
// Aniated frames will be stored in AnimFrames
|
||||||
|
SetLength(AnimFrames, Length(Images));
|
||||||
|
InitImage(CachedFrame);
|
||||||
|
CachedIndex := -1;
|
||||||
|
|
||||||
|
for I := 0 to High(Images) do
|
||||||
|
begin
|
||||||
|
// Create new logical screen
|
||||||
|
NewImage(ScreenWidth, ScreenHeight, ifA8R8G8B8, AnimFrames[I]);
|
||||||
|
// Animate frames to current log screen
|
||||||
|
AnimateFrame(I, AnimFrames[I]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Now release raw 8bit frames and put animated 32bit ones
|
||||||
|
// to output array
|
||||||
|
FreeImage(CachedFrame);
|
||||||
|
for I := 0 to High(AnimFrames) do
|
||||||
|
begin
|
||||||
|
FreeImage(Images[I]);
|
||||||
|
Images[I] := AnimFrames[I];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1007,6 +1208,14 @@ initialization
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Fixed bug - loading of GIF with NETSCAPE app extensions
|
||||||
|
failed with Delphi 2009.
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- GIF loading and animation mostly rewritten, based on
|
||||||
|
modification by Sergey Galezdinov (ExtraGIF in Extras/Contrib).
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
||||||
- Fixed loading of some rare GIFs, problems with LZW
|
- Fixed loading of some rare GIFs, problems with LZW
|
||||||
decompression.
|
decompression.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingJpeg.pas 128 2008-07-23 11:57:36Z galfar $
|
$Id: ImagingJpeg.pas 180 2009-10-16 01:07:26Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -43,22 +43,22 @@ unit ImagingJpeg;
|
||||||
{$DEFINE IMJPEGLIB}
|
{$DEFINE IMJPEGLIB}
|
||||||
{ $DEFINE PASJPEG}
|
{ $DEFINE PASJPEG}
|
||||||
|
|
||||||
{ Automatically use FPC's PasJpeg when compiling with Lazarus.}
|
{ Automatically use FPC's PasJpeg when compiling with Lazarus. But not when
|
||||||
|
WINDOWS is defined. See http://galfar.vevb.net/imaging/smf/index.php/topic,90.0.html}
|
||||||
{$IFDEF LCL}
|
{$IF Defined(LCL) and not Defined(WINDOWS)}
|
||||||
{$UNDEF IMJPEGLIB}
|
{$UNDEF IMJPEGLIB}
|
||||||
{$DEFINE PASJPEG}
|
{$DEFINE PASJPEG}
|
||||||
{$ENDIF}
|
{$IFEND}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, ImagingTypes, Imaging, ImagingColors,
|
SysUtils, ImagingTypes, Imaging, ImagingColors,
|
||||||
{$IF Defined(IMJPEGLIB)}
|
{$IF Defined(IMJPEGLIB)}
|
||||||
imjpeglib, imjmorecfg, imjcomapi, imjdapimin,
|
imjpeglib, imjmorecfg, imjcomapi, imjdapimin, imjdeferr, imjerror,
|
||||||
imjdapistd, imjcapimin, imjcapistd, imjdmarker, imjcparam,
|
imjdapistd, imjcapimin, imjcapistd, imjdmarker, imjcparam,
|
||||||
{$ELSEIF Defined(PASJPEG)}
|
{$ELSEIF Defined(PASJPEG)}
|
||||||
jpeglib, jmorecfg, jcomapi, jdapimin,
|
jpeglib, jmorecfg, jcomapi, jdapimin, jdeferr, jerror,
|
||||||
jdapistd, jcapimin, jcapistd, jdmarker, jcparam,
|
jdapistd, jcapimin, jcapistd, jdmarker, jcparam,
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
ImagingUtility;
|
ImagingUtility;
|
||||||
|
@ -70,7 +70,10 @@ uses
|
||||||
|
|
||||||
type
|
type
|
||||||
{ Class for loading/saving Jpeg images. Supports load/save of
|
{ Class for loading/saving Jpeg images. Supports load/save of
|
||||||
8 bit grayscale and 24 bit RGB images.}
|
8 bit grayscale and 24 bit RGB images. Jpegs can be saved with optional
|
||||||
|
progressive encoding.
|
||||||
|
Based on IJG's JpegLib so doesn't support alpha channels and lossless
|
||||||
|
coding.}
|
||||||
TJpegFileFormat = class(TImageFileFormat)
|
TJpegFileFormat = class(TImageFileFormat)
|
||||||
private
|
private
|
||||||
FGrayScale: Boolean;
|
FGrayScale: Boolean;
|
||||||
|
@ -110,10 +113,11 @@ const
|
||||||
const
|
const
|
||||||
{ Jpeg file identifiers.}
|
{ Jpeg file identifiers.}
|
||||||
JpegMagic: TChar2 = #$FF#$D8;
|
JpegMagic: TChar2 = #$FF#$D8;
|
||||||
JFIFSignature: TChar4 = 'JFIF';
|
|
||||||
EXIFSignature: TChar4 = 'Exif';
|
|
||||||
BufferSize = 16384;
|
BufferSize = 16384;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SJpegError = 'JPEG Error';
|
||||||
|
|
||||||
type
|
type
|
||||||
TJpegContext = record
|
TJpegContext = record
|
||||||
case Byte of
|
case Byte of
|
||||||
|
@ -139,40 +143,23 @@ type
|
||||||
|
|
||||||
var
|
var
|
||||||
JIO: TIOFunctions;
|
JIO: TIOFunctions;
|
||||||
|
JpegErrorMgr: jpeg_error_mgr;
|
||||||
|
|
||||||
{ Intenal unit jpeglib support functions }
|
{ Intenal unit jpeglib support functions }
|
||||||
|
|
||||||
procedure JpegError(CurInfo: j_common_ptr);
|
procedure JpegError(CInfo: j_common_ptr);
|
||||||
begin
|
var
|
||||||
end;
|
Buffer: string;
|
||||||
|
|
||||||
procedure EmitMessage(CurInfo: j_common_ptr; msg_level: Integer);
|
|
||||||
begin
|
begin
|
||||||
|
{ Create the message and raise exception }
|
||||||
|
CInfo^.err^.format_message(CInfo, buffer);
|
||||||
|
raise EImagingError.CreateFmt(SJPEGError + ' %d: ' + Buffer, [CInfo.err^.msg_code]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure OutputMessage(CurInfo: j_common_ptr);
|
procedure OutputMessage(CurInfo: j_common_ptr);
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure FormatMessage(CurInfo: j_common_ptr; var buffer: string);
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ResetErrorMgr(CurInfo: j_common_ptr);
|
|
||||||
begin
|
|
||||||
CurInfo^.err^.num_warnings := 0;
|
|
||||||
CurInfo^.err^.msg_code := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
JpegErrorRec: jpeg_error_mgr = (
|
|
||||||
error_exit: JpegError;
|
|
||||||
emit_message: EmitMessage;
|
|
||||||
output_message: OutputMessage;
|
|
||||||
format_message: FormatMessage;
|
|
||||||
reset_error_mgr: ResetErrorMgr);
|
|
||||||
|
|
||||||
procedure ReleaseContext(var jc: TJpegContext);
|
procedure ReleaseContext(var jc: TJpegContext);
|
||||||
begin
|
begin
|
||||||
if jc.common.err = nil then
|
if jc.common.err = nil then
|
||||||
|
@ -221,7 +208,7 @@ begin
|
||||||
FillInputBuffer(cinfo);
|
FillInputBuffer(cinfo);
|
||||||
end;
|
end;
|
||||||
Src.Pub.next_input_byte := @PByteArray(Src.Pub.next_input_byte)[num_bytes];
|
Src.Pub.next_input_byte := @PByteArray(Src.Pub.next_input_byte)[num_bytes];
|
||||||
// Inc(LongInt(Src.Pub.next_input_byte), num_bytes);
|
//Inc(LongInt(Src.Pub.next_input_byte), num_bytes);
|
||||||
Dec(Src.Pub.bytes_in_buffer, num_bytes);
|
Dec(Src.Pub.bytes_in_buffer, num_bytes);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -311,7 +298,11 @@ end;
|
||||||
procedure InitDecompressor(Handle: TImagingHandle; var jc: TJpegContext);
|
procedure InitDecompressor(Handle: TImagingHandle; var jc: TJpegContext);
|
||||||
begin
|
begin
|
||||||
FillChar(jc, sizeof(jc), 0);
|
FillChar(jc, sizeof(jc), 0);
|
||||||
jc.common.err := @JpegErrorRec;
|
// Set standard error handlers and then override some
|
||||||
|
jc.common.err := jpeg_std_error(JpegErrorMgr);
|
||||||
|
jc.common.err.error_exit := JpegError;
|
||||||
|
jc.common.err.output_message := OutputMessage;
|
||||||
|
|
||||||
jpeg_CreateDecompress(@jc.d, JPEG_LIB_VERSION, sizeof(jc.d));
|
jpeg_CreateDecompress(@jc.d, JPEG_LIB_VERSION, sizeof(jc.d));
|
||||||
JpegStdioSrc(jc.d, Handle);
|
JpegStdioSrc(jc.d, Handle);
|
||||||
jpeg_read_header(@jc.d, True);
|
jpeg_read_header(@jc.d, True);
|
||||||
|
@ -329,15 +320,19 @@ procedure InitCompressor(Handle: TImagingHandle; var jc: TJpegContext;
|
||||||
Saver: TJpegFileFormat);
|
Saver: TJpegFileFormat);
|
||||||
begin
|
begin
|
||||||
FillChar(jc, sizeof(jc), 0);
|
FillChar(jc, sizeof(jc), 0);
|
||||||
jc.common.err := @JpegErrorRec;
|
// Set standard error handlers and then override some
|
||||||
|
jc.common.err := jpeg_std_error(JpegErrorMgr);
|
||||||
|
jc.common.err.error_exit := JpegError;
|
||||||
|
jc.common.err.output_message := OutputMessage;
|
||||||
|
|
||||||
jpeg_CreateCompress(@jc.c, JPEG_LIB_VERSION, sizeof(jc.c));
|
jpeg_CreateCompress(@jc.c, JPEG_LIB_VERSION, sizeof(jc.c));
|
||||||
JpegStdioDest(jc.c, Handle);
|
JpegStdioDest(jc.c, Handle);
|
||||||
|
if Saver.FGrayScale then
|
||||||
|
jc.c.in_color_space := JCS_GRAYSCALE
|
||||||
|
else
|
||||||
|
jc.c.in_color_space := JCS_RGB;
|
||||||
jpeg_set_defaults(@jc.c);
|
jpeg_set_defaults(@jc.c);
|
||||||
jpeg_set_quality(@jc.c, Saver.FQuality, True);
|
jpeg_set_quality(@jc.c, Saver.FQuality, True);
|
||||||
if Saver.FGrayScale then
|
|
||||||
jpeg_set_colorspace(@jc.c, JCS_GRAYSCALE)
|
|
||||||
else
|
|
||||||
jpeg_set_colorspace(@jc.c, JCS_YCbCr);
|
|
||||||
if Saver.FProgressive then
|
if Saver.FProgressive then
|
||||||
jpeg_simple_progression(@jc.c);
|
jpeg_simple_progression(@jc.c);
|
||||||
end;
|
end;
|
||||||
|
@ -376,13 +371,14 @@ var
|
||||||
jc: TJpegContext;
|
jc: TJpegContext;
|
||||||
Info: TImageFormatInfo;
|
Info: TImageFormatInfo;
|
||||||
Col32: PColor32Rec;
|
Col32: PColor32Rec;
|
||||||
{$IFDEF RGBSWAPPED}
|
NeedsRedBlueSwap: Boolean;
|
||||||
Pix: PColor24Rec;
|
Pix: PColor24Rec;
|
||||||
{$ENDIF}
|
|
||||||
begin
|
begin
|
||||||
// Copy IO functions to global var used in JpegLib callbacks
|
// Copy IO functions to global var used in JpegLib callbacks
|
||||||
|
Result := False;
|
||||||
SetJpegIO(GetIO);
|
SetJpegIO(GetIO);
|
||||||
SetLength(Images, 1);
|
SetLength(Images, 1);
|
||||||
|
|
||||||
with JIO, Images[0] do
|
with JIO, Images[0] do
|
||||||
try
|
try
|
||||||
InitDecompressor(Handle, jc);
|
InitDecompressor(Handle, jc);
|
||||||
|
@ -390,6 +386,8 @@ begin
|
||||||
JCS_GRAYSCALE: Format := ifGray8;
|
JCS_GRAYSCALE: Format := ifGray8;
|
||||||
JCS_RGB: Format := ifR8G8B8;
|
JCS_RGB: Format := ifR8G8B8;
|
||||||
JCS_CMYK: Format := ifA8R8G8B8;
|
JCS_CMYK: Format := ifA8R8G8B8;
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
end;
|
end;
|
||||||
NewImage(jc.d.image_width, jc.d.image_height, Format, Images[0]);
|
NewImage(jc.d.image_width, jc.d.image_height, Format, Images[0]);
|
||||||
jpeg_start_decompress(@jc.d);
|
jpeg_start_decompress(@jc.d);
|
||||||
|
@ -398,11 +396,18 @@ begin
|
||||||
LinesPerCall := 1;
|
LinesPerCall := 1;
|
||||||
Dest := Bits;
|
Dest := Bits;
|
||||||
|
|
||||||
|
// If Jpeg's colorspace is RGB and not YCbCr we need to swap
|
||||||
|
// R and B to get Imaging's native order
|
||||||
|
NeedsRedBlueSwap := jc.d.jpeg_color_space = JCS_RGB;
|
||||||
|
{$IFDEF RGBSWAPPED}
|
||||||
|
// Force R-B swap for FPC's PasJpeg
|
||||||
|
NeedsRedBlueSwap := True;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
while jc.d.output_scanline < jc.d.output_height do
|
while jc.d.output_scanline < jc.d.output_height do
|
||||||
begin
|
begin
|
||||||
LinesRead := jpeg_read_scanlines(@jc.d, @Dest, LinesPerCall);
|
LinesRead := jpeg_read_scanlines(@jc.d, @Dest, LinesPerCall);
|
||||||
{$IFDEF RGBSWAPPED}
|
if NeedsRedBlueSwap and (Format = ifR8G8B8) then
|
||||||
if Format = ifR8G8B8 then
|
|
||||||
begin
|
begin
|
||||||
Pix := PColor24Rec(Dest);
|
Pix := PColor24Rec(Dest);
|
||||||
for I := 0 to Width - 1 do
|
for I := 0 to Width - 1 do
|
||||||
|
@ -411,7 +416,6 @@ begin
|
||||||
Inc(Pix);
|
Inc(Pix);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
|
||||||
Inc(Dest, PtrInc * LinesRead);
|
Inc(Dest, PtrInc * LinesRead);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -526,7 +530,7 @@ end;
|
||||||
function TJpegFileFormat.TestFormat(Handle: TImagingHandle): Boolean;
|
function TJpegFileFormat.TestFormat(Handle: TImagingHandle): Boolean;
|
||||||
var
|
var
|
||||||
ReadCount: LongInt;
|
ReadCount: LongInt;
|
||||||
ID: array[0..9] of Char;
|
ID: array[0..9] of AnsiChar;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
if Handle <> nil then
|
if Handle <> nil then
|
||||||
|
@ -554,8 +558,20 @@ initialization
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.5 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Fixed swapped Red-Blue order when loading Jpegs with
|
||||||
|
jc.d.jpeg_color_space = JCS_RGB.
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Changed the Jpeg error manager, messages were not properly formated.
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Fixed wrong color space setting in InitCompressor.
|
||||||
|
- Fixed problem with progressive Jpegs in FPC (modified JpegLib,
|
||||||
|
can't use FPC's PasJpeg in Windows).
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
||||||
-- FPC's PasJpeg wasn't really used in last version, fixed.
|
- FPC's PasJpeg wasn't really used in last version, fixed.
|
||||||
|
|
||||||
-- 0.24.1 Changes/Bug Fixes ---------------------------------
|
-- 0.24.1 Changes/Bug Fixes ---------------------------------
|
||||||
- Fixed loading of CMYK jpeg images. Could cause heap corruption
|
- Fixed loading of CMYK jpeg images. Could cause heap corruption
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingOpenGL.pas 128 2008-07-23 11:57:36Z galfar $
|
$Id: ImagingOpenGL.pas 165 2009-08-14 12:34:40Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -33,17 +33,20 @@ unit ImagingOpenGL;
|
||||||
{$I ImagingOptions.inc}
|
{$I ImagingOptions.inc}
|
||||||
|
|
||||||
{ Define this symbol if you want to use dglOpenGL header.}
|
{ Define this symbol if you want to use dglOpenGL header.}
|
||||||
{.$DEFINE USE_DGL_HEADERS}
|
{ $DEFINE USE_DGL_HEADERS}
|
||||||
|
{ $DEFINE USE_GLSCENE_HEADERS}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Classes, ImagingTypes, Imaging, ImagingFormats,
|
SysUtils, Classes, ImagingTypes, Imaging, ImagingFormats,
|
||||||
{$IFDEF USE_DGL_HEADERS}
|
{$IF Defined(USE_DGL_HEADERS)}
|
||||||
dglOpenGL,
|
dglOpenGL,
|
||||||
|
{$ELSEIF Defined(USE_GLSCENE_HEADERS)}
|
||||||
|
OpenGL1x,
|
||||||
{$ELSE}
|
{$ELSE}
|
||||||
gl, glext,
|
gl, glext,
|
||||||
{$ENDIF}
|
{$IFEND}
|
||||||
ImagingUtility;
|
ImagingUtility;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -278,6 +281,10 @@ const
|
||||||
GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
|
GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
|
||||||
GL_HALF_FLOAT_ARB = $140B;
|
GL_HALF_FLOAT_ARB = $140B;
|
||||||
|
|
||||||
|
// Other GL constants
|
||||||
|
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = $8B4C;
|
||||||
|
|
||||||
|
|
||||||
{$IFDEF MSWINDOWS}
|
{$IFDEF MSWINDOWS}
|
||||||
GLLibName = 'opengl32.dll';
|
GLLibName = 'opengl32.dll';
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
@ -880,6 +887,9 @@ initialization
|
||||||
not only A8R8G8B8
|
not only A8R8G8B8
|
||||||
- support for cube and 3D maps
|
- support for cube and 3D maps
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes ---------------------------------
|
||||||
|
- Added support for GLScene's OpenGL header.
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
-- 0.25.0 Changes/Bug Fixes ---------------------------------
|
||||||
- Added 3Dc compressed texture formats support.
|
- Added 3Dc compressed texture formats support.
|
||||||
- Added detection of 3Dc formats to texture caps.
|
- Added detection of 3Dc formats to texture caps.
|
||||||
|
|
|
@ -1,47 +1,53 @@
|
||||||
{ $Id: ImagingOptions.inc 132 2008-08-27 20:37:38Z galfar $ }
|
{ $Id: ImagingOptions.inc 174 2009-09-08 09:37:59Z galfar $ }
|
||||||
|
|
||||||
{
|
{
|
||||||
User Options
|
User Options
|
||||||
Following defines and options can be changed by user.
|
Following defines and options can be changed by user.
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Source options. }
|
{ Source options }
|
||||||
|
|
||||||
{$DEFINE USE_INLINE} // use function inlining for some functions
|
{$DEFINE USE_INLINE} // Use function inlining for some functions
|
||||||
// works in Free Pascal and Delphi 9+
|
// works in Free Pascal and Delphi 9+.
|
||||||
{$DEFINE USE_ASM} // if defined, assembler versions of some
|
{.$DEFINE USE_ASM} // Ff defined, assembler versions of some
|
||||||
// functions will be used (only for x86)
|
// functions will be used (only for x86).
|
||||||
{ $DEFINE DEBUG} // if defined, debug info, range/IO/overflow
|
|
||||||
|
// Debug options: If none of these two are defined
|
||||||
|
// your project settings are used.
|
||||||
|
{ $DEFINE IMAGING_DEBUG} // If defined, debug info, range/IO/overflow
|
||||||
// checking, stack frames, assertions, and
|
// checking, stack frames, assertions, and
|
||||||
// other debugging options will be turned on
|
// other debugging options will be turned on.
|
||||||
|
{$DEFINE IMAGING_RELEASE} // If defined, all debug info is off.
|
||||||
|
|
||||||
{ File format support linking options. Undefine formats which you don't want
|
|
||||||
to be registred automatically. }
|
|
||||||
|
|
||||||
{.$DEFINE LINK_JPEG} // link support for Jpeg images
|
|
||||||
{.$DEFINE LINK_PNG} // link support for PNG images
|
|
||||||
{$DEFINE LINK_TARGA} // link support for Targa images
|
|
||||||
{$DEFINE LINK_BITMAP} // link support for Windows Bitmap images
|
|
||||||
{.$DEFINE LINK_DDS} // link support for DDS images
|
|
||||||
{.$DEFINE LINK_GIF} // link support for GIF images
|
|
||||||
{.$DEFINE LINK_MNG} // link support for MNG images
|
|
||||||
{.$DEFINE LINK_JNG} // link support for JNG images
|
|
||||||
{.$DEFINE LINK_PNM} // link support for PortableMap images (PBM, PGM, PPM, PAM, PFM)
|
|
||||||
|
|
||||||
{.$DEFINE LINK_EXTRAS} // link support for file formats defined in
|
(* File format support linking options.
|
||||||
|
Define formats which you don't want to be registred automatically.
|
||||||
|
Default: all formats are registered = no symbols defined.
|
||||||
|
Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line
|
||||||
|
*)
|
||||||
|
|
||||||
|
//{$DEFINE DONT_LINK_JPEG} // link support for Jpeg images
|
||||||
|
//{$DEFINE DONT_LINK_PNG} // link support for PNG images
|
||||||
|
//{$DEFINE DONT_LINK_TARGA} // link support for Targa images
|
||||||
|
//{$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images
|
||||||
|
{$DEFINE DONT_LINK_DDS} // link support for DDS images
|
||||||
|
{$DEFINE DONT_LINK_GIF} // link support for GIF images
|
||||||
|
{$DEFINE DONT_LINK_MNG} // link support for MNG images
|
||||||
|
{$DEFINE DONT_LINK_JNG} // link support for JNG images
|
||||||
|
{$DEFINE DONT_LINK_PNM} // link support for PortableMap images (PBM, PGM, PPM, PAM, PFM)
|
||||||
|
|
||||||
|
{$DEFINE DONT_LINK_EXTRAS} // link support for file formats defined in
|
||||||
// Extras package. Exactly which formats will be
|
// Extras package. Exactly which formats will be
|
||||||
// registered depends on settings in
|
// registered depends on settings in
|
||||||
// ImagingExtras.pas unit.
|
// ImagingExtras.pas unit.
|
||||||
|
|
||||||
{ Component set used in ImagignComponents.pas unit. You usually don't need
|
{ Component set used in ImagignComponents.pas unit. You usually don't need
|
||||||
to be concerned with this - proper component library is selected automatically
|
to be concerned with this - proper component library is selected automatically
|
||||||
according to your compiler (only exception is using CLX in Delphi 6/7). }
|
according to your compiler. }
|
||||||
|
|
||||||
{$DEFINE COMPONENT_SET_VCL} // use Borland's VCL
|
{ $DEFINE COMPONENT_SET_VCL} // use Delphi VCL
|
||||||
{ $DEFINE COMPONENT_SET_CLX} // use Borland's CLX (set automatically when using Kylix,
|
{$DEFINE COMPONENT_SET_LCL} // use Lazarus LCL (set automatically when compiling with FPC)
|
||||||
// must be se manually when compiling with Delphi 6/7)
|
|
||||||
{ $DEFINE COMPONENT_SET_LCL} // use Lazarus' LCL (set automatically when
|
|
||||||
// compiling with FPC)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Auto Options
|
Auto Options
|
||||||
|
@ -85,7 +91,7 @@
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFEND}
|
{$IFEND}
|
||||||
|
|
||||||
{$IFDEF DEBUG}
|
{$IF Defined(IMAGING_DEBUG)}
|
||||||
{$ASSERTIONS ON}
|
{$ASSERTIONS ON}
|
||||||
{$DEBUGINFO ON}
|
{$DEBUGINFO ON}
|
||||||
{$RANGECHECKS ON}
|
{$RANGECHECKS ON}
|
||||||
|
@ -95,13 +101,13 @@
|
||||||
{$OPTIMIZATION OFF}
|
{$OPTIMIZATION OFF}
|
||||||
{$STACKFRAMES ON}
|
{$STACKFRAMES ON}
|
||||||
{$LOCALSYMBOLS ON}
|
{$LOCALSYMBOLS ON}
|
||||||
{ $DEFINE MEMCHECK}
|
{$DEFINE MEMCHECK}
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
{$S+}
|
{$S+}
|
||||||
{$CHECKPOINTER ON}
|
{$CHECKPOINTER ON}
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$ELSE}
|
{$ELSEIF Defined(IMAGING_RELEASE)}
|
||||||
{$ASSERTIONS OFF}
|
{$ASSERTIONS OFF}
|
||||||
{$DEBUGINFO OFF}
|
{$DEBUGINFO OFF}
|
||||||
{$RANGECHECKS OFF}
|
{$RANGECHECKS OFF}
|
||||||
|
@ -115,7 +121,8 @@
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
{$S-}
|
{$S-}
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{$ENDIF}
|
{$IFEND}
|
||||||
|
|
||||||
|
|
||||||
{ Compiler capabilities }
|
{ Compiler capabilities }
|
||||||
|
|
||||||
|
@ -151,40 +158,11 @@
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
{$DEFINE COMPONENT_SET_LCL}
|
{$DEFINE COMPONENT_SET_LCL}
|
||||||
{$UNDEF COMPONENT_SET_VCL}
|
{$UNDEF COMPONENT_SET_VCL}
|
||||||
{$UNDEF COMPONENT_SET_CLX}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF KYLIX}
|
|
||||||
{$DEFINE COMPONENT_SET_CLX}
|
|
||||||
{$UNDEF COMPONENT_SET_VCL}
|
|
||||||
{$UNDEF COMPONENT_SET_LCL}
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$IFDEF DELPHI}
|
{$IFDEF DELPHI}
|
||||||
{$UNDEF COMPONENT_SET_LCL}
|
{$UNDEF COMPONENT_SET_LCL}
|
||||||
{$IF CompilerVersion >= 17}
|
{$DEFINE COMPONENT_SET_VCL}
|
||||||
{$UNDEF COMPONENT_SET_CLX} // Delphi 9+ has no CLX
|
|
||||||
{$IFEND}
|
|
||||||
{$IFNDEF COMPONENT_SET_VCL}
|
|
||||||
{$IFNDEF COMPONENT_SET_CLX}
|
|
||||||
{$DEFINE COMPONENT_SET_VCL} // use VCL as default if not set
|
|
||||||
{$ENDIF}
|
|
||||||
{$ENDIF}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF COMPONENT_SET_VCL}
|
|
||||||
{$UNDEF COMPONENT_SET_CLX}
|
|
||||||
{$UNDEF COMPONENT_SET_LCL}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF COMPONENT_SET_CLX}
|
|
||||||
{$UNDEF COMPONENT_SET_VCL}
|
|
||||||
{$UNDEF COMPONENT_SET_LCL}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF COMPONENT_SET_LCL}
|
|
||||||
{$UNDEF COMPONENT_SET_VCL}
|
|
||||||
{$UNDEF COMPONENT_SET_CLX}
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{ Platform options }
|
{ Platform options }
|
||||||
|
@ -220,16 +198,4 @@
|
||||||
{$INLINE ON} // turns inlining on for compilers that support it
|
{$INLINE ON} // turns inlining on for compilers that support it
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{ Extension dependencies check }
|
|
||||||
|
|
||||||
{$IFDEF LINK_MNG} // MNG uses internaly both PNG and JNG
|
|
||||||
{$DEFINE LINK_JNG}
|
|
||||||
{$DEFINE LINK_PNG}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{$IFDEF LINK_JNG} // JNG uses internaly both PNG and JPEG
|
|
||||||
{$DEFINE LINK_PNG}
|
|
||||||
{$DEFINE LINK_JPEG}
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingPortableMaps.pas 127 2008-05-31 01:57:13Z galfar $
|
$Id: ImagingPortableMaps.pas 163 2009-07-28 21:44:10Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -46,7 +46,7 @@ type
|
||||||
TPortableMapInfo = record
|
TPortableMapInfo = record
|
||||||
Width: LongInt;
|
Width: LongInt;
|
||||||
Height: LongInt;
|
Height: LongInt;
|
||||||
FormatId: Char;
|
FormatId: AnsiChar;
|
||||||
MaxVal: LongInt;
|
MaxVal: LongInt;
|
||||||
BitCount: LongInt;
|
BitCount: LongInt;
|
||||||
Depth: LongInt;
|
Depth: LongInt;
|
||||||
|
@ -200,7 +200,7 @@ var
|
||||||
MonoData: Pointer;
|
MonoData: Pointer;
|
||||||
Info: TImageFormatInfo;
|
Info: TImageFormatInfo;
|
||||||
PixelFP: TColorFPRec;
|
PixelFP: TColorFPRec;
|
||||||
LineBuffer: array[0..LineBufferCapacity - 1] of Char;
|
LineBuffer: array[0..LineBufferCapacity - 1] of AnsiChar;
|
||||||
LineEnd, LinePos: LongInt;
|
LineEnd, LinePos: LongInt;
|
||||||
MapInfo: TPortableMapInfo;
|
MapInfo: TPortableMapInfo;
|
||||||
LineBreak: string;
|
LineBreak: string;
|
||||||
|
@ -228,7 +228,7 @@ var
|
||||||
function ReadString: string;
|
function ReadString: string;
|
||||||
var
|
var
|
||||||
S: AnsiString;
|
S: AnsiString;
|
||||||
C: Char;
|
C: AnsiChar;
|
||||||
begin
|
begin
|
||||||
// First skip all whitespace chars
|
// First skip all whitespace chars
|
||||||
SetLength(S, 1);
|
SetLength(S, 1);
|
||||||
|
@ -266,7 +266,7 @@ var
|
||||||
// Dec pos, current is the begining of the the string
|
// Dec pos, current is the begining of the the string
|
||||||
Dec(LinePos);
|
Dec(LinePos);
|
||||||
|
|
||||||
Result := S;
|
Result := string(S);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ReadIntValue: LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
function ReadIntValue: LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
|
@ -276,7 +276,7 @@ var
|
||||||
|
|
||||||
procedure FindLineBreak;
|
procedure FindLineBreak;
|
||||||
var
|
var
|
||||||
C: Char;
|
C: AnsiChar;
|
||||||
begin
|
begin
|
||||||
LineBreak := #10;
|
LineBreak := #10;
|
||||||
repeat
|
repeat
|
||||||
|
@ -586,7 +586,11 @@ var
|
||||||
begin
|
begin
|
||||||
SetLength(S, Length(S) + 1);
|
SetLength(S, Length(S) + 1);
|
||||||
S[Length(S)] := Delimiter;
|
S[Length(S)] := Delimiter;
|
||||||
|
{$IF Defined(DCC) and Defined(UNICODE)}
|
||||||
|
GetIO.Write(Handle, @AnsiString(S)[1], Length(S));
|
||||||
|
{$ELSE}
|
||||||
GetIO.Write(Handle, @S[1], Length(S));
|
GetIO.Write(Handle, @S[1], Length(S));
|
||||||
|
{$IFEND}
|
||||||
Inc(LineLength, Length(S));
|
Inc(LineLength, Length(S));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -807,7 +811,6 @@ begin
|
||||||
FName := SPGMFormatName;
|
FName := SPGMFormatName;
|
||||||
FSupportedFormats := PGMSupportedFormats;
|
FSupportedFormats := PGMSupportedFormats;
|
||||||
AddMasks(SPGMMasks);
|
AddMasks(SPGMMasks);
|
||||||
|
|
||||||
RegisterOption(ImagingPGMSaveBinary, @FSaveBinary);
|
RegisterOption(ImagingPGMSaveBinary, @FSaveBinary);
|
||||||
FIdNumbers := '25';
|
FIdNumbers := '25';
|
||||||
end;
|
end;
|
||||||
|
@ -818,7 +821,10 @@ var
|
||||||
MapInfo: TPortableMapInfo;
|
MapInfo: TPortableMapInfo;
|
||||||
begin
|
begin
|
||||||
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
||||||
MapInfo.FormatId := Iff(FSaveBinary, FIdNumbers[1], FIdNumbers[0]);
|
if FSaveBinary then
|
||||||
|
MapInfo.FormatId := FIdNumbers[1]
|
||||||
|
else
|
||||||
|
MapInfo.FormatId := FIdNumbers[0];
|
||||||
MapInfo.Binary := FSaveBinary;
|
MapInfo.Binary := FSaveBinary;
|
||||||
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
||||||
end;
|
end;
|
||||||
|
@ -853,7 +859,6 @@ begin
|
||||||
FName := SPPMFormatName;
|
FName := SPPMFormatName;
|
||||||
FSupportedFormats := PPMSupportedFormats;
|
FSupportedFormats := PPMSupportedFormats;
|
||||||
AddMasks(SPPMMasks);
|
AddMasks(SPPMMasks);
|
||||||
|
|
||||||
RegisterOption(ImagingPPMSaveBinary, @FSaveBinary);
|
RegisterOption(ImagingPPMSaveBinary, @FSaveBinary);
|
||||||
FIdNumbers := '36';
|
FIdNumbers := '36';
|
||||||
end;
|
end;
|
||||||
|
@ -864,7 +869,10 @@ var
|
||||||
MapInfo: TPortableMapInfo;
|
MapInfo: TPortableMapInfo;
|
||||||
begin
|
begin
|
||||||
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
||||||
MapInfo.FormatId := Iff(FSaveBinary, FIdNumbers[1], FIdNumbers[0]);
|
if FSaveBinary then
|
||||||
|
MapInfo.FormatId := FIdNumbers[1]
|
||||||
|
else
|
||||||
|
MapInfo.FormatId := FIdNumbers[0];
|
||||||
MapInfo.Binary := FSaveBinary;
|
MapInfo.Binary := FSaveBinary;
|
||||||
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
||||||
end;
|
end;
|
||||||
|
@ -952,11 +960,17 @@ var
|
||||||
begin
|
begin
|
||||||
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
FillChar(MapInfo, SizeOf(MapInfo), 0);
|
||||||
Info := GetFormatInfo(Images[Index].Format);
|
Info := GetFormatInfo(Images[Index].Format);
|
||||||
|
|
||||||
if (Info.ChannelCount > 1) or Info.IsIndexed then
|
if (Info.ChannelCount > 1) or Info.IsIndexed then
|
||||||
MapInfo.TupleType := ttRGBFP
|
MapInfo.TupleType := ttRGBFP
|
||||||
else
|
else
|
||||||
MapInfo.TupleType := ttGrayScaleFP;
|
MapInfo.TupleType := ttGrayScaleFP;
|
||||||
MapInfo.FormatId := Iff(MapInfo.TupleType = ttGrayScaleFP, FIdNumbers[1], FIdNumbers[0]);
|
|
||||||
|
if MapInfo.TupleType = ttGrayScaleFP then
|
||||||
|
MapInfo.FormatId := FIdNumbers[1]
|
||||||
|
else
|
||||||
|
MapInfo.FormatId := FIdNumbers[0];
|
||||||
|
|
||||||
MapInfo.Binary := True;
|
MapInfo.Binary := True;
|
||||||
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
Result := SaveDataInternal(Handle, Images, Index, MapInfo);
|
||||||
end;
|
end;
|
||||||
|
@ -983,6 +997,9 @@ initialization
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.3 Changes/Bug Fixes -----------------------------------
|
||||||
|
- Fixed D2009 Unicode related bug in PNM saving.
|
||||||
|
|
||||||
-- 0.24.3 Changes/Bug Fixes -----------------------------------
|
-- 0.24.3 Changes/Bug Fixes -----------------------------------
|
||||||
- Improved compatibility of 16bit/component image loading.
|
- Improved compatibility of 16bit/component image loading.
|
||||||
- Changes for better thread safety.
|
- Changes for better thread safety.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingTarga.pas 84 2007-05-27 13:54:27Z galfar $
|
$Id: ImagingTarga.pas 139 2008-09-18 02:01:42Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -91,7 +91,7 @@ type
|
||||||
TTargaFooter = packed record
|
TTargaFooter = packed record
|
||||||
ExtOff: LongWord; // Extension Area Offset
|
ExtOff: LongWord; // Extension Area Offset
|
||||||
DevDirOff: LongWord; // Developer Directory Offset
|
DevDirOff: LongWord; // Developer Directory Offset
|
||||||
Signature: array[0..15] of Char; // TRUEVISION-XFILE
|
Signature: TChar16; // TRUEVISION-XFILE
|
||||||
Reserved: Byte; // ASCII period '.'
|
Reserved: Byte; // ASCII period '.'
|
||||||
NullChar: Byte; // 0
|
NullChar: Byte; // 0
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingTypes.pas 132 2008-08-27 20:37:38Z galfar $
|
$Id: ImagingTypes.pas 171 2009-09-02 01:34:19Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -39,7 +39,7 @@ const
|
||||||
{ Current Minor version of Imaging.}
|
{ Current Minor version of Imaging.}
|
||||||
ImagingVersionMinor = 26;
|
ImagingVersionMinor = 26;
|
||||||
{ Current patch of Imaging.}
|
{ Current patch of Imaging.}
|
||||||
ImagingVersionPatch = 0;
|
ImagingVersionPatch = 4;
|
||||||
|
|
||||||
{ Imaging Option Ids whose values can be set/get by SetOption/
|
{ Imaging Option Ids whose values can be set/get by SetOption/
|
||||||
GetOption functions.}
|
GetOption functions.}
|
||||||
|
@ -91,6 +91,11 @@ const
|
||||||
Allowed values are in range 0 (no compresstion) to 9 (best compression).
|
Allowed values are in range 0 (no compresstion) to 9 (best compression).
|
||||||
Default value is 5.}
|
Default value is 5.}
|
||||||
ImagingPNGCompressLevel = 26;
|
ImagingPNGCompressLevel = 26;
|
||||||
|
{ Boolean option that specifies whether PNG images with more frames (APNG format)
|
||||||
|
are animated by Imaging (according to frame disposal/blend methods) or just
|
||||||
|
raw frames are loaded and sent to user (if you want to animate APNG yourself).
|
||||||
|
Default value is 1.}
|
||||||
|
ImagingPNGLoadAnimated = 27;
|
||||||
|
|
||||||
{ Specifies whether MNG animation frames are saved with lossy or lossless
|
{ Specifies whether MNG animation frames are saved with lossy or lossless
|
||||||
compression. Lossless frames are saved as PNG images and lossy frames are
|
compression. Lossless frames are saved as PNG images and lossy frames are
|
||||||
|
@ -140,10 +145,11 @@ const
|
||||||
{ Boolean option that specifies whether GIF images with more frames
|
{ Boolean option that specifies whether GIF images with more frames
|
||||||
are animated by Imaging (according to frame disposal methods) or just
|
are animated by Imaging (according to frame disposal methods) or just
|
||||||
raw frames are loaded and sent to user (if you want to animate GIF yourself).
|
raw frames are loaded and sent to user (if you want to animate GIF yourself).
|
||||||
Default value is 1.}
|
Default value is 1.
|
||||||
|
Raw frames are 256 color indexed images (ifIndex8), whereas
|
||||||
|
animated frames are always in 32bit ifA8R8G8B8 format (simplifies animating).}
|
||||||
ImagingGIFLoadAnimated = 56;
|
ImagingGIFLoadAnimated = 56;
|
||||||
|
|
||||||
|
|
||||||
{ This option is used when reducing number of colors used in
|
{ This option is used when reducing number of colors used in
|
||||||
image (mainly when converting from ARGB image to indexed
|
image (mainly when converting from ARGB image to indexed
|
||||||
format). Mask is 'anded' (bitwise AND) with every pixel's
|
format). Mask is 'anded' (bitwise AND) with every pixel's
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
$Id: ImagingUtility.pas 128 2008-07-23 11:57:36Z galfar $
|
$Id: ImagingUtility.pas 175 2009-10-06 11:55:15Z galfar $
|
||||||
Vampyre Imaging Library
|
Vampyre Imaging Library
|
||||||
by Marek Mauder
|
by Marek Mauder
|
||||||
http://imaginglib.sourceforge.net
|
http://imaginglib.sourceforge.net
|
||||||
|
@ -56,6 +56,7 @@ type
|
||||||
TBooleanArray = array[0..MaxInt - 1] of Boolean;
|
TBooleanArray = array[0..MaxInt - 1] of Boolean;
|
||||||
PBooleanArray = ^TBooleanArray;
|
PBooleanArray = ^TBooleanArray;
|
||||||
|
|
||||||
|
TDynByteArray = array of Byte;
|
||||||
TDynIntegerArray = array of Integer;
|
TDynIntegerArray = array of Integer;
|
||||||
TDynBooleanArray = array of Boolean;
|
TDynBooleanArray = array of Boolean;
|
||||||
|
|
||||||
|
@ -98,10 +99,11 @@ type
|
||||||
end;
|
end;
|
||||||
PFloatHelper = ^TFloatHelper;
|
PFloatHelper = ^TFloatHelper;
|
||||||
|
|
||||||
TChar2 = array[0..1] of Char;
|
TChar2 = array[0..1] of AnsiChar;
|
||||||
TChar3 = array[0..2] of Char;
|
TChar3 = array[0..2] of AnsiChar;
|
||||||
TChar4 = array[0..3] of Char;
|
TChar4 = array[0..3] of AnsiChar;
|
||||||
TChar8 = array[0..7] of Char;
|
TChar8 = array[0..7] of AnsiChar;
|
||||||
|
TChar16 = array[0..15] of AnsiChar;
|
||||||
|
|
||||||
{ Options for BuildFileList function:
|
{ Options for BuildFileList function:
|
||||||
flFullNames - file names in result will have full path names
|
flFullNames - file names in result will have full path names
|
||||||
|
@ -156,10 +158,13 @@ function PosNoCase(const SubStr, S: string; Offset: LongInt = 1): LongInt; {$IFD
|
||||||
function StrToken(var S: string; Sep: Char): string;
|
function StrToken(var S: string; Sep: Char): string;
|
||||||
{ Same as StrToken but searches from the end of S string.}
|
{ Same as StrToken but searches from the end of S string.}
|
||||||
function StrTokenEnd(var S: string; Sep: Char): string;
|
function StrTokenEnd(var S: string; Sep: Char): string;
|
||||||
|
{ Fills instance of TStrings with tokens from string S where tokens are separated by
|
||||||
|
one of Seps characters.}
|
||||||
|
procedure StrTokensToList(const S: string; Sep: Char; Tokens: TStrings);
|
||||||
{ Returns string representation of integer number (with digit grouping).}
|
{ Returns string representation of integer number (with digit grouping).}
|
||||||
function IntToStrFmt(const I: Int64): string;
|
function IntToStrFmt(const I: Int64): string; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
{ Returns string representation of float number (with digit grouping).}
|
{ Returns string representation of float number (with digit grouping).}
|
||||||
function FloatToStrFmt(const F: Double; Precision: Integer = 2): string;
|
function FloatToStrFmt(const F: Double; Precision: Integer = 2): string; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
|
|
||||||
{ Clamps integer value to range <Min, Max>}
|
{ Clamps integer value to range <Min, Max>}
|
||||||
function ClampInt(Number: LongInt; Min, Max: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
function ClampInt(Number: LongInt; Min, Max: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF}
|
||||||
|
@ -447,7 +452,7 @@ var
|
||||||
if CaseSensitive then
|
if CaseSensitive then
|
||||||
Result := A = B
|
Result := A = B
|
||||||
else
|
else
|
||||||
Result := UpCase(A) = UpCase(B);
|
Result := AnsiUpperCase (A) = AnsiUpperCase (B);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function MatchAt(MaskPos, KeyPos: LongInt): Boolean;
|
function MatchAt(MaskPos, KeyPos: LongInt): Boolean;
|
||||||
|
@ -609,101 +614,6 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function PosEx(const SubStr, S: string; Offset: LongInt = 1): LongInt;
|
function PosEx(const SubStr, S: string; Offset: LongInt = 1): LongInt;
|
||||||
{$IFDEF USE_ASM}
|
|
||||||
asm
|
|
||||||
// The Original ASM Code is (C) Fastcode project.
|
|
||||||
test eax, eax
|
|
||||||
jz @Nil
|
|
||||||
test edx, edx
|
|
||||||
jz @Nil
|
|
||||||
dec ecx
|
|
||||||
jl @Nil
|
|
||||||
|
|
||||||
push esi
|
|
||||||
push ebx
|
|
||||||
|
|
||||||
mov esi, [edx-4] //Length(Str)
|
|
||||||
mov ebx, [eax-4] //Length(Substr)
|
|
||||||
sub esi, ecx //effective length of Str
|
|
||||||
add edx, ecx //addr of the first char at starting position
|
|
||||||
cmp esi, ebx
|
|
||||||
jl @Past //jump if EffectiveLength(Str)<Length(Substr)
|
|
||||||
test ebx, ebx
|
|
||||||
jle @Past //jump if Length(Substr)<=0
|
|
||||||
|
|
||||||
add esp, -12
|
|
||||||
add ebx, -1 //Length(Substr)-1
|
|
||||||
add esi, edx //addr of the terminator
|
|
||||||
add edx, ebx //addr of the last char at starting position
|
|
||||||
mov [esp+8], esi //save addr of the terminator
|
|
||||||
add eax, ebx //addr of the last char of Substr
|
|
||||||
sub ecx, edx //-@Str[Length(Substr)]
|
|
||||||
neg ebx //-(Length(Substr)-1)
|
|
||||||
mov [esp+4], ecx //save -@Str[Length(Substr)]
|
|
||||||
mov [esp], ebx //save -(Length(Substr)-1)
|
|
||||||
movzx ecx, byte ptr [eax] //the last char of Substr
|
|
||||||
|
|
||||||
@Loop:
|
|
||||||
cmp cl, [edx]
|
|
||||||
jz @Test0
|
|
||||||
@AfterTest0:
|
|
||||||
cmp cl, [edx+1]
|
|
||||||
jz @TestT
|
|
||||||
@AfterTestT:
|
|
||||||
add edx, 4
|
|
||||||
cmp edx, [esp+8]
|
|
||||||
jb @Continue
|
|
||||||
@EndLoop:
|
|
||||||
add edx, -2
|
|
||||||
cmp edx, [esp+8]
|
|
||||||
jb @Loop
|
|
||||||
@Exit:
|
|
||||||
add esp, 12
|
|
||||||
@Past:
|
|
||||||
pop ebx
|
|
||||||
pop esi
|
|
||||||
@Nil:
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
@Continue:
|
|
||||||
cmp cl, [edx-2]
|
|
||||||
jz @Test2
|
|
||||||
cmp cl, [edx-1]
|
|
||||||
jnz @Loop
|
|
||||||
@Test1:
|
|
||||||
add edx, 1
|
|
||||||
@Test2:
|
|
||||||
add edx, -2
|
|
||||||
@Test0:
|
|
||||||
add edx, -1
|
|
||||||
@TestT:
|
|
||||||
mov esi, [esp]
|
|
||||||
test esi, esi
|
|
||||||
jz @Found
|
|
||||||
@String:
|
|
||||||
movzx ebx, word ptr [esi+eax]
|
|
||||||
cmp bx, word ptr [esi+edx+1]
|
|
||||||
jnz @AfterTestT
|
|
||||||
cmp esi, -2
|
|
||||||
jge @Found
|
|
||||||
movzx ebx, word ptr [esi+eax+2]
|
|
||||||
cmp bx, word ptr [esi+edx+3]
|
|
||||||
jnz @AfterTestT
|
|
||||||
add esi, 4
|
|
||||||
jl @String
|
|
||||||
@Found:
|
|
||||||
mov eax, [esp+4]
|
|
||||||
add edx, 2
|
|
||||||
|
|
||||||
cmp edx, [esp+8]
|
|
||||||
ja @Exit
|
|
||||||
|
|
||||||
add esp, 12
|
|
||||||
add eax, edx
|
|
||||||
pop ebx
|
|
||||||
pop esi
|
|
||||||
end;
|
|
||||||
{$ELSE}
|
|
||||||
var
|
var
|
||||||
I, X: LongInt;
|
I, X: LongInt;
|
||||||
Len, LenSubStr: LongInt;
|
Len, LenSubStr: LongInt;
|
||||||
|
@ -728,11 +638,10 @@ begin
|
||||||
end;
|
end;
|
||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
function PosNoCase(const SubStr, S: string; Offset: LongInt): LongInt;
|
function PosNoCase(const SubStr, S: string; Offset: LongInt): LongInt;
|
||||||
begin
|
begin
|
||||||
Result := PosEx(LowerCase(SubStr), LowerCase(S), Offset);
|
Result := PosEx(AnsiLowerCase(SubStr), AnsiLowerCase(S), Offset);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function StrToken(var S: string; Sep: Char): string;
|
function StrToken(var S: string; Sep: Char): string;
|
||||||
|
@ -775,6 +684,19 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure StrTokensToList(const S: string; Sep: Char; Tokens: TStrings);
|
||||||
|
var
|
||||||
|
Token, Str: string;
|
||||||
|
begin
|
||||||
|
Tokens.Clear;
|
||||||
|
Str := S;
|
||||||
|
while Str <> '' do
|
||||||
|
begin
|
||||||
|
Token := StrToken(Str, Sep);
|
||||||
|
Tokens.Add(Token);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function IntToStrFmt(const I: Int64): string;
|
function IntToStrFmt(const I: Int64): string;
|
||||||
begin
|
begin
|
||||||
Result := Format('%.0n', [I * 1.0]);
|
Result := Format('%.0n', [I * 1.0]);
|
||||||
|
@ -790,8 +712,7 @@ begin
|
||||||
Result := Number;
|
Result := Number;
|
||||||
if Result < Min then
|
if Result < Min then
|
||||||
Result := Min
|
Result := Min
|
||||||
else
|
else if Result > Max then
|
||||||
if Result > Max then
|
|
||||||
Result := Max;
|
Result := Max;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -800,8 +721,7 @@ begin
|
||||||
Result := Number;
|
Result := Number;
|
||||||
if Result < Min then
|
if Result < Min then
|
||||||
Result := Min
|
Result := Min
|
||||||
else
|
else if Result > Max then
|
||||||
if Result > Max then
|
|
||||||
Result := Max;
|
Result := Max;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -831,7 +751,7 @@ end;
|
||||||
function NextPow2(Num: LongInt): LongInt;
|
function NextPow2(Num: LongInt): LongInt;
|
||||||
begin
|
begin
|
||||||
Result := Num and -Num;
|
Result := Num and -Num;
|
||||||
while (Result < Num) do
|
while Result < Num do
|
||||||
Result := Result shl 1;
|
Result := Result shl 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1552,6 +1472,12 @@ initialization
|
||||||
-- TODOS ----------------------------------------------------
|
-- TODOS ----------------------------------------------------
|
||||||
- nothing now
|
- nothing now
|
||||||
|
|
||||||
|
-- 0.26.1 Changes/Bug Fixes -----------------------------------
|
||||||
|
- Some formatting changes.
|
||||||
|
- Changed some string functions to work with localized strings.
|
||||||
|
- ASM version of PosEx had bugs, removed it.
|
||||||
|
- Added StrTokensToList function.
|
||||||
|
|
||||||
-- 0.25.0 Changes/Bug Fixes -----------------------------------
|
-- 0.25.0 Changes/Bug Fixes -----------------------------------
|
||||||
- Fixed error in ClipCopyBounds which was causing ... bad clipping!
|
- Fixed error in ClipCopyBounds which was causing ... bad clipping!
|
||||||
|
|
||||||
|
|
|
@ -492,6 +492,7 @@ begin
|
||||||
{ Calculate max # of rows allowed in one allocation chunk }
|
{ Calculate max # of rows allowed in one allocation chunk }
|
||||||
ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
|
ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
|
||||||
(long(blocksperrow) * SIZEOF(JBLOCK));
|
(long(blocksperrow) * SIZEOF(JBLOCK));
|
||||||
|
|
||||||
if (ltemp <= 0) then
|
if (ltemp <= 0) then
|
||||||
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
||||||
if (ltemp < long(numrows)) then
|
if (ltemp < long(numrows)) then
|
||||||
|
|
|
@ -27,13 +27,8 @@ uses
|
||||||
NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
|
NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
|
||||||
size_t and will be a multiple of sizeof(align_type). }
|
size_t and will be a multiple of sizeof(align_type). }
|
||||||
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
const
|
|
||||||
MAX_ALLOC_CHUNK = long(32752);
|
|
||||||
{$ELSE}
|
|
||||||
const
|
const
|
||||||
MAX_ALLOC_CHUNK = long(1000000000);
|
MAX_ALLOC_CHUNK = long(1000000000);
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{GLOBAL}
|
{GLOBAL}
|
||||||
procedure jpeg_open_backing_store (cinfo : j_common_ptr;
|
procedure jpeg_open_backing_store (cinfo : j_common_ptr;
|
||||||
|
|
|
@ -124,7 +124,7 @@ type
|
||||||
FStrmPos: Integer;
|
FStrmPos: Integer;
|
||||||
FOnProgress: TNotifyEvent;
|
FOnProgress: TNotifyEvent;
|
||||||
FZRec: TZStreamRec;
|
FZRec: TZStreamRec;
|
||||||
FBuffer: array [Word] of Char;
|
FBuffer: array [Word] of Byte;
|
||||||
protected
|
protected
|
||||||
procedure Progress(Sender: TObject); dynamic;
|
procedure Progress(Sender: TObject); dynamic;
|
||||||
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
|
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
|
||||||
|
@ -228,7 +228,7 @@ type
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
ZErrorMessages: array[0..9] of PChar = (
|
ZErrorMessages: array[0..9] of PAnsiChar = (
|
||||||
'need dictionary', // Z_NEED_DICT (2)
|
'need dictionary', // Z_NEED_DICT (2)
|
||||||
'stream end', // Z_STREAM_END (1)
|
'stream end', // Z_STREAM_END (1)
|
||||||
'', // Z_OK (0)
|
'', // Z_OK (0)
|
||||||
|
@ -491,7 +491,7 @@ end;
|
||||||
function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
|
function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||||||
var
|
var
|
||||||
I: Integer;
|
I: Integer;
|
||||||
Buf: array [0..4095] of Char;
|
Buf: array [0..4095] of Byte;
|
||||||
begin
|
begin
|
||||||
if (Offset = 0) and (Origin = soFromBeginning) then
|
if (Offset = 0) and (Origin = soFromBeginning) then
|
||||||
begin
|
begin
|
||||||
|
|
|
@ -172,7 +172,7 @@ begin
|
||||||
c^.sub.lit := t^.base;
|
c^.sub.lit := t^.base;
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
if (t^.base >= $20) and (t^.base < $7f) then
|
if (t^.base >= $20) and (t^.base < $7f) then
|
||||||
Tracevv('inflate: literal '+char(t^.base))
|
Tracevv('inflate: literal '+AnsiChar(t^.base))
|
||||||
else
|
else
|
||||||
Tracevv('inflate: literal '+IntToStr(t^.base));
|
Tracevv('inflate: literal '+IntToStr(t^.base));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
|
@ -99,7 +99,7 @@ begin
|
||||||
Dec(k, t^.bits);
|
Dec(k, t^.bits);
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
if (t^.base >= $20) and (t^.base < $7f) then
|
if (t^.base >= $20) and (t^.base < $7f) then
|
||||||
Tracevv('inflate: * literal '+char(t^.base))
|
Tracevv('inflate: * literal '+AnsiChar(t^.base))
|
||||||
else
|
else
|
||||||
Tracevv('inflate: * literal '+ IntToStr(t^.base));
|
Tracevv('inflate: * literal '+ IntToStr(t^.base));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
@ -241,7 +241,7 @@ begin
|
||||||
|
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
if (t^.base >= $20) and (t^.base < $7f) then
|
if (t^.base >= $20) and (t^.base < $7f) then
|
||||||
Tracevv('inflate: * literal '+char(t^.base))
|
Tracevv('inflate: * literal '+AnsiChar(t^.base))
|
||||||
else
|
else
|
||||||
Tracevv('inflate: * literal '+IntToStr(t^.base));
|
Tracevv('inflate: * literal '+IntToStr(t^.base));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
|
@ -376,23 +376,23 @@ const
|
||||||
|
|
||||||
|
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
procedure Assert(cond : boolean; msg : string);
|
procedure Assert(cond : boolean; msg : AnsiString);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
procedure Trace(x : string);
|
procedure Trace(x : AnsiString);
|
||||||
procedure Tracev(x : string);
|
procedure Tracev(x : AnsiString);
|
||||||
procedure Tracevv(x : string);
|
procedure Tracevv(x : AnsiString);
|
||||||
procedure Tracevvv(x : string);
|
procedure Tracevvv(x : AnsiString);
|
||||||
procedure Tracec(c : boolean; x : string);
|
procedure Tracec(c : boolean; x : AnsiString);
|
||||||
procedure Tracecv(c : boolean; x : string);
|
procedure Tracecv(c : boolean; x : AnsiString);
|
||||||
|
|
||||||
function zlibVersion : string;
|
function zlibVersion : AnsiString;
|
||||||
{ The application can compare zlibVersion and ZLIB_VERSION for consistency.
|
{ The application can compare zlibVersion and ZLIB_VERSION for consistency.
|
||||||
If the first character differs, the library code actually used is
|
If the first character differs, the library code actually used is
|
||||||
not compatible with the zlib.h header file used by the application.
|
not compatible with the zlib.h header file used by the application.
|
||||||
This check is automatically made by deflateInit and inflateInit. }
|
This check is automatically made by deflateInit and inflateInit. }
|
||||||
|
|
||||||
function zError(err : int) : string;
|
function zError(err : int) : AnsiString;
|
||||||
function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf;
|
function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf;
|
||||||
procedure ZFREE (var strm : z_stream; ptr : voidpf);
|
procedure ZFREE (var strm : z_stream; ptr : voidpf);
|
||||||
procedure TRY_FREE (var strm : z_stream; ptr : voidpf);
|
procedure TRY_FREE (var strm : z_stream; ptr : voidpf);
|
||||||
|
@ -416,9 +416,9 @@ const
|
||||||
const
|
const
|
||||||
z_verbose : int = 1;
|
z_verbose : int = 1;
|
||||||
|
|
||||||
function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: string;
|
function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: AnsiString;
|
||||||
Stream_size: LongInt): LongInt;
|
Stream_size: LongInt): LongInt;
|
||||||
function inflateInit_(var Stream: z_stream; const Version: string;
|
function inflateInit_(var Stream: z_stream; const Version: AnsiString;
|
||||||
Stream_size: Longint): LongInt;
|
Stream_size: Longint): LongInt;
|
||||||
|
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
|
@ -430,29 +430,29 @@ implementation
|
||||||
uses
|
uses
|
||||||
imzdeflate, imzinflate;
|
imzdeflate, imzinflate;
|
||||||
|
|
||||||
function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: string;
|
function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: AnsiString;
|
||||||
Stream_size: LongInt): LongInt;
|
Stream_size: LongInt): LongInt;
|
||||||
begin
|
begin
|
||||||
Result := imzdeflate.deflateInit_(@Stream, Level, Version, Stream_size);
|
Result := imzdeflate.deflateInit_(@Stream, Level, Version, Stream_size);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function inflateInit_(var Stream: z_stream; const Version: string;
|
function inflateInit_(var Stream: z_stream; const Version: AnsiString;
|
||||||
Stream_size: Longint): LongInt;
|
Stream_size: Longint): LongInt;
|
||||||
begin
|
begin
|
||||||
Result := imzinflate.inflateInit_(@Stream, Version, Stream_size);
|
Result := imzinflate.inflateInit_(@Stream, Version, Stream_size);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function zError(err : int) : string;
|
function zError(err : int) : AnsiString;
|
||||||
begin
|
begin
|
||||||
zError := z_errmsg[Z_NEED_DICT-err];
|
zError := z_errmsg[Z_NEED_DICT-err];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function zlibVersion : string;
|
function zlibVersion : AnsiString;
|
||||||
begin
|
begin
|
||||||
zlibVersion := ZLIB_VERSION;
|
zlibVersion := ZLIB_VERSION;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure z_error (m : string);
|
procedure z_error (m : AnsiString);
|
||||||
begin
|
begin
|
||||||
WriteLn(output, m);
|
WriteLn(output, m);
|
||||||
Write('Zlib - Halt...');
|
Write('Zlib - Halt...');
|
||||||
|
@ -460,42 +460,42 @@ begin
|
||||||
Halt(1);
|
Halt(1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Assert(cond : boolean; msg : string);
|
procedure Assert(cond : boolean; msg : AnsiString);
|
||||||
begin
|
begin
|
||||||
if not cond then
|
if not cond then
|
||||||
z_error(msg);
|
z_error(msg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Trace(x : string);
|
procedure Trace(x : AnsiString);
|
||||||
begin
|
begin
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Tracev(x : string);
|
procedure Tracev(x : AnsiString);
|
||||||
begin
|
begin
|
||||||
if (z_verbose>0) then
|
if (z_verbose>0) then
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Tracevv(x : string);
|
procedure Tracevv(x : AnsiString);
|
||||||
begin
|
begin
|
||||||
if (z_verbose>1) then
|
if (z_verbose>1) then
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Tracevvv(x : string);
|
procedure Tracevvv(x : AnsiString);
|
||||||
begin
|
begin
|
||||||
if (z_verbose>2) then
|
if (z_verbose>2) then
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Tracec(c : boolean; x : string);
|
procedure Tracec(c : boolean; x : AnsiString);
|
||||||
begin
|
begin
|
||||||
if (z_verbose>0) and (c) then
|
if (z_verbose>0) and (c) then
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Tracecv(c : boolean; x : string);
|
procedure Tracecv(c : boolean; x : AnsiString);
|
||||||
begin
|
begin
|
||||||
if (z_verbose>1) and c then
|
if (z_verbose>1) and c then
|
||||||
WriteLn(x);
|
WriteLn(x);
|
||||||
|
|
|
@ -637,7 +637,7 @@ const
|
||||||
}
|
}
|
||||||
|
|
||||||
const
|
const
|
||||||
Buf_size = (8 * 2*sizeof(char));
|
Buf_size = (8 * 2*sizeof(uch));
|
||||||
{ Number of bits used within bi_buf. (bi_buf might be implemented on
|
{ Number of bits used within bi_buf. (bi_buf might be implemented on
|
||||||
more than 16 bits on some systems.) }
|
more than 16 bits on some systems.) }
|
||||||
|
|
||||||
|
@ -916,7 +916,7 @@ begin
|
||||||
{$ifdef DEBUG}
|
{$ifdef DEBUG}
|
||||||
if (n>31) and (n<128) then
|
if (n>31) and (n<128) then
|
||||||
Tracecv(tree <> tree_ptr(@static_ltree),
|
Tracecv(tree <> tree_ptr(@static_ltree),
|
||||||
(^M'n #'+IntToStr(n)+' '+char(n)+' l '+IntToStr(len)+' c '+
|
(^M'n #'+IntToStr(n)+' '+AnsiChar(n)+' l '+IntToStr(len)+' c '+
|
||||||
IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')'))
|
IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')'))
|
||||||
else
|
else
|
||||||
Tracecv(tree <> tree_ptr(@static_ltree),
|
Tracecv(tree <> tree_ptr(@static_ltree),
|
||||||
|
@ -1962,7 +1962,7 @@ begin
|
||||||
{ send a literal byte }
|
{ send a literal byte }
|
||||||
{$ifdef DEBUG}
|
{$ifdef DEBUG}
|
||||||
Tracevvv(#13'cd '+IntToStr(lc));
|
Tracevvv(#13'cd '+IntToStr(lc));
|
||||||
Tracecv((lc > 31) and (lc < 128), ' '+char(lc)+' ');
|
Tracecv((lc > 31) and (lc < 128), ' '+AnsiChar(lc)+' ');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
send_bits(s, ltree[lc].fc.Code, ltree[lc].dl.Len);
|
send_bits(s, ltree[lc].fc.Code, ltree[lc].dl.Len);
|
||||||
end
|
end
|
||||||
|
@ -2106,7 +2106,7 @@ begin
|
||||||
{$endif} { STORED_FILE_OK }
|
{$endif} { STORED_FILE_OK }
|
||||||
|
|
||||||
{$ifdef FORCE_STORED}
|
{$ifdef FORCE_STORED}
|
||||||
if (buf <> pchar(0)) then
|
if (buf <> pcharf(0)) then
|
||||||
begin { force stored block }
|
begin { force stored block }
|
||||||
{$else}
|
{$else}
|
||||||
if (stored_len+4 <= opt_lenb) and (buf <> pcharf(0)) then
|
if (stored_len+4 <= opt_lenb) and (buf <> pcharf(0)) then
|
||||||
|
|
|
@ -61,7 +61,7 @@ uses
|
||||||
|
|
||||||
function deflateInit_(strm : z_streamp;
|
function deflateInit_(strm : z_streamp;
|
||||||
level : int;
|
level : int;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
|
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ function deflateInit2_(var strm : z_stream;
|
||||||
windowBits : int;
|
windowBits : int;
|
||||||
memLevel : int;
|
memLevel : int;
|
||||||
strategy : int;
|
strategy : int;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
var
|
var
|
||||||
s : deflate_state_ptr;
|
s : deflate_state_ptr;
|
||||||
|
@ -622,7 +622,7 @@ end;
|
||||||
|
|
||||||
function deflateInit_(strm : z_streamp;
|
function deflateInit_(strm : z_streamp;
|
||||||
level : int;
|
level : int;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
begin
|
begin
|
||||||
if (strm = Z_NULL) then
|
if (strm = Z_NULL) then
|
||||||
|
@ -1528,7 +1528,7 @@ begin
|
||||||
begin
|
begin
|
||||||
WriteLn(' start ',start,', match ',match ,' length ', length);
|
WriteLn(' start ',start,', match ',match ,' length ', length);
|
||||||
repeat
|
repeat
|
||||||
Write(char(s.window^[match]), char(s.window^[start]));
|
Write(AnsiChar(s.window^[match]), AnsiChar(s.window^[start]));
|
||||||
Inc(match);
|
Inc(match);
|
||||||
Inc(start);
|
Inc(start);
|
||||||
Dec(length);
|
Dec(length);
|
||||||
|
@ -1539,7 +1539,7 @@ begin
|
||||||
begin
|
begin
|
||||||
Write('\\[',start-match,',',length,']');
|
Write('\\[',start-match,',',length,']');
|
||||||
repeat
|
repeat
|
||||||
Write(char(s.window^[start]));
|
Write(AnsiChar(s.window^[start]));
|
||||||
Inc(start);
|
Inc(start);
|
||||||
Dec(length);
|
Dec(length);
|
||||||
Until (length = 0);
|
Until (length = 0);
|
||||||
|
@ -1910,7 +1910,7 @@ end;
|
||||||
begin
|
begin
|
||||||
{ No match, output a literal byte }
|
{ No match, output a literal byte }
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
Tracevv(char(s.window^[s.strstart]));
|
Tracevv(AnsiChar(s.window^[s.strstart]));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
{_tr_tally_lit (s, 0, s.window^[s.strstart], bflush);}
|
{_tr_tally_lit (s, 0, s.window^[s.strstart], bflush);}
|
||||||
bflush := _tr_tally (s, 0, s.window^[s.strstart]);
|
bflush := _tr_tally (s, 0, s.window^[s.strstart]);
|
||||||
|
@ -2071,7 +2071,7 @@ begin
|
||||||
single literal. If there was a match but the current match
|
single literal. If there was a match but the current match
|
||||||
is longer, truncate the previous match to a single literal. }
|
is longer, truncate the previous match to a single literal. }
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
Tracevv(char(s.window^[s.strstart-1]));
|
Tracevv(AnsiChar(s.window^[s.strstart-1]));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);
|
bflush := _tr_tally (s, 0, s.window^[s.strstart-1]);
|
||||||
|
|
||||||
|
@ -2104,7 +2104,7 @@ begin
|
||||||
if (s.match_available) then
|
if (s.match_available) then
|
||||||
begin
|
begin
|
||||||
{$IFDEF DEBUG}
|
{$IFDEF DEBUG}
|
||||||
Tracevv(char(s.window^[s.strstart-1]));
|
Tracevv(AnsiChar(s.window^[s.strstart-1]));
|
||||||
bflush :=
|
bflush :=
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
_tr_tally (s, 0, s.window^[s.strstart-1]);
|
_tr_tally (s, 0, s.window^[s.strstart-1]);
|
||||||
|
|
|
@ -31,13 +31,13 @@ function inflateInit(var z : z_stream) : int;
|
||||||
|
|
||||||
|
|
||||||
function inflateInit_(z : z_streamp;
|
function inflateInit_(z : z_streamp;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
|
|
||||||
|
|
||||||
function inflateInit2_(var z: z_stream;
|
function inflateInit2_(var z: z_stream;
|
||||||
w : int;
|
w : int;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
|
|
||||||
function inflateInit2(var z: z_stream;
|
function inflateInit2(var z: z_stream;
|
||||||
|
@ -246,7 +246,7 @@ end;
|
||||||
|
|
||||||
function inflateInit2_(var z: z_stream;
|
function inflateInit2_(var z: z_stream;
|
||||||
w : int;
|
w : int;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
begin
|
begin
|
||||||
if (version = '') or (version[1] <> ZLIB_VERSION[1]) or
|
if (version = '') or (version[1] <> ZLIB_VERSION[1]) or
|
||||||
|
@ -333,7 +333,7 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function inflateInit_(z : z_streamp;
|
function inflateInit_(z : z_streamp;
|
||||||
const version : string;
|
const version : AnsiString;
|
||||||
stream_size : int) : int;
|
stream_size : int) : int;
|
||||||
begin
|
begin
|
||||||
{ initialize state }
|
{ initialize state }
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<Version Value="7"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
|
</Flags>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<TargetFileExt Value=".exe"/>
|
||||||
|
<Icon Value="0"/>
|
||||||
|
<UseXPManifest Value="True"/>
|
||||||
|
<ActiveEditorIndexAtStart Value="0"/>
|
||||||
|
</General>
|
||||||
|
<VersionInfo>
|
||||||
|
<ProjectVersion Value=""/>
|
||||||
|
</VersionInfo>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IgnoreBinaries Value="False"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
<Units Count="1">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="ConvertFontMap.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="ConvertFontMap"/>
|
||||||
|
<CursorPos X="25" Y="38"/>
|
||||||
|
<TopLine Value="33"/>
|
||||||
|
<EditorIndex Value="0"/>
|
||||||
|
<UsageCount Value="20"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit0>
|
||||||
|
</Units>
|
||||||
|
<JumpHistory Count="1" HistoryIndex="0">
|
||||||
|
<Position1>
|
||||||
|
<Filename Value="ConvertFontMap.lpr"/>
|
||||||
|
<Caret Line="82" Column="17" TopLine="54"/>
|
||||||
|
</Position1>
|
||||||
|
</JumpHistory>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="8"/>
|
||||||
|
<PathDelim Value="\"/>
|
||||||
|
<Target>
|
||||||
|
<Filename Value="..\..\bin\ConvertFontMap"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)\"/>
|
||||||
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<SmartLinkUnit Value="True"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Debugging>
|
||||||
|
<UseLineInfoUnit Value="False"/>
|
||||||
|
<StripSymbols Value="True"/>
|
||||||
|
</Debugging>
|
||||||
|
<LinkSmart Value="True"/>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions Count="3">
|
||||||
|
<Item1>
|
||||||
|
<Name Value="EAbort"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item2>
|
||||||
|
<Item3>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item3>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
|
@ -0,0 +1,91 @@
|
||||||
|
(*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at
|
||||||
|
* http://www.opensource.org/licenses/cddl1.php.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at
|
||||||
|
* http://www.opensource.org/licenses/cddl1.php. If applicable,
|
||||||
|
* add the following below this CDDL HEADER, with the fields enclosed
|
||||||
|
* by brackets "[]" replaced with your own identifying * information:
|
||||||
|
* Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Portions Copyright 2009 Andreas Schneider
|
||||||
|
*)
|
||||||
|
program ConvertFontMap;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, sysutils, DOM, XMLRead;
|
||||||
|
|
||||||
|
{$IFDEF WINDOWS}{$R ConvertFontMap.rc}{$ENDIF}
|
||||||
|
|
||||||
|
type
|
||||||
|
TFontInfo = packed record
|
||||||
|
Character: char;
|
||||||
|
LeftOffset: SmallInt;
|
||||||
|
CharWidth: Word;
|
||||||
|
Width: Word;
|
||||||
|
Height: Word;
|
||||||
|
X1: Single;
|
||||||
|
Y1: Single;
|
||||||
|
X2: Single;
|
||||||
|
Y2: Single;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
xmlDoc: TXMLDocument;
|
||||||
|
chars: TDOMNodeList;
|
||||||
|
root, parent, charNode: TDOMElement;
|
||||||
|
outFile: TFileStream;
|
||||||
|
spaceWidth: Word;
|
||||||
|
fontInfo: TFontInfo;
|
||||||
|
i: Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if ParamCount = 2 then
|
||||||
|
begin
|
||||||
|
ReadXMLFile(xmlDoc, ParamStr(1));
|
||||||
|
outFile := TFileStream.Create(ParamStr(2), fmCreate);
|
||||||
|
|
||||||
|
root := xmlDoc.DocumentElement;
|
||||||
|
parent := TDOMElement(root.FindNode('characters'));
|
||||||
|
chars := parent.ChildNodes;
|
||||||
|
|
||||||
|
spaceWidth := StrToInt(root.AttribStrings['spacewidth']);
|
||||||
|
outFile.Write(spaceWidth, SizeOf(spaceWidth));
|
||||||
|
|
||||||
|
for i := 0 to chars.Count - 1 do
|
||||||
|
begin
|
||||||
|
charNode := TDOMElement(chars[i]);
|
||||||
|
fontInfo.Character := Char(StrToInt(charNode.AttribStrings['char']));
|
||||||
|
fontInfo.LeftOffset := StrToInt(charNode.AttribStrings['A']);
|
||||||
|
fontInfo.CharWidth := StrToInt(charNode.AttribStrings['C']);
|
||||||
|
fontInfo.Width := StrToInt(charNode.AttribStrings['wid']);
|
||||||
|
fontInfo.Height := StrToInt(charNode.AttribStrings['hgt']);
|
||||||
|
fontInfo.X1 := StrToFloat(charNode.AttribStrings['X1']);
|
||||||
|
fontInfo.Y1 := StrToFloat(charNode.AttribStrings['Y1']);
|
||||||
|
fontInfo.X2 := StrToFloat(charNode.AttribStrings['X2']);
|
||||||
|
fontInfo.Y2 := StrToFloat(charNode.AttribStrings['Y2']);
|
||||||
|
outFile.Write(fontInfo, SizeOf(fontInfo));
|
||||||
|
end;
|
||||||
|
|
||||||
|
outFile.Free;
|
||||||
|
xmlDoc.Free;
|
||||||
|
|
||||||
|
end else
|
||||||
|
Writeln('Usage: ', ExtractFileName(ParamStr(0)), ' <In Font XML> <Out Font Bin>');
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue