[Delphi XE6 FireMonkey ] How to manipulate pixels on a bitmap by scanline property.
2014-09-04 09:05
459 查看
We have been developing image processing software for above 14 years with old versions of Delphi, such as Delphi 6 and Delphi 7. We often working on pixels of bitmap by its Scanline property. We want to do
such things with FireMonkey framework in Delphi XE6. But at beginning, we even don't know how to do it with the familiar approach, the Scanline property, because TBitmap class itself in FireMonkey has no the Scanline property anymore.
We have to study how to work with FireMonkey by searching for information from Internet. And we have found a piece of code at Delphi official website: http://docwiki.embarcadero.com/CodeExamples/XE6/en/FMX.AlphaColorToScanline_(Delphi)
The code in the above page illustrated that for accessing the pixels on a bitmap, we have to beg a help from class TBitmapData. The demo code cannot be compiled through XE6, because the compiler reports lack
of method GetPixelFormatBytes(). The code is for copying specified amount of lines of pixels from a source bitmap to a destination bitmap written with XE3. We have modified the original code a little bit
to copy the all the pixels from the source to a destination, the code could be compiled by XE6 and runs well then.
First of all, creating a FireMonkey Destop project in XE6, drop two TImage components and a TButton component and a TOpenDialog component
onto the form. Double click the TButton component and typing in the following code to its code block.
------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
bd1, bd2 : TBitmapData;
w, h : Integer;
begin
OpenDialog1.Filter := 'JPEG Image|*.jpg';
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
w := Image1.Bitmap.Width;
h := Image1.Bitmap.Height;
Image2.Bitmap.PixelFormat := Image1.Bitmap.PixelFormat;
Image2.Bitmap.SetSize(w, h);
try
Image1.Bitmap.Map(TMapAccess.Read, bd1);
Image2.Bitmap.Map(TMapAccess.Write, bd2);
AlphaColorToScanline(@PAlphaColorArray(bd1.Data)[0], bd2.Data,
Round(w * h), Image1.Bitmap.PixelFormat);
finally
Image1.Bitmap.Unmap(bd1);
Image2.Bitmap.Unmap(bd2);
end;
end;
end;
------------------------------
As you can see that the TBitmapData class is really great for being as a delegate to accessing data in a TBitmap object. We can mapping a
TBitmap object to be as a TBitmapData object, and then mess up bitmap data around with TBitmapData. And we can even control over the accessing permissions to those bitmap data.
We can copy all the pixels from a bitmap to another, but how can we manipulating each single pixel on a bitmap in our familiar approach,
with the scanline property, separately? The answer is included in TBitmapData class. In the following, we did the same things as above with scanline property.
------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
bd1, bd2 : TBitmapData;
x, y, w, h : Integer;
p1, p2 : PAlphaColorArray;
begin
OpenDialog1.Filter := 'JPEG Image|*.jpg';
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
w := Image1.Bitmap.Width;
h := Image1.Bitmap.Height;
Image2.Bitmap.PixelFormat := Image1.Bitmap.PixelFormat;
Image2.Bitmap.SetSize(w, h);
try
Image1.Bitmap.Map(TMapAccess.Read, bd1);
Image2.Bitmap.Map(TMapAccess.Write, bd2);
for y := 0 to (h - 1) do
begin
p1 := PAlphaColorArray(bd1.GetScanline(y));
p2 := PAlphaColorArray(bd2.GetScanline(y));
for x := 0 to (w - 1) do
begin
p2[x] := p1[x];
end;
end;
finally
Image1.Bitmap.Unmap(bd1);
Image2.Bitmap.Unmap(bd2);
end;
end;
end;
------------------------------
Wow, we can manipulating bitmap's pixels as before in FireMonkey framework. That's cool. The benefits of accessing individual pixel on a bitmap is that we can developing our own image filters now.
We haven't appreciating all the power of FireMonkey. But we believe that we can do more cool things with it. We will keep on studying it, and sharing more as we can.
Ma Xiaoguang and Ma Xiaoming
such things with FireMonkey framework in Delphi XE6. But at beginning, we even don't know how to do it with the familiar approach, the Scanline property, because TBitmap class itself in FireMonkey has no the Scanline property anymore.
We have to study how to work with FireMonkey by searching for information from Internet. And we have found a piece of code at Delphi official website: http://docwiki.embarcadero.com/CodeExamples/XE6/en/FMX.AlphaColorToScanline_(Delphi)
The code in the above page illustrated that for accessing the pixels on a bitmap, we have to beg a help from class TBitmapData. The demo code cannot be compiled through XE6, because the compiler reports lack
of method GetPixelFormatBytes(). The code is for copying specified amount of lines of pixels from a source bitmap to a destination bitmap written with XE3. We have modified the original code a little bit
to copy the all the pixels from the source to a destination, the code could be compiled by XE6 and runs well then.
First of all, creating a FireMonkey Destop project in XE6, drop two TImage components and a TButton component and a TOpenDialog component
onto the form. Double click the TButton component and typing in the following code to its code block.
------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
bd1, bd2 : TBitmapData;
w, h : Integer;
begin
OpenDialog1.Filter := 'JPEG Image|*.jpg';
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
w := Image1.Bitmap.Width;
h := Image1.Bitmap.Height;
Image2.Bitmap.PixelFormat := Image1.Bitmap.PixelFormat;
Image2.Bitmap.SetSize(w, h);
try
Image1.Bitmap.Map(TMapAccess.Read, bd1);
Image2.Bitmap.Map(TMapAccess.Write, bd2);
AlphaColorToScanline(@PAlphaColorArray(bd1.Data)[0], bd2.Data,
Round(w * h), Image1.Bitmap.PixelFormat);
finally
Image1.Bitmap.Unmap(bd1);
Image2.Bitmap.Unmap(bd2);
end;
end;
end;
------------------------------
As you can see that the TBitmapData class is really great for being as a delegate to accessing data in a TBitmap object. We can mapping a
TBitmap object to be as a TBitmapData object, and then mess up bitmap data around with TBitmapData. And we can even control over the accessing permissions to those bitmap data.
We can copy all the pixels from a bitmap to another, but how can we manipulating each single pixel on a bitmap in our familiar approach,
with the scanline property, separately? The answer is included in TBitmapData class. In the following, we did the same things as above with scanline property.
------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
bd1, bd2 : TBitmapData;
x, y, w, h : Integer;
p1, p2 : PAlphaColorArray;
begin
OpenDialog1.Filter := 'JPEG Image|*.jpg';
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
w := Image1.Bitmap.Width;
h := Image1.Bitmap.Height;
Image2.Bitmap.PixelFormat := Image1.Bitmap.PixelFormat;
Image2.Bitmap.SetSize(w, h);
try
Image1.Bitmap.Map(TMapAccess.Read, bd1);
Image2.Bitmap.Map(TMapAccess.Write, bd2);
for y := 0 to (h - 1) do
begin
p1 := PAlphaColorArray(bd1.GetScanline(y));
p2 := PAlphaColorArray(bd2.GetScanline(y));
for x := 0 to (w - 1) do
begin
p2[x] := p1[x];
end;
end;
finally
Image1.Bitmap.Unmap(bd1);
Image2.Bitmap.Unmap(bd2);
end;
end;
end;
------------------------------
Wow, we can manipulating bitmap's pixels as before in FireMonkey framework. That's cool. The benefits of accessing individual pixel on a bitmap is that we can developing our own image filters now.
We haven't appreciating all the power of FireMonkey. But we believe that we can do more cool things with it. We will keep on studying it, and sharing more as we can.
Ma Xiaoguang and Ma Xiaoming
相关文章推荐
- How to manipulate pixels on a bitmap by scanline property(Ma Xiaoguang and Ma Xiaoming)
- How to install oracle by Command Line Interface(CLI) in silent mode on Linux
- How To Properly Set SVN svn:externals Property In SVN Command Line
- How to Build Android Applications Based on FFmpeg by An Example
- How to view or edit pdf/image metadata from command line on Linux
- #347 – 通过Command设置按钮的内容(How to Set Content Property for Button Based on Command)
- How to read a file line by line?
- How to set a breakpoint on a property within a third-party managed component?
- How to determine who is logged on to a database by using Microsoft Jet UserRoster in Access 2000
- How to decode a H.264 frame on iOS by hardware decoding?
- How to Build Android Applications Based on FFmpeg by An Example
- How to Use Android ADB Command Line Tool on mac
- How to populate the datagrid on background thread with data binding by using Visual C#
- [Shell]How to display text on specific line of text file
- How to draw bitmap on the form - 如何在窗体上画(贴)位图
- Log4j on package level and how to test log entries produced by Log4j
- How to solve "warning:waiting for transaction lock on /var/lib/" produced by pressing "Ctrl + c"?
- This tip shows how to extract the width and height from a bitmap source file on disk.
- virtual memory layout and how to get it by the correspoinding functuon
- How to install subversion 1.7 (svn1.7) on ubuntu14.04 LTS [Tested By Carson Zang, passed!]