WoodyJ007
asked on
Passing bitmaps through COM
Any idea how to pass bitmaps through COM?
I have an automation server that is generating Bitmaps (TBitmap).
I want a client to call something like GetBitmap on the server.
I've experimented with IPicture but I can't seem to get it to work properly.
Examples would be good.
Thanks
Woody.
I have an automation server that is generating Bitmaps (TBitmap).
I want a client to call something like GetBitmap on the server.
I've experimented with IPicture but I can't seem to get it to work properly.
Examples would be good.
Thanks
Woody.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks. I'll give it a try and get back to you later.
ooops of course: should be
var ret: OleVariant;
ret:=DCOMConn.AppServer.Do wnLoad('so mefile.ext ension');
ziolko.
var ret: OleVariant;
ret:=DCOMConn.AppServer.Do
ziolko.
ASKER
Will it work if I change it from a TFileStream to a THandleStream?
The Server code looks like this....
function TAIBallTest.GetBitmap(Port : Integer): OleVariant;
Var
Bmp : TBitmap;
FSize : LongInt;
ms : TStream;
P : Pointer;
Tmp : OleVariant;
begin
Bmp := Form1.GetBitmap(Port);
Result := UNASSIGNED;
tmp:=UNASSIGNED;
try
ms:=THandleStream.Create(B mp.Handle) ;
if ms = nil then
begin
Result:=NULL;
Exit;
end;
ms.Position:=0;
fsize:=ms.Size;
Result:=VarArrayCreate([0, 1],varVari ant);
Result[0]:='TOTAL='+IntToS tr(fsize)+ ',CONTENT= BITMAP';
tmp:=VarArrayCreate([1,fsi ze],varByt e);
P:=VarArrayLock(tmp);
try
ms.ReadBuffer(P^,fsize);
finally
VarArrayUnLock(tmp);
end;
Result[1]:=tmp;
ms.Free;
tmp:=UNASSIGNED;
VarClear(tmp);
except
//
end;
end;
I can't seem to figure out the client side (thats if I can use THandleStream at all)
So far...
Var
Bitmap : OleVariant;
stream : TStream;
ResultBitmap : TBitmap;
Tmp : String;
FSize : LongInt;
P : Pointer;
cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
Bitmap := AIBall.GetBitmap(1);
If VarIsArray(Bitmap) Then
Begin
stream:=ThandleStream.Crea te(ResultB itmap.Hand le);
try
tmp:=string(Bitmap[0]);
cont:=Bitmap[1];
System.Delete(tmp,1,Pos('= ',tmp));
fsize:=StrToInt(Copy(tmp,1 ,Pos(',',t mp)-1));
stream.Position:=0;
P:=VarArrayLock(cont);
try
stream.WriteBuffer(P^,fsiz e);
finally
VarArrayUnLock(cont);
end;
stream.Size:=fsize;
finally
stream.Free;
end;
end;
Bitmap:=UNASSIGNED;
VarClear(Bitmap);
ResultBitmap.SaveToFile('C :\Crapdump \b.bmp');
ResultBitmap.Free;
The Server code looks like this....
function TAIBallTest.GetBitmap(Port
Var
Bmp : TBitmap;
FSize : LongInt;
ms : TStream;
P : Pointer;
Tmp : OleVariant;
begin
Bmp := Form1.GetBitmap(Port);
Result := UNASSIGNED;
tmp:=UNASSIGNED;
try
ms:=THandleStream.Create(B
if ms = nil then
begin
Result:=NULL;
Exit;
end;
ms.Position:=0;
fsize:=ms.Size;
Result:=VarArrayCreate([0,
Result[0]:='TOTAL='+IntToS
tmp:=VarArrayCreate([1,fsi
P:=VarArrayLock(tmp);
try
ms.ReadBuffer(P^,fsize);
finally
VarArrayUnLock(tmp);
end;
Result[1]:=tmp;
ms.Free;
tmp:=UNASSIGNED;
VarClear(tmp);
except
//
end;
end;
I can't seem to figure out the client side (thats if I can use THandleStream at all)
So far...
Var
Bitmap : OleVariant;
stream : TStream;
ResultBitmap : TBitmap;
Tmp : String;
FSize : LongInt;
P : Pointer;
cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
Bitmap := AIBall.GetBitmap(1);
If VarIsArray(Bitmap) Then
Begin
stream:=ThandleStream.Crea
try
tmp:=string(Bitmap[0]);
cont:=Bitmap[1];
System.Delete(tmp,1,Pos('=
fsize:=StrToInt(Copy(tmp,1
stream.Position:=0;
P:=VarArrayLock(cont);
try
stream.WriteBuffer(P^,fsiz
finally
VarArrayUnLock(cont);
end;
stream.Size:=fsize;
finally
stream.Free;
end;
end;
Bitmap:=UNASSIGNED;
VarClear(Bitmap);
ResultBitmap.SaveToFile('C
ResultBitmap.Free;
I'll get back to You tomorrow.
ziolko.
ziolko.
You can try THandleStream but if this wont work simply use TStream and then ResultBitmap.LoadFromStrea m(), code will look something like this:
ResultBitmap := TBitmap.Create;
Bitmap := AIBall.GetBitmap(1);
If VarIsArray(Bitmap) Then
Begin
stream:=TStream.Create;
try
tmp:=string(Bitmap[0]);
cont:=Bitmap[1];
System.Delete(tmp,1,Pos('= ',tmp));
fsize:=StrToInt(Copy(tmp,1 ,Pos(',',t mp)-1));
stream.Position:=0;
P:=VarArrayLock(cont);
try
stream.WriteBuffer(P^,fsiz e);
finally
VarArrayUnLock(cont);
end;
stream.Size:=fsize;
ResultBitmap.LoadFromStrea m(stream);
finally
stream.Free;
end;
end;
Bitmap:=UNASSIGNED;
VarClear(Bitmap);
ResultBitmap.SaveToFile('C :\Crapdump \b.bmp');
ResultBitmap.Free
ziolko.
ResultBitmap := TBitmap.Create;
Bitmap := AIBall.GetBitmap(1);
If VarIsArray(Bitmap) Then
Begin
stream:=TStream.Create;
try
tmp:=string(Bitmap[0]);
cont:=Bitmap[1];
System.Delete(tmp,1,Pos('=
fsize:=StrToInt(Copy(tmp,1
stream.Position:=0;
P:=VarArrayLock(cont);
try
stream.WriteBuffer(P^,fsiz
finally
VarArrayUnLock(cont);
end;
stream.Size:=fsize;
ResultBitmap.LoadFromStrea
finally
stream.Free;
end;
end;
Bitmap:=UNASSIGNED;
VarClear(Bitmap);
ResultBitmap.SaveToFile('C
ResultBitmap.Free
ziolko.
ASKER
I can't seem to get this to work. Your TFileStream code works fine but I don't really want to save files and load files when I send and receive.
I've tried using TMemoryStream but that doesn't seem to work either. Below is the unit code I am currently using to test it. (simple form with two Images and a button)
Cheers
Woody
...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Function MakeImage1VariantArray : OleVariant;
Procedure LoadVariantArrayIntoImage2 (Var VArray : OleVariant);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.MakeImage1VariantAr ray: OleVariant;
Var
Bmp : TBitmap;
FSize: LongInt;
MemStream : TMemoryStream;
P : Pointer;
vTmp : OleVariant;
begin
Result := UNASSIGNED;
// Get the bitmap
Bmp := Image1.Picture.Bitmap;
vTmp := UNASSIGNED;
Try
MemStream := TMemoryStream.Create;
Bmp.SaveToStream(MemStream );
MemStream.Position := 0;
FSize := MemStream.Size;
Result := VarArrayCreate([0,1], varVariant);
Result[0] := 'TOTAL=' + IntToStr(FSize);
vTmp := VarArrayCreate([1, FSize], varByte);
P := VarArrayLock(vTmp);
Try
MemStream.ReadBuffer(P^, FSize);
Finally
VarArrayUnLock(vTmp);
End;
Result[1] := vTmp;
MemStream.Free;
VTmp:=UNASSIGNED;
VarClear(vTmp);
Except
//
End;
end;
procedure TForm1.Button1Click(Sender : TObject);
Var
vBitmap : OleVariant;
begin
vBitmap := MakeImage1VariantArray;
LoadVariantArrayIntoImage2 (vBitmap);
end;
procedure TForm1.LoadVariantArrayInt oImage2(va r VArray : OleVariant);
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
MemStream.Position := 0;
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
ResultBitmap.LoadFromStrea m(MemStrea m);
Image2.Picture.Bitmap.Assi gn(ResultB itmap);
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
end.
I've tried using TMemoryStream but that doesn't seem to work either. Below is the unit code I am currently using to test it. (simple form with two Images and a button)
Cheers
Woody
...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Function MakeImage1VariantArray : OleVariant;
Procedure LoadVariantArrayIntoImage2
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.MakeImage1VariantAr
Var
Bmp : TBitmap;
FSize: LongInt;
MemStream : TMemoryStream;
P : Pointer;
vTmp : OleVariant;
begin
Result := UNASSIGNED;
// Get the bitmap
Bmp := Image1.Picture.Bitmap;
vTmp := UNASSIGNED;
Try
MemStream := TMemoryStream.Create;
Bmp.SaveToStream(MemStream
MemStream.Position := 0;
FSize := MemStream.Size;
Result := VarArrayCreate([0,1], varVariant);
Result[0] := 'TOTAL=' + IntToStr(FSize);
vTmp := VarArrayCreate([1, FSize], varByte);
P := VarArrayLock(vTmp);
Try
MemStream.ReadBuffer(P^, FSize);
Finally
VarArrayUnLock(vTmp);
End;
Result[1] := vTmp;
MemStream.Free;
VTmp:=UNASSIGNED;
VarClear(vTmp);
Except
//
End;
end;
procedure TForm1.Button1Click(Sender
Var
vBitmap : OleVariant;
begin
vBitmap := MakeImage1VariantArray;
LoadVariantArrayIntoImage2
end;
procedure TForm1.LoadVariantArrayInt
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
MemStream.Position := 0;
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
ResultBitmap.LoadFromStrea
Image2.Picture.Bitmap.Assi
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
end.
ASKER
I was forgetting to rewind the stream.
Thanks.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Function MakeImage1VariantArray : OleVariant;
Procedure LoadVariantArrayIntoImage2 (Var VArray : OleVariant);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.MakeImage1VariantAr ray: OleVariant;
Var
Bmp : TBitmap;
FSize: LongInt;
Stream : TMemoryStream;
P : Pointer;
vTmp : OleVariant;
begin
Result := UNASSIGNED;
// Get the bitmap
Bmp := Image1.Picture.Bitmap;
vTmp := UNASSIGNED;
Try
Stream := TMemoryStream.Create;
Bmp.SaveToStream(Stream);
FSize := Stream.Size;
Stream.Position := 0;
Result := VarArrayCreate([0,1], varVariant);
Result[0] := 'TOTAL=' + IntToStr(FSize);
vTmp := VarArrayCreate([1, FSize], varByte);
P := VarArrayLock(vTmp);
Try
Stream.ReadBuffer(P^, FSize);
Finally
VarArrayUnLock(vTmp);
End;
Result[1] := vTmp;
Stream.Free;
VTmp := UNASSIGNED;
VarClear(vTmp);
Except
//
End;
end;
procedure TForm1.Button1Click(Sender : TObject);
Var
vBitmap : OleVariant;
begin
vBitmap := MakeImage1VariantArray;
LoadVariantArrayIntoImage2 (vBitmap);
end;
procedure TForm1.LoadVariantArrayInt oImage2(va r VArray : OleVariant);
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
MemStream.Position := 0;
ResultBitmap.LoadFromStrea m(MemStrea m);
Image2.Picture.Bitmap.Assi gn(ResultB itmap);
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
end.
Thanks.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
Function MakeImage1VariantArray : OleVariant;
Procedure LoadVariantArrayIntoImage2
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.MakeImage1VariantAr
Var
Bmp : TBitmap;
FSize: LongInt;
Stream : TMemoryStream;
P : Pointer;
vTmp : OleVariant;
begin
Result := UNASSIGNED;
// Get the bitmap
Bmp := Image1.Picture.Bitmap;
vTmp := UNASSIGNED;
Try
Stream := TMemoryStream.Create;
Bmp.SaveToStream(Stream);
FSize := Stream.Size;
Stream.Position := 0;
Result := VarArrayCreate([0,1], varVariant);
Result[0] := 'TOTAL=' + IntToStr(FSize);
vTmp := VarArrayCreate([1, FSize], varByte);
P := VarArrayLock(vTmp);
Try
Stream.ReadBuffer(P^, FSize);
Finally
VarArrayUnLock(vTmp);
End;
Result[1] := vTmp;
Stream.Free;
VTmp := UNASSIGNED;
VarClear(vTmp);
Except
//
End;
end;
procedure TForm1.Button1Click(Sender
Var
vBitmap : OleVariant;
begin
vBitmap := MakeImage1VariantArray;
LoadVariantArrayIntoImage2
end;
procedure TForm1.LoadVariantArrayInt
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
MemStream.Position := 0;
ResultBitmap.LoadFromStrea
Image2.Picture.Bitmap.Assi
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
end.
only one line is missing in proceedure below
procedure TForm1.LoadVariantArrayInt oImage2(va r VArray : OleVariant);
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
MemStream.Position := 0;
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
MemStream.Position:=0; // <- You have to reset position to begining of stream, because bitmaps LoadFromStream begins reading from current position
ResultBitmap.LoadFromStrea m(MemStrea m);
Image2.Picture.Bitmap.Assi gn(ResultB itmap);
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
ziolko.
procedure TForm1.LoadVariantArrayInt
Var
ResultBitmap : TBitmap;
P : Pointer;
FSize : LongInt;
TmpStr : String;
MemStream : TMemoryStream;
Cont : OleVariant;
begin
ResultBitmap := TBitmap.Create;
If VarIsArray(VArray) Then
Begin
MemStream := TMemoryStream.Create;
Try
TmpStr := String(VArray[0]);
Cont := VArray[1];
System.Delete(TmpStr, 1, Pos('=', TmpStr));
FSize := StrToInt(TmpStr);
MemStream.Position := 0;
P := VarArrayLock(Cont);
Try
MemStream.WriteBuffer(P^, FSize);
Finally
VarArrayUnLock(Cont);
End;
MemStream.Size := FSize;
MemStream.Position:=0; // <- You have to reset position to begining of stream, because bitmaps LoadFromStream begins reading from current position
ResultBitmap.LoadFromStrea
Image2.Picture.Bitmap.Assi
Finally
MemStream.Free;
End;
End;
VArray := UNASSIGNED;
VarClear(VArray);
ResultBitmap.Free
end;
ziolko.
hi ziolko !
i've got a big problem with an active x which results a TBitmap as OleVariant. I tried
to use your function above to load it but it results "index out of range". i hope that
ypu can help me with that ? would be perfect if you could mail me: fuluppi@tiscali.de
thanks in advance!
ItsMe
i've got a big problem with an active x which results a TBitmap as OleVariant. I tried
to use your function above to load it but it results "index out of range". i hope that
ypu can help me with that ? would be perfect if you could mail me: fuluppi@tiscali.de
thanks in advance!
ItsMe
I'll post You sample app, if error persists debug project and let me know where error occurs
ziolko.
ziolko.
You should pack you bitmap into the variant array and path it to your client.