Vampyre Image Processing Package

The Morfik PaintBox package contains a single widget (Vampire Image Processing Widget) that provides a canvas for server-side drawing. The package is based upon part of the Vampyre Imaging Library and is a powerful drawing tool.


package-view.png
package-down.png


A Quick Walkthrough

To use the Morfik PaintBox package simply add the package to the project by utilizing the “Used Packages” command on the project ribbon (see Figure 1 Used Packages Command), or simply drag the package file onto the application main client area. Once added a single widget will appear on the home ribbon when the form designer is active (see Figure 2 Widgets List). This widget can be placed on application forms and provides functionality through server-side coding.


security-fig1.png
Figure 1: Used Packages Command


1.png
Figure 2: Widget Gallery


A Quick Walkthrough – Sample

To get started, open a new Morifk 3 application and add the Morfik PaintBox package. From the Widget List, select the Image PaintBox widget and place it on a form and resize it to about 700px wide by 350px high. Switch to the Events tab in the Property Inspector and double-click on the event, On Paint, to create a stub procedure and notice that one of the parameters passed through is the Canvas object. This object is the one that does the heavy lifting.

In the Implementation section, add the following Uses clause:


FX Code

Uses mfk_vipImagingCanvases, mfk_vipImagingFormats;


Add the code as seen below to the event.


FX Code

Procedure Form1.mfk_vipImgPaintBox1Paint(Sender: TObject; Canvas: TCanvas);
Var
    R: TRect;
Begin
    Canvas.FillColor32 := clWhite;
    Canvas.PenWidth := 8;
    Canvas.Clear;
    Canvas.FloodFill(1, 1, True);
    Canvas.PenColor32 := DelphiToColor32(clTeal);
    Canvas.Line(0, 0, mfk_vipImgPaintBox1.Width, mfk_vipImgPaintBox1.Height);
    R.Top := 75;
    R.Left := 75;
    R.Right := 300;
    R.Bottom := 300;
    Canvas.PenMode := pmSolid;
    Canvas.PenColor32 := DelphiToColor32(clRed);
    Canvas.FillColor32 := DelphiToColor32(clGreen);
    Canvas.Ellipse(R);
    R.Top := 100;
    R.Left := 150;
    R.Right := 240;
    R.Bottom := 250;
    Canvas.PenColor32 := clWhite;
    Canvas.PenWidth := 2;
    Canvas.FrameRect(R);
    Canvas.PenWidth := 1;
End;


When you run the application, you should see an image similar to the one in Figure 3 – Sample PaintBox Image.


2.png
Figure 3: Sample Paintbox Image


There are a number of filters that can also be applied to the canvas. For example, add the following code before the end of the event procedure above:


FX Code

Canvas.ApplyConvolution5x5(FilterGaussian5x5);


And the image will change to the one displayed in Figure 4 – After Gaussian Blur.


3.png
Figure 4: After Gaussian Blur

The Canvas Object in More Detail

The canvas class (TImagingCanvas) is defined in the mfk_vipImagingCanvases unit which also contains supporting classes. The classes are heavily commented For most methods and properties, colors can be specified either as 32-bit colors or floating-point colors. Thirty-two-bit colors are specified as hexadecimal $AARRGGBB where AA represents the Alpha channel value and R, G, B are red, green and blue values. Floating-point colors are specified using a TColorFPRec that is defined as


FX Code

TColorFPRec = Packed Record
  Case LongInt Of
    0: (B, G, R, A: Single);
    1: (Channels: Array[0..3] of Single);
End;


Drawing functions such as HorzLine and Rectangle use the current PenWidth and PenColor when creating lines and also will use the FillColor when drawing shapes. To draw only borders for shapes, set the FillMode to fmClear.

A number of 3x3 and 5x5 filters have been predefined for you (such as FilterPrewittHorz3x3 and FilterAverage5x5) but you can also define your own by configuring either a TConvolutionFilter3x3 or TConvolutionFilter5x5 record.

TCanvas is an alias for the TImagingCanvas defined in the mfk_vipImagingCanvases module. The TImagingCanvas class works for most image data formats except special compressed formats such as Jpeg2000, Tiff and IJL. To improve speed of processing, you can use the TFastARGB32Canvas which only supports colors in the $AARRGGBB format.

