|
Tutorial 4. Working with raster layers Next | Previous
|
|
Raster layers can be useful for non-standard visualizing of image regions. In this tutorial we will process a small image region under the mouse. A raster layer will be used to visualize a result of region processing.
|
|
Setting up a raster layer
|
|
Start a new application (File/New/Application). Drop a TZImageBox and TZRasterLayer components from the PixeLook palette page onto the main form. Set the following properties of ZRasterLayer1 in the Object Inspector:
|
Parent = ZImageBox1, this attaches the raster layer to an image window; Active = true, this activates the layer, so that it can accept mouse messages PixelFormat = pf8bit, for simplicity, we only work with 8-bit images Transparency.Mode = [tmTransparent], this indicates that some regions of the raster layer will be transparent. The color black defines transparent regions. Transparency.TranspColor = clBlack, Black color defines transparent regions.
|
|
Image visualization via TZDataBitmap object
|
|
Now we read an image into the ZImageBox1. In this example we do not use the TZBitmapLink component. We connect an image file with an image window directly via the TZDataBitmap object. First, declare this object in the form class:
|
|
|
|
Then we read an image in FormCreate (do not forget to destroy the image!):
|
procedure TForm1.FormCreate(Sender: TObject); begin BM:=TZDataBitmap.CreateOpen(mmDisk,'c:\work\images\lena256.bmp'); ZImageBox1.Bitmap:=BM; end;
procedure TForm1.FormDestroy(Sender: TObject); begin BM.Free; end;
|
|
Dynamic changing of a raster layer
|
|
Now we create the OnMouseMove event handler to respond to the mouse moving:
|
procedure TForm1.ZRasterLayer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Double); var xx,yy:integer; begin // delete previous region ZRasterLayer1.ImageRect:=Rect(0,0,0,0); ZRasterLayer1.Invalidate; xx:=trunc(x); yy:=trunc(y);
//check if the mouse is inside the image if (xx<0) or (xx>=BM.DimX) or (yy<0) or (yy>=BM.DimY) then exit;
//create a new region. A 40x40 rectangle is used as an example ZRasterLayer1.ImageRect:=Rect(xx-20,yy-20,xx+20,yy+20); end;
|
|
When a new region is created in a raster layer the OnNewRect event occurs. Using this event we create a specific processing of the new region, and update this region on the screen:
|
procedure TForm1.ZRasterLayer1NewRect(Sender: TObject); begin with ZRasterLayer1 do begin ProcessRect(BM,ImageRect,Bitmap); // our image processing procedure invalidate; end; end;
|
|
Image processing examples
|
|
Now we implement some examples of image processing whose results are visualized by the raster layer. The procedure ProcessRect takes the original image BM, processes it in the ImageRect region and places the result into the raster layer’s Bitmap image.
The first example simply inverts the image in the region:
|
procedure ProcessRect(InIm:TZDataBitmap; R:TRect; OutIm:TZDataBitmap); var P1,P2:PByteArray; x,y:integer; b:byte; begin for y:=R.Top to R.Bottom do if (y>=0) and (y<InIm.DimY) then begin P1:=InIm.ScanLine[y]; P2:=OutIm.ScanLine[y-R.Top]; for x:=R.Left to R.Right do if (x>=0) and (x<InIm.DimX) then begin b:=255-P1[x]; if b=0 then b:=1; P2[x-R.Left]:=b; end; end; end;
|
|
The second example is more complex. It computes a histogram of the image inside a region, then equalizes it and visualizes the results of equalization. In this example the region is a circle with radius 20.
|
|
var Hist:array[0..255] of integer;
procedure ProcessRect(InIm:TZDataBitmap; R:TRect; OutIm:TZDataBitmap); var P1,P2:PByteArray; x,y:integer; xc,yc:integer; b:byte; begin // determine a center of the region and check if it lies in the image xc:=(R.Left+R.Right) div 2; yc:=(R.Top+R.Bottom) div 2; if (xc<0) or (xc>=InIm.DimX) or (yc<0) or (yc>=InIm.DimY) then;
// compute a histogram inside a circle FillChar(Hist[0],sizeof(Hist),0); for y:=R.Top to R.Bottom do if (y>=0) and (y<InIm.DimY) then begin P1:=InIm.ScanLine[y]; for x:=R.Left to R.Right do if (x>=0) and (x<InIm.DimX) and ((x-xc)+sqr(y-yc) < 400) then inc(Hist[P1[x]]); end;
// histogram equalization for x:=1 to 255 do inc(Hist[x],Hist[x-1]); for x:=0 to 255 do Hist[x]:=trunc(Hist[x]/Hist[255]*255);
// backprojection of the equalized histogram to the image for y:=R.Top to R.Bottom do if (y>=0) and (y<InIm.DimY) then begin P1:=InIm.ScanLine[y]; P2:=OutIm.ScanLine[y-R.Top]; for x:=R.Left to R.Right do if (x>=0) and (x<InIm.DimX) then begin b:=0; // only the circle of radius 20 is not transparent if sqr(x-xc)+sqr(y-yc) < 400 then begin b:=Hist[P1[x]]; if b=0 then b:=1; end; P2[x-R.Left]:=b; end; end; end; |