Navigation

Related Articles

Back to Latest Articles

C# Tutorial: How To Scale Images Without Deforming Them


Andraz Krzisnik
C# Tutorial: How To Scale Images Without...

Let’s Get Started

A very basic problem that we face in image processing is how to scale images without making them look deformed when we want to make it of an arbitrary size.

This tutorial will show you, how you can take images of different sizes and process them in a way, they all come out with a desired size, without stretching them. The no stretching part will be done by adding padding to a smaller dimension, width or height.

This process can prove very useful when preparing training, testing and validating data for a convolutional neural network. Padding added to the image hold 0 for all color channels or in other words it’s black. Image being processed will always be placed in the middle, regardless if the padding will be added horizontally or vertically.

This project is related to a Zero Padding Project, which adds a border of desired thickness all around the image.


We Will Scale Images With a Function That Returns Processed Image

Let’s take a look at the function that will be doing the heavy lifting for us.

private Bitmap Resize(Bitmap img, int dim)
{
    img = ScaleImage(img, dim, dim);
    int w = img.Width;
    int h = img.Height;
    int p = (dim - Math.Min(w, h)) / 2;
    int padw = (w < h) ? p : 0;
    int padh = (h < w) ? p : 0;
    BitmapData sd = img.LockBits(new Rectangle(0, 0, w, h),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    int bytes = sd.Stride * sd.Height;
    byte[] buffer = new byte[bytes];
    Marshal.Copy(sd.Scan0, buffer, 0, bytes);
    img.UnlockBits(sd);
    Bitmap resimg = new Bitmap(dim, dim);
    BitmapData rd = resimg.LockBits(new Rectangle(0, 0, dim, dim),
        ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    int resbytes = rd.Stride * rd.Height;
    byte[] result = new byte[resbytes];
    Array.Clear(result, 0, resbytes);
    int rcurrent,bcurrent = 0;

    for (int y = padh; y < h + padh; y++)
    {
        for (int x = padw; x < w + padw; x++)
        {
            rcurrent = y * rd.Stride + x * 4;
            bcurrent = (y - padh) * sd.Stride + (x - padw) * 4;
            for (int i = 0; i < 3; i++)
            {
                result[rcurrent + i] = buffer[bcurrent + i];
            }
            result[rcurrent + 3] = 255;
        }
    }
    Marshal.Copy(result, 0, rd.Scan0, resbytes);
    resimg.UnlockBits(rd);
    return resimg;
}

As you can see this is a function that takes 2 arguments, one for the image we are processing and the other for a dimension of which will be the new width and height. Since this was purposefully made for further processing with convolution, both dimensions are of the same size.

Complete Project Available For Download

Download Project

 

Related Articles

C# Tutorial

C# Tutorial: How To Convert a Color Image To Grayscale

Grayscale images are basically black and white images. These images are good for programming, since their pixels hold only intensity values or in other words, shades of gray, they...

Posted on by Andraz Krzisnik
Frequency Domain Filtering

How To Use Bandpass Filters – C# Guide

Bandpass filters are the counterpart of bandreject filters. Therefore, they attenuate every frequency outside the ring. In case you’re just tuning in, let me clarify what I...

Posted on by Andraz Krzisnik