BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

DIB to TImage

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Graphics
View previous topic :: View next topic  
Author Message
John Carlyle-Clarke
Guest





PostPosted: Fri Nov 12, 2004 11:35 am    Post subject: DIB to TImage Reply with quote



I have a DIB in memory, which is created using GetMem. In other
words, it's not a GDI object, it's just on the heap. It's a 24-bit
bitmap, and it consists of a BITMAPINFOHEADER and an array of RGB
data.

What is the best way to display this in a TImage control?

Thanks!
Back to top
Tomaz Koritnik
Guest





PostPosted: Fri Nov 12, 2004 1:23 pm    Post subject: Re: DIB to TImage Reply with quote



Hi

You have to use SetDIBits GDI function, or SetDIBitsToDevice if you want to
draw it directly to screen. Note that scanlines in your memory bitmap MUST
be DWord aligned, otherwise you can't use any of previously specified
functions. These two are also the only functions there exists in GDI to do
what you want.

regards
Tomaz


"John Carlyle-Clarke" <john.cc (AT) nospam (DOT) europlacer.co.uk> wrote

Quote:
I have a DIB in memory, which is created using GetMem. In other
words, it's not a GDI object, it's just on the heap. It's a 24-bit
bitmap, and it consists of a BITMAPINFOHEADER and an array of RGB
data.

What is the best way to display this in a TImage control?

Thanks!



Back to top
Joris Van Damme
Guest





PostPosted: Fri Nov 12, 2004 1:34 pm    Post subject: Re: DIB to TImage Reply with quote



"John Carlyle-Clarke" <john.cc (AT) nospam (DOT) europlacer.co.uk> wrote

Quote:
I have a DIB in memory, which is created using GetMem. In other
words, it's not a GDI object, it's just on the heap. It's a 24-bit
bitmap, and it consists of a BITMAPINFOHEADER and an array of RGB
data.

What is the best way to display this in a TImage control?

One way to do it is:

First create DIB as GDI object, yielding an HBITMAP

DibHandle:=CreateDIBSection(0,na^,DIB_RGB_COLORS,nc,0,0);

....where na is a pointer to your BITMAPINFOHEADER.

After this call, nc is now a pointer to the actual raster, the pixel bits.
You cannot make Windows accept your memory directly, it has to allocate its
own raster memory. Thus, next, you'll have to use something like CopyMemory
to copy the raster date to the memory pointed to by nc.

Next, making a TBitmap object to encapsulate this DIB is easy...

mybitmap:=TBitmap.Create;
mybitmap.Handle:=DibHandle;

This transfers ownership of DibHandle, so you don't have to worry about
freeing it.

If you want to display the DIB in a TImage, your next step is going to be...

Image1.Picture.Assign(mybitmap);

That does not transfer ownership (but does not involve a big copy or
duplication either, only an incrementation of a reference count). So you'll
still have to dispose of mybitmap...

mybitmap.Destroy;

Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html



Back to top
John Carlyle-Clarke
Guest





PostPosted: Fri Nov 12, 2004 2:53 pm    Post subject: Re: DIB to TImage Reply with quote

"Tomaz Koritnik" <nospam (AT) nospam (DOT) com> wrote in
news:4194b94e (AT) newsgroups (DOT) borland.com:

Quote:
You have to use SetDIBits GDI function, or SetDIBitsToDevice if
you want to draw it directly to screen. Note that scanlines in
your memory bitmap MUST be DWord aligned, otherwise you can't use
any of previously specified functions. These two are also the only
functions there exists in GDI to do what you want.

Thanks Tomaz. I have an implementation that looks like this:

function CopyDibToTBitmap(pDib: PChar; Bitmap: TBitmap): boolean;
var
iResult : integer;
begin

Bitmap.Width := BitmapWidth(pDib);
Bitmap.Height := BitmapHeight(pDib);
Bitmap.PixelFormat := pf24bit;

iResult := SetDIBits(
0,
Bitmap.Handle,
0,
BitmapHeight(pDib),
pDIB + sizeof(TBitmapInfoHeader),
PBITMAPINFO(pDib)^,
DIB_RGB_COLORS);

result := (iResult <> 0);

end;

