(This problem has also been put on Stack Overflow, but I've not seen any results there as of yet:
I am writing a support class for sprite/texture atlas functionality, using C# with OpenTK. Most functionality is working fine thus far (simple 2D tiles on an orthographic view).
My problem relates to unexpected display results when calling the GDI+ Bitmap.MakeTransparent() method to set a color (Magenta / 0xFFFF00FF) for use as a color-key.
It would seem that I am using incorrect pixel format parameters for the bitmap.LockBits() and GL.TexImage2D() calls. My code was based on examples which indeed worked, but which had in common that the rectangle passed to LockBits() was for the entire image.
The calls which pertain to this process are:
<!-- language: C# --> Bitmap bitmap = new Bitmap(filename); bitmap.MakeTransparent(Color.Magenta); GL.GenTextures(1, out texture_id); GL.BindTexture(TextureTarget.Texture2D, texture_id); // "rect" is initialized for one of: // - the dimensions of the entire image // (0, 0, bitmap.width, bitmap.height) // - the dimensions for a sub-rectangle within the image (for one tile) // (tile_x * tile_width, tile_y * tile_height, tile_width, tile_height) // I observe different behaviors for a sub-rectangle, // as compared to the entire image, when in combination with // the .MakeTransparent() call. // // This code is in a load_tile() method, and the plan was to make // multiple calls per image file, one per tile to extract as a GL texture. // Without transparency, that worked fine. Rectangle rect = new Rectangle(xx, yy, width, height); BitmapData data = bitmap.LockBits(rect, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); // In the absence of calling bitmap.MakeTransparent(), // images loaded and displayed as expected with Format24bppRgb. // With MakeTransparent() and Format32bppRgb, the results seem to be OS-dependent. // (At first I thought the "correct" combination to be found, // but then found that the results were "right" only under Windows 7.) GL.TexImage2D( OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, // texture_target, 0, // level, OpenTK.Graphics.OpenGL.PixelInternalFormat.Rgba, // internal_format data.Width, data.Height, // width, height, 0, // border, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, // pixel_format OpenTK.Graphics.OpenGL.PixelType.UnsignedByte, // pixel_type data.Scan0 // pixels ); // Certainly the internal_format and pixel_format arguments are pertinent, // but other combinations I have tried produced various undesired display results. // After reading various (OpenGL, OpenTK, and GDI+) docs, still I am not enlightened.. bitmap.UnlockBits(data);
I have tested a small demo using the code above on different boxen, and observe these results:
Windows 7 box: magenta pixels act as transparent (the desired result)
Windows XP box: magenta pixels rendered as black
Ubuntu Linux box: magenta pixels rendered as magenta
This surprises me, as I anticipated that (GDI+ and OpenGL and the OpenTK bindings) would act the same on different boxes.
To the extent that I have absorbed the GDI+ and OpenGL / OpenTK API documentation, I think my puzzlement relates to these two points:
What is a correct way of calling MakeTransparent() + LockBits() + GL.TexImage2D(), so as to result in the specified color being rendered as transparent?
Why do I see strange display results (as if the "stride" was mis-calculated) for certain pixel format parameter combinations, when LockBits() is called for a sub-rectangle rather than the entire image?
(I can post complete code, or images showing what I am seeing on the not-working system combinations, if wanted.)