 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
John Carlyle-Clarke Guest
|
Posted: Fri Nov 12, 2004 11:35 am Post subject: DIB to TImage |
|
|
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
|
Posted: Fri Nov 12, 2004 1:23 pm Post subject: Re: DIB to TImage |
|
|
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
|
Posted: Fri Nov 12, 2004 1:34 pm Post subject: Re: DIB to TImage |
|
|
"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
|
Posted: Fri Nov 12, 2004 2:53 pm Post subject: Re: DIB to TImage |
|
|
"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
|
Posted: Fri Nov 12, 2004 3:08 pm Post subject: Re: DIB to TImage |
|
|
| 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
|
Posted: Fri Nov 12, 2004 4:20 pm Post subject: Re: DIB to TImage |
|
|
"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
|
Posted: Fri Nov 12, 2004 5:12 pm Post subject: Re: DIB to TImage |
|
|
| 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
|
Posted: Fri Nov 12, 2004 5:15 pm Post subject: Re: DIB to TImage |
|
|
"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
|
Posted: Sat Nov 13, 2004 11:21 am Post subject: Re: DIB to TImage |
|
|
| 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
|
Posted: Mon Nov 15, 2004 4:29 pm Post subject: Re: DIB to TImage |
|
|
"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 |
|
 |
|
|
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
|
|