 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
CC Guest
|
Posted: Mon Oct 11, 2004 5:54 pm Post subject: Use TBitmap to save HBITMAP to file |
|
|
Greetings -
I have a routine that is sending me a HBITMAP handle.
How can I use TBitmap (or something else if it would be better) to save the
bitmap to a file?
I've tried:
Graphics::TBitmap *tempBtMap = new Graphics::TBitmap();
tempBtMap->Handle=hbitmap;
tempBtMap->SaveToFile("c:\tmp\junk22.bmp");
---
But this gets me a blank file?
Any help would be much appreciated
Thanks,
CurtC
|
|
| Back to top |
|
 |
Damon Chandler (TeamB) Guest
|
Posted: Tue Oct 12, 2004 5:02 am Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Hi Curt,
The code you posted should work if the HBITMAP is a handle to a DIB
section bitmap. If not--i.e., if the HBITMAP is a handle to a
device-dependent bitmap (DDB)--you might have to copy the palette
information as well (if the bitmap uses 8 or fewer bits per pixel). You
can test whether the bitmap is a DIB section bitmap or a DDB by using
the following code...
DIBSECTION bmp_info;
int const obj_size =
GetObject(hbitmap, sizeof(DIBSECTION), &bmp_info);
ShowMessage(obj_size);
If obj_size is 24, then it's a DDB; if obj_size is 84, then it's a DIB
section bitmap.
Also, you should ensure that the handle you're given is valid; test this
by dropping a TImage on your form and then doing...
Image1->Picture->Bitmap->Handle = hbitmap;
Image1->AutoSize = true;
Image1 should display the picture in its correct size. If all else
fails, try the SaveBitmap() function that's provided here...
http://tinyurl.com/4olyg
Good luck,
--
Damon (TeamB)
C++Builder Developer's Journal: http://bcbjournal.org
BCBCAQ: http://caq.bcbjournal.org
CC wrote:
| Quote: | Graphics::TBitmap *tempBtMap = new Graphics::TBitmap();
tempBtMap->Handle=hbitmap;
tempBtMap->SaveToFile("c:\tmp\junk22.bmp");
|
|
|
| Back to top |
|
 |
CC Guest
|
Posted: Tue Oct 12, 2004 4:53 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Damon -
I used the example code you supplied.
The obj_size returned zero (0).
I still cannot save the bitmap with:
Graphics::TBitmap *tempBtMap = new Graphics::TBitmap();
tempBtMap->Handle=hbitmap;
tempBtMap->SaveToFile("c:\tmp\junk.bmp");
(I get a zero length file)
But immediately after the code I can display it with the following.
LPBITMAPINFO bmi = (LPBITMAPINFO)::GlobalLock(hbitmap);
tempBtMap->Height = bmi->bmiHeader.biHeight;
tempBtMap->Width = bmi->bmiHeader.biWidth;
SetDIBits( tempBtMap->Canvas->Handle,
tempBtMap->Handle,
0,
(UINT) bmi->bmiHeader.biHeight,
lpBits, // calculated offset to bits
bmi, DIB_RGB_COLORS );
GlobalUnlock( hbitmap );
GlobalFree( hbitmap );
Form1->Image1->Picture->Assign(tempBtMap); //show it
delete tempBtMap;
------
One note about the the HBITMAP - it is a HBITMAP being returned from the
win32 twain manager.
I'm not sure why I can display it with the code, but cannot do anything
else, like saving it.
By the way - I bought your book on graphics - it is an awesome book, but it
is quite overwelming to me being a graphics newbie. Great job!
Thanks for the assistance,
Curt
----- Original Message -----
From: "Damon Chandler (TeamB)"
<editor (AT) REMOVE_THIS_SPAM_GUARD (DOT) bcbjournal.org>
Newsgroups: borland.public.cppbuilder.graphics
Sent: Tuesday, October 12, 2004 12:02 AM
Subject: Re: Use TBitmap to save HBITMAP to file
| Quote: | Hi Curt,
The code you posted should work if the HBITMAP is a handle to a DIB
section bitmap. If not--i.e., if the HBITMAP is a handle to a
device-dependent bitmap (DDB)--you might have to copy the palette
information as well (if the bitmap uses 8 or fewer bits per pixel). You
can test whether the bitmap is a DIB section bitmap or a DDB by using
the following code...
DIBSECTION bmp_info;
int const obj_size =
GetObject(hbitmap, sizeof(DIBSECTION), &bmp_info);
ShowMessage(obj_size);
If obj_size is 24, then it's a DDB; if obj_size is 84, then it's a DIB
section bitmap.
Also, you should ensure that the handle you're given is valid; test this
by dropping a TImage on your form and then doing...
Image1->Picture->Bitmap->Handle = hbitmap;
Image1->AutoSize = true;
Image1 should display the picture in its correct size. If all else
fails, try the SaveBitmap() function that's provided here...
http://tinyurl.com/4olyg
Good luck,
--
Damon (TeamB)
C++Builder Developer's Journal: http://bcbjournal.org
BCBCAQ: http://caq.bcbjournal.org
CC wrote:
Graphics::TBitmap *tempBtMap = new Graphics::TBitmap();
tempBtMap->Handle=hbitmap;
tempBtMap->SaveToFile("c:\tmp\junk22.bmp");
|
"CC" <nospamer (AT) aol (DOT) com> wrote
| Quote: | Greetings -
I have a routine that is sending me a HBITMAP handle.
How can I use TBitmap (or something else if it would be better) to save
the
bitmap to a file?
I've tried:
Graphics::TBitmap *tempBtMap = new Graphics::TBitmap();
tempBtMap->Handle=hbitmap;
tempBtMap->SaveToFile("c:\tmp\junk22.bmp");
---
But this gets me a blank file?
Any help would be much appreciated
Thanks,
CurtC
|
|
|
| Back to top |
|
 |
