如何正确地将托管位图转换为非托管位图?
我正在尝试在 Visual C++.NET 2008 中使用 OpenGL 创建纹理立方体。 经过一番谷歌搜索后,使用 GLU,我发现我必须使用 gluBuild2DMipmaps。
问题是,我使用 System::Drawing::Bitmap.FromFile() 读取位图
现在,如何将此托管位图对象传递给 gluBuild2DMipmaps,它接受 const void * 参数???
我已经使用这些代码尝试了 LockBits:
BYTE * data;
/*ambil raw data*/
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,b->Width,b->Height);
System::Drawing::Imaging::BitmapData ^ bitmapData;
b->LockBits(
rect,
System::Drawing::Imaging::ImageLockMode::ReadWrite,
b->PixelFormat ,bitmapData);
::memcpy(data,bitmapData->Scan0.ToPointer(),b->Width * b->Height);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, data);
使用 24bpp BMP 文件,它卡在 lockbit 行上,并显示消息 System.ArgumentException:附加信息:参数无效。
我做错了什么???
我刚刚找到了正确的解决方案。这是因为有几个问题:
- 我使用了错误的重载函数。请参阅我调用 lockBits 的不同方式,
- 我没有初始化指针
dataBitmap
。 - 而且,由于
GLuint *texture;
是托管指针,我必须使用pin_pointer
将其转换为非托管指针。
谢谢,这是正确的方法:
void CBox::LoadTextureRaw(String ^ filename, int wrap)
{
//GLuint texture;
System::Drawing::Bitmap ^ bitmap = gcnew Bitmap(filename);
int h = bitmap->Height;
int w = bitmap->Width;
int s = w * h;
dataTexture = new BYTE[s * 3];
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,bitmap->Width,bitmap->Height);
System::Drawing::Imaging::BitmapData ^ bitmapData =
bitmap->LockBits(rect,System::Drawing::Imaging::ImageLockMode::ReadWrite , System::Drawing::Imaging::PixelFormat::Format24bppRgb);
::memcpy(dataTexture,bitmapData->Scan0.ToPointer(),s);
bitmap->UnlockBits(bitmapData);
pin_ptr<GLuint*> pt = &texture;//pin managed pointer, to be unmanaged... asyeeeem
**pt = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h,GL_RGB, GL_UNSIGNED_BYTE, dataTexture);
}
I am trying to create a textured Cube using OpenGL in Visual C++.NET 2008.
After some googgling, using GLU, I found that I must use gluBuild2DMipmaps.
The problem Is, I read the bitmap using System::Drawing::Bitmap.FromFile()
Now, How do I pass this managed Bitmap object to gluBuild2DMipmaps, which accept const void * parameter???
I already try the LockBits using these code:
BYTE * data;
/*ambil raw data*/
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,b->Width,b->Height);
System::Drawing::Imaging::BitmapData ^ bitmapData;
b->LockBits(
rect,
System::Drawing::Imaging::ImageLockMode::ReadWrite,
b->PixelFormat ,bitmapData);
::memcpy(data,bitmapData->Scan0.ToPointer(),b->Width * b->Height);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, data);
Using a 24bpp BMP file, it stuck on the line lockbit with message System.ArgumentException : Additional information: Parameter is not valid.
What did I do wrong????
I just found the correct solution. It's because a couple of problem:
- I use the wrong overloaded function. See the different in how I call lockBits
- I am not initializing the pointer
dataBitmap
. - And also, as
GLuint * texture;
is a managed pointer, I must convert it into unmanaged pointer usingpin_pointer
.
Thanks, and this is the correct method :
void CBox::LoadTextureRaw(String ^ filename, int wrap)
{
//GLuint texture;
System::Drawing::Bitmap ^ bitmap = gcnew Bitmap(filename);
int h = bitmap->Height;
int w = bitmap->Width;
int s = w * h;
dataTexture = new BYTE[s * 3];
System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,bitmap->Width,bitmap->Height);
System::Drawing::Imaging::BitmapData ^ bitmapData =
bitmap->LockBits(rect,System::Drawing::Imaging::ImageLockMode::ReadWrite , System::Drawing::Imaging::PixelFormat::Format24bppRgb);
::memcpy(dataTexture,bitmapData->Scan0.ToPointer(),s);
bitmap->UnlockBits(bitmapData);
pin_ptr<GLuint*> pt = &texture;//pin managed pointer, to be unmanaged... asyeeeem
**pt = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h,GL_RGB, GL_UNSIGNED_BYTE, dataTexture);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我使用以下代码来复制位图数据:
您可以注意到我必须 P/Invoke memcpy 例程来复制锁定的内存。
Image 类是在我的项目中定义的类,它将方法 GetPixelData() 定义为返回 T[,] 的简单例程,其中 T 是如下所示的结构
请阅读以下引用:
因此,请确保没有 Indexed 或 Gdi 像素格式值。
I use the following code to copy Bitmap data:
You can note I had to P/Invoke memcpy routine to copy locked memory.
The Image class is a class defined in my project, which defines the method GetPixelData() as a simple routine returning a T[,], where T is a structure like the following
Read the following quote:
So, make sure to do not have the Indexed or Gdi pixel format values.