Board index » cppbuilder » OpenGl image to Tbitmap

OpenGl image to Tbitmap


2006-05-14 06:26:53 PM
cppbuilder55
I have following code:
Graphics::TBitmap *bm = new Graphics::TBitmap;
//bm->LoadFromFile("pawel.bmp");
bm->Width = Panel1->Width;
bm->Height = Panel1->Height;
int *buff = new int[Panel1->Width*Panel1->Height];
glReadPixels (0, 0, Panel1->Width, Panel1->Height, GL_RGBA,
GL_UNSIGNED_BYTE, buff);
bm->HandleType = bmDIB;
//*bm = *buff;
Image1->Picture->Bitmap = bm;
delete bm;
Mu question is how to insert buff data to bm(Tbitmap)????
 
 

Re:OpenGl image to Tbitmap

wowiii wrote:
Quote
I have following code:
Don't know anything about OpenGL but...
Quote
int *buff = new int[Panel1->Width*Panel1->Height];
glReadPixels (0, 0, Panel1->Width, Panel1->Height, GL_RGBA,
GL_UNSIGNED_BYTE, buff);
It seems glreadPixels() reads pixels as RGBA. This means that each pixel
is represented as 4 bytes, one for each color + one for the alpha
channel. IOW, the buffer needed to store all pixel is :
Panel1->Width * Panel1->Height * 4
You can try someyhing like this (not tested):
Graphics::TBitmap *bm = new Graphics::TBitmap;
bm->Width = Panel1->Width;
bm->Height = Panel1->Height;
bm->PixelFormat = pf32Bits;
LPBITMAPINFO Bmpi = (LPBITMAPINFO)new char[sizeof(BITMAPINFO)];
ZeroMemory(Bmpi,sizeof(BITMAPINFO));
Bmpi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Bmpi->bmiHeader.biWidth = bm->Width;
Bmpi->bmiHeader.biHeight = bm->Height;
Bmpi->bmiHeader.biPlanes = 1;
Bmpi->bmiHeader.biCompression = BI_RGB;
Bmpi->bmiHeader.biBitCount = 32;
int DestNumberOfBytesPerRow=
((((bm->Width * Bmpi->bmiHeader.biBitCount) + 31) & ~31) / 8);
Bmpi->bmiHeader.biSizeImage=
DestNumberOfBytesPerRow * bm->Height;
char* buff=new char[Bmpi->bmiHeader.biSizeImage];
glReadPixels (0, 0, Panel1->Width, Panel1->Height, GL_RGBA,
GL_UNSIGNED_BYTE, buff);
Image1->Picture->Bitmap = bm;
delete bm;
HTH
Michel
--
----------------------------------------
Michel Leunen
mailto: see my homepage.
C++Builder, BCC5.5.1 Web site:
www.leunen.com/
----------------------------------------
 

Re:OpenGl image to Tbitmap

Uzytkownik "Michel Leunen" < XXXX@XXXXX.COM >napisal w wiadomosci
Quote
wowiii wrote:
>I have following code:

Don't know anything about OpenGL but...

>int *buff = new int[Panel1->Width*Panel1->Height];
>glReadPixels (0, 0, Panel1->Width, Panel1->Height, GL_RGBA,
>GL_UNSIGNED_BYTE, buff);

It seems glreadPixels() reads pixels as RGBA. This means that each pixel
is represented as 4 bytes, one for each color + one for the alpha channel.
IOW, the buffer needed to store all pixel is :

Panel1->Width * Panel1->Height * 4

You can try someyhing like this (not tested):

Graphics::TBitmap *bm = new Graphics::TBitmap;
bm->Width = Panel1->Width;
bm->Height = Panel1->Height;
bm->PixelFormat = pf32Bits;

LPBITMAPINFO Bmpi = (LPBITMAPINFO)new char[sizeof(BITMAPINFO)];
ZeroMemory(Bmpi,sizeof(BITMAPINFO));
Bmpi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Bmpi->bmiHeader.biWidth = bm->Width;
Bmpi->bmiHeader.biHeight = bm->Height;
Bmpi->bmiHeader.biPlanes = 1;
Bmpi->bmiHeader.biCompression = BI_RGB;
Bmpi->bmiHeader.biBitCount = 32;
int DestNumberOfBytesPerRow=
((((bm->Width * Bmpi->bmiHeader.biBitCount) + 31) & ~31) / 8);
Bmpi->bmiHeader.biSizeImage=
DestNumberOfBytesPerRow * bm->Height;

char* buff=new char[Bmpi->bmiHeader.biSizeImage];

glReadPixels (0, 0, Panel1->Width, Panel1->Height, GL_RGBA,
GL_UNSIGNED_BYTE, buff);

Image1->Picture->Bitmap = bm;
delete bm;

