From 6adaa12975c261c0ecba092086006f82400eed09 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 15 Mar 2016 14:04:06 +0000 Subject: [PATCH] fpspreadsheet: Add stream variant of TsWorksheet.WriteImage. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4557 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/fpsimages.pas | 102 ++++++++++++------- components/fpspreadsheet/fpsopendocument.pas | 20 ++-- components/fpspreadsheet/fpspreadsheet.pas | 97 ++++++++++++++---- components/fpspreadsheet/fpsstrings.pas | 1 + components/fpspreadsheet/fpsutils.pas | 10 ++ components/fpspreadsheet/xlsxooxml.pas | 50 +++++---- 6 files changed, 194 insertions(+), 86 deletions(-) diff --git a/components/fpspreadsheet/fpsimages.pas b/components/fpspreadsheet/fpsimages.pas index 4c36c4872..93f8ea0b9 100644 --- a/components/fpspreadsheet/fpsimages.pas +++ b/components/fpspreadsheet/fpsimages.pas @@ -14,32 +14,45 @@ type TsImageType = integer; const + {@@ Identifier for unknown image type } itUnknown = -1; var + {@@ Identifier for the PNG image type (value 0) } itPNG: TsImageType; + {@@ Identifier for the JPEG image type (value 1) } itJPEG: TsImageType; + {@@ Identifier for the TIFF image type (value 2) } itTIFF: TsImageType; + {@@ Identifier for the BMP image type (value 3) } itBMP: TsImageType; + {@@ Identifier for the GIF image type (value 4) } itGIF: TsImageType; + {@@ Identifier for the SVG image type (value 5) } itSVG: TsImageType; + {@@ Identifier for the WMF image type (value 6) } itWMF: TsImageType; + {@@ Identifier for the EMF image type (value 7) } itEMF: TsImageType; + {@@ Identifier for the PCX image type (value 8) } itPCX: TsImageType; type { TsEmbeddedObj } TsEmbeddedObj = class private + FFileName: String; FStream: TMemoryStream; - FName: String; FImageType: TsImageType; // image type, see itXXXX FWidth: Double; // image width, in mm FHeight: Double; // image height, in mm + protected + function CheckStream(AImageType: TsImageType): Boolean; public - constructor Create(AName: String); destructor Destroy; override; - property Name: String read FName; + function LoadFromFile(const AFileName: String): Boolean; + function LoadFromStream(AStream: TStream): Boolean; + property FileName: String read FFileName; property ImageType: TsImagetype read FImageType; property ImageWidth: Double read FWidth; property ImageHeight: Double read FHeight; @@ -522,6 +535,9 @@ begin end; end; end; + if not done then + exit; + sW := Extract('width', s); sH := Extract('height', s); sVB := Extract('viewBox', s); @@ -724,15 +740,16 @@ function GetImageInfo(AStream: TStream; out AWidth, AHeight: DWord; var itr: TImageTypeRecord; // [i]mage [t]ype [r]ecord begin - AStream.Position := 0; if InRange(AImageType, 0, High(ImageTypeRegistry)) then begin + AStream.Position := 0; if ImageTypeRegistry[AImageType].GetImageSize(AStream, AWidth, AHeight, dpiX, dpiY) then Result := AImageType; end else begin for Result := 0 to High(ImageTypeRegistry) do begin + AStream.Position := 0; itr := ImageTypeRegistry[Result]; if itr.GetImageSize(AStream, AWidth, AHeight, dpiX, dpiY) then exit; @@ -835,45 +852,62 @@ end; { TsEmbeddedObj } {==============================================================================} -constructor TsEmbeddedObj.Create(AName: String); -var - w, h: Double; -begin - inherited Create; - FName := AName; - - FStream := TMemoryStream.Create; - FStream.LoadFromFile(AName); - FImageType := GetImageInfo(FStream, w, h, GetImageTypefromFileName(AName)); - if FImageType <> itUnknown then - begin - FWidth := inToMM(w); - FHeight := inToMM(h); - end else - begin - FreeAndNil(FStream); - abort; - end; -end; - destructor TsEmbeddedObj.Destroy; begin FreeAndNil(FStream); inherited Destroy; end; +function TsEmbeddedObj.CheckStream(AImageType: TsImageType): Boolean; +var + w, h: Double; +begin + FImageType := GetImageInfo(FStream, w, h, AImageType); + if FImageType <> itUnknown then + begin + FWidth := inToMM(w); + FHeight := inToMM(h); + Result := true; + end else + Result := false; +end; + +function TsEmbeddedObj.LoadFromFile(const AFileName: String): Boolean; +var + s: TStream; +begin + FreeAndNil(FStream); + FStream := TMemoryStream.Create; + s := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyNone); + try + FStream.LoadFromStream(s); + Result := CheckStream(GetImageTypeFromFileName(AFileName)); + if Result then FFileName := AFileName; + finally + s.Free; + end; +end; + +function TsEmbeddedObj.LoadFromStream(AStream: TStream): Boolean; +begin + FreeAndNil(FStream); + FStream := TMemoryStream.Create; + FStream.CopyFrom(AStream, AStream.Size); + Result := CheckStream(itUnknown); +end; + initialization - itPNG := RegisterImageType('image/png', 'png', @GetPNGSize); - itJPEG := RegisterImageType('image/jpeg', 'jpg|jpeg|jfif|jfe', @GetJPGSize); - itTIFF := RegisterImageType('image/tiff', 'tif|tiff', @GetTIFSize); - itBMP := RegisterImageType('image/bmp', 'bmp', @GetBMPSize); - itGIF := RegisterImageType('image/gif', 'gif', @GetGIFSize); - itSVG := RegisterImageType('image/svg+xml', 'svg', @GetSVGSize); - itWMF := RegisterImageType('application/x-msmetafile', 'wmf', @GetWMFSize); - itEMF := RegisterImageType('image/x-emf', 'emf', @GetEMFSize); - itPCX := RegisterImageType('image/pcx', 'pcx', @GetPCXSize); +{0} itPNG := RegisterImageType('image/png', 'png', @GetPNGSize); +{1} itJPEG := RegisterImageType('image/jpeg', 'jpg|jpeg|jfif|jfe', @GetJPGSize); +{2} itTIFF := RegisterImageType('image/tiff', 'tif|tiff', @GetTIFSize); +{3} itBMP := RegisterImageType('image/bmp', 'bmp', @GetBMPSize); +{4} itGIF := RegisterImageType('image/gif', 'gif', @GetGIFSize); +{5} itSVG := RegisterImageType('image/svg+xml', 'svg', @GetSVGSize); +{6} itWMF := RegisterImageType('application/x-msmetafile', 'wmf', @GetWMFSize); +{7} itEMF := RegisterImageType('image/x-emf', 'emf', @GetEMFSize); +{8} itPCX := RegisterImageType('image/pcx', 'pcx', @GetPCXSize); end. diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index 857d53b4f..8d3cf51d7 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -6000,6 +6000,7 @@ procedure TsSpreadOpenDocWriter.WriteShapes(AStream: TStream; var i: Integer; img: TsImage; + imgType: TsImageType; r1,c1,r2,c2: Cardinal; roffs1,coffs1, roffs2, coffs2: Double; x, y, w, h: Double; @@ -6013,14 +6014,15 @@ begin for i:=0 to ASheet.GetImageCount-1 do begin img := ASheet.GetImage(i); - if not ASheet.CalcImageExtent(i, - r1, c1, r2, c2, - roffs1, coffs1, roffs2, coffs2, // mm - x, y, w, h) // mm - then begin - FWorkbook.AddErrorMsg('Failure reading image "%s"', [FWorkbook.GetEmbeddedObj(img.Index).Name]); - continue; - end; + imgType := FWorkbook.GetEmbeddedObj(img.Index).ImageType; + if imgType = itUnknown then + Continue; + + ASheet.CalcImageExtent(i, + r1, c1, r2, c2, + roffs1, coffs1, roffs2, coffs2, // mm + x, y, w, h); // mm + AppendToStream(AStream, Format( ''); AppendToStream(FSDrawings[FCurSheetNum], Format( @@ -3334,7 +3337,7 @@ begin ''+ '' + '', [ - i+2, i+1, ExtractFilename(Workbook.GetEmbeddedObj(img.Index).Name), + i+2, i+1, descr, i+1, mmToEMU(x), mmToEMU(y), mmToEMU(w), mmToEMU(h) @@ -3565,7 +3568,8 @@ procedure TsSpreadOOXMLWriter.WriteVMLDrawings_HeaderFooterImages( FWorkbook.AddErrorMsg(rsIncorrectPositionOfImageInHeaderFooter, [AName]); exit; end; - fn := ChangeFileExt(Workbook.GetEmbeddedObj(AImage.Index).Name, ''); + fn := ChangeFileExt(Workbook.GetEmbeddedObj(AImage.Index).FileName, ''); + if fn = '' then fn := 'image'; AppendToStream(AStream, Format( ' ' + LineEnding, [ - rId, // Id="rID1" - imgIdx + 1, ExtractFileExt(imgName) // Target="../media/image1.png" + rId, // Id="rID1" + img.Index + 1, ext // Target="../media/image1.png" ])); inc(rId); end; @@ -3721,15 +3726,16 @@ begin img := AWorksheet.PageLayout.FooterImages[sec]; if img.Index = -1 then continue; - imgName := FWorkbook.GetEmbeddedObj(img.Index).Name; - imgIdx := img.Index; +// imgName := FWorkbook.GetEmbeddedObj(img.Index).Name; +// imgIdx := img.Index; // imgIdx := FWorkbook.FindEmbeddedObj(imgName); + ext := GetImageTypeExt(FWorkbook.GetEmbeddedObj(img.Index).Imagetype); AppendToStream(FSVmlDrawingsRels[fileIndex], Format( - ' ', [ rId, - imgIdx + 1, ExtractFileExt(imgName) + img.Index + 1, ext ])); inc(rId); end;