Damon Chandler (TeamB) Guest
|
Posted: Tue Oct 12, 2004 5:15 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Curt,
If you can display the bitmap using SetDIBits(), then you actually
have a handle to a so-called DIB (device-independent bitmap). A DIB is
different from a DDB or a DIB section bitmap in that a DIB is not a true
GDI object; rather, it's a chunk of memory that contains a BITMAPINFO
structure and an array of pixels. A handle to a DIB (your hbitmap) is
nothing more than a handle to the memory chunk; this is why in your
displaying code you must first call the GlobalLock() function.
Here's a function to save a DIB to a file...
// saves a DIB to a file
DWORD SaveDIBToFile(
// name of the file to save as
IN LPCSTR filename,
// reference to the DIB
IN const BITMAPINFO& bmi,
// pointer to the pixels (if not packed)
IN const unsigned char* pBits
)
{
DWORD dwBytesWrote = 0;
// first determine the size (in bytes) of the color table
short num_colors = bmi.bmiHeader.biClrUsed;
if (num_colors == 0 && bmi.bmiHeader.biBitCount <
{
num_colors = (1 << bmi.bmiHeader.biBitCount);
}
const size_t color_table_size =
sizeof(RGBQUAD) * num_colors;
// next, determine the size (in bytes) of the pixels array
const size_t pixels_size =
bmi.bmiHeader.biSizeImage != 0 ?
bmi.bmiHeader.biSizeImage :
abs(bmi.bmiHeader.biHeight) *
((((bmi.bmiHeader.biWidth *
bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3);
// initialize the file header
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4D42;
bmfh.bfSize =
// size of the file header
sizeof(BITMAPFILEHEADER) +
// size of the DIB's header
sizeof(BITMAPINFOHEADER) +
// size of the color table
color_table_size +
// size of the pixels array
pixels_size;
bmfh.bfOffBits = bmfh.bfSize - pixels_size;
// create the file
HANDLE hFile =
CreateFile(
filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwWritten = 0;
// write the file header
bool write_ok = WriteFile(
hFile, &bmfh, sizeof(BITMAPFILEHEADER),
&dwWritten, NULL
);
if (write_ok && (dwWritten == sizeof(BITMAPFILEHEADER)))
{
// accrue the number of bytes written
dwBytesWrote += dwWritten;
// write the DIB header
write_ok = WriteFile(
hFile, &bmi.bmiHeader, sizeof(BITMAPINFOHEADER),
&dwWritten, NULL
);
if (write_ok &&
(dwWritten == sizeof(BITMAPINFOHEADER)))
{
// accrue the number of bytes written
dwBytesWrote += dwWritten;
// write the color table
if (color_table_size != 0)
{
WriteFile(
hFile, bmi.bmiColors, color_table_size,
&dwWritten, NULL
);
// accrue the number of bytes written
dwBytesWrote += dwWritten;
}
// write the pixels
if (!pBits)
{
// assume a packed DIB if no
// pointer is supplied
pBits = reinterpret_cast<unsigned char*>(
const_cast<RGBQUAD*>(bmi.bmiColors) +
num_colors
);
}
WriteFile(
hFile, pBits, pixels_size, &dwWritten, NULL
);
// accrue the number of bytes written
dwBytesWrote += dwWritten;
}
}
CloseHandle(hFile);
}
return dwBytesWrote;
}
Based on the displaying code that you posted, I believe you'd call this
function as follows...
SaveDIBToFile("my_bitmap.bmp", *bmi, lpBits);
(You may need to cast the last variable to an unsigned char*.)
And, thanks, BTW, for the kind words about the book. This function is
actually from Chapter 7. Chapters 6 and 7 should get up to speed on
bitmaps.
Best of luck,
--
Damon (TeamB)
C++Builder Developer's Journal: http://bcbjournal.org
BCBCAQ: http://caq.bcbjournal.org
CC wrote:
| Quote: | Damon -
I used the example code you supplied.
The obj_size returned zero (0).
But immediately after the code I can display it with the following.
LPBITMAPINFO bmi = (LPBITMAPINFO)::GlobalLock(hbitmap);
[...] |
|
|
| Back to top |
|
 |
CC Guest
|
Posted: Tue Oct 12, 2004 5:48 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Damon-
Thank you very much - the code worked wonderfully.
Also - forgot to mention, your articles on bcbcaq were fabuluous they helped
me a great deal - now if I could just understand them to half the extent you
do.
Also - do you know of a decent portable way to convert bitmap files to tiff
files?
(I've looked at libtiff.org, but haven't found anything specific) I'm trying
to find a generic way to write tiff files in code that would be portable
between unix/PC.
I'm sure if I understood the graphics files I could write one, but it would
take me a long time to learn both formats, and translating between the 2.
Thanks again for your assistance, it is much appreciated - The TeamB/BCB
newsgroups is what brought me back to Borland C++ from the microsoft world
CurtC
"Damon Chandler (TeamB)" <editor (AT) REMOVE_THIS_SPAM_GUARD (DOT) bcbjournal.org>
wrote in message news:416c1107 (AT) newsgroups (DOT) borland.com...
| Quote: | Curt,
If you can display the bitmap using SetDIBits(), then you actually
have a handle to a so-called DIB (device-independent bitmap). A DIB is
different from a DDB or a DIB section bitmap in that a DIB is not a true
GDI object; rather, it's a chunk of memory that contains a BITMAPINFO
structure and an array of pixels. A handle to a DIB (your hbitmap) is
nothing more than a handle to the memory chunk; this is why in your
displaying code you must first call the GlobalLock() function.
Here's a function to save a DIB to a file...
// saves a DIB to a file
DWORD SaveDIBToFile(
// name of the file to save as
IN LPCSTR filename,
// reference to the DIB
IN const BITMAPINFO& bmi,
// pointer to the pixels (if not packed)
IN const unsigned char* pBits
)
{
DWORD dwBytesWrote = 0;
// first determine the size (in bytes) of the color table
short num_colors = bmi.bmiHeader.biClrUsed;
if (num_colors == 0 && bmi.bmiHeader.biBitCount <
{
num_colors = (1 << bmi.bmiHeader.biBitCount);
}
const size_t color_table_size =
sizeof(RGBQUAD) * num_colors;
// next, determine the size (in bytes) of the pixels array
const size_t pixels_size =
bmi.bmiHeader.biSizeImage != 0 ?
bmi.bmiHeader.biSizeImage :
abs(bmi.bmiHeader.biHeight) *
((((bmi.bmiHeader.biWidth *
bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3);
// initialize the file header
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4D42;
bmfh.bfSize =
// size of the file header
sizeof(BITMAPFILEHEADER) +
// size of the DIB's header
sizeof(BITMAPINFOHEADER) +
// size of the color table
color_table_size +
// size of the pixels array
pixels_size;
bmfh.bfOffBits = bmfh.bfSize - pixels_size;
// create the file
HANDLE hFile =
CreateFile(
filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwWritten = 0;
// write the file header
bool write_ok = WriteFile(
hFile, &bmfh, sizeof(BITMAPFILEHEADER),
&dwWritten, NULL
);
if (write_ok && (dwWritten == sizeof(BITMAPFILEHEADER)))
{
// accrue the number of bytes written
dwBytesWrote += dwWritten;
// write the DIB header
write_ok = WriteFile(
hFile, &bmi.bmiHeader, sizeof(BITMAPINFOHEADER),
&dwWritten, NULL
);
if (write_ok &&
(dwWritten == sizeof(BITMAPINFOHEADER)))
{
// accrue the number of bytes written
dwBytesWrote += dwWritten;
// write the color table
if (color_table_size != 0)
{
WriteFile(
hFile, bmi.bmiColors, color_table_size,
&dwWritten, NULL
);
// accrue the number of bytes written
dwBytesWrote += dwWritten;
}
// write the pixels
if (!pBits)
{
// assume a packed DIB if no
// pointer is supplied
pBits = reinterpret_cast<unsigned char*>(
const_cast<RGBQUAD*>(bmi.bmiColors) +
num_colors
);
}
WriteFile(
hFile, pBits, pixels_size, &dwWritten, NULL
);
// accrue the number of bytes written
dwBytesWrote += dwWritten;
}
}
CloseHandle(hFile);
}
return dwBytesWrote;
}
Based on the displaying code that you posted, I believe you'd call this
function as follows...
SaveDIBToFile("my_bitmap.bmp", *bmi, lpBits);
(You may need to cast the last variable to an unsigned char*.)
And, thanks, BTW, for the kind words about the book. This function is
actually from Chapter 7. Chapters 6 and 7 should get up to speed on
bitmaps.
Best of luck,
--
Damon (TeamB)
C++Builder Developer's Journal: http://bcbjournal.org
BCBCAQ: http://caq.bcbjournal.org
CC wrote:
Damon -
I used the example code you supplied.
The obj_size returned zero (0).
But immediately after the code I can display it with the following.
LPBITMAPINFO bmi = (LPBITMAPINFO)::GlobalLock(hbitmap);
[...]
|
|
|
| Back to top |
|
 |
Michel Leunen Guest
|
Posted: Tue Oct 12, 2004 7:29 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
CC wrote:
| Quote: | Also - do you know of a decent portable way to convert bitmap files to tiff
files?
|
Have a look at GDI+. It allows you to convert a bitmap file to a tiff
file quite easily.
http://www.leunen.com/cbuilder/gdiplus.html
Michel
--
----------------------------------------
Michel Leunen
mailto: see my homepage.
C++Builder, C++BuilderX, BCC5.5.1 Web site:
http://www.leunen.com/
----------------------------------------
|
|
| Back to top |
|
 |
CC Guest
|
Posted: Tue Oct 12, 2004 8:38 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Yep - I've heard about the GDI+ -
I'll have to see how to convert that -
One of the things I was shooting for was portability between windows and
unix - 1 common routine that would operate on both.
I'll definately look at the GDI+ option
Thank for the info.
Curt
----- Original Message -----
From: "Michel Leunen" <nospam (AT) noreply (DOT) please>
Newsgroups: borland.public.cppbuilder.graphics
Sent: Tuesday, October 12, 2004 2:29 PM
Subject: Re: Use TBitmap to save HBITMAP to file
| Quote: | CC wrote:
Also - do you know of a decent portable way to convert bitmap files to
tiff
files?
Have a look at GDI+. It allows you to convert a bitmap file to a tiff
file quite easily.
http://www.leunen.com/cbuilder/gdiplus.html
Michel
--
----------------------------------------
Michel Leunen
mailto: see my homepage.
C++Builder, C++BuilderX, BCC5.5.1 Web site:
http://www.leunen.com/
----------------------------------------
"Michel Leunen" <nospam (AT) noreply (DOT) please> wrote |
| Quote: | CC wrote:
Also - do you know of a decent portable way to convert bitmap files to
tiff
files?
Have a look at GDI+. It allows you to convert a bitmap file to a tiff
file quite easily.
http://www.leunen.com/cbuilder/gdiplus.html
Michel
--
----------------------------------------
Michel Leunen
mailto: see my homepage.
C++Builder, C++BuilderX, BCC5.5.1 Web site:
http://www.leunen.com/
----------------------------------------
|
|
|
| Back to top |
|
 |
Damon Chandler (TeamB) Guest
|
Posted: Tue Oct 12, 2004 10:58 pm Post subject: Re: Use TBitmap to save HBITMAP to file |
|
|
Curt,
| Quote: | Also - do you know of a decent portable way to convert bitmap files to tiff
files?
|
Which version of BCB are you using? I've used libTIFF in the past, and
it has worked well with BCB6 (haven't tried it with previous versions).
If you're using BCB6, I can send you the required headers + a
BCB-compatible libTIFF.lib file, which should be all you need to get up
and running.
You might also want to have a look at Scott Heiman's library which uses
libTIFF...
http://members.cox.net/scottheiman/bmglib.htm
Cheers,
--
Damon (TeamB)
C++Builder Developer's Journal: http://bcbjournal.org
BCBCAQ: http://caq.bcbjournal.org
|
|
| 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
|
|