To make our own histogram analysis using Delphi, first you need to make (or download the source code) of the graphical user interface for image processing we described in the previous chapter. To compute the image histogram, you need to make a vector variable to store the count of each pixel level. After that, you may begin to check the pixel value, and increment the variable that store the pixels count for that level. Histogram for color pixel is computed in the same way, but independently done for each R, G, and B element.
Creating Histogram Form
- Open the GUI project created in the previous chapter.
- Create a new form, change the form name property to HistogramForm, change the Caption to 'Histogram', set the ClientHeight property to 170, set the ClientWidth property to 275, and set the form style property to fsMDIChild.Make OnClose event handler, click Events tab on the object inspector, double click the OnClose event handler edit box. You'll be directed to the event handler, and change the Action variable to caFree between begin and end.
procedure THistogramForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action:=caFree;
end; - Go to menu Project->Options, on the Forms page, click HistogramForm to select, and press > to move the it from auto created forms list to available forms list.
- Save the unit (File->Save) as HistogramUnit.
To add variables to store the histogram, add the variables to the original HistogramForm abstraction in private section. Also add a procedure ShowHistogram() to compute histogram in the public section. Add ExtCtrls in under the uses of the interface section, as we're going to use TImage in the form class abstraction.
usesWriting The Histogram Computation Procedure
ExtCtrls, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
type
THistogramForm = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
MaxCount:Integer;
HistogramGray:Array[0..255]of Integer;
HistogramRed:Array[0..255]of Integer;
HistogramGreen:Array[0..255]of Integer;
HistogramBlue:Array[0..255]of Integer;
public
{ Public declarations }
procedure ShowHistogram(Image:TImage);
end;
In the implementation, write the ShowHistogram procedure as shown below:
procedure THistogramForm.ShowHistogram(Image:TImage);
var
i,j:integer;
pixelPointer:PByteArray;
begin
try
begin
for i:=0 to 255 do
begin
HistogramGray[i]:=0;
HistogramRed[i]:=0;
HistogramGreen[i]:=0;
HistogramBlue[i]:=0;
end;
if Image.Picture.Bitmap.PixelFormat=pf8bit then
begin
for i:=0 to Image.Height-1 do
begin
pixelPointer:=Image.Picture.Bitmap.ScanLine[i];
for j:=0 to Image.Width-1 do
begin
Inc(HistogramGray[pixelPointer[j]]);
end;
end;
MaxCount:=0;
for i:=0 to 255 do
if HistogramGray[i]>MaxCount then
MaxCount:=HistogramGray[i];
end;
if Image.Picture.Bitmap.PixelFormat=pf24bit then
begin
for i:=0 to Image.Height-1 do
begin
pixelPointer:=Image.Picture.Bitmap.ScanLine[i];
for j:=0 to Image.Width-1 do
begin
Inc(HistogramBlue[pixelPointer[3*j]]);
Inc(HistogramGreen[pixelPointer[3*j+1]]);
Inc(HistogramRed[pixelPointer[3*j+2]]);
end;
end;
for i:=0 to 255 do
begin
if HistogramRed[i]>MaxCount then
MaxCount:=HistogramRed[i];
if HistogramGreen[i]>MaxCount then
MaxCount:=HistogramGreen[i];
if HistogramBlue[i]>MaxCount then
MaxCount:=HistogramBlue[i];
end;
end;
Canvas.MoveTo(10, 160);
Canvas.Pen.Color:=clBlack;
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-round(150*HistogramGray[i]/MaxCount));
Canvas.Pen.Color:=clRed;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramRed[i]/MaxCount)));
Canvas.Pen.Color:=clGreen;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramGreen[i]/MaxCount)));
Canvas.Pen.Color:=clBlue;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramBlue[i]/MaxCount)));
end;
except
Free; //free the histogram form if an exception happens
ShowMessage('Operation is not completed');
end;
end;
Histogram Form Repainting
When the form is activated from minimized condition, we need to redraw the canvas we have drawn on ShowHistogram procedure. Place a focus on the histogram form, go to object inspector, on the Events tab, double click OnPaint event and we will be directed to the event handler, edit as shown below:
Calling Histogram Procedure from Main Form
To call showHistogram procedure, we need the user interface in the main form. On the main form, double click the MainMenu component, and add menu item Image->Histogram (see figure 1), then double click the Histogram item, so we will be directed to its event handler, and edit as shown below:
Make sure that in that main unit uses HistogramUnit under the uses of implementation section. Now you can save all form, compile, and run the executable. The example of executable running is shown in figure 2.
Source Code Download
When the form is activated from minimized condition, we need to redraw the canvas we have drawn on ShowHistogram procedure. Place a focus on the histogram form, go to object inspector, on the Events tab, double click OnPaint event and we will be directed to the event handler, edit as shown below:
procedure THistogramForm.FormPaint(Sender: TObject);
var
i:integer;
begin
Canvas.MoveTo(10, 160);;
Canvas.Pen.Color:=clBlack;
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-round(150*HistogramGray[i]/MaxCount));
Canvas.Pen.Color:=clRed;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramRed[i]/MaxCount)));
Canvas.Pen.Color:=clGreen;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramGreen[i]/MaxCount)));
Canvas.Pen.Color:=clBlue;
Canvas.MoveTo(10, 160);
for i:=0 to 255 do
Canvas.LineTo(10+i,
160-(round(150*HistogramBlue[i]/MaxCount)));
end;
Calling Histogram Procedure from Main Form
To call showHistogram procedure, we need the user interface in the main form. On the main form, double click the MainMenu component, and add menu item Image->Histogram (see figure 1), then double click the Histogram item, so we will be directed to its event handler, and edit as shown below:
procedure TMainForm.Histogram1Click(Sender: TObject);
begin
if ImageForm<>nil then
begin
ImageForm:=TImageForm(ActiveMDIChild);
try
begin
Application.CreateForm(THistogramForm,HistogramForm);
HistogramForm.ShowHistogram(ImageForm.Image1);
end;
except
HistogramForm.Free;
ShowMessage('Cannot complete the operation');
end;
end;
end;
Make sure that in that main unit uses HistogramUnit under the uses of implementation section. Now you can save all form, compile, and run the executable. The example of executable running is shown in figure 2.
Source Code Download
You can download the source code for both Delphi 7 and Turbo Delphi Explorer. The Delphi 7 source code can be downloaded here, and the Turbo Delphi Explorer source code here.
0 comments:
Post a Comment