DLL/ BB Image Sharing

BlitzPlus Forums/BlitzPlus Programming/DLL/ BB Image Sharing

Whats the best(ie fastest) way to share an image between BBplus code and a DLL.

The idea is to create a DLL that starts a thread capturing webcam pics and comparing them. When a particular circumstance is met (ie motion, object, color detection etc) it will save(buffer not file) that image image and set a flag to true. The DLL will provide:

Bool WaitDetect(int timeOut, int camNum)
Bool isDetect(int camNum)
bbImg getImage(camNum)

Where getImage hopefully transfers the img directly into a blitz image type. Is there away to do this? How do I send an image back to the DLL?

I tried to send an image to a DLL, written in Delphi.
First, in Blitz, I needed to get the ImageBuffer, then lock it (LockBuffer) and then I sent the buffer's handle + 72 to the DLL. The DLL also needed the buffer's width, height and bitdepth (read with GraphicsDepth)
In Delphi, I used this as a pointer to a bytearray. I believe in C++, you need the * sign to do this.
Inside the DLL, I copied the data from the bytearray into an image, I processed it and finally copied the data back into the array.
The speed of the operations depends on what buffer I tried to use (ImageBuffer/BackBuffer/FrontBuffer) and the amount of data I needed to process.

Later on, I tried to use the IDirect3DDevice. I needed the Delphi DirectX7 declarations for it. I sent SystemProperty("Direct3DDevice7") to the DLL, and in Delphi, declared this parameter as a IDirect3DDevice7. Then I could for instance obtain and change it's rendertarget by using Set/GetRenderTarget().

b32, Thanks for replying. This sounds very promising. Did this work for you? Do you have any sample code? Thanks again :)

Hmm, it was a while ago I was trying this, and the code is a bit of a mess. Still, I hope it helps.
This is method 2: sending the device to the dll:
//this function copies the z-buffer to the rendertarget
procedure LockZBuffer(lpDevice : IDirect3DDevice7); stdcall;
var
   surf2, surf : IDirectDrawSurface7;
   caps : TDDSCaps2;
begin
  //get rendertarget
  lpDevice.GetRenderTarget(surf);
  surf.GetCaps(caps);
  caps.dwCaps := DDSCAPS_ZBUFFER;
  //get z-buffer
  surf.GetAttachedSurface(caps, surf2);
  //copy z-buffer to rendertarget
  surf.BltFast(0, 0, surf2, rect(0,0,799,599), 0);
  //clear z-buffer
  lpDevice.Clear(1, r, D3DCLEAR_ZBUFFER, $000000, 0, 0);
end;

Called with:
LockZBuffer SystemProperty$("Direct3DDevice7")
------------------------------------------------------------
Method1:
Sending the image's handle+72 to the dll
//this is the complete .dll
//it scales an image and copies it onto a blitz imagebuffer
library scaleimage;

uses
  SysUtils,
  Dialogs,
  Classes,
  Graphics,
  DIB;

{$R *.res}

var
        backbuffer                  : pbytearray;
        imagebits,
        imagewidth, imageheight     : integer;
        odib,
        idib                        : tdib;


procedure FreeAdres; stdcall;
begin
idib.free;
odib.free;
end;

//load image that should be scaled
procedure SetImage(f : pchar); stdcall;
begin
if not(fileexists(f)) then exit;

//load image
idib := tdib.create;
idib.loadfromfile(f);
imagewidth      := idib.width;
imageheight     := idib.height;
end;

//get imagebuffer and bitdepth from blitz
procedure GetAdres(a : pinteger; pbits : integer); stdcall;
begin
        //set pbytearray to blitz3d image
        backbuffer  := pbytearray(a^);
        imagebits   := pbits div 8;

        //create 800x600 image with selected bitdepth
        odib := tdib.create;
        if pbits = 16 then pbits := 24;
        odib.setsize(800, 600, pbits);
        odib.canvas.brush.color := 0;
end;

//actual stretchdraw
procedure StretchDrawImage(ix, iy, iw, ih : integer); stdcall;
var
        w, x, y         : integer;
        p               : pbytearray;
begin
   //clear background
   odib.canvas.fillrect(rect(0, 0, 800, 600));
   //stretchdraw image
   odib.canvas.stretchdraw(rect(ix, iy, ix + iw, iy + ih), idib);
   w := (800 * imagebits);

   //send to blitz
   for y := 0 to 599 do
   begin
    p := odib.scanline[y];
    for x := 0 to 799 do
     begin
     move(p[x * imagebits], backbuffer[y * w + x * imagebits], imagebits);
     end;
   end;
end;

//fill color
procedure SetColor(r, g, b : byte); stdcall;
begin
idib.canvas.brush.color := b shl 16 + g shl 8 + r;
end;

//fill routine
procedure Fill(x, y : integer); stdcall;
begin
idib.canvas.FloodFill(x, y, idib.canvas.pixels[x, y], fsSurface);
end;

function GetWidth : integer; stdcall;
begin
result := imagewidth;
end;

function GetHeight : integer; stdcall;
begin
result := imageheight;
end;

exports
        SetImage,
        GetAdres,
        StretchDrawImage,
        FreeAdres,
        GetWidth,
        GetHeight,
        SetColor,
        Fill;

begin
end.


{
  //redundant code
        imagebuffer := pbytearray(b^);

        imb := 4;
        imbw := imagewidth * imb;

        idib.setsize(imagewidth, imageheight, 32);
        for y := 0 to imageheight - 1 do
        begin
         p := idib.scanline[y];
         for x := 0 to imagewidth * 4 - 1 do
          p[x] := imagebuffer[y * imbw + x];
        end;
}

Called with
	;-------------------
	;create buffer image
	;-------------------
	WidthBuffer		= 800
	HeightBuffer	= 600
	image 			= CreateImage(WidthBuffer, HeightBuffer)
	bufferimage		= ImageBuffer(image)
	
	;-----------------------------------------------------
	;store pointers, load in image data to internal buffer
	;-----------------------------------------------------
	LockBuffer 		bufferimage
	GetAdres 		bufferimage + 72, GraphicsDepth()
	UnlockBuffer 	bufferimage

Both methods worked for me, however I haven't tested them on other machines.