Как правильно преобразовать управляемое растровое изображение в неуправляемое растровое изображение? - PullRequest
0 голосов
/ 05 февраля 2011

Я пытаюсь создать текстурированный куб, используя OpenGL в Visual C ++. NET 2008. После некоторого поиска, используя 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);

Используя BMP-файл 24bpp, он застрял на строке lockbit с сообщением System.ArgumentException: Дополнительная информация: параметр недействителен.

Что я сделал не так ????


Я только что нашел правильное решение. Это потому что пара проблем:

  1. Я использую неправильную перегруженную функцию. Посмотрите, как я называю lockBits
  2. Я не инициализирую указатель dataBitmap.
  3. А также, поскольку 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);     
}

1 Ответ

1 голос
/ 06 февраля 2011

Я использую следующий код для копирования Растровое изображение данных:

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

Итак, убедитесь, что неимеют значения формата Indexed или Gdi в пикселях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...