One import method to remember is the UpdateCanvasState method which must be called whenever you change the format or resolution of the source image. Also you can check the Valid property to make sure that the canvas is in an acceptable state; otherwise operations on the canvas may crash.

The methods of the TImagingCanvas class are too numerous for this document but include methods for drawing on the canvas, applying filters, color manipulation, pen control and alpha manipulation.

Another interesting class, defined in the mfk_vipImagingBitmap module, is the TBitmapFileFormat, which can be used to convert between supported image types.

For more information on the canvas object please refer to http://galfar.vevb.net/imaging/doc/html/canvasusage.html and for tips on using the canvas refer to http://galfar.vevb.net/imaging/doc/html/canvas.html.

Please note, if you want to change the size of the image at run time, it is best to set it in the OnBeforePrint event, such as in the sample below:


FX Code

Procedure mfk_vipImgPaintBox1BeforePrint(Sender: TWebControl; Canvas: TWebCanvas; Var Print: Boolean);
Begin
    mfk_vipImgPaintBox1.Height := mfk_vipImgPaintBox1.Width;
End;


In addition to the PaintBox class, there are useful classes defined in the mfk_vipImagingClasses module and supporting functions in the mfk_vipImaging module. The TSingleImage class and the TMultiImage class both descend from the TBaseImage class and both provide a number of methods for image manipulation.

In the sample code below, a 220px x 220px PaintBox widget on a form is used to display an image loaded from the server which is then resized to fit the dimensions of the widget during the OnPaint event. A TSingleImage object is used to load a jpg image file (or to load any file with gif, bmp, png or jpg extension) and a TCanvas object (ImagingCanvas) is created around the TSingleImage. The jpg image is then resized using a Bicubic resize filter and the result is drawn onto the PaintBox canvas.


FX Code

Procedure Form1.mfk_vipImagingWidget1Paint(Sender: TObject; Canvas: TCanvas);
Var
    SImg          : TSingleImage;
    ImagingCanvas : TCanvas;
Begin
    Canvas.FillColor32 := DelphiToColor32(clWhite);
    Canvas.FillRect(Canvas.ClipRect);
    SImg       := TSingleImage.Create('demo.jpg');
    If (SImg.Width > SImg.Height) And (SImg.Width > 220) Then
    Begin
        SImg.Resize(220, (220 * SImg.Height) div SImg.Width, rfBicubic);
    End
    Else If (SImg.Height > SImg.Width) And (SImg.Height > 220) Then
    Begin
        SImg.Resize((220 * SImg.Width) div SImg.Height, 220, rfBicubic);
    End;
    ImagingCanvas := TCanvas.Create(SImg);
    ImagingCanvas.DrawAlpha(ImagingCanvas.ClipRect, Canvas,
            GetCoordIntInPixel(mfk_vipImagingWidget1.Width div 2) - (SImg.Width div 2),
            GetCoordIntInPixel(mfk_vipImagingWidget1.Height div 2) - (SImg.Height div 2));
    ImagingCanvas.Free;
    SImg.Free;
End;


More information on the low level functions in mfk_vipImaging can be found at http://galfar.vevb.net/imaging/doc/html/lowlevel.html. The image classes are documented at http://galfar.vevb.net/imaging/doc/RefDoc/_ImagingClasses_pas_14_Classes.html.

Temporary Images and the Image Cache

When using the PaintBox widget, a temporary image will be created and saved in the resources directory. The temporary file name will be of the format PaintBox758300710090610.png (the number represents the creation time). The temporary file cache will be cleaned up, and temporary files removed in a separate server thread, based upon two values in the mfk_vipCacheCleaner module. The first constant, DefaultTimeOut (value 360), controls the time in seconds that the file will be kept in the resources directory; the second constant, DefaultPeriod (default 600) controls the time in seconds between sweeps of the cache. To change these values, you must edit the mfk_vipCacheCleaner module. Also note that the mfk_vipCacheCleaner module must be added to the uses clause in at least one module for the cleanup process to occur.

See Also

Back to top