source: trunk/Packages/bgrabitmap/bgrawinbitmap.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 7.3 KB
Line 
1{
2 /**************************************************************************\
3 bgrawinbitmap.pas
4 -----------------
5 This unit should NOT be added to the 'uses' clause.
6 It contains accelerations for Windows. Notably, it
7 provides direct access to bitmap data.
8
9 ****************************************************************************
10 * *
11 * This file is part of BGRABitmap library which is distributed under the *
12 * modified LGPL. *
13 * *
14 * See the file COPYING.modifiedLGPL.txt, included in this distribution, *
15 * for details about the copyright. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
20 * *
21 ****************************************************************************
22}
23
24unit BGRAWinBitmap;
25
26{$mode objfpc}{$H+}
27
28interface
29
30uses
31 Classes, SysUtils, BGRALCLBitmap, Windows, Graphics, GraphType;
32
33type
34 { TBGRAWinBitmap }
35
36 TBGRAWinBitmap = class(TBGRALCLBitmap)
37 private
38 procedure AlphaCorrectionNeeded;
39 protected
40 DIB_SectionHandle: HBITMAP;
41 FReversed: boolean;
42 function DIBitmapInfo(AWidth, AHeight: integer): TBitmapInfo;
43
44 procedure ReallocData; override;
45 procedure FreeData; override;
46
47 procedure RebuildBitmap; override;
48 procedure FreeBitmap; override;
49
50 procedure Init; override;
51 function GetBitmap: TBitmap; override;
52
53 public
54 procedure LoadFromBitmapIfNeeded; override;
55 procedure Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean=True); overload; override;
56 procedure Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean = True); overload; override;
57 procedure DataDrawOpaque(ACanvas: TCanvas; ARect: TRect; AData: Pointer;
58 ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); override;
59 procedure GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer); override;
60 end;
61
62implementation
63
64uses BGRADefaultBitmap, BGRABitmapTypes;
65
66type
67 { TWinBitmapTracker }
68
69 TWinBitmapTracker = class(TBitmap)
70 protected
71 FUser: TBGRAWinBitmap;
72 procedure Changed(Sender: TObject); override;
73 public
74 constructor Create(AUser: TBGRAWinBitmap); overload;
75 end;
76
77procedure TWinBitmapTracker.Changed(Sender: TObject);
78begin
79 if FUser <> nil then
80 FUser.AlphaCorrectionNeeded;
81 inherited Changed(Sender);
82end;
83
84constructor TWinBitmapTracker.Create(AUser: TBGRAWinBitmap);
85begin
86 FUser := AUser;
87 inherited Create;
88end;
89
90{ TBGRAWinBitmap }
91
92procedure TBGRAWinBitmap.FreeData;
93begin
94 if DIB_SectionHandle <> 0 then
95 begin
96 DeleteObject(DIB_SectionHandle);
97 FData := nil;
98 DIB_SectionHandle := 0;
99 end;
100end;
101
102procedure TBGRAWinBitmap.RebuildBitmap;
103begin
104 if FBitmap = nil then
105 begin
106 FBitmap := TWinBitmapTracker.Create(self);
107 FBitmap.Handle := DIB_SectionHandle;
108 end;
109end;
110
111procedure TBGRAWinBitmap.FreeBitmap;
112begin
113 if FBitmap <> nil then
114 begin
115 FBitmap.Handle := 0;
116 FBitmap.Free;
117 FBitmap := nil;
118 end;
119end;
120
121procedure TBGRAWinBitmap.Init;
122begin
123 inherited Init;
124 FLineOrder := riloBottomToTop;
125end;
126
127function TBGRAWinBitmap.GetBitmap: TBitmap;
128begin
129 Result:=inherited GetBitmap;
130 if (LineOrder = riloTopToBottom) and not FReversed then
131 begin
132 VerticalFlip;
133 FReversed:= true;
134 end;
135end;
136
137procedure TBGRAWinBitmap.LoadFromBitmapIfNeeded;
138begin
139 if FReversed then
140 begin
141 FReversed := false;
142 VerticalFlip;
143 end;
144 if FAlphaCorrectionNeeded then
145 begin
146 DoAlphaCorrection;
147 end;
148end;
149
150procedure TBGRAWinBitmap.Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean);
151begin
152 if self = nil then exit;
153 Draw(ACanvas, Classes.Rect(x,y,x+Width,y+Height), Opaque);
154end;
155
156procedure TBGRAWinBitmap.Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean);
157var
158 info: TBITMAPINFO;
159begin
160 if (self = nil) or (Width = 0) or (Height = 0) then exit;
161 if TBGRAPixel_RGBAOrder then SwapRedBlue;
162 if Opaque then
163 begin
164 info := DIBitmapInfo(Width, Height);
165 if LineOrder = riloTopToBottom then
166 StretchDIBits(ACanvas.Handle, Rect.Left, Rect.Bottom, Rect.Right -
167 Rect.Left, Rect.Top - Rect.Bottom,
168 0, 0, Width, Height, Data, info, DIB_RGB_COLORS, SRCCOPY)
169 else
170 StretchDIBits(ACanvas.Handle, Rect.Left, Rect.Top, Rect.Right -
171 Rect.Left, Rect.Bottom - Rect.Top,
172 0, 0, Width, Height, Data, info, DIB_RGB_COLORS, SRCCOPY);
173 end
174 else
175 begin
176 if Empty then exit;
177 if LineOrder = riloTopToBottom then VerticalFlip;
178 LoadFromBitmapIfNeeded;
179 ACanvas.StretchDraw(Rect, Bitmap);
180 if LineOrder = riloTopToBottom then VerticalFlip;
181 end;
182 if TBGRAPixel_RGBAOrder then SwapRedBlue;
183end;
184
185procedure TBGRAWinBitmap.DataDrawOpaque(ACanvas: TCanvas; ARect: TRect;
186 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer);
187var
188 info: TBITMAPINFO;
189 IsFlipped: boolean;
190 Temp: TBGRAPtrBitmap;
191begin
192 Temp := nil;
193 IsFlipped := False;
194 if ALineOrder = riloTopToBottom then
195 begin
196 Temp := TBGRAPtrBitmap.Create(AWidth, AHeight, AData);
197 Temp.VerticalFlip;
198 IsFlipped := True;
199 end;
200 if TBGRAPixel_RGBAOrder then
201 begin
202 if Temp = nil then
203 Temp := TBGRAPtrBitmap.Create(AWidth, AHeight, AData);
204 Temp.SwapRedBlue;
205 end;
206
207 info := DIBitmapInfo(AWidth, AHeight);
208 StretchDIBits(ACanvas.Handle, ARect.Left, ARect.Top, ARect.Right -
209 ARect.Left, ARect.Bottom - ARect.Top,
210 0, 0, AWidth, AHeight, AData, info, DIB_RGB_COLORS, SRCCOPY);
211
212 if Temp <> nil then
213 begin
214 if TBGRAPixel_RGBAOrder then Temp.SwapRedBlue;
215 if IsFlipped then
216 Temp.VerticalFlip;
217 Temp.Free;
218 end;
219end;
220
221procedure TBGRAWinBitmap.AlphaCorrectionNeeded; inline;
222begin
223 FAlphaCorrectionNeeded := True;
224end;
225
226function TBGRAWinBitmap.DIBitmapInfo(AWidth, AHeight: integer): TBitmapInfo;
227begin
228 with {%H-}Result.bmiHeader do
229 begin
230 biSize := sizeof(Result.bmiHeader);
231 biWidth := AWidth;
232 biHeight := AHeight;
233 biPlanes := 1;
234 biBitCount := 32;
235 biCompression := BI_RGB;
236 biSizeImage := 0;
237 biXPelsPerMeter := 0;
238 biYPelsPerMeter := 0;
239 biClrUsed := 0;
240 biClrImportant := 0;
241 end;
242end;
243
244procedure TBGRAWinBitmap.ReallocData;
245var
246 ScreenDC: HDC;
247 info: TBitmapInfo;
248begin
249 FreeData;
250 if (Width <> 0) and (Height <> 0) then
251 begin
252 ScreenDC := GetDC(0);
253 info := DIBitmapInfo(Width, Height);
254 DIB_SectionHandle := CreateDIBSection(ScreenDC, info, DIB_RGB_COLORS, FData, 0, 0);
255
256 if (NbPixels > 0) and (FData = nil) then
257 raise EOutOfMemory.Create('TBGRAWinBitmap.ReallocBitmap: Windows error ' +
258 IntToStr(GetLastError));
259
260 ReleaseDC(0, ScreenDC);
261 end;
262 InvalidateBitmap;
263end;
264
265procedure TBGRAWinBitmap.GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer);
266begin
267 self.Canvas.CopyRect(Classes.rect(0, 0, Width, Height), CanvasSource,
268 Classes.rect(X, Y, X + Width, Y + Height));
269end;
270
271end.
272
Note: See TracBrowser for help on using the repository browser.