我正在尝试使用Visual C ++ .NET 2008中的OpenGL创建一个带纹理的Cube。 经过一些去角质,使用GLU后,我发现必须使用gluBuild2DMipmaps。
问题是,我使用System :: Drawing :: Bitmap.FromFile()读取位图
现在,如何将此托管的Bitmap对象传递给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文件,它卡在行锁定位上,并显示消息System.ArgumentException:附加信息:参数无效。
我做错了什么????
我刚刚找到了正确的解决方案。这是因为有几个问题:
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);
}
答案 0 :(得分:1)
我使用以下代码复制 Bitmap 数据:
Image image = null;
Bitmap iBitmap = new Bitmap(fs);
BitmapData iBitmapData;
GCHandle hImageData;
if ((iBitmap.Flags & (int)ImageFlags.ColorSpaceRgb) != 0) {
switch (iBitmap.PixelFormat) {
case PixelFormat.Format1bppIndexed:
case PixelFormat.Format4bppIndexed:
case PixelFormat.Format8bppIndexed:
// Allocate image raster
image = new RasterImage<ColorBGR8>(iBitmap.Width, iBitmap.Height);
break;
case PixelFormat.Format16bppRgb565:
// Allocate image raster
image = new RasterImage<ColorBGR16>(iBitmap.Width, iBitmap.Height);
break;
case PixelFormat.Format24bppRgb:
// Allocate image raster
image = new RasterImage<ColorBGR24>(iBitmap.Width, iBitmap.Height);
break;
case PixelFormat.Format32bppRgb:
// Allocate image raster
image = new RasterImage<ColorBGR32>(iBitmap.Width, iBitmap.Height);
break;
case PixelFormat.Format32bppArgb:
// Allocate image raster
image = new RasterImage<ColorABGR32>(iBitmap.Width, iBitmap.Height);
break;
default:
throw new Exception("Image RGB pixel format not supported");
}
} else if ((iBitmap.Flags & (int)ImageFlags.ColorSpaceGray) != 0) {
switch (iBitmap.PixelFormat) {
case PixelFormat.Format1bppIndexed:
case PixelFormat.Format4bppIndexed:
case PixelFormat.Format8bppIndexed:
// Allocate image raster
image = new RasterImage<ColorY8>(iBitmap.Width, iBitmap.Height);
break;
default:
throw new Exception("Image GRAY pixel format not supported");
}
if (RenderContext.Caps.TextureSwizzle == false) {
throw new Exception("unable to load GRAY pixel format image (ARB_texture_swizzle extension not supported)");
}
} else if ((iBitmap.Flags & (int)ImageFlags.ColorSpaceYcbcr) != 0) {
throw new Exception("Image YCbCr pixel format not supported");
} else if ((iBitmap.Flags & (int)ImageFlags.ColorSpaceYcck) != 0) {
throw new Exception("Image YCCK pixel format not supported");
} else if ((iBitmap.Flags & (int)ImageFlags.ColorSpaceCmyk) != 0) {
throw new Exception("Image CMYK pixel format not supported");
} else
throw new Exception("Image pixel format not supported");
// Obtain source and destination data pointers
iBitmapData = iBitmap.LockBits(new Rectangle(0, 0, iBitmap.Width, iBitmap.Height), ImageLockMode.ReadOnly, iBitmap.PixelFormat);
hImageData = GCHandle.Alloc(image.GetPixelData(), GCHandleType.Pinned);
// Alternative without using custom Image class:
//T[,] buffer = new ColorRGB24[iBitmap.Width, iBitmap.Height];
//hImageData = GCHandle.Alloc(buffer, GCHandleType.Pinned);
// Copy Bitmap data to Image
memcpy(hImageData.AddrOfPinnedObject(), iBitmapData.Scan0, iBitmapData.Stride*iBitmapData.Height);
hImageData.Free();
iBitmap.UnlockBits(iBitmapData);
return (image);
您可以注意到我必须通过P / Invoke memcpy 例程来复制锁定的内存。
Image 类是我的项目中定义的类,它将方法 GetPixelData()定义为返回 T [,]的简单例程,其中 T 是如下结构
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ColorRGB24 : IColorRGB<byte>
{
public byte r;
public byte g;
public byte b;
}
阅读以下引用:
Using System.Drawing.Imaging.PixelFormat values, such as Indexed and Gdi, will throw an System.ArgumentException
因此,请确保没有索引或 Gdi 像素格式值。