HTH
Michel
--
----------------------------------------
Michel Leunen
mailto: see my homepage.
C++Builder, BCC5.5.1 Web site:
www.leunen.com/
----------------------------------------
//------------------------------------------------------------------------------
I try to solve problem in that way:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Graphics::TBitmap *bm = new Graphics::TBitmap;
bm->Width = Panel1->Width;
bm->Height = Panel1->Height;
bm->HandleType = bmDIB;
Memo1->Lines->Add(Panel1->Width);
Memo1->Lines->Add(Panel1->Height);
bm->PixelFormat = pf32bit;
int bit = 4;
unsigned char *buff = new unsigned char[Panel1->Width*Panel1->Height*bit];
unsigned char *buff2 = new unsigned char[Panel1->Width*Panel1->Height*bit];
for (int i = 0 ; i < Panel1->Width*Panel1->Height*bit ; i++)
{
buff[i] = 0;
buff2[i] = 0;
}
glReadPixels(0, 0, Panel1->Width, Panel1->Height, GL_RGBA, GL_UNSIGNED_BYTE,
buff);
for(int i = 0 ; i < Panel1->Height ; i++)
{
for (int j = 0 ; j < Panel1->Width*bit ; j++)
{
buff2[Panel1->Width*4*i+j] =
buff[Panel1->Width*4*(Panel1->Height-i-1)+j];
}
}
for(int i = 0 ; i < Panel1->Width*Panel1->Height ; i++)
{
buff[i*4+2] = buff2[i*4+0];
buff[i*4+1] = buff2[i*4+1];
buff[i*4+0] = buff2[i*4+2];
}
BitmapFromBuffer(bm,buff,32);
Image1->Picture->Bitmap = bm;
delete buff;
delete buff2;
delete bm;
}
//---------------------------------------------------------------------------
void TForm1::BitmapFromBuffer(Graphics::TBitmap *Bitmap, unsigned char
*buffer,
unsigned int color_depth)
{
LPBITMAPINFO lpBitmapInfo;
// GlobalAlloc() z GMEM_FIXED flag zwroaca wskaznik
lpBitmapInfo = (BITMAPINFO*)GlobalAlloc(GMEM_FIXED,
sizeof(BITMAPINFO));
// czyszcze strukture BitmapInfo
ZeroMemory(lpBitmapInfo, sizeof(BITMAPINFO));
// Inicjalizuje strukture BitmapInfo
lpBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpBitmapInfo->bmiHeader.biWidth = Bitmap->Width;
lpBitmapInfo->bmiHeader.biHeight = Bitmap->Height;
lpBitmapInfo->bmiHeader.biPlanes = 1;
lpBitmapInfo->bmiHeader.biBitCount = (WORD)color_depth;
lpBitmapInfo->bmiHeader.biCompression = BI_RGB;
//uzycie kontekstu urzadzenia aby wywolac GetDiBits
// use screen's DC for the call to GetDIBits
HDC ScreenDC = GetDC(NULL);
HBITMAP HBitmap = Bitmap->ReleaseHandle();
//obliczeni potrzebnej pamieci
// Call GetDiBits first with a NULL lpBits
// parameter so the device driver
// will calculate the biSizeImage field to
// tell us how much memory to allocate
// for the Bits
GetDIBits(ScreenDC, HBitmap, 0,
lpBitmapInfo->bmiHeader.biHeight,
NULL, lpBitmapInfo, DIB_RGB_COLORS);
//jezeli sterownik nie obliczy rozmiaru liczymi go sami
// if the driver didn't calculate the size
// lets estimate it ourselves
if (lpBitmapInfo->bmiHeader.biSizeImage == 0)
{
lpBitmapInfo->bmiHeader.biSizeImage =
((((Bitmap->Width * color_depth) + 31) & ~31) / 8) *
Bitmap->Height;
}
// create a new buffer to hold the 32-bit aligned data
unsigned char *bits =
new unsigned char[lpBitmapInfo->bmiHeader.biSizeImage];
for (int i = 0 ; i < lpBitmapInfo->bmiHeader.biSizeImage ; i++)
{
bits[i] = 0;
}
// calculate the zero-padding per image
int padding = lpBitmapInfo->bmiHeader.biSizeImage -
(lpBitmapInfo->bmiHeader.biWidth *
(color_depth / 8) * lpBitmapInfo->bmiHeader.biHeight);
// calculate the zero-padding per row
int row_padding = padding / lpBitmapInfo->bmiHeader.biHeight;
// copy the buffer to the bits (accounting for DIB being
// stored upside-down)
for (int y = 0; y < Bitmap->Height; y++)
{
int x_padded = 0;
int row = Bitmap->Width * (color_depth / 8) * y;
int bottom_row = Bitmap->Width * (color_depth / 8) *
(Bitmap->Height - y - 1);
for (unsigned int x = 0;
x < Bitmap->Width * (color_depth / 8); x++)
{
*(bits + x_padded + bottom_row) = *(buffer + x + row);
x_padded++;
}
x_padded = x_padded + row_padding;
}
// set the bits to the bitmap
SetDIBits(ScreenDC, HBitmap, 0, lpBitmapInfo->bmiHeader.biHeight,
bits, lpBitmapInfo, DIB_RGB_COLORS);
delete [] bits;
GlobalFree(lpBitmapInfo);
// oddaje divice constekt
ReleaseDC(NULL, ScreenDC);
// Restore the handle
Bitmap->Handle = HBitmap;
}
But I have problem. When Panel1 is small this program works very good but
when Panel1 is quite big that means Height and width are over 400 pix. Some
errors appear on bitmap or bitmap is white, without any image. Does anyone
knows why??
 

{smallsort}

Re:OpenGl image to Tbitmap

"wowiii" < XXXX@XXXXX.COM >wrote in message
Quote
int *buff = new int[Panel1->Width*Panel1->Height];
As Micheal pointed out, your buffer is too smal.
Quote
Mu question is how to insert buff data to bm(Tbitmap)????
Have a look at the SetDIB...() functions, such as SetDIBits(),
SetDIBitsToDevice(), and SetDIBColorTable().
Gambit
 

Re:OpenGl image to Tbitmap

Remy Lebeau (TeamB) wrote:
Quote
"wowiii" < XXXX@XXXXX.COM >wrote in message
news:446705e5$ XXXX@XXXXX.COM ...

>int *buff = new int[Panel1->Width*Panel1->Height];

As Micheal pointed out, your buffer is too smal.
Am missing something here? He's sizing the buffer with ints, which I
understand to be 32 bits wide in BCB, so the RGBA pixels ought to fit, yes?
-- Pete