Mr_Dark's picture

Glu.ScaleImage to OpenTK 0.9.9.3

I have a specific function which will put the data from a bitmap in a byte[]. I used to do this with glu.ScaleImage but now I'm upgrading to OpenTK 0.9.9.3 and it's not possible anymore.

I need to have this byte[] array to I can make a specific color transparent.

// above: load bitmap from file
 
System.Drawing.Imaging.BitmapData data;
data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
 
 byte[] bgrBuffer = new byte[bufferSizeInPixels * 3];
unsafe
{
    fixed (byte* pBgrBuffer = bgrBuffer)
    {
        glu.ScaleImage((OpenTK.Graphics.OpenGL.PixelFormat)32992, w, h, PixelType.UnsignedByte, data.Scan0, w, h, PixelType.UnsignedByte, (IntPtr)pBgrBuffer);
    }
}
 
// below: loop byte array to make specific color transparent

Does anyone have an idea to fix this? I used this method in C++ and I don't know if there's a better way to do this in C#.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

You can scale the System.Drawing.Bitmap directly:

static Bitmap Scale(Bitmap bitmap, int w, int h)
    Bitmap scaledBitmap = new Bitmap(w, h);
 
    // Scale the bitmap in high quality mode.
    using (Graphics gr = Graphics.FromImage(scaledBitmap))
    {
        // Higher quality than GLU, but rather slow. You can safely comment these four lines out for better performance.
        gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
 
        gr.DrawImage(bitmap, new Rectangle(0, 0, w, h), new Rectangle(0, 0, bitmap.Width, bitmap.Height), GraphicsUnit.Pixel);
    }
 
    return scaledBitmap;
}

Here, bitmap is the original image, scaledBitmap is the scaled image and w/h is the scaled width and height. Call this method and retrieve the BitmapData of the scaled bitmap afterwards - and don't forget to Dispose() the original bitmap if you don't need it anymore!

Mr_Dark's picture

I was not scaling the image but putting all it's data in a byte[] so I can read that (it's in a function to create a texture).

Think I've found the solution to my problem using System.Runtime.InteropServices.Marchal

// bitmap is passed in the function
 
            int h = bitmap.Height;
            int w = bitmap.Width;
            int bufferSizeInPixels = w * h;
 
            System.Drawing.Imaging.BitmapData data;
            data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
 
            byte[] bgrBuffer = new byte[bufferSizeInPixels * 3];
            unsafe
            {
                Marshal.Copy(data.Scan0, bgrBuffer, 0, (bufferSizeInPixels * 3));
            }
 
            byte[] bgraBuffer = new byte[bufferSizeInPixels * 4];
            int posBgr = 0;
            int posBgra = 0;
            for (int i = 0; i < bufferSizeInPixels; i++)
            {
                bgraBuffer[posBgra] = bgrBuffer[posBgr]; //This is the buffer value of B.
                bgraBuffer[posBgra + 1] = bgrBuffer[posBgr + 1]; //This is the buffer value of G.
                bgraBuffer[posBgra + 2] = bgrBuffer[posBgr + 2]; //This is the buffer value of R.
 
                //Sets the alpha buffer value.
                if (255 == bgrBuffer[posBgr] && 
                    136 == bgrBuffer[posBgr + 1] && 
                    0 == bgrBuffer[posBgr + 2])
                {
                    bgraBuffer[posBgra + 3] = 0;
                }
                else
                {
                    bgraBuffer[posBgra + 3] = 255;
                }
                posBgr += 3;
                posBgra += 4;
            }