Assigning an ImageMagick wand picture to a Delphi TBitmap

I could not find this anywhere so I had to experiment:

I mentioned PascalMagick before and that it’s part of the FreePascal RTL.

The following assigns an image that has been processed with the Magick Wand API of ImageMagick to a Delphi TBitmap.

First, we need to convert the image to bitmap format using MagickSetFormat:

  Status := MagickSetImageFormat(FWand, PAnsiChar('BMP'));
  // check status here

Then we get it as a blob by calling MagickGetImageBlob.

var
  Size: Cardinal;
  blob: Pointer;
begin
  blob := MagickGetImageBlob(FWand, @Size);
  // check if blob is assigned

Note that the memory for the blob is allocated by the dll, we will have to pass it to MagickRelinquishMemory to free it later.

The easiest way I found to assign some memory to a TBitmap is TBitmap.LoadFromStream. The stream in this case could be a TMemoryStream, but unfortunately there is no way to create a TMemoryStream for an existing memory block. So I wrote a descendant of TCustomMemoryStream that provides this functionality.

type
  TdzMagickBlob = class(TCustomMemoryStream)
  public
    constructor Create(_Memory: Pointer; _Size: Cardinal);
    destructor Destroy; override;
  end;

constructor TdzMagickBlob.Create(_Memory: Pointer; _Size: Cardinal);
begin
  inherited Create;
  SetPointer(_Memory, _Size);
end;

destructor TdzMagickBlob.Destroy;
begin
  if Size <> 0 then
    MagickRelinquishMemory(Memory);
  inherited;
end;

Remember what I said above about passing the blob back to the dll to free the memory? That’s what the destructor does.

Now we only need to load the bitmap from the stream:

  bmp := TBitmap.Create;

  blobStream := TdzMagickBlob.Create(blob, size);
  try
    blobStream.Position := 0;
    bmp.LoadFromStream(blobStream);
  finally
    FreeAndNil(blobStream);
  end;

There we go: The image has been assigned to the TBitmap object.

I would have liked to omit the stream and directly assign the memory to TBitmap.Scanline[], but I found no easy way to do that.

This is part of the object oriented layer I wrote for encapsulating (some of) the MagickWand functionality. I will put this code into my dzlib later.