You've already forked lazarus-ccr
pyramidtiff: using fpimage copact mem image formats, converting whole directories
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3839 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="9"/>
|
||||
@ -29,19 +29,23 @@
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="1">
|
||||
<RequiredPackages Count="3">
|
||||
<Item1>
|
||||
<PackageName Value="LazUtils"/>
|
||||
<PackageName Value="MultiThreadProcsLaz"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="CodeTools"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<PackageName Value="LazUtils"/>
|
||||
</Item3>
|
||||
</RequiredPackages>
|
||||
<Units Count="1">
|
||||
<Unit0>
|
||||
<Filename Value="pyramidtiff.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="pyramidtiff"/>
|
||||
</Unit0>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
@ -59,12 +63,6 @@
|
||||
<AllowLabel Value="False"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<Other>
|
||||
<CompilerMessages>
|
||||
<MsgFileName Value=""/>
|
||||
</CompilerMessages>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
|
@ -1,32 +1,3 @@
|
||||
{ Graphic functions for pyramidtiff.
|
||||
|
||||
Copyright (C) 2012 Mattias Gaertner mattias@freepascal.org
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version with the following modification:
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,and
|
||||
to copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the terms
|
||||
and conditions of the license of that module. An independent module is a
|
||||
module which is not derived from or based on this library. If you modify
|
||||
this library, you may extend this exception to your version of the library,
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
}
|
||||
program pyramidtiff;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
@ -35,30 +6,32 @@ uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Classes, SysUtils, math, LazFileUtils, CustApp,
|
||||
FPimage, FPReadJPEG, FPReadPNG, FPReadBMP, FPImgCanv,
|
||||
Classes, SysUtils, math, LazFileUtils, CodeToolsStructs, CustApp,
|
||||
FPimage, FPReadJPEG, FPReadPNG, FPReadBMP, FPImgCanv, FPCanvas, MTProcs,
|
||||
PyTiGraphics, FPReadTiff, FPTiffCmn, FPWriteTiff;
|
||||
|
||||
const
|
||||
Version = '1.0';
|
||||
Version = '1.1';
|
||||
type
|
||||
|
||||
{ TPyramidTiffer }
|
||||
|
||||
TPyramidTiffer = class(TCustomApplication)
|
||||
private
|
||||
FInputPath: string;
|
||||
FMinSize: Word;
|
||||
FOutputPath: string;
|
||||
FQuiet: boolean;
|
||||
//FSkipCheck: boolean;
|
||||
FTileHeight: Word;
|
||||
FTileWidth: Word;
|
||||
FVerbose: boolean;
|
||||
procedure LoadTiff(out Img: TPTMemImgBase;
|
||||
procedure LoadTiff(out Img: TFPCompactImgBase;
|
||||
Reader: TFPReaderTiff; InStream: TMemoryStream;
|
||||
var ErrorMsg: string);
|
||||
procedure LoadOther(out Img: TPTMemImgBase;
|
||||
procedure LoadOther(out Img: TFPCompactImgBase;
|
||||
Reader: TFPCustomImageReader; InStream: TMemoryStream);
|
||||
function ShrinkImage(LastImg: TPTMemImgBase): TPTMemImgBase;
|
||||
function ShrinkImage(LastImg: TFPCompactImgBase): TFPCompactImgBase;
|
||||
procedure TiffReaderCreateImage(Sender: TFPReaderTiff; IFD: TTiffIFD);
|
||||
protected
|
||||
procedure DoRun; override;
|
||||
@ -66,18 +39,33 @@ type
|
||||
procedure ReadConfig;
|
||||
function CheckIfFileIsPyramidTiled(Filename: string; out ErrorMsg: string): boolean;
|
||||
function CheckIfStreamIsPyramidTiled(s: TStream; out ErrorMsg: string): boolean;
|
||||
function Convert(InputFilename, OutputFilename: string; out ErrorMsg: string): boolean;
|
||||
function Convert(Img: TPTMemImgBase; OutputFilename: string; out ErrorMsg: string): boolean;
|
||||
function GetReaderClass(Filename: string): TFPCustomImageReaderClass;
|
||||
function ConvertDir(InputDir, OutputDir: string; out ErrorMsg: string): boolean;
|
||||
procedure ConvertFilesParallel(Index: PtrInt; Data: Pointer; {%H-}Item: TMultiThreadProcItem);
|
||||
function ConvertFile(InputFilename, OutputFilename: string; out ErrorMsg: string): boolean;
|
||||
function Convert(Img: TFPCompactImgBase; OutputFilename: string; out ErrorMsg: string): boolean;
|
||||
public
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure WriteHelp(WithHeader: boolean); virtual;
|
||||
|
||||
property TileWidth: Word read FTileWidth write FTileWidth;
|
||||
property TileHeight: Word read FTileHeight write FTileHeight;
|
||||
property MinSize: Word read FMinSize write FMinSize;
|
||||
//property SkipCheck: boolean read FSkipCheck write FSkipCheck;
|
||||
property Verbose: boolean read FVerbose write FVerbose;
|
||||
property Quiet: boolean read FQuiet write FQuiet;
|
||||
property InputPath: string read FInputPath write FInputPath;
|
||||
property OutputPath: string read FOutputPath write FOutputPath;
|
||||
end;
|
||||
|
||||
{ TMyCanvas }
|
||||
|
||||
TMyCanvas = class(TFPImageCanvas)
|
||||
protected
|
||||
procedure DoCopyRect({%H-}x, {%H-}y: integer; {%H-}canvas: TFPCustomCanvas;
|
||||
const {%H-}SourceRect: TRect); override;
|
||||
procedure DoDraw({%H-}x, {%H-}y: integer; const {%H-}anImage: TFPCustomImage); override;
|
||||
end;
|
||||
|
||||
function CompareIFDForSize(i1, i2: Pointer): integer;
|
||||
@ -87,8 +75,8 @@ var
|
||||
Size1: Int64;
|
||||
Size2: Int64;
|
||||
begin
|
||||
Size1:=int64(IFD1.ImageWidth)*IFD1.ImageHeight;
|
||||
Size2:=int64(IFD2.ImageWidth)*IFD2.ImageHeight;
|
||||
Size1:=IFD1.ImageWidth*IFD1.ImageHeight;
|
||||
Size2:=IFD2.ImageWidth*IFD2.ImageHeight;
|
||||
if Size1>Size2 then Result:=1
|
||||
else if Size1<Size2 then Result:=-1
|
||||
else Result:=0;
|
||||
@ -117,12 +105,25 @@ begin
|
||||
Result:=l;
|
||||
end;
|
||||
|
||||
{ TMyCanvas }
|
||||
|
||||
procedure TMyCanvas.DoCopyRect(x, y: integer; canvas: TFPCustomCanvas;
|
||||
const SourceRect: TRect);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TMyCanvas.DoDraw(x, y: integer; const anImage: TFPCustomImage);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
{ TMyApplication }
|
||||
|
||||
procedure TPyramidTiffer.TiffReaderCreateImage(Sender: TFPReaderTiff;
|
||||
IFD: TTiffIFD);
|
||||
var
|
||||
Desc: TPTMemImgDesc;
|
||||
Desc: TFPCompactImgDesc;
|
||||
begin
|
||||
// free old image
|
||||
FreeAndNil(IFD.Img);
|
||||
@ -133,10 +134,10 @@ begin
|
||||
IFD.GreenBits),
|
||||
IFD.BlueBits),
|
||||
IFD.GrayBits);
|
||||
IFD.Img:=CreatePTMemImg(Desc,IFD.ImageWidth,IFD.ImageHeight);
|
||||
IFD.Img:=CreateFPCompactImg(Desc,IFD.ImageWidth,IFD.ImageHeight);
|
||||
end;
|
||||
|
||||
function TPyramidTiffer.ShrinkImage(LastImg: TPTMemImgBase): TPTMemImgBase;
|
||||
function TPyramidTiffer.ShrinkImage(LastImg: TFPCompactImgBase): TFPCompactImgBase;
|
||||
|
||||
function Half(i: integer): integer;
|
||||
begin
|
||||
@ -147,16 +148,16 @@ function TPyramidTiffer.ShrinkImage(LastImg: TPTMemImgBase): TPTMemImgBase;
|
||||
var
|
||||
ImgCanvas: TFPImageCanvas;
|
||||
begin
|
||||
Result:=TPTMemImgBase(CreatePTMemImg(LastImg.Desc, Half(LastImg.Width), Half(
|
||||
Result:=TFPCompactImgBase(CreateFPCompactImg(LastImg.Desc, Half(LastImg.Width), Half(
|
||||
LastImg.Height)));
|
||||
ImgCanvas:=TFPImageCanvas.create(Result);
|
||||
ImgCanvas:=TMyCanvas.create(Result);
|
||||
ImgCanvas.Interpolation:=TLinearInterpolation.Create;
|
||||
ImgCanvas.StretchDraw(0, 0, Result.Width, Result.Height, LastImg);
|
||||
ImgCanvas.Interpolation.Free;
|
||||
ImgCanvas.Free;
|
||||
end;
|
||||
|
||||
procedure TPyramidTiffer.LoadTiff(out Img: TPTMemImgBase;
|
||||
procedure TPyramidTiffer.LoadTiff(out Img: TFPCompactImgBase;
|
||||
Reader: TFPReaderTiff; InStream: TMemoryStream; var ErrorMsg: string);
|
||||
begin
|
||||
Reader.OnCreateImage:=@TiffReaderCreateImage;
|
||||
@ -165,23 +166,24 @@ begin
|
||||
ErrorMsg:='tiff has no image';
|
||||
exit;
|
||||
end;
|
||||
Img:=Reader.GetBiggestImage.Img as TPTMemImgBase;
|
||||
Img:=Reader.GetBiggestImage.Img as TFPCompactImgBase;
|
||||
end;
|
||||
|
||||
procedure TPyramidTiffer.LoadOther(out Img: TPTMemImgBase;
|
||||
procedure TPyramidTiffer.LoadOther(out Img: TFPCompactImgBase;
|
||||
Reader: TFPCustomImageReader; InStream: TMemoryStream);
|
||||
begin
|
||||
Img:=TPTMemImgRGBA8Bit.Create(0, 0);
|
||||
Img:=TFPCompactImgRGB8Bit.Create(0, 0);
|
||||
Reader.ImageRead(InStream, Img);
|
||||
Img:=GetMinimumPTMemImg(Img, true) as TPTMemImgBase;
|
||||
Img:=GetMinimumFPCompactImg(Img, true) as TFPCompactImgBase;
|
||||
end;
|
||||
|
||||
procedure TPyramidTiffer.DoRun;
|
||||
var
|
||||
InputFilename: String;
|
||||
OutputFilename: String;
|
||||
ErrorMsg: string;
|
||||
begin
|
||||
if GetCurrentDir='' then
|
||||
SetCurrentDir(GetEnvironmentVariable('PWD'));
|
||||
|
||||
ReadConfig;
|
||||
|
||||
if HasOption('min-size') then begin
|
||||
@ -206,10 +208,10 @@ begin
|
||||
ParamError('can not combine option -c and -i');
|
||||
if HasOption('o') then
|
||||
ParamError('can not combine option -c and -o');
|
||||
InputFilename:=CleanAndExpandFilename(GetOptionValue('c'));
|
||||
if not FileExistsUTF8(InputFilename) then
|
||||
ParamError('check file not found: '+InputFilename);
|
||||
if CheckIfFileIsPyramidTiled(InputFilename,ErrorMsg) then begin
|
||||
InputPath:=CleanAndExpandFilename(GetOptionValue('c'));
|
||||
if not FileExistsUTF8(InputPath) then
|
||||
ParamError('check file not found: '+InputPath);
|
||||
if CheckIfFileIsPyramidTiled(InputPath,ErrorMsg) then begin
|
||||
if not Quiet then
|
||||
writeln('ok');
|
||||
end else begin
|
||||
@ -224,17 +226,31 @@ begin
|
||||
if not HasOption('o') then
|
||||
ParamError('missing parameter -o');
|
||||
|
||||
InputFilename:=CleanAndExpandFilename(GetOptionValue('i'));
|
||||
if not FileExistsUTF8(InputFilename) then
|
||||
ParamError('input file not found: '+InputFilename);
|
||||
OutputFilename:=CleanAndExpandFilename(GetOptionValue('o'));
|
||||
if not DirectoryExistsUTF8(ExtractFilePath(OutputFilename)) then
|
||||
ParamError('output directory not found: '+ExtractFilePath(OutputFilename));
|
||||
|
||||
if not Convert(InputFilename,OutputFilename,ErrorMsg) then begin
|
||||
if not Quiet then
|
||||
writeln('ERROR: ',ErrorMsg);
|
||||
ExitCode:=1;
|
||||
GetCurrentDirUTF8;
|
||||
InputPath:=CleanAndExpandFilename(GetOptionValue('i'));
|
||||
OutputPath:=CleanAndExpandFilename(GetOptionValue('o'));
|
||||
if DirPathExists(InputPath) then begin
|
||||
// convert whole directory
|
||||
if not DirPathExists(OutputPath) then
|
||||
ParamError('output directory not found: '+OutputPath);
|
||||
if not ConvertDir(InputPath,OutputPath,ErrorMsg) then begin
|
||||
if not Quiet then
|
||||
writeln('ERROR: ',ErrorMsg);
|
||||
ExitCode:=1;
|
||||
end;
|
||||
end else begin
|
||||
// convert single file
|
||||
if not FileExistsUTF8(InputPath) then
|
||||
ParamError('input file not found: '+InputPath);
|
||||
if not DirectoryExistsUTF8(ExtractFilePath(OutputPath)) then
|
||||
ParamError('output directory not found: '+ExtractFilePath(OutputPath));
|
||||
if DirPathExists(OutputPath) then
|
||||
ParamError('output is a directory, but input is a file');
|
||||
if not ConvertFile(InputPath,OutputPath,ErrorMsg) then begin
|
||||
if not Quiet then
|
||||
writeln('ERROR: ',ErrorMsg);
|
||||
ExitCode:=1;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -362,7 +378,8 @@ begin
|
||||
end;
|
||||
if SmallerImg=nil then begin
|
||||
// this is the smallest image
|
||||
if (Img.ImageWidth>DWord(MinSize)*2) or (Img.ImageHeight>DWord(MinSize)*2) then begin
|
||||
if (Img.ImageWidth>MinSize*2)
|
||||
or (Img.ImageHeight>MinSize*2) then begin
|
||||
ErrorMsg:='missing small scale step. min-size='+IntToStr(MinSize)+'.'
|
||||
+' Smallest image: '+IntToStr(Img.ImageWidth)+'x'+IntToStr(Img.ImageHeight);
|
||||
exit;
|
||||
@ -392,15 +409,101 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPyramidTiffer.Convert(InputFilename, OutputFilename: string; out
|
||||
function TPyramidTiffer.GetReaderClass(Filename: string
|
||||
): TFPCustomImageReaderClass;
|
||||
var
|
||||
Ext: String;
|
||||
i: Integer;
|
||||
begin
|
||||
Result:=nil;
|
||||
Ext:=lowercase(ExtractFileExt(Filename));
|
||||
Delete(Ext,1,1); // delete '.'
|
||||
if (Ext='tif') or (Ext='tiff') then
|
||||
Result:=TFPReaderTiff
|
||||
else begin
|
||||
for i:=0 to ImageHandlers.Count-1 do begin
|
||||
if Pos(Ext,ImageHandlers.Extentions[ImageHandlers.TypeNames[i]])<1
|
||||
then continue;
|
||||
Result:=ImageHandlers.ImageReader[ImageHandlers.TypeNames[i]];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPyramidTiffer.ConvertDir(InputDir, OutputDir: string; out
|
||||
ErrorMsg: string): boolean;
|
||||
var
|
||||
FileInfo: TSearchRec;
|
||||
Files: TFilenameToStringTree;
|
||||
Item: PStringToStringTreeItem;
|
||||
InputFile: String;
|
||||
OutputFile: String;
|
||||
FileList: TStringList;
|
||||
begin
|
||||
Result:=false;
|
||||
ErrorMsg:='';
|
||||
InputDir:=AppendPathDelim(InputDir);
|
||||
OutputDir:=AppendPathDelim(OutputDir);
|
||||
Files:=TFilenameToStringTree.Create(false);
|
||||
FileList:=TStringList.Create;
|
||||
try
|
||||
if FindFirstUTF8(InputDir+AllFilesMask,faAnyFile,FileInfo)=0 then begin
|
||||
repeat
|
||||
// skip special files
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='') then
|
||||
continue;
|
||||
if GetReaderClass(FileInfo.Name)=nil then continue;
|
||||
Files[FileInfo.Name]:='1';
|
||||
until FindNextUTF8(FileInfo)<>0;
|
||||
end;
|
||||
FindCloseUTF8(FileInfo);
|
||||
if CompareFilenames(InputDir,OutputDir)=0 then begin
|
||||
// input and out dir are the same
|
||||
// => remove output files from input list
|
||||
for Item in Files do begin
|
||||
InputFile:=Item^.Name;
|
||||
if (CompareFileExt(InputFile,'tif',false)=0) then continue;
|
||||
OutputFile:=ChangeFileExt(InputFile,'.tif');
|
||||
Files.Remove(OutputFile);
|
||||
end;
|
||||
end;
|
||||
// convert
|
||||
for Item in Files do
|
||||
FileList.Add(Item^.Name);
|
||||
try
|
||||
ProcThreadPool.DoParallel(@ConvertFilesParallel,0,FileList.Count-1,FileList);
|
||||
Result:=true;
|
||||
except
|
||||
on E: Exception do
|
||||
ErrorMsg:=E.Message;
|
||||
end;
|
||||
finally
|
||||
FileList.Free;
|
||||
Files.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPyramidTiffer.ConvertFilesParallel(Index: PtrInt; Data: Pointer;
|
||||
Item: TMultiThreadProcItem);
|
||||
var
|
||||
Files: TStringList;
|
||||
InputFilename: String;
|
||||
OutputFilename: String;
|
||||
ErrorMsg: string;
|
||||
begin
|
||||
Files:=TStringList(Data);
|
||||
InputFilename:=AppendPathDelim(InputPath)+Files[Index];
|
||||
OutputFilename:=AppendPathDelim(OutputPath)+ChangeFileExt(Files[Index],'.tif');
|
||||
if not ConvertFile(InputFilename,OutputFilename,ErrorMsg) then
|
||||
raise Exception.Create(ErrorMsg+',input='+InputFilename+',output='+OutputFilename);
|
||||
end;
|
||||
|
||||
function TPyramidTiffer.ConvertFile(InputFilename, OutputFilename: string; out
|
||||
ErrorMsg: string): boolean;
|
||||
var
|
||||
InStream: TMemoryStream;
|
||||
Ext: String;
|
||||
ReaderClass: TFPCustomImageReaderClass;
|
||||
Reader: TFPCustomImageReader;
|
||||
Img: TPTMemImgBase;
|
||||
i: Integer;
|
||||
Img: TFPCompactImgBase;
|
||||
begin
|
||||
Result:=false;
|
||||
ErrorMsg:='';
|
||||
@ -416,21 +519,9 @@ begin
|
||||
InStream.Position:=0;
|
||||
|
||||
// get the right image type reader
|
||||
Ext:=lowercase(ExtractFileExt(InputFilename));
|
||||
Delete(Ext,1,1); // delete '.'
|
||||
if (Ext='tif') or (Ext='tiff') then
|
||||
ReaderClass:=TFPReaderTiff
|
||||
else begin
|
||||
for i:=0 to ImageHandlers.Count-1 do begin
|
||||
if Pos(Ext,ImageHandlers.Extentions[ImageHandlers.TypeNames[i]])<1
|
||||
then continue;
|
||||
ReaderClass:=ImageHandlers.ImageReader[ImageHandlers.TypeNames[i]];
|
||||
if Verbose then
|
||||
writeln('reading ',ImageHandlers.TypeNames[i]);
|
||||
end;
|
||||
end;
|
||||
ReaderClass:=GetReaderClass(InputFilename);
|
||||
if ReaderClass=nil then begin
|
||||
ErrorMsg:='unknown file extension "'+Ext+'"';
|
||||
ErrorMsg:='unknown file extension "'+ExtractFileExt(InputFilename)+'"';
|
||||
exit;
|
||||
end;
|
||||
Reader:=ReaderClass.Create;
|
||||
@ -459,16 +550,30 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPyramidTiffer.Convert(Img: TPTMemImgBase; OutputFilename: string; out
|
||||
function TPyramidTiffer.Convert(Img: TFPCompactImgBase; OutputFilename: string; out
|
||||
ErrorMsg: string): boolean;
|
||||
|
||||
procedure AddTiff(Writer: TFPWriterTiff; Img: TFPCustomImage;
|
||||
PageNumber, PageCount, TileWidth, TileHeight: integer;
|
||||
Desc: TFPCompactImgDesc);
|
||||
begin
|
||||
Img.Extra[TiffPageNumber]:=IntToStr(PageNumber);
|
||||
Img.Extra[TiffPageCount]:=IntToStr(PageCount);
|
||||
Img.Extra[TiffTileWidth]:=IntToStr(TileWidth);
|
||||
Img.Extra[TiffTileLength]:=IntToStr(TileHeight);
|
||||
SetFPImgExtraTiff(Desc,Img,false);
|
||||
Img.Extra[TiffCompression]:=IntToStr(TiffCompressionDeflateZLib);
|
||||
Writer.AddImage(Img);
|
||||
end;
|
||||
|
||||
var
|
||||
OutStream: TMemoryStream;
|
||||
Writer: TFPWriterTiff;
|
||||
Size: Int64;
|
||||
Count: Integer;
|
||||
Index: Integer;
|
||||
LastImg: TPTMemImgBase;
|
||||
NewImg: TPTMemImgBase;
|
||||
LastImg: TFPCompactImgBase;
|
||||
NewImg: TFPCompactImgBase;
|
||||
begin
|
||||
Result:=false;
|
||||
try
|
||||
@ -481,6 +586,8 @@ begin
|
||||
end;
|
||||
|
||||
// create images
|
||||
if Verbose then
|
||||
writeln('Creating file "',OutputFilename,'"');
|
||||
OutStream:=TMemoryStream.Create;
|
||||
Writer:=nil;
|
||||
LastImg:=nil;
|
||||
@ -488,31 +595,14 @@ begin
|
||||
try
|
||||
Writer:=TFPWriterTiff.Create;
|
||||
Index:=0;
|
||||
Img.Extra[TiffPageNumber]:=IntToStr(Index);
|
||||
Img.Extra[TiffPageCount]:=IntToStr(Count);
|
||||
Img.Extra[TiffTileWidth]:=IntToStr(TileWidth);
|
||||
Img.Extra[TiffTileLength]:=IntToStr(TileHeight);
|
||||
SetFPImgExtraTiff(Img.Desc,Img,false);
|
||||
Img.Extra[TiffCompression]:=IntToStr(TiffCompressionDeflateZLib);
|
||||
Writer.AddImage(Img);
|
||||
|
||||
AddTiff(Writer,Img,Index,Count,TileWidth,TileHeight,Img.Desc);
|
||||
// add smaller images
|
||||
LastImg:=Img;
|
||||
while Index+1<Count do begin
|
||||
Index+=1;
|
||||
// create next image with half the width and height
|
||||
NewImg:=ShrinkImage(LastImg);
|
||||
// set tiff page number and count
|
||||
NewImg.Extra[TiffPageNumber]:=IntToStr(Index);
|
||||
NewImg.Extra[TiffPageCount]:=IntToStr(Count);
|
||||
NewImg.Extra[TiffTileWidth]:=IntToStr(TileWidth);
|
||||
NewImg.Extra[TiffTileLength]:=IntToStr(TileHeight);
|
||||
SetFPImgExtraTiff(NewImg.Desc,NewImg,false);
|
||||
Img.Extra[TiffCompression]:=IntToStr(TiffCompressionDeflateZLib);
|
||||
// add image to tiff
|
||||
if Verbose then
|
||||
writeln(' adding image ',Index,'/',Count,', size=',NewImg.Width,'x',NewImg.Height);
|
||||
Writer.AddImage(NewImg);
|
||||
AddTiff(Writer,NewImg,Index,Count,TileWidth,TileHeight,NewImg.Desc);
|
||||
// free last step
|
||||
if LastImg<>Img then
|
||||
FreeAndNil(LastImg);
|
||||
@ -528,6 +618,8 @@ begin
|
||||
|
||||
// save to file
|
||||
OutStream.SaveToFile(OutputFilename);
|
||||
if Verbose then
|
||||
writeln('Saved file "',OutputFilename,'"');
|
||||
Result:=true;
|
||||
finally
|
||||
if LastImg<>Img then
|
||||
@ -567,13 +659,13 @@ begin
|
||||
if WithHeader then begin
|
||||
writeln('Version ',Version);
|
||||
writeln;
|
||||
writeln('pyramidtiff creates a tiff containing the original image, the image');
|
||||
writeln('with half the width and half the height (rounded up), the image with');
|
||||
writeln('quartered width/height (rounded up), ... and so forth.');
|
||||
writeln('pyramidtiff creates a tiff containing multiple images:');
|
||||
writeln('the original image,');
|
||||
writeln('the image with half the width and half the height (rounded up),');
|
||||
writeln('the image with quartered width/height (rounded up),');
|
||||
writeln('... and so forth.');
|
||||
writeln;
|
||||
end;
|
||||
writeln('-c <input file>');
|
||||
writeln(' Check if file is a pyramid, tiled tif. 0 = yes, 1 = no.');
|
||||
writeln('-i <input file>');
|
||||
write(' Input image file can be a:');
|
||||
for i:=0 to ImageHandlers.Count-1 do begin
|
||||
@ -581,8 +673,14 @@ begin
|
||||
write(' ',ImageHandlers.Extentions[ImgType]);
|
||||
end;
|
||||
writeln;
|
||||
writeln(' If input file is a directory then the -o must be a directory too.');
|
||||
writeln(' All image files in the directory will be converted.');
|
||||
writeln('-o <output file>');
|
||||
writeln(' Output image file. It will always be a tif file, no matter what extension it has.');
|
||||
writeln(' Output image file. It will always be a tif file, no matter what');
|
||||
writeln(' extension it has.');
|
||||
writeln('-c <input file>');
|
||||
writeln(' Check if file is a pyramid, tiled tif. 0 = yes, 1 = no.');
|
||||
writeln(' You can not use both -c and -i');
|
||||
writeln('--width=<tilewidth>');
|
||||
writeln(' In pixel. Default=',TileWidth);
|
||||
writeln('--height=<tileheight>');
|
||||
|
@ -40,167 +40,6 @@ uses
|
||||
LazLogger, FPCanvas, FPWriteTiff, FPTiffCmn;
|
||||
|
||||
type
|
||||
TPTMemImgDesc = record
|
||||
Gray: boolean; // true = red=green=blue, false: a RGB image
|
||||
Depth: word; // 8 or 16 bit
|
||||
HasAlpha: boolean;
|
||||
end;
|
||||
|
||||
{ TPTMemImgBase }
|
||||
|
||||
TPTMemImgBase = class(TFPCustomImage)
|
||||
private
|
||||
FDesc: TPTMemImgDesc;
|
||||
public
|
||||
property Desc: TPTMemImgDesc read FDesc;
|
||||
end;
|
||||
TPTMemImgBaseClass = class of TPTMemImgBase;
|
||||
|
||||
{ TPTMemImgGray16Bit }
|
||||
|
||||
TPTMemImgGray16Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PWord;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TPTMemImgGrayAlpha16BitValue = packed record
|
||||
g,a: word;
|
||||
end;
|
||||
PPTMemImgGrayAlpha16BitValue = ^TPTMemImgGrayAlpha16BitValue;
|
||||
|
||||
{ TPTMemImgGrayAlpha16Bit }
|
||||
|
||||
TPTMemImgGrayAlpha16Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PPTMemImgGrayAlpha16BitValue;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
{ TPTMemImgGray8Bit }
|
||||
|
||||
TPTMemImgGray8Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PByte;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TPTMemImgGrayAlpha8BitValue = packed record
|
||||
g,a: byte;
|
||||
end;
|
||||
PPTMemImgGrayAlpha8BitValue = ^TPTMemImgGrayAlpha8BitValue;
|
||||
|
||||
{ TPTMemImgGrayAlpha8Bit }
|
||||
|
||||
TPTMemImgGrayAlpha8Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PPTMemImgGrayAlpha8BitValue;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TPTMemImgRGBA8BitValue = packed record
|
||||
r,g,b,a: byte;
|
||||
end;
|
||||
PPTMemImgRGBA8BitValue = ^TPTMemImgRGBA8BitValue;
|
||||
|
||||
{ TPTMemImgRGBA8Bit }
|
||||
|
||||
TPTMemImgRGBA8Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PPTMemImgRGBA8BitValue;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TPTMemImgRGB8BitValue = packed record
|
||||
r,g,b: byte;
|
||||
end;
|
||||
PPTMemImgRGB8BitValue = ^TPTMemImgRGB8BitValue;
|
||||
|
||||
{ TPTMemImgRGB8Bit }
|
||||
|
||||
TPTMemImgRGB8Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PPTMemImgRGB8BitValue;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TPTMemImgRGB16BitValue = packed record
|
||||
r,g,b: word;
|
||||
end;
|
||||
PPTMemImgRGB16BitValue = ^TPTMemImgRGB16BitValue;
|
||||
|
||||
{ TPTMemImgRGB16Bit }
|
||||
|
||||
TPTMemImgRGB16Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PPTMemImgRGB16BitValue;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
{ TPTMemImgRGBA16Bit }
|
||||
|
||||
TPTMemImgRGBA16Bit = class(TPTMemImgBase)
|
||||
protected
|
||||
FData: PFPColor;
|
||||
function GetInternalColor(x, y: integer): TFPColor; override;
|
||||
function GetInternalPixel({%H-}x, {%H-}y: integer): integer; override;
|
||||
procedure SetInternalColor (x, y: integer; const Value: TFPColor); override;
|
||||
procedure SetInternalPixel({%H-}x, {%H-}y: integer; {%H-}Value: integer); override;
|
||||
public
|
||||
constructor Create(AWidth, AHeight: integer); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetSize(AWidth, AHeight: integer); override;
|
||||
end;
|
||||
|
||||
TCreateCompatibleMemImgEvent = procedure(Sender: TObject; Img: TFPCustomImage;
|
||||
NewWidth, NewHeight: integer; out NewImage: TFPCustomImage) of object;
|
||||
|
||||
@ -216,46 +55,14 @@ type
|
||||
function MaxSupport: double; virtual;
|
||||
end;
|
||||
|
||||
{ Create a descriptor to select a memimg class }
|
||||
function GetPTMemImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean): TPTMemImgDesc;
|
||||
|
||||
{ Returns a memimg class that fits the descriptor }
|
||||
function GetPTMemImgClass(const Desc: TPTMemImgDesc): TPTMemImgBaseClass;
|
||||
|
||||
{ Create a memimg with the descriptor }
|
||||
function CreatePTMemImg(const Desc: TPTMemImgDesc; Width, Height: integer): TFPCustomImage;
|
||||
|
||||
{ Create a memimg with the same features as Img.
|
||||
If Img is a TPTMemImgBaseClass it will create that.
|
||||
Otherwise it returns a memimg that fits the Img using GetMinimumPTDesc. }
|
||||
function CreateCompatiblePTMemImg(Img: TFPCustomImage; Width, Height: integer
|
||||
): TFPCustomImage;
|
||||
|
||||
{ As CreateCompatiblePTMemImg, but the image has always an alpha channel. }
|
||||
function CreateCompatiblePTMemImgWithAlpha(Img: TFPCustomImage;
|
||||
Width, Height: integer): TFPCustomImage;
|
||||
|
||||
{ Returns the smallest descriptor that allows to store the Img.
|
||||
It returns HasAlpha=false if all pixel are opaque.
|
||||
It returns Gray=true if all red=green=blue.
|
||||
It returns Depth=8 if all lo byte equals the hi byte or all lo bytes are 0.
|
||||
To ignore rounding errors you can pass a FuzzyDepth. For example a FuzzyDepth
|
||||
of 3 ignores the lower 3 bits when comparing. }
|
||||
function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TPTMemImgDesc;
|
||||
|
||||
{ Create a smaller memimg with the same information as Img.
|
||||
Pass FreeImg=true to call Img.Free }
|
||||
function GetMinimumPTMemImg(Img: TFPCustomImage; FreeImg: boolean;
|
||||
FuzzyDepth: word = 4): TFPCustomImage;
|
||||
|
||||
procedure SetFPImgExtraTiff(const Desc: TPTMemImgDesc; Img: TFPCustomImage;
|
||||
procedure SetFPImgExtraTiff(const Desc: TFPCompactImgDesc; Img: TFPCustomImage;
|
||||
ClearTiffExtras: boolean);
|
||||
|
||||
function dbgs(const Desc: TPTMemImgDesc): string; overload;
|
||||
function dbgs(const Desc: TFPCompactImgDesc): string; overload;
|
||||
|
||||
implementation
|
||||
|
||||
procedure SetFPImgExtraTiff(const Desc: TPTMemImgDesc; Img: TFPCustomImage;
|
||||
procedure SetFPImgExtraTiff(const Desc: TFPCompactImgDesc; Img: TFPCustomImage;
|
||||
ClearTiffExtras: boolean);
|
||||
begin
|
||||
if ClearTiffExtras then
|
||||
@ -275,186 +82,13 @@ begin
|
||||
Img.Extra[TiffAlphaBits]:='0';
|
||||
end;
|
||||
|
||||
function dbgs(const Desc: TPTMemImgDesc): string;
|
||||
function dbgs(const Desc: TFPCompactImgDesc): string;
|
||||
begin
|
||||
Result:='Depth='+dbgs(Desc.Depth)
|
||||
+',Gray='+dbgs(Desc.Gray)
|
||||
+',HasAlpha='+dbgs(Desc.HasAlpha);
|
||||
end;
|
||||
|
||||
function GetPTMemImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean
|
||||
): TPTMemImgDesc;
|
||||
begin
|
||||
Result.Gray:=Gray;
|
||||
Result.Depth:=Depth;
|
||||
Result.HasAlpha:=HasAlpha;
|
||||
end;
|
||||
|
||||
function GetPTMemImgClass(const Desc: TPTMemImgDesc): TPTMemImgBaseClass;
|
||||
begin
|
||||
if Desc.Gray then begin
|
||||
if Desc.HasAlpha then begin
|
||||
// gray, alpha
|
||||
if Desc.Depth<=8 then
|
||||
Result:=TPTMemImgGrayAlpha8Bit
|
||||
else
|
||||
Result:=TPTMemImgGrayAlpha16Bit;
|
||||
end else begin
|
||||
// gray, no alpha
|
||||
if Desc.Depth<=8 then
|
||||
Result:=TPTMemImgGray8Bit
|
||||
else
|
||||
Result:=TPTMemImgGray16Bit;
|
||||
end;
|
||||
end else begin
|
||||
// RGB
|
||||
if Desc.HasAlpha then begin
|
||||
// RGB, alpha
|
||||
if Desc.Depth<=8 then
|
||||
Result:=TPTMemImgRGBA8Bit
|
||||
else
|
||||
Result:=TPTMemImgRGBA16Bit;
|
||||
end else begin
|
||||
// RGB, no alpha
|
||||
if Desc.Depth<=8 then
|
||||
Result:=TPTMemImgRGB8Bit
|
||||
else
|
||||
Result:=TPTMemImgRGB16Bit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function CreatePTMemImg(const Desc: TPTMemImgDesc; Width, Height: integer
|
||||
): TFPCustomImage;
|
||||
var
|
||||
ImgClass: TPTMemImgBaseClass;
|
||||
begin
|
||||
ImgClass:=GetPTMemImgClass(Desc);
|
||||
Result:=ImgClass.Create(Width,Height);
|
||||
end;
|
||||
|
||||
function CreateCompatiblePTMemImg(Img: TFPCustomImage; Width, Height: integer
|
||||
): TFPCustomImage;
|
||||
begin
|
||||
if Img is TPTMemImgBase then
|
||||
Result:=CreatePTMemImg(TPTMemImgBase(Img).Desc,Width,Height)
|
||||
else
|
||||
Result:=CreatePTMemImg(GetMinimumPTDesc(Img),Width,Height);
|
||||
//DebugLn(['CreateCompatibleQVMemImg '+Img.ClassName+' '+Result.ClassName]);
|
||||
end;
|
||||
|
||||
function CreateCompatiblePTMemImgWithAlpha(Img: TFPCustomImage; Width,
|
||||
Height: integer): TFPCustomImage;
|
||||
var
|
||||
Desc: TPTMemImgDesc;
|
||||
begin
|
||||
if Img is TPTMemImgBase then
|
||||
Desc:=TPTMemImgBase(Img).Desc
|
||||
else
|
||||
Desc:=GetMinimumPTDesc(Img);
|
||||
Desc.HasAlpha:=true;
|
||||
Result:=CreatePTMemImg(Desc,Width,Height);
|
||||
end;
|
||||
|
||||
function GetMinimumPTDesc(Img: TFPCustomImage; FuzzyDepth: word = 4): TPTMemImgDesc;
|
||||
var
|
||||
AllLoEqualsHi, AllLoAre0: Boolean;
|
||||
FuzzyMaskLoHi: Word;
|
||||
|
||||
procedure Need16Bit(c: word); inline;
|
||||
var
|
||||
l: Byte;
|
||||
begin
|
||||
c:=c and FuzzyMaskLoHi;
|
||||
l:=Lo(c);
|
||||
AllLoAre0:=AllLoAre0 and (l=0);
|
||||
AllLoEqualsHi:=AllLoEqualsHi and (l=Hi(c));
|
||||
end;
|
||||
|
||||
var
|
||||
TestGray: Boolean;
|
||||
TestAlpha: Boolean;
|
||||
Test16Bit: Boolean;
|
||||
BaseImg: TPTMemImgBase;
|
||||
ImgDesc: TPTMemImgDesc;
|
||||
y: Integer;
|
||||
x: Integer;
|
||||
col: TFPColor;
|
||||
FuzzyMaskWord: Word;
|
||||
FuzzyOpaque: Word;
|
||||
begin
|
||||
TestGray:=true;
|
||||
TestAlpha:=true;
|
||||
Test16Bit:=FuzzyDepth<8;
|
||||
Result.HasAlpha:=false;
|
||||
Result.Gray:=true;
|
||||
Result.Depth:=8;
|
||||
if Img is TPTMemImgBase then begin
|
||||
BaseImg:=TPTMemImgBase(Img);
|
||||
ImgDesc:=BaseImg.Desc;
|
||||
if ImgDesc.Depth<=8 then Test16Bit:=false;
|
||||
if ImgDesc.Gray then TestGray:=false;
|
||||
if not ImgDesc.HasAlpha then TestAlpha:=false;
|
||||
end;
|
||||
|
||||
if (not TestGray) and (not TestAlpha) and (not Test16Bit) then exit;
|
||||
|
||||
FuzzyMaskWord:=Word($ffff) shl FuzzyDepth;
|
||||
FuzzyOpaque:=alphaOpaque and FuzzyMaskWord;
|
||||
FuzzyMaskLoHi:=Word(lo(FuzzyMaskWord))+(Word(lo(FuzzyMaskWord)) shl 8);
|
||||
AllLoAre0:=true;
|
||||
AllLoEqualsHi:=true;
|
||||
for y:=0 to Img.Height-1 do begin
|
||||
for x:=0 to Img.Width-1 do begin
|
||||
col:=Img.Colors[x,y];
|
||||
if TestAlpha and ((col.alpha and FuzzyMaskWord)<>FuzzyOpaque) then begin
|
||||
TestAlpha:=false;
|
||||
Result.HasAlpha:=true;
|
||||
if (not TestGray) and (not Test16Bit) then break;
|
||||
end;
|
||||
if TestGray
|
||||
and ((col.red and FuzzyMaskWord)<>(col.green and FuzzyMaskWord))
|
||||
or ((col.red and FuzzyMaskWord)<>(col.blue and FuzzyMaskWord)) then begin
|
||||
TestGray:=false;
|
||||
Result.Gray:=false;
|
||||
if (not TestAlpha) and (not Test16Bit) then break;
|
||||
end;
|
||||
if Test16Bit then begin
|
||||
Need16Bit(col.red);
|
||||
Need16Bit(col.green);
|
||||
Need16Bit(col.blue);
|
||||
Need16Bit(col.alpha);
|
||||
if (not AllLoAre0) and (not AllLoEqualsHi) then begin
|
||||
Test16Bit:=false;
|
||||
Result.Depth:=16;
|
||||
if (not TestAlpha) and (not TestGray) then break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetMinimumPTMemImg(Img: TFPCustomImage; FreeImg: boolean;
|
||||
FuzzyDepth: word = 4): TFPCustomImage;
|
||||
var
|
||||
Desc: TPTMemImgDesc;
|
||||
ImgClass: TPTMemImgBaseClass;
|
||||
y: Integer;
|
||||
x: Integer;
|
||||
begin
|
||||
Desc:=GetMinimumPTDesc(Img,FuzzyDepth);
|
||||
//debugln(['GetMinimumQVMemImg Depth=',Desc.Depth,' Gray=',Desc.Gray,' HasAlpha=',Desc.HasAlpha]);
|
||||
ImgClass:=GetPTMemImgClass(Desc);
|
||||
if Img.ClassType=ImgClass then
|
||||
exit(Img);
|
||||
Result:=CreatePTMemImg(Desc,Img.Width,Img.Height);
|
||||
for y:=0 to Img.Height-1 do
|
||||
for x:=0 to Img.Width-1 do
|
||||
Result.Colors[x,y]:=Img.Colors[x,y];
|
||||
if FreeImg then
|
||||
Img.Free;
|
||||
end;
|
||||
|
||||
function ColorRound (c : double) : word;
|
||||
begin
|
||||
if c > $FFFF then
|
||||
@ -465,405 +99,6 @@ begin
|
||||
result := round(c);
|
||||
end;
|
||||
|
||||
{ TPTMemImgGrayAlpha16Bit }
|
||||
|
||||
function TPTMemImgGrayAlpha16Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
var
|
||||
v: TPTMemImgGrayAlpha16BitValue;
|
||||
begin
|
||||
v:=FData[x+y*Width];
|
||||
Result.red:=v.g;
|
||||
Result.green:=Result.red;
|
||||
Result.blue:=Result.red;
|
||||
Result.alpha:=v.a;
|
||||
end;
|
||||
|
||||
function TPTMemImgGrayAlpha16Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha16Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
var
|
||||
v: TPTMemImgGrayAlpha16BitValue;
|
||||
begin
|
||||
v.g:=Value.red;
|
||||
v.a:=Value.alpha;
|
||||
FData[x+y*Width]:=v;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha16Bit.SetInternalPixel(x, y: integer; Value: integer
|
||||
);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgGrayAlpha16Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(true,16,true);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgGrayAlpha16Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha16Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TPTMemImgGrayAlpha16BitValue)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgGrayAlpha8Bit }
|
||||
|
||||
function TPTMemImgGrayAlpha8Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
var
|
||||
v: TPTMemImgGrayAlpha8BitValue;
|
||||
begin
|
||||
v:=FData[x+y*Width];
|
||||
Result.red:=(v.g shl 8)+v.g;
|
||||
Result.green:=Result.red;
|
||||
Result.blue:=Result.red;
|
||||
Result.alpha:=(v.a shl 8)+v.a;
|
||||
end;
|
||||
|
||||
function TPTMemImgGrayAlpha8Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha8Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
var
|
||||
v: TPTMemImgGrayAlpha8BitValue;
|
||||
begin
|
||||
v.g:=Value.red shr 8;
|
||||
v.a:=Value.alpha shr 8;
|
||||
FData[x+y*Width]:=v;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha8Bit.SetInternalPixel(x, y: integer; Value: integer
|
||||
);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgGrayAlpha8Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(true,8,true);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgGrayAlpha8Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGrayAlpha8Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TPTMemImgGrayAlpha8BitValue)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgGray16Bit }
|
||||
|
||||
function TPTMemImgGray16Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
begin
|
||||
Result.red:=FData[x+y*Width];
|
||||
Result.green:=Result.red;
|
||||
Result.blue:=Result.red;
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
function TPTMemImgGray16Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray16Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
begin
|
||||
FData[x+y*Width]:=Value.red;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray16Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgGray16Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(true,16,false);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgGray16Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray16Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(Word)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgGray8Bit }
|
||||
|
||||
function TPTMemImgGray8Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
begin
|
||||
Result.red:=FData[x+y*Width];
|
||||
Result.red:=(Word(Result.red) shl 8)+Result.red;
|
||||
Result.green:=Result.red;
|
||||
Result.blue:=Result.red;
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
function TPTMemImgGray8Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray8Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
begin
|
||||
FData[x+y*Width]:=Value.red shr 8;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray8Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgGray8Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(true,8,false);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgGray8Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgGray8Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(Byte)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgRGBA8Bit }
|
||||
|
||||
function TPTMemImgRGBA8Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
var
|
||||
v: TPTMemImgRGBA8BitValue;
|
||||
begin
|
||||
v:=FData[x+y*Width];
|
||||
Result.red:=(v.r shl 8)+v.r;
|
||||
Result.green:=(v.g shl 8)+v.g;
|
||||
Result.blue:=(v.b shl 8)+v.b;
|
||||
Result.alpha:=(v.a shl 8)+v.a;
|
||||
end;
|
||||
|
||||
function TPTMemImgRGBA8Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA8Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
var
|
||||
v: TPTMemImgRGBA8BitValue;
|
||||
begin
|
||||
v.r:=Value.red shr 8;
|
||||
v.g:=Value.green shr 8;
|
||||
v.b:=Value.blue shr 8;
|
||||
v.a:=Value.alpha shr 8;
|
||||
FData[x+y*Width]:=v;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA8Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgRGBA8Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(false,8,true);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgRGBA8Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA8Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TPTMemImgRGBA8BitValue)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgRGB8Bit }
|
||||
|
||||
function TPTMemImgRGB8Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
var
|
||||
v: TPTMemImgRGB8BitValue;
|
||||
begin
|
||||
v:=FData[x+y*Width];
|
||||
Result.red:=(v.r shl 8)+v.r;
|
||||
Result.green:=(v.g shl 8)+v.g;
|
||||
Result.blue:=(v.b shl 8)+v.b;
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
function TPTMemImgRGB8Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB8Bit.SetInternalColor(x, y: integer; const Value: TFPColor
|
||||
);
|
||||
var
|
||||
v: TPTMemImgRGB8BitValue;
|
||||
begin
|
||||
v.r:=Value.red shr 8;
|
||||
v.g:=Value.green shr 8;
|
||||
v.b:=Value.blue shr 8;
|
||||
FData[x+y*Width]:=v;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB8Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgRGB8Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(false,8,false);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgRGB8Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB8Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TPTMemImgRGB8BitValue)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgRGB16Bit }
|
||||
|
||||
function TPTMemImgRGB16Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
var
|
||||
v: TPTMemImgRGB16BitValue;
|
||||
begin
|
||||
v:=FData[x+y*Width];
|
||||
Result.red:=v.r;
|
||||
Result.green:=v.g;
|
||||
Result.blue:=v.b;
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
function TPTMemImgRGB16Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB16Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
var
|
||||
v: TPTMemImgRGB16BitValue;
|
||||
begin
|
||||
v.r:=Value.red;
|
||||
v.g:=Value.green;
|
||||
v.b:=Value.blue;
|
||||
FData[x+y*Width]:=v;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB16Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgRGB16Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(false,16,false);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgRGB16Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGB16Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TPTMemImgRGB16BitValue)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TPTMemImgRGBA16Bit }
|
||||
|
||||
function TPTMemImgRGBA16Bit.GetInternalColor(x, y: integer): TFPColor;
|
||||
begin
|
||||
Result:=FData[x+y*Width];
|
||||
end;
|
||||
|
||||
function TPTMemImgRGBA16Bit.GetInternalPixel(x, y: integer): integer;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA16Bit.SetInternalColor(x, y: integer;
|
||||
const Value: TFPColor);
|
||||
begin
|
||||
FData[x+y*Width]:=Value;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA16Bit.SetInternalPixel(x, y: integer; Value: integer);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
constructor TPTMemImgRGBA16Bit.Create(AWidth, AHeight: integer);
|
||||
begin
|
||||
FDesc:=GetPTMemImgDesc(false,16,true);
|
||||
inherited Create(AWidth, AHeight);
|
||||
end;
|
||||
|
||||
destructor TPTMemImgRGBA16Bit.Destroy;
|
||||
begin
|
||||
ReAllocMem(FData,0);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPTMemImgRGBA16Bit.SetSize(AWidth, AHeight: integer);
|
||||
begin
|
||||
if (AWidth=Width) and (AHeight=Height) then exit;
|
||||
ReAllocMem(FData,SizeOf(TFPColor)*AWidth*AHeight);
|
||||
inherited SetSize(AWidth,AHeight);
|
||||
end;
|
||||
|
||||
{ TLinearInterpolation }
|
||||
|
||||
procedure TLinearInterpolation.CreatePixelWeights(OldSize, NewSize: integer;
|
||||
|
Reference in New Issue
Block a user