pDib is actually a pointer to the DIB data (I know having it as
PChar is a bit wierd, but this is old code). The DWORD aligned
scanlines follow after the header in memory.

My problem is that this code worked on Win98 systems, but fails on
any NT derivative. The failures are fairly random. Adding debug
code in seems to change the behaviour, which also seems to vary from
one machine to another, and with the actual bitmaps in use.

I also tried this code, which produces the same result:

function BitmapWidth(Dib: PChar): Integer;
begin
if Dib = nil then
BitmapWidth := 0
else
BitmapWidth := PBitmapInfoHeader(Dib)^.biWidth;
end;

function BitmapHeight(Dib: PChar): Integer;
begin
if Dib = nil then
BitmapHeight := 0
else
BitmapHeight := PBitmapInfoHeader(Dib)^.biHeight;
end;

function DibToImage(Dib: PChar; Im: TImage): Boolean;
var
theHdc : hdc;
rcDest : TRect;
bitmap : TBitmap;
begin

result := false;

bitmap := TBitmap.Create;

try

if TestDib(Dib) then
begin

rcDest.Top := 0;
rcDest.left := 0;
rcDest.Right := BitmapWidth(Dib);
rcDest.Bottom := BitmapHeight(Dib);

bitmap.PixelFormat := pf24bit;
bitmap.width := BitmapWidth(Dib);
bitmap.height := BitmapHeight(Dib);

theHdc := bitmap.Canvas.Handle;

result := SendDibToDC(theHdc, Dib, rcDest);

end;

if result then
begin
Im.Picture.Assign(bitmap);
Im.Refresh;
end;

finally
bitmap.free;
end;

end;

function SendDibToDC(Handle: hdc; PDIB: PChar; rcDest: TRect):
Boolean;
var
PBits : PChar;
PInfo : PBitmapInfoHeader;
dwResult : dword;
begin

PInfo := PBitmapInfoHeader(PDIB);
PBits := PDIB + sizeof(TBitmapInfoHeader);

dwResult := StretchDIBits(
Handle, { handle of device context }
rcDest.left, { x-coordinate of upper-left corner of dest. rect.
}
rcDest.Top, { y-coordinate of upper-left corner of dest. rect. }
rcDest.Right - rcDest.left, { dest rectangle width }
rcDest.Bottom - rcDest.Top, { dest rectangle height }
0, { x-coordinate of upper-left corner of source rect. }
0, { y-coordinate of upper-left corner of source rect. }
PInfo.biWidth, { src rectangle width }
PInfo.biHeight, { src rectangle height }
PBits, { address of array with DIB
bits }
PBitmapInfo(PInfo)^, { address of structure with bitmap info. }
DIB_RGB_COLORS, { RGB or palette indices }
SRCCOPY
);

if dwResult = GDI_ERROR then
begin
ShowSysErr('StretchDIBits failed. ');
result := false;
end
else
result := true;

end;

I've traced out the parameters and they all seem correct. I've
tried saving the DIB data to a file, and it looks valid. I've added
a method which dumps out the BITMAPINFOHEADER and it looks valid.

In the case of the StretchDIBits call, it is not returning an error
- it just returns zero and appears to do nothing.

In the case of the SetDIBits call, it returns zero and a call to
GetLastError returns ERROR_ACCESS_DENIED.

Any ideas what I can try next?


Back to top
Joris Van Damme
Guest





PostPosted: Fri Nov 12, 2004 3:08 pm    Post subject: Re: DIB to TImage Reply with quote

Quote:
My problem is that this code worked on Win98 systems, but fails on
any NT derivative. The failures are fairly random. Adding debug
code in seems to change the behaviour, which also seems to vary from
one machine to another, and with the actual bitmaps in use.

I've seen many reports of odd behaviour with SetDIBits and its derivatives.
Some claim that the weirdness has to do with Delphi memory management,
though I have my doubts.

Quote:
Any ideas what I can try next?

The CreateDIBSection solution explained in my other mail is so much more
easier, a mere few lines of code, and... it works.

Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html



Back to top
John Carlyle-Clarke
Guest





PostPosted: Fri Nov 12, 2004 4:20 pm    Post subject: Re: DIB to TImage Reply with quote

"Joris Van Damme" <PleaseReplyTo (AT) TheGroupInstead (DOT) be> wrote in
news:4194d1cf (AT) newsgroups (DOT) borland.com:

