(* Copyright (c) 1998-2016 by Carlotta Calandra. All rights reserved. Copyright (c) 2011-2016 by Xequte Software. This software comes without express or implied warranty. In no case shall the author be liable for any damage or unwanted behavior of any computer hardware and/or software. Author grants you the right to include the component in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE. ImageEn, IEvolution and ImageEn ActiveX may not be included in any commercial, shareware or freeware libraries or components. www.ImageEn.com *) (* File version 1001 *) unit QRDBImageEn; {$I ie.inc} {$ifdef IEINCLUDEDB} interface uses Windows, Messages, classes, Graphics, Db, dbctrls, ImageEnView, ImageEnio, hyiedefs, DBImageEn, QuickRpt, QRImageEn, ievect, hyieutils, ieview; type TQRDBImageEn = class(TQRPrintable) private FAutoDisplay: Boolean; FDataLink: TFieldDataLink; FPictureLoaded: Boolean; fDataFieldImageFormat: TDataFieldImageFormat; fStreamHeaders: boolean; // attiva/disattiva caricamento header negli streams fCenter: boolean; // centra immagine se pių piccola della client fFit: boolean; fZoom: integer; fViewX: integer; fViewY: integer; fBitmapInfoHeader256: TBitmapInfoHeader256; // usato internamente da PaintTo e DrawTo fHDrawDib: HDRAWDIB; // per disegno su schermo fShadowSize: integer; fShadowType: TIEShadowType; fGammaCorrection: double; fImageBorder: boolean; // per bordo a filo immagine fImageShadow: boolean; // ombra sul bordo dell'immagine (false=ombra sul frame) fPrintObjects: boolean; fAbsolutePath: string; procedure SetAutoDisplay(Value: Boolean); function GetDataField: string; function GetField: TField; procedure SetDataField(const Value: string); procedure FitZoom(bmpww, bmphh, ww, hh: integer); procedure SetDataSource(Value: TDataSource); function GetDataSource: TDataSource; protected procedure Notification(AComponent: TComponent;Operation: TOperation); override; procedure DataChange(Sender: TObject); virtual; function GetDataFieldImageFormat: TDataFieldImageFormat; virtual; procedure LoadPictureEx(ffImageEnIO: TImageEnIO; ffImageEnVect: TImageEnVect); procedure SetAbsolutePath(const v: string); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Paint; override; procedure LoadPicture; virtual; function LoadedFieldImageFormat: TDataFieldImageFormat; virtual; property PictureLoaded: boolean read fPictureLoaded; property Field: TField read GetField; procedure Print(OfsX, OfsY : integer); override; published property AutoDisplay: Boolean read FAutoDisplay write SetAutoDisplay default True; property DataField: string read GetDataField write SetDataField; property DataFieldImageFormat: TDataFieldImageFormat read GetDataFieldImageFormat default ifBitmap; property StreamHeaders: boolean read fStreamHeaders write fStreamHeaders default true; property Fit: boolean read fFit write fFit default true; property Center: boolean read fCenter write fCenter default true; property ShadowSize: integer read fShadowSize write fShadowSize default 8; property DataSource: TDataSource read GetDataSource write SetDataSource; property ShadowType: TIEShadowType read fShadowType write fShadowType default iestSmooth2; property GammaCorrection: double read fGammaCorrection write fGammaCorrection; property ImageBorder: boolean read fImageBorder write fImageBorder default true; property ImageShadow: boolean read fImageShadow write fImageShadow default true; property PrintObjects: boolean read fPrintObjects write fPrintObjects default false; property AbsolutePath: string read fAbsolutePath write SetAbsolutePath; end; {$ifndef IEREGISTERQR} procedure Register; {$endif} implementation uses Math, dbtables, sysutils, imageenproc, iexBitmaps; {$ifndef IEREGISTERQR} procedure Register; begin RegisterComponents('ImageEn', [TQRDBImageEn]); end; {$endif} ///////////////////////////////////////////////////////////////////////////////////// procedure TQrDBImageEn.SetAutoDisplay(Value: Boolean); begin if FAutoDisplay <> Value then begin FAutoDisplay := Value; if Value then LoadPicture; end; end; ///////////////////////////////////////////////////////////////////////////////////// constructor TQRDBImageEn.Create(AOwner: TComponent); begin inherited Create(AOwner); ZeroMemory(@fBitmapInfoHeader256, sizeof(TBitmapInfoHeader256)); fStreamHeaders := true; fDataFieldImageFormat := ifBitmap; FAutoDisplay := True; FDataLink := TFieldDataLink.Create; FDataLink.Control := Self; FDataLink.OnDataChange := DataChange; fZoom := 100; fCenter := True; fFit := True; fViewX := 0; fViewY := 0; fHDrawDib := IEDrawDibOpen; fShadowSize := 8; fShadowType := iestSmooth2; fGammaCorrection := 1; fImageBorder := true; fImageShadow := true; fPrintObjects := false; fAbsolutePath := ''; end; ///////////////////////////////////////////////////////////////////////////////////// destructor TQRDBImageEn.Destroy; begin FDataLink.Free; FDataLink := nil; IEDrawDibClose(fHDrawDib); inherited Destroy; end; ///////////////////////////////////////////////////////////////////////////////////// function TQRDBImageEn.GetDataField: string; begin Result := FDataLink.FieldName; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.SetDataField(const Value: string); begin FDataLink.FieldName := Value; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then DataSource := nil; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.DataChange(Sender: TObject); begin FPictureLoaded := False; if not assigned(fDataLink) then exit; if not assigned(fDataLink.DataSource) then exit; if not assigned(fDataLink.DataSource.DataSet) then exit; if not FDataLink.DataSource.DataSet.Active then exit; if FAutoDisplay then LoadPicture; end; ///////////////////////////////////////////////////////////////////////////////////// // Carica immagine da fdatalink.field senza controllare fPictureLoaded // non assegna fDataFieldImageFormat procedure TQRDBImageEn.LoadPictureEx(ffImageEnIO: TImageEnIO; ffImageEnVect: TImageEnVect); var BlobStream: TStream; ifm: TDataFieldImageFormat; ss: string; begin ffImageEnIO.StreamHeaders := fStreamHeaders or fPrintObjects; if (FDataLink.Field is TBlobField) and ((FDataLink.Field as TBlobField).BlobSize>0) then begin BlobStream := nil; ifm := LoadedFieldImageFormat; try BlobStream := FDataLink.DataSource.DataSet.CreateBlobStream(TBlobField(FDataLink.Field), bmRead); if assigned(ffImageEnIO.Bitmap) then begin case ifm of ifBitmap: ffImageEnIO.LoadFromStreamBMP(BlobStream); ifJpeg: ffImageEnIO.LoadFromStreamJpeg(BlobStream); ifGif: ffImageEnIO.LoadFromStreamGif(BlobStream); ifPCX: ffImageEnIO.LoadFromStreamPCX(BlobStream); ifTIFF: ffImageEnIO.LoadFromStreamTIFF(BlobStream); {$ifdef IEINCLUDEPNG} ifPNG: ffImageEnIO.LoadFromStreamPNG(BlobStream); {$endif} ifTGA: ffImageEnIO.LoadFromStreamTGA(BlobStream); ifPXM: ffImageEnIO.LoadFromStreamPXM(BlobStream); ifICO: ffImageEnIO.LoadFromStreamICO(BlobStream); {$ifdef IEINCLUDEJPEG2000} ifJP2: ffImageEnIO.LoadFromStreamJP2(BlobStream); ifJ2K: ffImageEnIO.LoadFromStreamJ2K(BlobStream); {$endif} ifWBMP: ffImageEnIO.LoadFromStreamWBMP(BlobStream); end; end else ffImageEnIO.ParamsFromStream(BlobStream); if fPrintObjects then begin ffImageEnVect.RemoveAllObjects; ffImageEnVect.LoadFromStreamIEV(BlobStream); end; finally BlobStream.Free; end; end else if (FDataLink.Field is TStringField) then begin ss := TStringField(FDataLink.Field).Value; if (ss<>'') and (fileexists(fAbsolutePath+ss)) then begin ss := fAbsolutePath+ss; ifm := LoadedFieldImageFormat; case ifm of ifBitmap: ffImageEnIO.LoadFromFileBMP(ss); ifJpeg: ffImageEnIO.LoadFromFileJpeg(ss); ifGif: ffImageEnIO.LoadFromFileGif(ss); ifPCX: ffImageEnIO.LoadFromFilePCX(ss); ifTIFF: ffImageEnIO.LoadFromFileTIFF(ss); {$ifdef IEINCLUDEPNG} ifPNG: ffImageEnIO.LoadFromFilePNG(ss); {$endif} ifTGA: ffImageEnIO.LoadFromFileTGA(ss); ifPXM: ffImageEnIO.LoadFromFilePXM(ss); ifICO: ffImageEnIO.LoadFromFileICO(ss); {$ifdef IEINCLUDEJPEG2000} ifJP2: ffImageEnIO.LoadFromFileJP2(ss); ifJ2K: ffImageEnIO.LoadFromFileJ2K(ss); {$endif} ifWBMP: ffImageEnIO.LoadFromFileWBMP(ss); end; if fPrintObjects then begin ffImageEnVect.RemoveAllObjects; if fileexists(ss+'.iev') then ffImageEnVEct.LoadFromFileIEV(ss+'.iev'); end; end; end; end; ///////////////////////////////////////////////////////////////////////////////////// // Carica immagine da field procedure TQRDBImageEn.LoadPicture; begin if (not FPictureLoaded) and (FDataLink.Field is TBlobField) and ((FDataLink.Field as TBlobField).BlobSize>0) then fDataFieldImageFormat := LoadedFieldImageFormat; end; ///////////////////////////////////////////////////////////////////////////////////// // restituisce il formato dell'immagine memorizzata in fDataLink.Field function TQRDBImageEn.LoadedFieldImageFormat: TDataFieldImageFormat; var BlobStream: TStream; ss: string; begin result := ifUnknown; if not FAutoDisplay then exit; if FDataLink.Field is TBlobField then begin BlobStream := nil; try BlobStream := FDataLink.DataSource.DataSet.CreateBlobStream(TBlobField(FDataLink.Field), bmRead); case FindStreamFormat(BlobStream) of ioBMP: result := ifBitmap; ioJPEG: result := ifJpeg; ioGIF: result := ifGIF; ioPCX: result := ifPCX; ioTIFF: result := ifTIFF; {$ifdef IEINCLUDEPNG} ioPNG: result := ifPNG; {$endif} ioTGA: result := ifTGA; ioPXM: result := ifPXM; ioICO: result := ifICO; ioJP2: result := ifJP2; ioJ2K: result := ifJ2K; ioWBMP: result := ifWBMP; end; finally BlobStream.free; end; end else if FDataLink.Field is TStringField then begin ss := TStringField(FDataLink.Field).Value; if (ss<>'') and (fileexists(fAbsolutePath+ss)) then begin case FindFileFormat( fAbsolutePath + ss, ffContentOnly ) of ioBMP: result := ifBitmap; ioJPEG: result := ifJpeg; ioGIF: result := ifGIF; ioPCX: result := ifPCX; ioTIFF: result := ifTIFF; {$ifdef IEINCLUDEPNG} ioPNG: result := ifPNG; {$endif} ioTGA: result := ifTGA; ioPXM: result := ifPXM; ioICO: result := ifICO; ioJP2: result := ifJP2; ioJ2K: result := ifJ2K; ioWBMP: result := ifWBMP; end; end; end; end; ///////////////////////////////////////////////////////////////////////////////////// function TQRDBImageEn.GetDataFieldImageFormat: TDataFieldImageFormat; begin result := fDataFieldImageFormat; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.Paint; begin with Canvas do begin Pen.Color := Frame.Color; Pen.Width := Frame.Width; Pen.Style := Frame.Style; MoveTo(0, 0); LineTo(width, height); MoveTo(0, height); LineTo(width, 0); end; end; ///////////////////////////////////////////////////////////////////////////////////// function TQRDBImageEn.GetField: TField; begin Result := FDataLink.Field; end; ///////////////////////////////////////////////////////////////////////////////////// procedure DoGammaCorrection(Gamma: double; fBitmap: TBitmap); const Inv255 = 1.0 / 255; var i, x, y: Integer; px: PRGB; InvGamma: double; lut: array [0..255] of byte; begin InvGamma := 1.0/Gamma; // Build LUT for i := 0 to 255 do lut[i] := blimit(round(255*Power(i*Inv255, InvGamma))); // for y := 0 to fBitmap.Height-1 do begin px := fBitmap.Scanline[y]; for x := 0 to fBitmap.Width-1 do begin with px^ do begin r := lut[r]; g := lut[g]; b := lut[b]; end; inc(px); end; end; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.Print(OfsX, OfsY : integer); var fImageEnIO: TImageEnIO; fBitmap: TBitmap; fImageEnVect: TImageEnVect; CalcLeft, CalcTop, CalcRight, CalcBottom : integer; fOffX, fOffY: integer; // inizio visualizzazione (solo per imm. centrate) fExtX, fExtY: integer; // estensione visualizzazione fZZWW, fZZHH: integer; // dimensioni bitmap zoommata ww, hh: integer; // width & height o1x, o1y, o2x, o2y: integer; rr: double; begin if assigned(fDataLink.DataSource) and FDataLink.DataSource.DataSet.Active then begin fImageEnVect := TImageEnVect.Create(self); fImageEnVect.Parent := self; fBitmap := fImageEnVect.Bitmap; fImageEnIO := TImageEnIO.Create(self); fImageEnIO.AttachedBitmap := fBitmap; LoadPictureEx(fImageEnIO, fImageEnVect); if fPrintObjects then begin fImageEnVect.Update; fImageEnVect.CopyObjectsToBack(true); end; if (fBitmap.Width>0) and (fBitmap.Height>0) then begin if fGammaCorrection<>1 then DoGammaCorrection(fGammaCorrection, fBitmap); with ParentReport.QRPrinter do begin CalcLeft := XPos(OfsX + Size.Left)+1; if Frame.DrawLeft then inc(CalcLeft, Frame.Width); CalcTop := YPos(OfsY + Size.Top)+1; if Frame.DrawTop then inc(CalcTop, Frame.Width); CalcRight := XPos(OfsX + Size.Left + Size.Width)-1; if Frame.DrawRight then dec(CalcRight, Frame.Width); CalcBottom := YPos(OfsY + Size.Top + Size.Height)-1; if Frame.DrawBottom then dec(CalcBottom, Frame.Width); ww := CalcRight-CalcLeft+1; hh := CalcBottom-CalcTop+1; // if fFit then FitZoom(fBitmap.Width, fBitmap.Height, ww, hh) else fZoom := 100; fZZWW := round(fzoom*(fbitmap.width/100)); // nuova width della bitmap fZZHH := round(fzoom*(fbitmap.height/100)); // nuova height della bitmap fOffX := 0; fOffY := 0; fExtX := imin(fZZWW, ww); // width destinazione bitmap fExtY := imin(fZZHH, hh); // height destinazione bitmap if fCenter then begin // centra immagine if fExtx0 then begin rr := fbitmap.width/fZZWW; o1x := round(fViewX*rr); o2x := round(fExtx*rr); if (o1x+o2x)>fBitmap.Width then dec(o2x); end; if fZZHH<>0 then begin rr := fbitmap.height/fZZHH; o1y := round(fViewY*rr); o2y := round(fExty*rr); if (o1y+o2y)>fBitmap.Height then dec(o2y); end; with fBitmapInfoHeader256 do begin biSize := sizeof(TBitmapInfoHeader); biWidth := fbitmap.width; biHeight := fbitmap.height; biPlanes := 1; if fbitmap.pixelformat=pf1bit then begin biBitCount := 1; // assegna colori bianco e nero (la Palette[0] č tutta zero...) Palette[1].rgbRed := 255; Palette[1].rgbGreen := 255; Palette[1].rgbBlue := 255; end else biBitCount := 24; biCompression := BI_RGB; end; inc(fOffX, CalcLeft); inc(fOffY, CalcTop); IEDrawDibDraw(fHDrawDib, canvas.handle, fOffX, fOffY, fExtx, fExty, PBitmapInfoHeader(@fBitmapInfoHeader256)^, fbitmap.ScanLine[fbitmap.height-1], o1x, o1y, o2x, o2y, 0); end; with Canvas do begin Pen.Color := Frame.Color; Pen.Width := Frame.Width; Pen.Style := Frame.Style; // shadow if fImageShadow then begin // ombra sull'immagine IERightShadow(Canvas, nil, fOffX+fExtx, fOffY, fOffX+fExtx+fShadowSize+2, fOffY+fExty+fShadowSize, fShadowType, clWhite); IEBottomShadow(Canvas, nil, fOffX, fOffY+fExty, fOffX+fExtx+fShadowSize, fOffY+fExty+fShadowSize+1, fShadowType, clWhite); end else begin // ombra sul frame IERightShadow(Canvas, nil, CalcRight+2, CalcTop, CalcRight+2+fShadowSize, CalcBottom+fShadowSize, fShadowType, clWhite); IEBottomShadow(Canvas, nil, CalcLeft, CalcBottom+1, CalcRight+fShadowSize, CalcBottom+1+fShadowSize, fShadowType, clWhite); end; if fImageBorder then begin // bordo sull'immagine moveto(fOffX, fOffY); lineto(fOffX+fExtx-1, fOffY); lineto(fOffX+fExtx-1, fOffY+fExty-1); lineto(fOffX, fOffY+fExty-1); lineto(fOffX, fOffY); end; end; end; fImageEnIO.free; fImageEnVect.free; end; if (not fImageBorder) and (not fImageShadow) then inherited; end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.FitZoom(bmpww, bmphh, ww, hh: integer); begin if (bmpww<>0) and (bmphh<>0) then fZoom := imin( trunc(ww/(bmpww/100)), trunc(hh/(bmphh/100)) ); end; ///////////////////////////////////////////////////////////////////////////////////// procedure TQRDBImageEn.SetDataSource(Value: TDataSource); begin FDataLink.DataSource := Value; if Value <> nil then Value.FreeNotification(Self); end; ///////////////////////////////////////////////////////////////////////////////////// function TQRDBImageEn.GetDataSource: TDataSource; begin Result := FDataLink.DataSource; end; procedure TQRDBImageEn.SetAbsolutePath(const v: string); begin fAbsolutePath := v; FPictureLoaded := false; LoadPicture; end; {$else} interface implementation {$endif} end.