Bitmap Pixel Values Changing Slightly - Using C#/WinForms/GDI+

Started by
0 comments, last by CandleJack 14 years ago
I'm having a strange problem working with Bitmaps in C#/WinForms. I'm working on a tilemap editor, and I have an ImageList control with the transparency key set to be 0xFF00FF Magenta. For some reason, during the tile extraction process, color values are changing very slightly, so that the human eye doesn't notice the difference, but it's no longer the 0xFF00FF transparency key value, and thus I'm seeing pixels I shouldn't be seeing. First I'll show you how I'm reading in the whole source tilesheet (this part works fine), then I will show you how I am extracting the individual tiles from it to be inserted into the ImageList (this is where the problem is occurring). I'm reading in a source bitmap tilesheet like this:
FileStream fs = System.IO.File.Open(filename, FileMode.Open);
BinaryReader br = new BinaryReader(fs);

// Read bitmap into byte array.
byte[] mapFile;
mapFile = br.ReadBytes(fs.Length);

// Create a memory stream from byte array.
MemoryStream ms = new MemoryStream(mapFile);

// Create Bitmap from memory stream.
Bitmap bmpTiles;
bmpTiles = (Bitmap)Image.FromStream(ms);

bmpTiles.Save("C:\\Temp3.bmp");


When I save the bitmap on the last line in the above code, everything has worked as expected. It saves a copy of the image with all the correct pixel color values. Now what I do from here is I extract the individual tile images into an ImageList control like so:
// Create the destination bitmap and associated graphics object.
Bitmap bmpDest = new Bitmap(tileSize_, tileSize_);
Graphics g = Graphics.FromImage(bmpDest);

Rectangle source = new Rectangle();
source.Width = tileSize_;
source.Height = tileSize_;

// Extract each tile from the source bitmap and add them to the ImageList.
int tileCount = 1;
for (int i = 0; i < bufferRows; i++)
{
    for (int j = 0; j < bufferCols_; j++)
    {
        // If there are no more tiles to load, jump out of the loop.
        if (tileCount >= numTiles + 1)
        {
            break;
        }

        // Calculate where the source tile is located.
        source.X = j * tileSize_;
        source.Y = i * tileSize_;

        // Copy the source tile to the destination bitmap.
        g.Clear(Color.Magenta);
        g.DrawImage(bmpTiles, 0, 0, source, GraphicsUnit.Pixel);
        bmpDest.Save("C:\\Temp4.bmp");

        AddTile((Image)bmpDest);

        tileCount++;
    }
}


So in the above code, I have the line bmpDest.Save("C:\\Temp4.bmp"); which will save the individual tile image to the disk, so while stepping through, I can open it up and inspect the pixel color values. On certain tiles (the ones on the right edge, illustrated below) is where the values are changing. So it would appear that the culprit is the line g.DrawImage(bmpTiles, 0, 0, source, GraphicsUnit.Pixel); Is there something about this that would cause it to not copy the pixel color values exactly as they are in the source image? Like some sort of anti-aliasing? To visually illustrate what is happening, here is the sample tilesheet (zoomed in so that it can be seen easier) that I was using to debug this made up of 16 of the same tile. I also used the fill tool in MSPaint to change the magenta pixels to yellow, to show that all of the magenta pixels are in fact the same value. And here is the bad version of the tilesheet after it was resaved with the bad pixel values. Again I used the fill tool to show that the pixels do NOT have the same values in this case. You can see near the right side that some magenta looking pixels did not change to yellow when I used the fill tool. Instead of 0xFF00FF, some of the magenta looking pixels are 0xFE00FE (ones that are adjacent to darker green pixels) and some are 0xFE01FE (ones that are adjacent to lighter green pixels). It's also strange how it only happens to the tiles on the far right of the tilesheet, and also how the only pixels that change are on the far left side of the tile itself. I would think that it should be happening to all of them. [Edited by - CandleJack on April 11, 2010 3:53:25 PM]
Advertisement
Just wanted to update this. I found a method of the graphics object called DrawImageUnscaled which seems to have fixed it. I don't know why it would be scaling anything when the source and destination are the same size but whatever, it works now.

This topic is closed to new replies.

Advertisement