(managed) bitmap from unmanaged (char) array in MC++

sem00009

Member
Joined
Nov 11, 2003
Messages
6
I am trying to create a new Bitmap in MC++ from a (char) array (values from 0..255) . I have already searched some forums but unfortunately I cannot get it work. Thats my code:

int row, column;
char* arr = new char[size];

// values initialized here

/*
I know that I have to change the permissions here, but the line

[SecurityPermissionAttribute(SecurityAction::Deny,UnmanagedCode=true)]

does not work. I have included System::Security::Permissions, but I guess I have to do more!

*/

// init IntPtr with address of array, ? correct ?
IntPtr iP = IntPtr(&arr);

Bitmap *p = new Bitmap(
row,column,row*sizeo(char),
System::Drawing::Imaging::PixelFormat::Format8bppIndexed,
iP);

.... and this does not work!

Is there anybody who can give me a hint how to do this?

Thanks,

Franz
 
Last edited by a moderator:
Code:
Bitmap *p = new Bitmap(row,column,row*sizeo(char),System:rawing::Imaging::PixelFormat::Format8bppIndexed,iP);
this is wrong. you are relating to the wrong thing. the
Code:
 row*sizeo(char)
should be the size in bytes of the stride... meaning one line of the image. so it should be (assuming you are using 8 bits-per-pixel)
Code:
Bitmap *p = new Bitmap(row,column,row,System:rawing::Imaging::PixelFormat::Format8bppIndexed,iP);
it is now "row" because its "row*1" since each pixel has 8bits = 1 byte.

as for the rest of the code, i cant say much.
 
Thanks Menge!

I have tried that myself, but sizeof(char) is 1 as expected - so nothing changed!

Now I will try to rewrite the FastBitmap-Class from the Microsoft dotnet Homepage in C++. When I have success I will post ist here!

At the moment I am using SetPixel, which works but is too slow for my (planned) application!

Thanks for the prompt answer,

Franz
 
Now my solution that works - not with constructor:

// arr is an array with unsigned char (0..255)
// values are from Image Class (image) used in this text
// i is integer with number of pixels!

// pointer on array
char *ptr=(char*) arr;

int row,column,columnLength;
columnLength = image->Width;

// setPixel Bitmap
Bitmap *p = new Bitmap(image->Width,image->Height,System::Drawing::Imaging::PixelFormat
::Format24bppRgb);

// pointer Bitmap
Bitmap *p2 = new Bitmap(image->Width,image->Height,System::Drawing::Imaging::
PixelFormat::Format24bppRgb);

Rectangle rect = Rectangle(0,0,image->Width,image->Height);

System::Drawing::Imaging::BitmapData *bmd = p2->LockBits(rect,System::Drawing::Imaging:
:ImageLockMode::WriteOnly,System::Drawing::Imaging::PixelFormat::Format24bppRgb);

unsigned char *origPointer = (unsigned char*) bmd->Scan0.ToPointer();

unsigned char *localPointer;

// one row is always multiple of 4!!!
int width = image->Width * 3; // 3 byte per Pixel!
if(width%4!=0){
width=4*(width/4+1);
}

while(i--){

row = i/columnLength;
column = i%columnLength;

// slow
int value=(int)((unsigned char)*ptr);
Color c = System::Drawing::Color::FromArgb(value,value,value);
p->SetPixel(column,row,c);

// fast
localPointer= origPointer + row * width + column * 3;
*localPointer = (unsigned char) *ptr;
*localPointer++;
*localPointer = (unsigned char) *ptr;
*localPointer++;
*localPointer = (unsigned char) *ptr;

*ptr++;

}

cout<<"setPixel stopped\n";

p2->UnlockBits(bmd);

p->Save("test.jpg",System::Drawing::Imaging::ImageFormat::Jpeg);

p2->Save("test2.jpg",System::Drawing::Imaging::ImageFormat::Jpeg);
 
Last edited by a moderator:
alternative

The first time you tried you were trying to use an 8 bit per pixel format with an index for the pallete at the beginning. so the Bitmap class assumed that about the pointer you gave it. It is obvious why it failed if your pixel format was actually 24 bytes per pixel, which not only has more bytes, but also it does not have an index for the colors used.

If all you wanted to do was to create a Bitmap out of an array pointing to this you could have done this directly

Bitmap *p = new Bitmap(row,column,row*3,System::Drawing::Imaging::PixelFormat::Format24bppRgb,iP);

which should work just fine.

The only time you will run into problems with this method will be when trying to a lot of bitmaps in a loop, such as displaying live video by displaying invidual frames. In that case you allocate too many new Bitmaps which in turn start to fill up the managed heap.

In that case you want to use LockBits and BitmapData to copy the pixels directly instead of creating a new object.

As far as IntPtr goes, I say just stick to unsigned char * for pointers.

// make this
unsigned char* arr = new unsigned char[size];

then just call the above function like this

Bitmap *p = new Bitmap(row,column,row*3,System::Drawing::Imaging::PixelFormat::Format24bppRgb,arr);
 
Back
Top