PowerPDF, support for images with transparency/alfa channel

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1394 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
jesusr
2010-12-01 21:41:42 +00:00
parent b34489c597
commit 60b1056879
4 changed files with 92 additions and 19 deletions

View File

@ -473,6 +473,7 @@ type
{ TPRImage }
TPRImage = class(TPRItem)
private
FSharedName: string;
procedure SetStretch(Value: boolean);
protected
FPicture: TPicture;
@ -484,6 +485,7 @@ type
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property SharedName: string read FSharedName write FSharedName;
published
property Picture: TPicture read FPicture write SetPicture;
property SharedImage: boolean read FSharedImage write FSharedImage;
@ -2312,14 +2314,16 @@ var
FIdx: integer;
begin
if (FPicture = nil) or (FPicture.Graphic = nil) or
(FPicture.Graphic.Empty) or not (FPicture.Graphic is TBitmap) then
(FPicture.Graphic.Empty) {or not (FPicture.Graphic is TFPImageBitmap)} then
Exit;
FDoc := ACanvas.PdfCanvas.Doc;
if SharedImage then
begin
FXObjectName := Self.Name;
if FXObjectName='' then
FXObjectName := FSharedName;
if FDoc.GetXObject(FXObjectName) = nil then
FDoc.AddXObject(FXObjectName, CreatePdfImage(FPicture.Graphic, 'Pdf-Bitmap'));
FDoc.AddXObject(FXObjectName, CreatePdfImage(FPicture.Graphic, 'Pdf-Bitmap', FDoc.ObjectMgr));
end
else
begin
@ -2334,7 +2338,7 @@ begin
if FIdx >= MAX_IMAGE_NUMBER then
FIdx := 0;
end;
FDoc.AddXObject(FXObjectName, CreatePdfImage(FPicture.Graphic, 'Pdf-Bitmap'));
FDoc.AddXObject(FXObjectName, CreatePdfImage(FPicture.Graphic, 'Pdf-Bitmap', FDoc.ObjectMgr));
end;
with ARect, ACanvas.PdfCanvas do
if FStretch then

View File

@ -346,6 +346,7 @@ type
property Info: TPdfInfo read GetInfo;
property Root: TPdfCatalog read GetRoot;
property OutlineRoot: TPdfOutlineRoot read GetOutlineRoot;
property ObjectMgr: TPdfXRef read FXRef;
property DefaultPageWidth: word read FDefaultPageWidth write FDefaultPageWidth;
property DefaultPageHeight: word read FDefaultPageHeight write FDefaultPageHeight;
property CompressionMethod: TPdfCompressionMethod

View File

