Enlarging an image without blurring by taking one pixel and turning it into four on a new image with different dimensions

StackOverflow https://stackoverflow.com/questions/22113324

Question

I have previously written an image enlarger algorithm that enlarges images without blurring by doubling the image size and making a single pixel into four pixels on the new image. This was originally built for 500x500 pixel images and it worked absolutely fine but now I need to use it for an image that has a different width and height.

I have tried changing the values but I cannot get it to work and there maybe something missing but I don't know. Can someone help fix this so it works with different dimensions? It was built to enlarge 500x500 pixel images but the image I need to enlarge is 634x490 pixels.

The original code that works with 500x500 is below and this will work if you paste it into a project and run it but you must supply a 500x500 pixel image to it:

        Bitmap oldImg = new Bitmap(Image.FromFile(@"NameOfImageToEnlarge.png"));
        Bitmap newImg = new Bitmap(1000, 1000);

        System.Drawing.Imaging.BitmapData data = oldImg.LockBits(new Rectangle(0, 0, 500, 500), System.Drawing.Imaging.ImageLockMode.ReadOnly, oldImg.PixelFormat);
        oldImg.UnlockBits(data);
        byte[] rgba = new byte[data.Stride * 500];
        System.Runtime.InteropServices.Marshal.Copy(data.Scan0, rgba, 0, data.Stride * 500);

        using (Graphics g = Graphics.FromImage(newImg))
        {
            for (int x = 0; x < 500; x++)
            {
                for (int y = 0; y < 500; y++)
                {
                    newImg.SetPixel(x * 2, y * 2, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
                    newImg.SetPixel(x * 2 + 1, y * 2, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
                    newImg.SetPixel(x * 2, y * 2 + 1, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
                    newImg.SetPixel(x * 2 + 1, y * 2 + 1, Color.FromArgb(oldImg.GetPixel(x, y).ToArgb()));
                }
            }
            newImg.Save(@"NameOfImageToSave.png");
        }

I also used some help to get the code above to work so I may have explained it more here: Taking pixels from one image and enlarging them on a new image to create a larger version of original

Was it helpful?

Solution

You don't need to do this. The approach you're using is called "Nearest Neighbour" interpolation; you can set this property and then call DrawImage and you're all set:

using(Bitmap source = ...)
using(Bitmap destination = new Bitmap(1000, 1000))
using(Graphics g = Graphics.FromImage(newImg)) {

    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    g.DrawImage( source, new Rectangle( 0, 0, destination.Width, destination.Height ) );
}

Also, if you're using GetPixel and SetPixel there is no need to use LockBits. In fact, in your example you call LockBits and then immediately call UnlockBits, but still read from the BitmapData's pointer, that is dangerous and may result in data-corruption if the GC moves memory around while your code is executing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top