Quote:
My problem is that this code worked on Win98 systems, but fails
on any NT derivative. The failures are fairly random. Adding
debug code in seems to change the behaviour, which also seems to
vary from one machine to another, and with the actual bitmaps in
use.

I've seen many reports of odd behaviour with SetDIBits and its
derivatives. Some claim that the weirdness has to do with Delphi
memory management, though I have my doubts.

That's very interesting - I've never seen any other mention of this.
I assumed it was probably down to an error somewhere else in the code
that 98 was allowing but NT was catching, or something similar. Do
you have any links?

Quote:

Any ideas what I can try next?

The CreateDIBSection solution explained in my other mail is so
much more easier, a mere few lines of code, and... it works.

I have three alternative methods to try that have been suggested:

1) Use scanline and copy the RGB to the TBitmap manually.
2) Your method with CreateDIBSection.
3) Creating a memory stream and using TBitmap.LoadFromStream

Of the three, I think yours looks most simple and quick. Thanks
again!

Back to top
Joris Van Damme
Guest





PostPosted: Fri Nov 12, 2004 5:12 pm    Post subject: Re: DIB to TImage Reply with quote

Quote:
I've seen many reports of odd behaviour with SetDIBits and its
derivatives. Some claim that the weirdness has to do with Delphi
memory management, though I have my doubts.

That's very interesting - I've never seen any other mention of this.
I assumed it was probably down to an error somewhere else in the code
that 98 was allowing but NT was catching, or something similar. Do
you have any links?

One old thread in particular involved Peter Haas reporting memory trouble,
and Joe Hecht saying that the SetDIBits stuff should not be used anymore. I
contributed to that thread too. That's not exactly a link, I know, but
depending on how eager you are to read this, maybe this vague memory of a
few names is sufficient to find the old thread... I know I've seen many
other similar reports of SetDIBits trouble, and many were mysterious enough,
excluding the posibility of a simple bug in the calling code. But no other
report I can remember exactly or locate, sorry.

Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html



Back to top
Finn Tolderlund
Guest





PostPosted: Fri Nov 12, 2004 5:15 pm    Post subject: Re: DIB to TImage Reply with quote

"John Carlyle-Clarke" <john.cc (AT) nospam (DOT) europlacer.co.uk> skrev i en
meddelelse news:Xns959FA6399CF64johncceuroplacercouk (AT) 192 (DOT) 168.1.69...
Quote:
"Joris Van Damme" <PleaseReplyTo (AT) TheGroupInstead (DOT) be> wrote in
news:4194d1cf (AT) newsgroups (DOT) borland.com:

My problem is that this code worked on Win98 systems, but fails
on any NT derivative. The failures are fairly random. Adding
debug code in seems to change the behaviour, which also seems to
vary from one machine to another, and with the actual bitmaps in
use.

I've seen many reports of odd behaviour with SetDIBits and its
derivatives. Some claim that the weirdness has to do with Delphi
memory management, though I have my doubts.

That's very interesting - I've never seen any other mention of this.
I assumed it was probably down to an error somewhere else in the code
that 98 was allowing but NT was catching, or something similar. Do
you have any links?

Perhaps this:
http://groups.google.com/groups?q=delphi+print+allocmem+memory+manager
--
Finn Tolderlund



Back to top
Joris Van Damme
Guest





PostPosted: Sat Nov 13, 2004 11:21 am    Post subject: Re: DIB to TImage Reply with quote

Quote:
...and was also written
in a "first thing in the morning and before coffee" state.

Is there such a thing as a 'before coffee' state? I missed that, sofar, I
always find a cup in my hand when finally waking up.... ;-)


Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html



Back to top
John Carlyle-Clarke
Guest





PostPosted: Mon Nov 15, 2004 4:29 pm    Post subject: Re: DIB to TImage Reply with quote

"Joris Van Damme" <PleaseReplyTo (AT) TheGroupInstead (DOT) be> wrote in
news:4194d1cf (AT) newsgroups (DOT) borland.com:

Quote:

The CreateDIBSection solution explained in my other mail is so
much more easier, a mere few lines of code, and... it works.

Indeed it does! Many thanks Joris (and all the other contributors).

Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Graphics All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.