Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

BCB v1 Scanline/PixelFormat

65 views
Skip to first unread message

Liam A. Doyle

unread,
Sep 4, 1999, 3:00:00 AM9/4/99
to
Dear All,

I tryed using the code containing ScanLine() and PixelFormat(), posted in
reply to TBitmap or Not by Manu, and get the error message

'ScanLine' is not a member of Graphics::TBitmap.

I assume that this is because I am using BCB 1. If this is correct does
anyone have alternative code. The original code posted is below.Thanks in
advance

Liam.
P.S I am trying to display a 512x512 16bit integer array as an image.
> int i,j;
> int size=256;
> // First you need to create a grey logical palette
> PALETTEENTRY pe[256];
> LOGPALETTE lp;
> HPALETTE hp;
> for (i=0;i<256;i++)
> {
> pe[i].peRed=i;
> pe[i].peGreen=i;
> pe[i].peBlue=i;
> pe[i].peFlags=PC_NOCOLLAPSE;
> }
> lp.palVersion=0x300;
> lp.palNumEntries=256;
> hp=CreatePalette(&lp);
> SetPaletteEntries(hp,0,256,pe);
>
> // Create the image to map
> char map[256][256],*ptr;
> int k=4;
> for (i=0;i<size;i++)
> {
> for (j=0;j<size;j++)
> {
>
map[i][j]=(cos((k*6.28/256.0)*j)+1.0)*64+(cos((k*6.28/256.0)*i)+1.0)*64;
> }
> }
>
> // Create the bitmap
> Graphics::TBitmap *bitmap;
> bitmap=new Graphics::TBitmap();
> bitmap->PixelFormat=pf8bit; // Make it 256 Color palette
> bitmap->Palette=hp; // Assing the 256 gray scale palette
> bitmap->Width=size;
> bitmap->Height=size;
> // Copy the map igage in to the Bitmap Object
> for (i=0;i<size;i++)
> {
> ptr=(char *)bitmap->ScanLine[i];
> _wmemcpy(ptr,map[i],128);
> }
>
> Canvas->Draw(0,0,bitmap); // Draw it into your bitmap
>
> DeleteObject(hp);
> delete bitmap;
>

Damon Chandler

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
Hi Liam,

> I tryed using the code containing ScanLine() and PixelFormat(), posted in
> reply to TBitmap or Not by Manu, and get the error message
> 'ScanLine' is not a member of Graphics::TBitmap.
> I assume that this is because I am using BCB 1. If this is correct does
> anyone have alternative code.

BCB1 doesn't have the ScanLine method, however, using a few DIB methods, you can
write your own. The Graphics.pas unit has two helper functions to ease the use
of DIB's: GetDIBSizes() and GetDIB(). You can use these to get the size of the
bits, the BITMAPINFO structure, and the actual bits. DIBs give you faster
access to the pixels, but DDBs render faster. As such, use DIB methods to
manipulate the pixels, then use SetDIBits() to set the bits to the DDB. Here's
some code that may help...

//in header...
Graphics::TBitmap *Bitmap;
LPBITMAPINFO lpbmi;
unsigned char *bits;
unsigned char *__fastcall ScanLine(int row);

//in source...
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Bitmap = Image1->Picture->Bitmap; // 24-bit bitmap
HBITMAP Hbm = Bitmap->ReleaseHandle();
HPALETTE Hpal = Bitmap->ReleasePalette();

// calculate the size needed for the bits
int InfoHeaderSize, ImageSize;
GetDIBSizes(Hbm, InfoHeaderSize, ImageSize);

// allocate memory for the BITMAPINFO structure and the bits
lpbmi = (LPBITMAPINFO)new unsigned char[sizeof(BITMAPINFO)];
bits = new unsigned char[ImageSize];

// get the BITMAPINFO and bits
GetDIB(Hbm, Hpal, lpbmi, bits);

Bitmap->Handle = Hbm;
Bitmap->Palette = Hpal;
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// free the memory
delete [] lpbmi;
delete [] bits;
}