@ -53,23 +53,26 @@ uses
type
TPdfImageCreator = class(TPersistent)
public
function CreateImage(AImage: TGraphic): TPdfImage; virtual;
function CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage; virtual;
end;
{ TPdfBitmapImage }
TPdfBitmapImage = class(TPdfImageCreator)
private
function CreateIndexedColorArray(ABitmap: TBitmap): TPdfArray;
function CreateMaskStream(AImage: TFPCustomImage): TPDfImage;
public
function CreateImage(AImage: TGraphic): TPdfImage; override;
function CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage; override;
end;
EPdfInvalidImageFormat = class(Exception);
function CreatePdfImage(AImage: TGraphic; ImageClassName: string): TPdfImage;
function CreatePdfImage(AImage: TGraphic; ImageClassName: string; ObjectMgr: TPdfObjectMgr=nil): TPdfImage;
implementation
function CreatePdfImage(AImage: TGraphic; ImageClassName: string): TPdfImage;
function CreatePdfImage(AImage: TGraphic; ImageClassName: string; ObjectMgr: TPdfObjectMgr=nil): TPdfImage;
var
PdfImageCreator: TPdfImageCreator;
begin
@ -82,14 +85,14 @@ begin
try
if PdfImageCreator = nil then
raise Exception.CreateFmt('AddImage --InvalidImageClassName:%s', [ImageClassName]);
Result := PdfImageCreator.CreateImage(AImage);
Result := PdfImageCreator.CreateImage(AImage, ObjectMgr);
finally
PdfImageCreator.Free;
end;
end;
{ TPdfImageCreator }
function TPdfImageCreator.CreateImage(AImage: TGraphic): TPdfImage;
function TPdfImageCreator.CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage;
begin
result := nil;
end;
@ -161,7 +164,41 @@ begin
end;
end;
function TPdfBitmapImage.CreateImage(AImage: TGraphic): TPdfImage;
function TPdfBitmapImage.CreateMaskStream(AImage: TFPCustomImage): TPDfImage;
var
pb: PByteArray;
y: Integer;
x: Integer;
begin
result := TPdfImage.CreateStream(nil);
with result do
try
with Attributes do
begin
AddItem('Type', TPdfName.CreateName('XObject'));
AddItem('Subtype', TPdfName.CreateName('Image'));
AddItem('Width', TPdfNumber.CreateNumber(aImage.Width));
AddItem('Height', TPdfNumber.CreateNumber(aImage.Height));
AddItem('BitsPerComponent', TPdfNumber.CreateNumber(8));
AddItem('ColorSpace',TPdfName.CreateName('DeviceGray'));
if USE_ZLIB then
PdfArrayByName('Filter').AddItem(TPdfName.CreateName('FlateDecode'));
new(pb);
for y := 0 to AImage.Height - 1 do
begin
for x := 0 to AImage.Width-1 do
pb^[x] := AImage.Pixels[x,y];
Stream.Write(pb^, AImage.Width);
end;
dispose(pb);
end;
finally
end;
end;
function TPdfBitmapImage.CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage;
var
ABitmap: TBitmap;
x, y: integer;
@ -170,14 +207,17 @@ var
{$IFDEF LAZ_POWERPDF}
aIntfImage: TLazIntfImage;
aColor : TFPColor;
Alpha : TFPMemoryImage;
maskimage : TPDFImage;
hasAlpha : boolean;
{$endif}
{$IFDEF USE_CLX}
const
{$IFDEF USE_CLX}
PIXEL_COLOR_SIZE = 4;
{$ELSE}
PIXEL_COLOR_SIZE = 3;
{$ENDIF}
{$ENDIF}
begin
result := TPdfImage.CreateStream(nil);
with result do
try
@ -197,8 +237,6 @@ begin
aIntfImage := TLazIntfImage.Create(0,0);
aIntfImage.LoadFromBitmap(aBitmap.Handle, aBitmap.MaskHandle);
{$ENDIF}
// if bitmap image has less then 8 bit color, set PixelFormat to 8 bit.
if (PixelFormat = pf1bit) or
{$IFNDEF USE_CLX}
@ -257,7 +295,22 @@ begin
Stream.Write(pb[x], 3);
x := x + PIXEL_COLOR_SIZE;
end;
Attributes.AddItem('ColorSpace', TPdfName.CreateName('DeviceRGB'));
end;
{$else}
Alpha := TFPMemoryImage.Create(AImage.Width, AImage.Height);
Alpha.UsePalette := true;
Alpha.Palette.Count := 256;
for x:=0 to $FF do
begin
aColor.Red:=x;
aColor.Red:=(aColor.Red shl 8) + aColor.Red;
aColor.Green:=aColor.Red;
aColor.Blue:=aColor.Red;
Alpha.Palette.Color[x]:=aColor;
end;
HasAlpha := false;
for y := 0 to aintfimage.Height - 1 do
begin
new(pb);
@ -268,11 +321,26 @@ begin
pb[ 1 ] := acolor.green shr 8;
pb[ 2 ] := acolor.blue shr 8;
Stream.write(pb[ 0 ], 3);
b := acolor.alpha shr 8;
Alpha.Pixels[x,y] := b;
if acolor.Alpha<>AlphaOpaque then
HasAlpha := true;
end;
dispose(pb);
{$endif}
Attributes.AddItem('ColorSpace', TPdfName.CreateName('DeviceRGB'));
end;
if HasAlpha then begin
MaskImage := CreateMaskStream(Alpha);
if ObjectMgr<>nil then
ObjectMgr.AddObject(MaskImage);
Attributes.AddItem('SMask', MaskImage);
end;
Alpha.Free;
{$endif}
end;
with Attributes do

View File

@ -35,13 +35,13 @@ type
{ TPdfJpegImage }
TPdfJpegImage = class(TPdfImageCreator)
public
function CreateImage(AImage: TGraphic): TPdfImage; override;
function CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage; override;
end;
implementation
// CreateImage
function TPdfJpegImage.CreateImage(AImage: TGraphic): TPdfImage;
function TPdfJpegImage.CreateImage(AImage: TGraphic; ObjectMgr: TPdfObjectMgr=nil): TPdfImage;
begin
// check whether specified graphic is valid image.
if not (AImage is TJpegImage) then