Grid InQuest II Visual C Example

Thanks to a contribution from Shane MacLaughlin of Atlas Computers Ltd. There is now a Windows Visual C++ example available for calling the Grid InQuest II dynamic link library.  This is uploaded to the repository source tree in the Examples/C folder along with a GCC example that I have added for calling Linux shareable objects:

Grid InQuest II Bitbucket Source

If any body else adds additional language wrappers, let me know and I will add them into the repository as well.

Grid InQuest II Launched Today!

Today sees the official launch of Ordnance Survey’s new geoid model OSGM15.  This is to replace their previous model OSGM02 that has been the cornerstone of the British National Grid coordinate system since 2002.  The new model is both a refinement of the accuracy and an increase in the model’s extent to cover offshore bathymetry.

As a consequence it will now be used to refine the definition of the British National Grid, the Irish Grid and the Irish Transverse Mercator map projections.  To accompany this Ordnance Survey, along with Ordnance Survey Ireland and the Land and Property Services of Northern Ireland, commissioned me to re-write their popular Grid InQuest software to serve as a reference implementation for this new system.

GIQ2

The new software is written in Free Pascal and there are binaries available for Linux, Windows and Mac OSX.  Moreover, the software is released under an open source licence so the entire project repository is available on Bitbucket here:

https://bitbucket.org/PaulFMichell/gridinquestii

If any one is interested in more details about what the software can do a digital manual is also available for download here:

https://bitbucket.org/PaulFMichell/…/GridInQuestII.pdf

Further technical data concerning the definition of OSGM15 can be found here:

OSGM15 and OSTN15 – Updated transformations for UK and Ireland

Free Pascal Fast Bitmaps (Part 2)

Whilst reading the Free Pascal mailing lists I read an interesting exchange where there was a discussion of the methods used by FPImage to store bitmap data (Questions regarding FPImage’s TFPMemoryImage.FData variable).  In this my eye was drawn to a class TFPCompactImgRGBA8Bit which was listed as using 32bits per pixel.  As covered in part one of this post, this is the magic pixel sized used by all of the fast software image handling libraries.  I was unaware that it was possible to vary the raw pixel storage in the FCL-Image library, but it turns out that the TFPCustomImage class is designed to allow the definition of descendants that can specify alternative memory allocation strategies.

The class mentioned TFPCompactImgRGBA8Bit does just this and assumes RGBA byte order within the 32bit pixel value.  Unfortunately some platforms, most notably Windows, store the colour components in a different order, BGRA to be precise, so I ideally would like a class that can adapt this order depending upon the target platform.  From this requirement was born my TCompactImage, as an adaptation of the TFPCompactImgRGBA8Bit class:

Unit CompImages;

{ FCL Compact Image Unit (c) 2016, Paul F. Michell. }

{$IFDEF FPC}
  {$ASMMODE INTEL}
  {$MODE OBJFPC}
  {$LONGSTRINGS ON}
{$ENDIF}

Interface

Uses
  Classes, fpImage;

{$I Defines.inc}

Type
  TCompactColor = Packed Record
    {$IFDEF BGRAIMAGE}
    Blue, Green, Red, Alpha: Byte;
    {$ELSE}
    Red, Green, Blue, Alpha: Byte;
    {$ENDIF}
  End;
  TCompactColorPointer = ^TCompactColor;

  TCompactImage = class(TFPCustomImage)
  Protected
    FData: TCompactColorPointer;
    Function GetInternalColor(x, y: Integer): TFPColor; 
                                              Override;
    Function GetInternalPixel({%H-}x, {%H-}y: Integer): 
                                     Integer; Override;
    Procedure SetInternalColor (x, y: Integer; 
                      Const Value: TFPColor); Override;
    Procedure SetInternalPixel({%H-}x, {%H-}y: Integer; 
                        {%H-}Value: Integer); Override;
  Public
    Destructor Destroy; Override;
    Procedure Clear(Color: TCompactColor);
    Procedure SetSize(AWidth, AHeight: Integer); 
                                              Override;
    Property Data: TCompactColorPointer Read FData 
                                           Write FData;
  End;

Implementation

Destructor TCompactImage.Destroy;
Begin
  ReAllocMem(FData, 0);
  Inherited Destroy;
End;

Procedure TCompactImage.SetSize(AWidth, 
                                     AHeight: Integer);
Begin
  If (AWidth<>Width) Or (AHeight<>Height) Then
    Begin
      ReAllocMem(FData, 
                 SizeOf(TCompactColor)*AWidth*AHeight);
      Inherited SetSize(AWidth, AHeight);
    End;
End;

Function TCompactImage.GetInternalColor(x, 
                                 y: Integer): TFPColor;
Var
  Color: TCompactColor;