// this substitues the ScanLine function
unsigned char *__fastcall TForm1::ScanLine(int row)
{
// 24-bit bitmap has 3 bytes per pixel, and it stored
// upside-down therefor the '3' and the 'Height - 1'
row = Bitmap->Width * 3 * (Bitmap->Height - 1 - row);
return (unsigned char *)(bits + row);
}

// example of useage: make the entire bitmap gray
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (int y = 0; y < Bitmap->Height; y++)
{
unsigned char *line = ScanLine(y);
for (int x = 0; x < Bitmap->Width * 3; x++)
line[x] = 128;
}

// call SetDIBits to set the changed bits to the
// device-dependant bitmap
SetDIBits(Bitmap->Canvas->Handle, Bitmap->Handle, 0,
Bitmap->Height, bits, lpbmi, DIB_RGB_COLORS);

Image1->Refresh();
}


Good luck.

--------------------------------------
Damon Chandler

http://bcbcaq.freeservers.com
Answers to <Commonly Asked Questions>

Liam A. Doyle

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
Dear Damon,

Thanks very much for the code example. Just a couple of questions? Where
exactly do the declarations go in the header i.e. public, private etc. I'm
still very new to the C++/builder enviroment. When I put the the code in the
public or private section, put a button and image component on the form and
compile I get the following message:

(Linker Fatal Error) Fatal:Failed to create map to file c:/program
files/borland/cbuilder/bin/project1.tds (error code 0).

Any suggestions or comments? I eventually want to display an image from an
array of 16 bit values. I'm also looking into doing it entirely in API
although it may be pointless if the VCL is easier its educational at least.

Thanks again for your time.

Regards,
Liam


Damon Chandler <dm...@cornell.edu> wrote in message
news:37D52CB6...@cornell.edu...


> Hi Liam,
> > I tryed using the code containing ScanLine() and PixelFormat(), posted
in
> > reply to TBitmap or Not by Manu, and get the error message
> > 'ScanLine' is not a member of Graphics::TBitmap.
> > I assume that this is because I am using BCB 1. If this is correct does
> > anyone have alternative code.
>
> BCB1 doesn't have the ScanLine method, however, using a few DIB methods,
you can
> write your own. The Graphics.pas unit has two helper functions to ease
the use
> of DIB's: GetDIBSizes() and GetDIB(). You can use these to get the size
of the
> bits, the BITMAPINFO structure, and the actual bits. DIBs give you faster
> access to the pixels, but DDBs render faster. As such, use DIB methods to
> manipulate the pixels, then use SetDIBits() to set the bits to the DDB.
Here's
> some code that may help...
>

> file://in header...


> Graphics::TBitmap *Bitmap;
> LPBITMAPINFO lpbmi;
> unsigned char *bits;
> unsigned char *__fastcall ScanLine(int row);
>

> file://in source...

Damon Chandler

unread,
Sep 8, 1999, 3:00:00 AM9/8/99
to
Hi Liam,

> Where exactly do the declarations go in the header i.e. public, private etc.

As long as your don't place them in the __published section, you'll be fine with
either public or private. In most cases, you'll want to place any class members
that are only used within your class, in the private section.


> I'm still very new to the C++/builder enviroment. When I put the the code
> in the public or private section, put a button and image component on the
> form and compile I get the following message:
>
> (Linker Fatal Error) Fatal:Failed to create map to file c:/program
> files/borland/cbuilder/bin/project1.tds (error code 0).

This sounds like a corrupted incremental linker file. Go to your project
directory, and delete all the *.il*, and *.tds files. If that doesn't fix it,
go to the Options | Project menu to bring up the options dialog, then select the
"Linker" tab, and unckeck "Use incremental linker."


> Any suggestions or comments? I eventually want to display an image from an
> array of 16 bit values. I'm also looking into doing it entirely in API
> although it may be pointless if the VCL is easier its educational at least.

There are some aspects that are simpler by using the VCL, but a raw API approach
is oftentimes faster.


Good luck!

0 new messages