source: trunk/Packages/DpiControls/NativePixelPointer.pas@ 523

Last change on this file since 523 was 506, checked in by chronos, 16 months ago
File size: 12.3 KB
Line 
1unit NativePixelPointer;
2
3interface
4
5uses
6 Math, Classes, SysUtils, Graphics;
7
8type
9 TColor32 = type Cardinal;
10 TColor32Component = (ccBlue, ccGreen, ccRed, ccAlpha);
11 TColor32Planes = array[0..3] of Byte;
12
13 { TPixel32 }
14
15 TPixel32 = packed record
16 private
17 procedure SetRGB(AValue: Cardinal); inline;
18 function GetRGB: Cardinal; inline;
19 public
20 property RGB: Cardinal read GetRGB write SetRGB;
21 case Integer of
22 0: (B, G, R, A: Byte);
23 1: (ARGB: TColor32);
24 2: (Planes: TColor32Planes);
25 3: (Components: array[TColor32Component] of Byte);
26 end;
27 PPixel32 = ^TPixel32;
28
29 { TPixelPointer }
30
31 TPixelPointer = record
32 private
33 function GetPixelARGB: TColor32; inline;
34 function GetPixelB: Byte; inline;
35 function GetPixelG: Byte; inline;
36 function GetPixelPlane(Index: Byte): Byte;
37 function GetPixelR: Byte; inline;
38 function GetPixelA: Byte; inline;
39 function GetPixelPlanes: TColor32Planes;
40 function GetPixelRGB: Cardinal;
41 procedure SetPixelARGB(Value: TColor32); inline;
42 procedure SetPixelB(Value: Byte); inline;
43 procedure SetPixelG(Value: Byte); inline;
44 procedure SetPixelPlane(Index: Byte; AValue: Byte);
45 procedure SetPixelR(Value: Byte); inline;
46 procedure SetPixelA(Value: Byte); inline;
47 procedure SetPixelRGB(Value: Cardinal);
48 public
49 Base: PPixel32;
50 Pixel: PPixel32;
51 Line: PPixel32;
52 RelLine: PPixel32;
53 BytesPerPixel: Integer;
54 BytesPerLine: Integer;
55 Data: PPixel32;
56 Width: Integer;
57 Height: Integer;
58 procedure NextLine; inline; // Move pointer to start of next line
59 procedure PreviousLine; inline; // Move pointer to start of previous line
60 procedure NextPixel; inline; // Move pointer to next pixel
61 procedure PreviousPixel; inline; // Move pointer to previous pixel
62 procedure SetXY(X, Y: Integer); inline; // Set pixel position relative to base
63 procedure SetX(X: Integer); inline; // Set horizontal pixel position relative to base
64 procedure CheckRange; inline; // Check if current pixel position is not out of range
65 class function Create(Bitmap: TRasterImage; BaseX: Integer = 0; BaseY: Integer = 0): TPixelPointer; static;
66 property PixelARGB: TColor32 read GetPixelARGB write SetPixelARGB;
67 property PixelRGB: Cardinal read GetPixelRGB write SetPixelRGB;
68 property PixelB: Byte read GetPixelB write SetPixelB;
69 property PixelG: Byte read GetPixelG write SetPixelG;
70 property PixelR: Byte read GetPixelR write SetPixelR;
71 property PixelA: Byte read GetPixelA write SetPixelA;
72 property PixelPlane[Index: Byte]: Byte read GetPixelPlane write SetPixelPlane;
73 end;
74 PPixelPointer = ^TPixelPointer;
75
76 function SwapRedBlue(Color: TColor32): TColor32;
77 procedure BitmapCopyRect(DstBitmap: TRasterImage; DstRect: TRect; SrcBitmap: TRasterImage; SrcPos: TPoint);
78 procedure BitmapStretchRect(DstBitmap: TRasterImage; DstRect: TRect;
79 SrcBitmap: TRasterImage; SrcRect: TRect);
80 procedure BitmapFill(Bitmap: TRasterImage; Color: TColor32);
81 procedure BitmapFillRect(Bitmap: TRasterImage; Color: TColor32; Rect: TRect);
82 procedure BitmapSwapRedBlue(Bitmap:TRasterImage);
83 procedure BitmapInvert(Bitmap: TRasterImage);
84 procedure BitmapBlendColor(Bitmap: TRasterImage; Color: TColor32);
85 function Color32(A, R, G, B: Byte): TColor32;
86 function Color32ToPixel32(Color: TColor32): TPixel32;
87 function Pixel32ToColor32(Color: TPixel32): TColor32;
88 function Color32ToColor(Color: TColor32): TColor;
89 function ColorToColor32(Color: TColor): TColor32;
90
91
92implementation
93
94resourcestring
95 SOutOfRange = 'Pixel pointer out of range [X: %d. Y: %d]';
96 SWrongBitmapSize = 'Wrong bitmap size [width: %d, height: %d]';
97
98{ TPixel32 }
99
100function TPixel32.GetRGB: Cardinal;
101begin
102 Result := ARGB and $ffffff;
103end;
104
105procedure TPixel32.SetRGB(AValue: Cardinal);
106begin
107 R := (AValue shr 16) and $ff;
108 G := (AValue shr 8) and $ff;
109 B := (AValue shr 0) and $ff;
110end;
111
112{ TPixelPointer }
113
114procedure TPixelPointer.NextLine; inline;
115begin
116 Line := Pointer(Line) + BytesPerLine;
117 Pixel := Line;
118end;
119
120procedure TPixelPointer.PreviousLine;
121begin
122 Line := Pointer(Line) - BytesPerLine;
123 Pixel := Line;
124end;
125
126procedure TPixelPointer.NextPixel; inline;
127begin
128 Pixel := Pointer(Pixel) + BytesPerPixel;
129end;
130
131procedure TPixelPointer.PreviousPixel;
132begin
133 Pixel := Pointer(Pixel) - BytesPerPixel;
134end;
135
136procedure TPixelPointer.SetXY(X, Y: Integer); inline;
137begin
138 Line := Pointer(Base) + Y * BytesPerLine;
139 SetX(X);
140end;
141
142procedure TPixelPointer.SetX(X: Integer); inline;
143begin
144 Pixel := Pointer(Line) + X * BytesPerPixel;
145end;
146
147procedure TPixelPointer.CheckRange;
148{$IFOPT R+}
149var
150 X: Integer;
151 Y: Integer;
152{$ENDIF}
153begin
154 {$IFOPT R+}
155 if (PByte(Pixel) < PByte(Data)) or
156 (PByte(Pixel) >= PByte(Data) + Height * BytesPerLine) then begin
157 X := PByte(Pixel) - PByte(Data);
158 Y := Floor(X / BytesPerLine);
159 X := X - Y * BytesPerLine;
160 X := Floor(X / BytesPerPixel);
161 raise Exception.Create(Format(SOutOfRange, [X, Y]));
162 end;
163 {$ENDIF}
164end;
165
166function TPixelPointer.GetPixelPlanes: TColor32Planes;
167begin
168 CheckRange;
169 Result := Pixel^.Planes;
170end;
171
172function TPixelPointer.GetPixelRGB: Cardinal;
173begin
174 CheckRange;
175 Result := Pixel^.RGB;
176end;
177
178procedure TPixelPointer.SetPixelARGB(Value: TColor32);
179begin
180 CheckRange;
181 Pixel^.ARGB := Value;
182end;
183
184procedure TPixelPointer.SetPixelB(Value: Byte);
185begin
186 CheckRange;
187 Pixel^.B := Value;
188end;
189
190procedure TPixelPointer.SetPixelG(Value: Byte);
191begin
192 CheckRange;
193 Pixel^.G := Value;
194end;
195
196procedure TPixelPointer.SetPixelPlane(Index: Byte; AValue: Byte);
197begin
198 CheckRange;
199 Pixel^.Planes[Index] := AValue;
200end;
201
202procedure TPixelPointer.SetPixelR(Value: Byte);
203begin
204 CheckRange;
205 Pixel^.R := Value;
206end;
207
208procedure TPixelPointer.SetPixelA(Value: Byte);
209begin
210 CheckRange;
211 Pixel^.A := Value;
212end;
213
214function TPixelPointer.GetPixelARGB: TColor32;
215begin
216 CheckRange;
217 Result := Pixel^.ARGB;
218end;
219
220function TPixelPointer.GetPixelB: Byte;
221begin
222 CheckRange;
223 Result := Pixel^.B;
224end;
225
226function TPixelPointer.GetPixelG: Byte;
227begin
228 CheckRange;
229 Result := Pixel^.G;
230end;
231
232function TPixelPointer.GetPixelPlane(Index: Byte): Byte;
233begin
234 CheckRange;
235 Result := Pixel^.Planes[Index];
236end;
237
238function TPixelPointer.GetPixelR: Byte;
239begin
240 CheckRange;
241 Result := Pixel^.R;
242end;
243
244function TPixelPointer.GetPixelA: Byte;
245begin
246 CheckRange;
247 Result := Pixel^.A;
248end;
249
250procedure TPixelPointer.SetPixelRGB(Value: Cardinal);
251begin
252 CheckRange;
253 Pixel^.RGB := Value;
254end;
255
256procedure BitmapCopyRect(DstBitmap: TRasterImage; DstRect: TRect;
257 SrcBitmap: TRasterImage; SrcPos: TPoint);
258var
259 SrcPtr, DstPtr: TPixelPointer;
260 X, Y: Integer;
261begin
262 SrcBitmap.BeginUpdate(True);
263 DstBitmap.BeginUpdate(True);
264 SrcPtr := TPixelPointer.Create(SrcBitmap, SrcPos.X, SrcPos.Y);
265 DstPtr := TPixelPointer.Create(DstBitmap, DstRect.Left, DstRect.Top);
266 for Y := 0 to DstRect.Height - 1 do begin
267 for X := 0 to DstRect.Width - 1 do begin
268 DstPtr.PixelARGB := SrcPtr.PixelARGB;
269 SrcPtr.NextPixel;
270 DstPtr.NextPixel;
271 end;
272 SrcPtr.NextLine;
273 DstPtr.NextLine;
274 end;
275 SrcBitmap.EndUpdate;
276 DstBitmap.EndUpdate;
277end;
278
279procedure BitmapStretchRect(DstBitmap: TRasterImage; DstRect: TRect;
280 SrcBitmap: TRasterImage; SrcRect: TRect);
281var
282 SrcPtr, DstPtr: TPixelPointer;
283 X, Y: Integer;
284 XX, YY: Integer;
285 R: TRect;
286 C: TColor32;
287begin
288 if (DstRect.Width = SrcRect.Width) and (DstRect.Height = SrcRect.Height) then begin
289 BitmapCopyRect(DstBitmap, DstRect, SrcBitmap, Point(SrcRect.Left, SrcRect.Top));
290 Exit;
291 end;
292 SrcBitmap.BeginUpdate(True);
293 DstBitmap.BeginUpdate(True);
294 SrcPtr := TPixelPointer.Create(SrcBitmap, SrcRect.Left, SrcRect.Top);
295 DstPtr := TPixelPointer.Create(DstBitmap, DstRect.Left, DstRect.Top);
296 for Y := 0 to DstRect.Height - 1 do begin
297 for X := 0 to DstRect.Width - 1 do begin
298 R := Rect(Trunc(X * SrcRect.Width / DstRect.Width),
299 Trunc(Y * SrcRect.Height / DstRect.Height),
300 Trunc((X + 1) * SrcRect.Width / DstRect.Width),
301 Trunc((Y + 1) * SrcRect.Height / DstRect.Height));
302 DstPtr.SetXY(X, Y);
303 SrcPtr.SetXY(R.Left, R.Top);
304 C := SrcPtr.PixelARGB;
305 DstPtr.PixelARGB := C;
306 for YY := 0 to R.Height - 1 do begin
307 for XX := 0 to R.Width - 1 do begin
308 DstPtr.PixelARGB := C;
309 DstPtr.NextPixel;
310 end;
311 DstPtr.NextLine;
312 end;
313 end;
314 end;
315 SrcBitmap.EndUpdate;
316 DstBitmap.EndUpdate;
317end;
318
319procedure BitmapFill(Bitmap: TRasterImage; Color: TColor32);
320var
321 X, Y: Integer;
322 Ptr: TPixelPointer;
323begin
324 Bitmap.BeginUpdate(True);
325 Ptr := TPixelPointer.Create(Bitmap);
326 for Y := 0 to Bitmap.Height - 1 do begin
327 for X := 0 to Bitmap.Width - 1 do begin
328 Ptr.PixelARGB := Color;
329 Ptr.NextPixel;
330 end;
331 Ptr.NextLine;
332 end;
333 Bitmap.EndUpdate;
334end;
335
336procedure BitmapFillRect(Bitmap: TRasterImage; Color: TColor32; Rect: TRect);
337var
338 X, Y: Integer;
339 Ptr: TPixelPointer;
340begin
341 Bitmap.BeginUpdate(True);
342 Ptr := TPixelPointer.Create(Bitmap, Rect.Left, Rect.Top);
343 for Y := 0 to Rect.Height - 1 do begin
344 for X := 0 to Rect.Width - 1 do begin
345 Ptr.PixelARGB := Color;
346 Ptr.NextPixel;
347 end;
348 Ptr.NextLine;
349 end;
350 Bitmap.EndUpdate;
351end;
352
353procedure BitmapSwapRedBlue(Bitmap: TRasterImage);
354var
355 X, Y: Integer;
356 Ptr: TPixelPointer;
357begin
358 Bitmap.BeginUpdate(True);
359 Ptr := TPixelPointer.Create(Bitmap);
360 for Y := 0 to Bitmap.Height - 1 do begin
361 for X := 0 to Bitmap.Width - 1 do begin
362 Ptr.PixelARGB := SwapRedBlue(Ptr.PixelARGB);
363 Ptr.NextPixel;
364 end;
365 Ptr.NextLine;
366 end;
367 Bitmap.EndUpdate;
368end;
369
370procedure BitmapInvert(Bitmap: TRasterImage);
371var
372 X, Y: Integer;
373 Ptr: TPixelPointer;
374begin
375 Bitmap.BeginUpdate(True);
376 Ptr := TPixelPointer.Create(Bitmap);
377 for Y := 0 to Bitmap.Height - 1 do begin
378 for X := 0 to Bitmap.Width - 1 do begin
379 Ptr.PixelARGB := Ptr.PixelARGB xor $ffffff;
380 Ptr.NextPixel;
381 end;
382 Ptr.NextLine;
383 end;
384 Bitmap.EndUpdate;
385end;
386
387procedure BitmapBlendColor(Bitmap: TRasterImage; Color: TColor32);
388var
389 X, Y: Integer;
390 Ptr: TPixelPointer;
391 A, R, G, B: Word;
392 Pixel: TPixel32;
393begin
394 Pixel := Color32ToPixel32(Color);
395 Bitmap.BeginUpdate(True);
396 Ptr := TPixelPointer.Create(Bitmap);
397 for Y := 0 to Bitmap.Height - 1 do begin
398 for X := 0 to Bitmap.Width - 1 do begin
399 A := Ptr.PixelA; //(Ptr.PixelA + Pixel.A) shr 1;
400 R := (Ptr.PixelR + Pixel.R) shr 1;
401 G := (Ptr.PixelG + Pixel.G) shr 1;
402 B := (Ptr.PixelB + Pixel.B) shr 1;
403 Ptr.PixelARGB := Color32(A, R, G, B);
404 Ptr.NextPixel;
405 end;
406 Ptr.NextLine;
407 end;
408 Bitmap.EndUpdate;
409end;
410
411function Color32(A, R, G, B: Byte): TColor32;
412begin
413 Result := ((A and $ff) shl 24) or ((R and $ff) shl 16) or
414 ((G and $ff) shl 8) or ((B and $ff) shl 0);
415end;
416
417function Color32ToPixel32(Color: TColor32): TPixel32;
418begin
419 Result.ARGB := Color;
420end;
421
422function Pixel32ToColor32(Color: TPixel32): TColor32;
423begin
424 Result := Color.ARGB;
425end;
426
427function Color32ToColor(Color: TColor32): TColor;
428begin
429 Result := ((Color shr 16) and $ff) or (Color and $00ff00) or
430 ((Color and $ff) shl 16);
431end;
432
433function ColorToColor32(Color: TColor): TColor32;
434begin
435 Result := $ff000000 or ((Color shr 16) and $ff) or (Color and $00ff00) or
436 ((Color and $ff) shl 16);
437end;
438
439class function TPixelPointer.Create(Bitmap: TRasterImage; BaseX: Integer;
440 BaseY: Integer): TPixelPointer;
441begin
442 Result.Width := Bitmap.Width;
443 Result.Height := Bitmap.Height;
444 if (Result.Width < 0) or (Result.Height < 0) then
445 raise Exception.Create(Format(SWrongBitmapSize, [Result.Width, Result.Height]));
446 Result.BytesPerLine := Bitmap.RawImage.Description.BytesPerLine;
447 Result.BytesPerPixel := Bitmap.RawImage.Description.BitsPerPixel shr 3;
448 Result.Data := PPixel32(Bitmap.RawImage.Data);
449 Result.Base := PPixel32(Bitmap.RawImage.Data + BaseX * Result.BytesPerPixel +
450 BaseY * Result.BytesPerLine);
451 Result.SetXY(0, 0);
452end;
453
454function SwapRedBlue(Color: TColor32): TColor32;
455begin
456 Result := (Color and $ff00ff00) or ((Color and $ff) shl 16) or ((Color shr 16) and $ff);
457end;
458
459end.
Note: See TracBrowser for help on using the repository browser.