You've already forked lazarus-ccr
1087 lines
30 KiB
ObjectPascal
1087 lines
30 KiB
ObjectPascal
![]() |
{ Graphic functions for pyramidtiff.
|
||
|
|
||
|
Copyright (C) 2008 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.
|
||
|
}
|
||
|
unit PyTiGraphics;
|
||
|
|
||
|
{$mode objfpc}{$H+}
|
||
|
|
||
|
{$inline on}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
Math, sysutils, Classes, FPimage, FPImgCanv,
|
||
|
LazLogger, FPCanvas, FPWriteTiff, FPTiffCmn;
|
||
|
|
||
|
type
|
||
|
TPTMemImgDesc = record
|
||
|
Gray: boolean;
|
||
|
Depth: word;
|
||
|
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;
|
||
|
|
||
|
{ TLinearInterpolation }
|
||
|
|
||
|
TLinearInterpolation = class(TFPCustomInterpolation)
|
||
|
private
|
||
|
procedure CreatePixelWeights(OldSize, NewSize: integer;
|
||
|
out Entries: Pointer; out EntrySize: integer; out Support: integer);
|
||
|
protected
|
||
|
procedure Execute(x,y,w,h: integer); override;
|
||
|
function Filter(x: double): double; virtual;
|
||
|
function MaxSupport: double; virtual;
|
||
|
end;
|
||
|
|
||
|
function GeTPTMemImgDesc(Gray: boolean; Depth: word; HasAlpha: boolean): TPTMemImgDesc;
|
||
|
function GeTPTMemImgClass(const Desc: TPTMemImgDesc): TPTMemImgBaseClass;
|
||
|
function CreateQVMemImg(const Desc: TPTMemImgDesc; Width, Height: integer): TFPCustomImage;
|
||
|
function CreateCompatibleQVMemImg(Img: TFPCustomImage; Width, Height: integer
|
||
|
): TFPCustomImage;
|
||
|
function CreateCompatibleQVMemImgWithAlpha(Img: TFPCustomImage;
|
||
|
Width, Height: integer): TFPCustomImage;
|
||
|
function GetMinimumQVDesc(Img: TFPCustomImage): TPTMemImgDesc;
|
||
|
function GetMinimumQVMemImg(Img: TFPCustomImage; FreeImg: boolean): TFPCustomImage;
|
||
|
|
||
|
procedure SetFPImgExtraTiff(const Desc: TPTMemImgDesc; Img: TFPCustomImage;
|
||
|
ClearTiffExtras: boolean);
|
||
|
|
||
|
procedure SaveAsDebugTiff(Img: TFPCustomImage; Filename: string);
|
||
|
function dbgs(const Desc: TPTMemImgDesc): string; overload;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
procedure SetFPImgExtraTiff(const Desc: TPTMemImgDesc; Img: TFPCustomImage;
|
||
|
ClearTiffExtras: boolean);
|
||
|
begin
|
||
|
if ClearTiffExtras then
|
||
|
FPTiffCmn.ClearTiffExtras(Img);
|
||
|
if Desc.Gray then begin
|
||
|
Img.Extra[TiffPhotoMetric]:='1';
|
||
|
Img.Extra[TiffGrayBits]:=IntToStr(Desc.Depth);
|
||
|
end else begin
|
||
|
Img.Extra[TiffPhotoMetric]:='2';
|
||
|
Img.Extra[TiffRedBits]:=IntToStr(Desc.Depth);
|
||
|
Img.Extra[TiffGreenBits]:=IntToStr(Desc.Depth);
|
||
|
Img.Extra[TiffBlueBits]:=IntToStr(Desc.Depth);
|
||
|
end;
|
||
|
if Desc.HasAlpha then
|
||
|
Img.Extra[TiffAlphaBits]:=IntToStr(Desc.Depth)
|
||
|
else
|
||
|
Img.Extra[TiffAlphaBits]:='0';
|
||
|
end;
|
||
|
|
||
|
procedure SaveAsDebugTiff(Img: TFPCustomImage; Filename: string);
|
||
|
var
|
||
|
Writer: TFPWriterTiff;
|
||
|
ms: TMemoryStream;
|
||
|
begin
|
||
|
ms:=nil;
|
||
|
Writer:=nil;
|
||
|
try
|
||
|
ms:=TMemoryStream.Create;
|
||
|
Writer:=TFPWriterTiff.Create;
|
||
|
Writer.ImageWrite(ms,Img);
|
||
|
ms.Position:=0;
|
||
|
ms.SaveToFile(Filename);
|
||
|
DebugLn(['SaveAsDebugTiff ',Img.ClassName,' ',Img.Width,'x',Img.Height,' ',Filename]);
|
||
|
finally
|
||
|
Writer.Free;
|
||
|
ms.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function dbgs(const Desc: TPTMemImgDesc): 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 CreateQVMemImg(const Desc: TPTMemImgDesc; Width, Height: integer
|
||
|
): TFPCustomImage;
|
||
|
var
|
||
|
ImgClass: TPTMemImgBaseClass;
|
||
|
begin
|
||
|
ImgClass:=GeTPTMemImgClass(Desc);
|
||
|
Result:=ImgClass.Create(Width,Height);
|
||
|
end;
|
||
|
|
||
|
function CreateCompatibleQVMemImg(Img: TFPCustomImage; Width, Height: integer
|
||
|
): TFPCustomImage;
|
||
|
begin
|
||
|
if Img is TPTMemImgBase then
|
||
|
Result:=CreateQVMemImg(TPTMemImgBase(Img).Desc,Width,Height)
|
||
|
else
|
||
|
Result:=TPTMemImgRGBA16Bit.create(Width,Height);
|
||
|
//DebugLn(['CreateCompatibleQVMemImg '+Img.ClassName+' '+Result.ClassName]);
|
||
|
end;
|
||
|
|
||
|
function CreateCompatibleQVMemImgWithAlpha(Img: TFPCustomImage; Width,
|
||
|
Height: integer): TFPCustomImage;
|
||
|
var
|
||
|
Desc: TPTMemImgDesc;
|
||
|
begin
|
||
|
if Img is TPTMemImgBase then begin
|
||
|
Desc:=TPTMemImgBase(Img).Desc;
|
||
|
Desc.HasAlpha:=true;
|
||
|
Result:=CreateQVMemImg(Desc,Width,Height)
|
||
|
end else
|
||
|
Result:=TPTMemImgRGBA16Bit.create(Width,Height);
|
||
|
end;
|
||
|
|
||
|
function GetMinimumQVDesc(Img: TFPCustomImage): TPTMemImgDesc;
|
||
|
|
||
|
function Need16Bit(c: word): boolean; inline;
|
||
|
var
|
||
|
l: Byte;
|
||
|
begin
|
||
|
l:=Lo(c);
|
||
|
Result:=(l<>0) and (l<>Hi(c));
|
||
|
end;
|
||
|
|
||
|
var
|
||
|
TestGray: Boolean;
|
||
|
TestAlpha: Boolean;
|
||
|
Test16Bit: Boolean;
|
||
|
BaseImg: TPTMemImgBase;
|
||
|
ImgDesc: TPTMemImgDesc;
|
||
|
y: Integer;
|
||
|
x: Integer;
|
||
|
col: TFPColor;
|
||
|
begin
|
||
|
TestGray:=true;
|
||
|
TestAlpha:=true;
|
||
|
Test16Bit:=true;
|
||
|
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;
|
||
|
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<>alphaOpaque) then begin
|
||
|
TestAlpha:=false;
|
||
|
Result.HasAlpha:=true;
|
||
|
if (not TestGray) and (not Test16Bit) then break;
|
||
|
end;
|
||
|
if TestGray
|
||
|
and ((col.red<>col.green) or (col.red<>col.blue)) then begin
|
||
|
TestGray:=false;
|
||
|
Result.Gray:=false;
|
||
|
if (not TestAlpha) and (not Test16Bit) then break;
|
||
|
end;
|
||
|
if Test16Bit then begin
|
||
|
if Need16Bit(col.red)
|
||
|
or Need16Bit(col.green)
|
||
|
or Need16Bit(col.blue)
|
||
|
or Need16Bit(col.alpha)
|
||
|
then begin
|
||
|
Test16Bit:=false;
|
||
|
Result.Depth:=16;
|
||
|
if (not TestAlpha) and (not TestGray) then break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function GetMinimumQVMemImg(Img: TFPCustomImage; FreeImg: boolean
|
||
|
): TFPCustomImage;
|
||
|
var
|
||
|
Desc: TPTMemImgDesc;
|
||
|
ImgClass: TPTMemImgBaseClass;
|
||
|
y: Integer;
|
||
|
x: Integer;
|
||
|
begin
|
||
|
Desc:=GetMinimumQVDesc(Img);
|
||
|
//debugln(['GetMinimumQVMemImg Depth=',Desc.Depth,' Gray=',Desc.Gray,' HasAlpha=',Desc.HasAlpha]);
|
||
|
ImgClass:=GeTPTMemImgClass(Desc);
|
||
|
if Img.ClassType=ImgClass then
|
||
|
exit(Img);
|
||
|
Result:=CreateQVMemImg(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
|
||
|
result := $FFFF
|
||
|
else if c < 0.0 then
|
||
|
result := 0
|
||
|
else
|
||
|
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;
|
||
|
out Entries: Pointer; out EntrySize: integer; out Support: integer);
|
||
|
// create an array of #NewSize entries. Each entry starts with an integer
|
||
|
// for the StartIndex, followed by #Support singles for the pixel weights.
|
||
|
// The sum of weights for each entry is 1.
|
||
|
var
|
||
|
Entry: Pointer;
|
||
|
|
||
|
procedure SetSupport(NewSupport: integer);
|
||
|
begin
|
||
|
Support:=NewSupport;
|
||
|
EntrySize:=SizeOf(integer)+SizeOf(Single)*Support;
|
||
|
Getmem(Entries,EntrySize*NewSize);
|
||
|
Entry:=Entries;
|
||
|
end;
|
||
|
|
||
|
var
|
||
|
i: Integer;
|
||
|
Factor: double;
|
||
|
StartPos: Double;
|
||
|
StartIndex: Integer;
|
||
|
j: Integer;
|
||
|
FirstValue: Double;
|
||
|
//Sum: double;
|
||
|
begin
|
||
|
if NewSize=OldSize then begin
|
||
|
SetSupport(1);
|
||
|
for i:=0 to NewSize-1 do begin
|
||
|
// 1:1
|
||
|
PInteger(Entry)^:=i;
|
||
|
inc(Entry,SizeOf(Integer));
|
||
|
PSingle(Entry)^:=1.0;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
end;
|
||
|
end else if NewSize<OldSize then begin
|
||
|
// shrink
|
||
|
SetSupport(Max(2,(OldSize+NewSize-1) div NewSize));
|
||
|
Factor:=double(OldSize)/double(NewSize);
|
||
|
for i:=0 to NewSize-1 do begin
|
||
|
StartPos:=Factor*i;
|
||
|
StartIndex:=Floor(StartPos);
|
||
|
PInteger(Entry)^:=StartIndex;
|
||
|
inc(Entry,SizeOf(Integer));
|
||
|
// first pixel
|
||
|
FirstValue:=(1.0-(StartPos-double(StartIndex)));
|
||
|
PSingle(Entry)^:=FirstValue/Factor;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
// middle pixel
|
||
|
for j:=1 to Support-2 do begin
|
||
|
PSingle(Entry)^:=1.0/Factor;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
end;
|
||
|
// last pixel
|
||
|
PSingle(Entry)^:=(Factor-FirstValue-(Support-2))/Factor;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
end;
|
||
|
end else begin
|
||
|
// enlarge
|
||
|
if OldSize=1 then begin
|
||
|
SetSupport(1);
|
||
|
for i:=0 to NewSize-1 do begin
|
||
|
// nothing to interpolate
|
||
|
PInteger(Entry)^:=0;
|
||
|
inc(Entry,SizeOf(Integer));
|
||
|
PSingle(Entry)^:=1.0;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
end;
|
||
|
end else begin
|
||
|
SetSupport(2);
|
||
|
Factor:=double(OldSize-1)/double(NewSize);
|
||
|
for i:=0 to NewSize-1 do begin
|
||
|
StartPos:=Factor*i+Factor/2;
|
||
|
StartIndex:=Floor(StartPos);
|
||
|
PInteger(Entry)^:=StartIndex;
|
||
|
inc(Entry,SizeOf(Integer));
|
||
|
// first pixel
|
||
|
FirstValue:=(1.0-(StartPos-double(StartIndex)));
|
||
|
// convert linear distribution
|
||
|
FirstValue:=Min(1.0,Max(0.0,Filter(FirstValue/MaxSupport)));
|
||
|
PSingle(Entry)^:=FirstValue;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
// last pixel
|
||
|
PSingle(Entry)^:=1.0-FirstValue;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
if Entry<>Entries+EntrySize*NewSize then
|
||
|
raise Exception.Create('TSimpleInterpolation.Execute inconsistency');
|
||
|
|
||
|
{WriteLn('CreatePixelWeights Old=',OldSize,' New=',NewSize,' Support=',Support,' EntrySize=',EntrySize,' Factor=',FloatToStr(Factor));
|
||
|
Entry:=Entries;
|
||
|
for i:=0 to NewSize-1 do begin
|
||
|
StartIndex:=PInteger(Entry)^;
|
||
|
inc(Entry,SizeOf(Integer));
|
||
|
write(i,' Start=',StartIndex);
|
||
|
Sum:=0;
|
||
|
for j:=0 to Support-1 do begin
|
||
|
FirstValue:=PSingle(Entry)^;
|
||
|
inc(Entry,SizeOf(Single));
|
||
|
write(' ',FloatToStr(FirstValue));
|
||
|
Sum:=Sum+FirstValue;
|
||
|
end;
|
||
|
writeln(' Sum=',FloatToStr(Sum));
|
||
|
end;}
|
||
|
end;
|
||
|
|
||
|
procedure TLinearInterpolation.Execute(x, y, w, h: integer);
|
||
|
// paint Image on Canvas at x,y,w*h
|
||
|
var
|
||
|
dy: Integer;
|
||
|
dx: Integer;
|
||
|
HorzResized: PFPColor;
|
||
|
xEntries: Pointer; // size:integer,weight1:single,weight2:single,...
|
||
|
xEntrySize: integer;
|
||
|
xSupport: integer;// how many horizontal pixel are needed to created one new pixel
|
||
|
yEntries: Pointer; // size:integer,weight1:single,weight2:single,...
|
||
|
yEntrySize: integer;
|
||
|
ySupport: integer;// how many vertizontal pixel are needed to created one new pixel
|
||
|
NewSupportLines: LongInt;
|
||
|
yEntry: Pointer;
|
||
|
SrcStartY: LongInt;
|
||
|
LastSrcStartY: LongInt;
|
||
|
sy: Integer;
|
||
|
xEntry: Pointer;
|
||
|
sx: LongInt;
|
||
|
cx: Integer;
|
||
|
f: Single;
|
||
|
NewCol: TFPColor;
|
||
|
Col: TFPColor;
|
||
|
CurEntry: Pointer;
|
||
|
NewRed, NewGreen, NewBlue, NewAlpha: Single;
|
||
|
begin
|
||
|
//WriteLn('TSimpleInterpolation.Execute Src=',image.width,'x',image.Height,' Dest=',x,',',y,',',w,'x',h);
|
||
|
if (w<=0) or (h<=0) or (image.Width=0) or (image.Height=0) then exit;
|
||
|
|
||
|
xEntries:=nil;
|
||
|
yEntries:=nil;
|
||
|
HorzResized:=nil;
|
||
|
try
|
||
|
CreatePixelWeights(image.Width,w,xEntries,xEntrySize,xSupport);
|
||
|
CreatePixelWeights(image.Height,h,yEntries,yEntrySize,ySupport);
|
||
|
//WriteLn('TSimpleInterpolation.Execute xSupport=',xSupport,' ySupport=',ySupport);
|
||
|
// create temporary buffer for the horizontally resized pixel for the current
|
||
|
// y line
|
||
|
GetMem(HorzResized,w*ySupport*SizeOf(TFPColor));
|
||
|
|
||
|
SrcStartY:=0;
|
||
|
for dy:=0 to h-1 do begin
|
||
|
if dy=0 then begin
|
||
|
yEntry:=yEntries;
|
||
|
SrcStartY:=PInteger(yEntry)^;
|
||
|
NewSupportLines:=ySupport;
|
||
|
end else begin
|
||
|
LastSrcStartY:=SrcStartY;
|
||
|
inc(yEntry,yEntrySize);
|
||
|
SrcStartY:=PInteger(yEntry)^;
|
||
|
NewSupportLines:=SrcStartY-LastSrcStartY;
|
||
|
//WriteLn('TSimpleInterpolation.Execute dy=',dy,' SrcStartY=',SrcStartY,' LastSrcStartY=',LastSrcStartY,' NewSupportLines=',NewSupportLines);
|
||
|
// move lines up
|
||
|
if (NewSupportLines>0) and (ySupport>NewSupportLines) then
|
||
|
System.Move(HorzResized[NewSupportLines*w],
|
||
|
HorzResized[0],
|
||
|
(ySupport-NewSupportLines)*w*SizeOf(TFPColor));
|
||
|
end;
|
||
|
|
||
|
// compute new horizontally resized line(s)
|
||
|
for sy:=ySupport-NewSupportLines to ySupport-1 do begin
|
||
|
xEntry:=xEntries;
|
||
|
for dx:=0 to w-1 do begin
|
||
|
sx:=PInteger(xEntry)^;
|
||
|
inc(xEntry,SizeOf(integer));
|
||
|
NewRed:=0.0;
|
||
|
NewGreen:=0.0;
|
||
|
NewBlue:=0.0;
|
||
|
NewAlpha:=0.0;
|
||
|
for cx:=sx to sx+xSupport-1 do begin
|
||
|
f:=PSingle(xEntry)^;
|
||
|
inc(xEntry,SizeOf(Single));
|
||
|
Col:=image.Colors[cx,SrcStartY+sy];
|
||
|
NewRed:=NewRed+Col.red*f;
|
||
|
NewGreen:=NewGreen+Col.green*f;
|
||
|
NewBlue:=NewBlue+Col.blue*f;
|
||
|
NewAlpha:=NewAlpha+Col.alpha*f;
|
||
|
end;
|
||
|
NewCol.red:=Min(round(NewRed),$ffff);
|
||
|
NewCol.green:=Min(round(NewGreen),$ffff);
|
||
|
NewCol.blue:=Min(round(NewBlue),$ffff);
|
||
|
NewCol.alpha:=Min(round(NewAlpha),$ffff);
|
||
|
HorzResized[dx+sy*w]:=NewCol;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// compute new vertically resized line
|
||
|
for dx:=0 to w-1 do begin
|
||
|
CurEntry:=yEntry+SizeOf(integer);
|
||
|
NewRed:=0.0;
|
||
|
NewGreen:=0.0;
|
||
|
NewBlue:=0.0;
|
||
|
NewAlpha:=0.0;
|
||
|
for sy:=0 to ySupport-1 do begin
|
||
|
f:=PSingle(CurEntry)^;
|
||
|
inc(CurEntry,SizeOf(Single));
|
||
|
Col:=HorzResized[dx+sy*w];
|
||
|
NewRed:=NewRed+Col.red*f;
|
||
|
NewGreen:=NewGreen+Col.green*f;
|
||
|
NewBlue:=NewBlue+Col.blue*f;
|
||
|
NewAlpha:=NewAlpha+Col.alpha*f;
|
||
|
end;
|
||
|
NewCol.red:=Min(round(NewRed),$ffff);
|
||
|
NewCol.green:=Min(round(NewGreen),$ffff);
|
||
|
NewCol.blue:=Min(round(NewBlue),$ffff);
|
||
|
NewCol.alpha:=Min(round(NewAlpha),$ffff);
|
||
|
Canvas.Colors[x+dx,y+dy]:=NewCol;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
if xEntries<>nil then FreeMem(xEntries);
|
||
|
if yEntries<>nil then FreeMem(yEntries);
|
||
|
if HorzResized<>nil then FreeMem(HorzResized);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TLinearInterpolation.Filter(x: double): double;
|
||
|
begin
|
||
|
Result:=x;
|
||
|
end;
|
||
|
|
||
|
function TLinearInterpolation.MaxSupport: double;
|
||
|
begin
|
||
|
Result:=1.0;
|
||
|
end;
|
||
|
|
||
|
end.
|
||
|
|