Begin
  Color := FData[x+y*Width];
  With Color Do
    Begin
      Result.Red := (Red ShL 8)+Red;
      Result.Green := (Green ShL 8)+Green;
      Result.Blue := (Blue ShL 8)+Blue;
      Result.Alpha := (Alpha ShL 8)+Alpha;
    End;
End;

Function TCompactImage.GetInternalPixel(x, 
                                  y: Integer): Integer;
Begin
  { Not used by Compact Images. }
  Result := 0;
End;

Procedure TCompactImage.SetInternalColor(x, y: Integer; 
                                Const Value: TFPColor);
Var
  Color: TCompactColor;
Begin
  Color.Red := Value.Red ShR 8;
  Color.Green := Value.Green ShR 8;
  Color.Blue := Value.Blue ShR 8;
  Color.Alpha := Value.Alpha ShR 8;
  FData[x+y*Width] := Color;
End;

Procedure TCompactImage.SetInternalPixel(x, y: Integer; 
                                       Value: Integer);
Begin
  { Not used by Compact Images. }
End;

Procedure TCompactImage.Clear(Color: TCompactColor);
Begin
  FillDWord(FData^, Width*Height, DWord(Color));
End;

End.

The key difference is the BGRAIMAGE define which enables the colour byte order to change with the target platform.  This is controlled by the ‘Defines.inc’ file:

{ Define platform specific byte order. }
{$IFDEF WINDOWS}
  {$DEFINE BGRAIMAGE}
{$ELSE} {$IFDEF LCLQT}
  {$DEFINE BGRAIMAGE}
{$ELSE}
  {$DEFINE RGBAIMAGE}
{$ENDIF}{$ENDIF}

This proves to be the base technique that fulfils my requirements of: platform portability; fast 32bit pixel access; no external dependencies; potential for headless use; integration with the FCL-Image library; and via TRawImage, the potential to integrate with LCL too.  In a future post I will upload my test program that will demonstrate a bridge to LCL and can achieve in the region of 30 frames per second of full screen updates.

 

 

Free Pascal Fast Bitmaps (Part 1)

Recently I have been looking again at the issue of generating large images for a Free Pascal program at interactive display rates. There are two scenarios where I find this useful, creating a back-buffer for graphically intensive programs such as GIS mapping or procedural graphics applications.  The second is for command-line, or server tools that can synthesise images in real-time for feeding into a web server response.

The bottlenecks encountered when developing high performance bitmap graphics are usually due to either the cost of access to individual pixels, or the transfer cost of a graphics buffer to screen or file.  For display access, the programmer is at the mercy of both the system’s desktop shell and the hardware driver.

I have come across these hurdles repeatedly in my career.  To many, the obvious solution would be to use the now ubiquitous hardware based GPU options, most likely OpenGL or OpenGLES.  Whilst they are very powerful there are two capabilities I need that are not so easy to achieve with this approach: complex polygon filling and high quality vector font rendering.  In addition, when targeting embedded systems or older hardware, these interfaces may not be available at all.

These days I also require code to be highly portable and ideally with very few external dependencies beyond the units supplied with Free Pascal and Lazarus.  In the past I have found the best results were achieved with the Graphics32 library.  Unfortunately, its development seems to have slowed of late and its support for Lazarus can be patchy. Another very useful library is BGRABitmap which was developed specifically for Lazarus and is the rendering library behind the LazPaint image editor.  This unfortunately does not compile with the current trunk compiler 3.1.1 due to changes in the UTF8 text handling, although I expect this will be fixed in due course.  Also both of these libraries are a poor choice for the sever/command-line role as they depend upon the LCL desktop interface.

There are many other graphics libraries, AggPas, Vampyre, LazRGBGraphics to name a few.  All of them share the same basic premise of handling memory images directly and optimise reading and writing pixels, but they are written from the ground up and so are not well integrated for use with the native image handling of Free Pascal and Lazarus.

So what are the native capabilities of Free Pascal and Lazarus and why have so many additional libraries been written?  The graphics library distributed with Free Pascal is called FCL-Image and it supports all of the common image file formats and provides a a memory based drawing canvas interface.  There is also the TBitmap implementation in the Lazarus Graphics unit.  This is largely compatible with Delphi’s TBitmap and uses the FCL for some of its file and drawing capabilities.  Unfortunately, both libraries are very slow in use compared to the third party libraries mentioned before.  The fundamental reason for this is due to the FCL library abstracting pixel representation as a 64bit quantity.  Whilst this provides superior colour accuracy, for more common place 32bit colour depths, it comes at the cost of requiring per pixel conversion between the two colour forms.  This conversion overhead is especially noticeable for large images being transferred to files or the screen.

I have attempted to use FCL-Image on a couple of occasions but ended up rejecting the solution because I couldn’t get the performance to an acceptable level for my application.  In both cases, I found myself wishing in frustration that I could use the 32bit techniques of the other libraries within the FCL.  As it happens, I have now discovered that you can and that will be the subject of my next post!