Selecting a region within an Image

The following code snippet shows you how to draw a selection rectangle over the top of an image and crop it accordingly.

You’ll need to add a Button and a PictureBox to a Form.

Click and drag over the PictureBox to select an area and when you’re ready, click the button and it will perform the crop and save the cropped selection as a new image. This follows on from my last post, have a play around with these methods and explore further!



using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Point startPoint = new Point();  //the point(x,y) we start drawing our rectange
        private Rectangle myRectangle = new Rectangle();  //a rectangle

        public Form1()
        {
            InitializeComponent();
        }

        private void pictureBox1_MouseEnter(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Cross;
        }

        private void pictureBox1_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            startPoint.X = e.X;  //start point gets mouse coords
            startPoint.Y = e.Y;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //are we holding the left mouse button?
            {
                Point endPoint = new Point();  //the end point (x,y) of our rectangle
                Pen p = new Pen(Brushes.Red);  //a red pen
                Graphics g = pictureBox1.CreateGraphics();

                endPoint.X = e.X;  //end point gets mouse coords
                endPoint.Y = e.Y;

                pictureBox1.Refresh();  //stop flicker and actually display rectangle

                Size myRectSize = new Size(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);  //calculate the size of our rectangle
                myRectangle = new Rectangle(startPoint, myRectSize);  //assign new rectangle object
                g.DrawRectangle(p, myRectangle);  //and draw it!
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Image myImage = CropImage(pictureBox1.Image, myRectangle);  //crop the image
            myImage.Save("C:\\testPic.png", ImageFormat.Png);  //save it
        }

        private static Image CropImage(Image imageToCrop, Rectangle rect)
        {
            Bitmap b = new Bitmap(imageToCrop);  //new bmp
            Image croppedImage = b.Clone(rect, b.PixelFormat);  //copy a section of the original

            return croppedImage;
        }
    }
}

Advertisements

Image resizing and cropping

A couple of methods to demonstrate the resizing and cropping of images.


private static Image ResizeImage(Image imageToResize, Size newSize)
{
    Bitmap b = new Bitmap(newSize.Width, newSize.Height);  //new bitmap
    Graphics g = Graphics.FromImage((Image)b);  //new graphics object 

    g.InterpolationMode = InterpolationMode.HighQualityBicubic;  //change this depending expanding/shrinking etc..
    g.DrawImage(imageToResize, 0, 0, newSize.Width, newSize.Height);  //draw the new image
    g.Dispose();  //done now thanks.

    return (Image)b;
}

You can of course use GetThumbnail in some instances and avoid all of this convolution, however using the interpolation method above will maintain far better image quality.


private static Image CropImage(Image imageToCrop, Rectangle rect)
{
    Bitmap b = new Bitmap(imageToCrop);  //new bmp
    Image croppedImage = b.Clone(rect, b.PixelFormat);  //copy a section of the original

    return croppedImage;
}

Create a thumbnail image from a ByteArray

So you have an image saved to your database as a byte array, below is a neat little method that accepts it as a parameter, converts it to a thumbnail and spit it back out as a byte array.

public static byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
    using (MemoryStream ms = new MemoryStream())
    using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
    {
        thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        return ms.ToArray();
    }
}

Save an Image to a Filestream

In order to save an image to a database, you should first convert it to a byte array using a filestream. Once completed this byte array can be written to your database, usually being stored as a VarBinary DataType. In order to work with filestreams you must first add a reference to System.IO at the top of your project, the following code will then take care of the rest:

string strBLOBFilePath = yourImageFilePath;
FileStream fsBLOBFile = new FileStream(strBLOBFilePath, FileMode.Open, FileAccess.Read);
Byte[] bytBLOBData = new Byte[fsBLOBFile.Length];

fsBLOBFile.Read(bytBLOBData, 0, bytBLOBData.Length);
fsBLOBFile.Close();

Load Image From Resources

Ok this is easy to do BUT this is not only my blog it is my online memory too and I keep forgetting how to do this! When you have image files loaded into a resource file in your project you can retrieve them like this…

PictureBox1.Image = (Bitmap)Properties.Resources.'filename';