Bitmaps Fundamentals

Introduction to Pictures

A picture is a representation of a type of graphic that displays on a piece of paper, a computer object (such as a form), etc. Here is an example:

A picture can be used as a background for a window or a web page. A picture can also be used for an aesthetic purpose to decorate a form.

Practical LearningPractical Learning: Introducing Bitmaps

  1. Start Microsoft Visual Studio
  2. Create a new Windows Forms App named BitmapsFundamentals

Introduction to Images

To support pictures, the .NET Framework provides a class named Image:

public abstract class Image : MarshalByRefObject,
                              ICloneable,
                              IDisposable,
                              System.Runtime.Serialization.ISerializable

The Image class contains various properties that allow you to get all types of information about a picture (or image). The class also contains methods that can be used to perform various types of operations on images.

Notice that Image is an abstract class, which means you cannot use its object directly in your application.

Introduction to Bitmaps

A bitmap is a computer file that holds the information about a picture and can "physically" represent that picture where necessary. In other words, a bitmap is the intermediary object between an "abstract" image and an actual picture.

To support bitmaps, the .NET Framework provides a class named Bitmap. That class is derived from the Image abstract class:

public sealed class Bitmap : System.Drawing.Image

Both classes are defined in the System.Drawing namespace of the System.Drawing.dll assembly. Since Bitmap is derived from Image, the Bitmap class inherits the properties and methods it can use.

An Image or a Bitmap as an Object

An Image or Bitmap Variable

We have just seen that we can start a picture from an Image or a Bitmap class. From that class, you can declare a variable of an Image or a Bitmap type. You can declare such a variable in the body of a function or method if you plan to use that variable only within that function. This can be done as follows:

private void Exercise_Load(object sender, EventArgs e)
{
    // An Image variable
    Image? _image = null;
    // A Bitmap variable
    Bitmap? _bitmap = null;
}

If you want various methods to use the same image, you can declare the variable in the body of the class. This can be done as follows:

namespace BitmapsFundamentals
{
    public class Exercise : Form
    {
        // An Image variable
        Image? _image;
        // A Bitmap variable
        Bitmap? _bitmap;
    }
}

An Image or Bitmap Argument

You can create a function or method that takes an image or a bitmap as argument. Here is an example:

using System.Drawing.Drawing2D;

namespace GraphicalApplication
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Present(Image img)
        {

        }
    }
}

In the body of the method, you can ignore or use the image or bitmap argument.

An Image/Bitmap Property

In a class, you can create a property that is based on an Image or a Bitmap type. You can create a complete property that starts with a private field. Here is an example:

public class Holder
{
    // A private field
    private Image? img;

    // A complete property
    public ImageImage
    {
        get
        {
            return img;
        }
        set
        {
            img = value;
        }
    }
}

In the same way, you can create an automatic property. Here is an example:

public class Picture
{
    public Bitmap Bitmap;
}

Fundamentals of Getting a Picture

A Bitmap from a Picture

There are various ways you can get a bitmap or picture to use in your application. You can import an existing picture or you can design your own bitmap. To use an existing bitmap, you can open it as a file. To support this, the Bitmap class is equipped with a constructor whose syntax is:

public Bitmap(string filename);

This constructor takes as argument the name of the file or the path to it. Here is an example of using it:

private void btnPicture_Click(object sender, EventArgs e)
{
    Image picture = new Bitmap("woman.bmp");
}

Opening a Picture File

Another way to get a picture in your application is to let a user select it as a computer file. To assist you with this, the .NET Framework provides a class named OpenFileDialog. To give you visual access to that object, the Toolbox is equipped with an Open File Dialog OpenFileDialog object. You can click in the Dialogs section of the Toolbox and click a form. Of course, you can also programmatically declare an OpenFileDialog variable, initialize it, and then use it.

After manually adding a Open File Dialog to a form or dynamically declaring an OpenFileDialog variable, you should indicate the types of files it would open. This is done by specifying a filter. There are different types of graphic files with various extensions.

When providing an Open File dialog box to your application, if you will support various types of graphics, construct a filter accordingly. Here is an example from Microsoft Paint:

Open

As you can see, the bitmap file is on top of the list.

Designing a Bitmap

As opposed to opening an existing picture, you can create your own. You can design a picture inside of Microsoft Visual studio or you can use an external application.

To create a bitmap in Microsoft Visual Studio, on the main menu, you can click Project -> Add New Item... In the middle list of the Add New Item dialog box, click Bitmap File, accept the suggested name or change the name, and click Add. You would be presented with a window you can use. You can either design a bitmap or you can paste an image from the clipboard.

There are many other more sophisticated applications used to create and manipulate graphics.

Fundamentals of Using a Bitmap

Introduction

We have just seen one way to get a bitmap. In later sections, we will see other ways to get a bitmap. Once you have such a bitmap, you can use it in your application. You have many options.

The Background Image of a Form

One of the most fundamental ways you can use a picture is to paint a form with it. To support this, the Control class is equipped with a property named BackgroundImage:

public virtual System.Drawing.Image? BackgroundImage { get; set; }

This property is inherited by the Form class and made available to a form of an application. Notice that this property is of type Image. As a result, if you have an image or an Image-based variable, you can assign it to the Form.BackgroundImage property. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    Image _bitmap = new Bitmap("Landscape.png");

    BackgroundImage = _bitmap;
}

Graphically Drawing an Image

In previous lessons, we learned to draw geometric shapes using the Graphics class. In the same way, that class allows you to display a picture on a Control-based object. To support this, the Graphics class is equipped with an overloaded method named DrawImage. One of the versions of this method uses the following syntax:

public void DrawImage(System.Drawing.Image image, int x, int y);

This version of the Graphics.DrawImage() method takes three arguments. The first argument is an image. The other two arguments specify the top-left coordinates where to start displaying the picture. Here is an example of calling this version of the Graphics.DrawImage() method:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Image _bitmap = new Bitmap("Flying.bmp");
    
    e.Graphics.DrawImage(_bitmap, 20, 20);
}

Passing a Bitmap to a Graphics Object

In our introduction to graphics, we saw various ways of getting a Graphics object, from the CreateGraphics() method of a Control-derived class, from the Win32 Handle of a control, or from the Paint event of a control. Besides these techniques, the Graphics class provides a method named FromImage. Its syntax is:

public static Graphics FromImage(Image image);

This static method takes as argument a variable of type Image. Therefore, when calling this method, pass an Image or an Image-based variable to it. After the method has been called, it produces a Graphics object. Here is an example of getting a Graphics object by calling this method:

private void Exercise_Load(object sender, EventArgs e)
{
    Image flower = new Bitmap("C:\\Exercises\\Flower.png");

    Graphics grapher = Graphics.FromImage(flower);
}

In this example, we first declared an Image variable and initialized it. you may know that such a variable is necessary only if you are planning to use it more than once. Otherwise, you can create the image directly in the parentheses of the Graphics.FromImage() method. This can be done as follows:

private void Exercise_Load(object sender, EventArgs e)
{
    Graphics grapher = Graphics.FromImage(new Bitmap("C:\\Exercises\\Flower.png"));
}

Either way, once you have initialized a Graphics object like that, you can use it like any of the graphics object we have used in previous lessons.

In the above example, we declared the variables (Graphics and Image or Bitmap in the method that needed them. Remember that if you want more that one method to share an object, you can declare its variable in the body pf the class.

The Characteristics of a Bitmap

The Location of a Bitmap

To represent a picture in your application, such as on a form, the primary information you must provide is its location. We saw that this information can be passed as the x and the y argument of the Graphics.DrawImage() method. This can be illustrated as follows:

As a reminder, here is an example of calling the above version of the Graphics.DrawImage() method:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    Graphics graph = CreateGraphics();
    Bitmap bmpPicture = new Bitmap("woman1.jpg");

    graph.DrawImage(bmpPicture, 10, 12);
}

As opposed to integers, you can also pass the location's values as floating point numbers. To ssupport this, the Graphics class provides the following version of its DrawImage() method:

public void DrawImage(Image image, float x, float y);

Here is an example of calling it:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    Graphics graph = CreateGraphics();
    Bitmap bmpPicture = new Bitmap("woman1.jpg");

    graph.DrawImage(bmpPicture, 10.50f, 12.20F);
}

You can also specify the location as a Point object. To support this, the Graphics class provides another version of its DrawImage() method as follows:

public void DrawImage(Image image, Point point);

If you want the values of the Point to be floating point numbers, the Graphics class provides the following version of the method:

public void DrawImage(Image image, PointF point);

The Width of a Bitmap

A picture usually appears as a geometric figure such as a rectangle:

A Picture

Through some manipulations, a picture can appear non-rectangular. Regardless of the perception, a picture is meant to fit a rectangular figure. The width of a bitmap is the distance, in pixels, from its left to its right borders. One you have a picture as an object, to let you get its width, the Image class, the parent of the Bitmap class, is equipped with a read-only property named Width:

public int Width { get; }

The classes that are derived from Image inherit this property.

The Height of a Bitmap

The height of a bitmap is the distance, in pixels, from its top to its bottom borders. To let you get the height of an existing picture, the Image class is equipped with a read-only property named Height:

public int Height { get; }

The Initial Size of Bitmap

A picture has a size, represented by a width and a height, in pixels. The size of a picture can be illustrated as follows:

The Size of a Picture

When creating or designing a Bitmap object, you can specify its primary size. To support this, the Bitmap class is equipped with the following constructor:

public Bitmap(int width, int height);

The width and the height arguments are as we illustrated them above. Here is an example of using this constructor:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    Bitmap bmpSample = new Bitmap(450, 625);
}

In this example, we explicitly specified the size values for the new bitmap. If you want the bitmap to use the whole area of a form, you can pass the width and the height of the form as arguments. This can be done as follows:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    Bitmap bmpSample = new Bitmap(Width, Height);
}

After creating such a bitmap, it is empty (but it is validly initialized). One of the most common reasons you create such a bitmap is because you are planning to use it as a placeholder for a picture. To proceed, call the Graphics.FromImage():

private void btnShowPicture_Click(object sender, EventArgs e)
{
    // Create a bitmap
    Bitmap bmpSample = new Bitmap(Width, Height);
            
    /* Then:
     * 1. Call the Graphics.FromImage() method
     * 2. Pass the above bitmap to that method
     * 3. Assign the method call to a Graphics variable */
    Graphics grapher = Graphics.FromImage(bmpBuilding);
}

After that, you can call the Image.FromFile() method to specify the picture file you want the bitmap to hold. Pass that method call to the previously initialized graphic object. This can be done as follows:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    // Create a bitmap
    Bitmap bmpBuilding = new Bitmap(Width, Height);

    /* Then:
     * 1. Call the Graphics.FromImage() method
     * 2. Pass the above bitmap to that method
     * 3. Assign the method call to a Graphics variable */
    Graphics grapher = Graphics.FromImage(bmpBuilding);

    /* 1. Open a picture file by calling the Image.FromFile() method 
     * 2. Pass that picture to the previous created graphic by calling its DrawImage() method */
    grapher.DrawImage(Image.FromFile("C:\\Exercises\\Flower.png"), 0, 0);
}

Finally, you can formally display the bitmap. If you are using a Paint event, you can use theGraphics object associated with event. This can be done as follows:

private void Exercise_Paint(object sender, EventArgs e)
{
    // Create a bitmap
    Bitmap bmpBuilding = new Bitmap(Width, Height);

    /* Then:
     * 1. Call the Graphics.FromImage() method
     * 2. Pass the above bitmap to that method
     * 3. Assign the method call to a Graphics variable */
    Graphics grapher = Graphics.FromImage(bmpBuilding);

    /* 1. Open a picture file by calling the Image.FromFile() method 
     * 2. Pass that picture to the previous created graphic by calling its DrawImage() method */
    grapher.DrawImage(Image.FromFile("C:\\Exercises\\Flower.png"), 0, 0);

    /* Now that the bitmap contains a picture, use the 
     * graphic of the current Paint event to display the bitmap */
    e.Graphics.DrawImage(bmpBuilding, 20, 20);
}

If you are using an event other than Paint, you can call the Control.CreateGraphics() method to get a graphic and display the bitmap. Here is an example of that being done when a button positioned on a form is clicked:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    Bitmap bmpBuilding = new Bitmap(Width, Height);

    Graphics grapher = Graphics.FromImage(bmpBuilding);

    grapher.DrawImage(Image.FromFile("C:\\Exercises\\Flower.png"), 0, 0);

    CreateGraphics().DrawImage(bmpBuilding, 20, 20);
}

One of the most common reasons you create the initial empty bitmap is when you are planning to use it in various methods. In this case, you would declare the bitmap and the graphic variables in the body of a class. You can then initialize them in a constructor of the form or in an event (or method) that would be accessed as soon as possible. In a Paint event, you can use the associated Graphics object to display the previously declared Bitmap variable. At the right time, pass the desired picture file to the previously declared and initialized Graphics object, and ask the compiler to refresh the control that is displaying the bitmap. This is usually done by calling the Control.Invalidate() method. These steps can be performed as follows:

namespace BitmpsFundamentals
{
    public partial class Exercise : Form
    {
        // Start a graphic object
        Graphics? grapher;
        // Start a bitmap object
        Bitmap?   bmpBuilding;

        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            // Initialize the bitmap
            bmpBuilding = new Bitmap(Width, Height);
            // Initialize the graphic object
            grapher = Graphics.FromImage(bmpBuilding);
        }

        private void Exercise_Paint(object sender, PaintEventArgs e)
        {
            // Use a graphic object to display the bitmap
            e.Graphics.DrawImage(bmpBuilding!, 20, 20);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Specify the picture for the graphic
            grapher!.DrawImage(Image.FromFile("C:\\Exercises\\Flower.png"), 0, 0);

            // Refresh the form
            Invalidate();
        }
    }
}

The Size of an Existing Image or Picture

At any time, if you have an existing picture, you may be interested in getting its size as both its width and its height as one object. To support this, the Image class is eqipped with a read-only property named Size:

public System.Drawing.Size Size { get; }

This property produces a Size object. The classes that are derived from Image, such as the Bitmap class, inherit this property. ere is an example of getting the size of a picture:

private void btnShowPicture_Click(object sender, EventArgs e)
{
    OpenFileDialog dlgOpen = new OpenFileDialog();

    if (dlgOpen.ShowDialog() == DialogResult.OK)
    {
        string strFilename = dlgOpen.FileName;
        Bitmap bmpPicture = new Bitmap(strFilename);
        Graphics graph = CreateGraphics();

        graph.DrawImage(bmpPicture, 120, 12);
        int width = bmpPicture.Width;
        int height = bmpPicture.Height;

        txtWidth.Text = width.ToString();
        txtHeight.Text = height.ToString();
    }
}

Here is an example of what this would produce:

The Size of a Picture

The Physical Dimensions of a Bitmap

Besides the Width, the Height, and the Size properties, to let you get the size of a bitmap, the Image class is equipped with a property named PhysicalDimensions:

public System.Drawing.SizeF PhysicalDimension { get; }

As you can see, this property produces the size of its bitmap, in decimal values. Here is an example of accessing this property:

namespace PictureCharacteristics
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Paint(object sender, PaintEventArgs e)
        {
            Graphics graph = e.Graphics;
            Bitmap bmpPicture = new Bitmap("C:\\Exercises\\Building.png");

            graph.DrawImage(bmpPicture, 10, 12);

            Text = "Picture Width: " + bmpPicture.PhysicalDimension.Width + 
                   ", Height: " + bmpPicture.PhysicalDimension.Height;
        }
    }
}

As you can see, this property is of type SizeF but its values depend on the type of picture.

The Transparency of a Bitmap

We already know that a graphic can be made of thousands to millions of colors. When you display a picture in your application, you can ask Microsoft Windows to "see through" one particular color. Seeing through is referred to as transparency. This is an operation regularly needed in graphics applications, the operating system is already equipped to select a default color it considers for transparency. In most cases, you can use that color. Otherwise, for your particular application, you can specify what color you want to use as "see through".

To support picture transparency, the Bitmap class is equipped with an overloaded method named MakeTransparent. It is available in two versions. One of the versions uses the following syntax:

public void MakeTransparent();

When you call this method, it lets the operating system choose the color used for transparency. In most cases, the operating system selects white as the transparency color. Consequently, when you display the picture, wherever a white spot or area is shown on the picture, that area would disappear to show behind it. Here is an example:

Building
private void Form1_Paint(object sender, PaintEventArgs e)
{
    Bitmap bmpBuilding = new Bitmap("building.bmp");
    e.Graphics.DrawImage(bmpBuilding, 0, 0);

    Bitmap bmpMonument = new Bitmap("monument.bmp");
    bmpMonument.MakeTransparent();
    e.Graphics.DrawImage(bmpMonument, 200, 260);
}

This would produce:

Instead of using the default transparency color of the operating system, you can specify your own color. To support this, the Bitmap class provides another version of the MakeTransparent() method. Its syntax is:

public void MakeTransparent(Color transparentColor);

With this method, instead of letting the operating system determine the transparency color, you pass your own as argument. Here is an example:

Flying Bird
private void Form1_Paint(object sender, PaintEventArgs e)
{
    Bitmap bmpFlying = new Bitmap("flying.bmp");
    e.Graphics.DrawImage(bmpFlying, 0, 0);

    Bitmap bmpGlobe = new Bitmap("globe.bmp");
    bmpGlobe.MakeTransparent(Color.Black);
    e.Graphics.DrawImage(bmpGlobe, 20, 120);
}

This would produce:

Transparent

Techniques of Getting an Image

Introduction

In our introductions to pictures, we saw that the Bitmap class is equipped with a constructor that takes a file name or path as argument. Actually, the Bitmap provides various options through different constructors.

An Image from a File

In our introduction to pictures, we saw that one way to get a bitmap is from the Bitmap(string filename) constructor. Indeed, there exist other options.

As another way to get a picture, The Image class, the parent of the Bitmap class, provides an overloaded method named FromFile. The children of the Image class inherit this method. This method has two versions. One of the versions uses the following syntax:

public static Image FromFile(string filename);

As you can see, this is a static method that you call without instantiating the class. The method takes as argument the name of, or the path to, the file. The method returns an Image object. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics grapher = e.Graphics;

    Image img = Image.FromFile("C:\\Exercises\\Flower.png");

    grapher!.DrawImage(img!, 20, 20);

}

In this example, we used an Image object. In some cases, you may want to use a formal bitmap. In that case, you can declare you can declare a Bitmap variable and then cast the returned value of a Bitmap.FromFile() method to a Bitmap object. Here is one to do it:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics grapher = e.Graphics;

    Bitmap img = (Bitmap)Image.FromFile("C:\\Exercises\\Flower.png");

    grapher!.DrawImage(img!, 20, 20);
}

An Image from a Stream

Another technique to get an image is to retrieve it from a stream. To support this, the Image class is equipped with an overloaded method named FromStream. One of the versions of this method uses the following syntax:

public static System.Drawing.Image FromStream(System.IO.Stream stream);

This method takes a Stream-based object as argument. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics grapher = e.Graphics;

    using (Stream stmPicture = new FileStream("C:\\Exercises\\Flower.png", FileMode.Open))
    {
        Image img = Image.FromStream(stmPicture);

        grapher!.DrawImage(img!, 20, 20);
    }
}

Techniques of Getting a Bitmap

A Bitmap from an Image

If you have an Image object, you can convert it to a formal Bitmap object. To support this, the Bitmap class provides a construcor whose syntax is:

public Bitmap(System.Drawing.Image original);

When calling this constructor, pass an Image or an Image-based object. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics grapher = e.Graphics;

    Bitmap img = new Bitmap(Image.FromFile("C:\\Exercises\\Flower.png");

    grapher!.DrawImage(img!, 20, 20);
}

A Bitmap from a Stream

The Bitmap class provides its own additional means to get a picture. This is done through various constructors. One of the constructors takes a stream as argument. Its syntax is:

public Bitmap(System.IO.Stream stream);

When using this constructor, pass a Stream based object. After that, you can use the resulting image as you fit. At a minimum, you can display it on aform. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics grapher = e.Graphics;

    using (Stream stmPicture = new FileStream("C:\\Exercises\\Building.png", FileMode.Open))
    {
        Image img = new Bitmap(stmPicture);

        grapher!.DrawImage(img!, 20, 20);
    }
}

Bitmaps and Icons

Introduction

An icon is primarily a graphics object. As a result, one way to use an icon is as a bitmap.

Converting an Icon to a Bitmap

We already know how to create or get an icon and how to create or get a bitmap. If you have an icon and want to use it as a bitmap, you can first convert that icon to a bitmap. To support this operation, the Icon class is equipped with a method named ToBitmap. Its syntax is:

public System.Drawing.Bitmap ToBitmap();

This method simply turns an Icon object into a bitmap. Once the conversion is made, the method produces a Bitmap object. Once you get that object, you can use the bitmap anyway you want. One simple operation you can perform is to display the bitmap on a form or a control of your choice. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics graph = e.Graphics;

    Icon icoTarget = new("C:\\Exercises\\Target.ico");

    Bitmap bmpTarget = icoTarget.ToBitmap();
    graph.DrawImage(bmpTarget, 20, 20);
}

In the same way, to support the conversion of an icon to a bitmap, the Bitmap class is equipped with a method named FromHicon. Its syntax is:

public static System.Drawing.Bitmap FromHicon(IntPtr hicon);

This method takes the Handle of an icon as argument. To proceed, you can pass an Icon object and apply its Handle property. After calling the method, it produces a Bitmap object. You can then use that object as a bitmap. At a minimum, you can display the bitmap on a form. Here is an example:

private void Exercise_Paint(object sender, PaintEventArgs e)
{
    Graphics graph = e.Graphics;

    Icon icoTarget = new("C:\\Exercises\\Home.ico");

    Bitmap bmpTarget = Bitmap.FromHicon(icoTarget.Handle);
    graph.DrawImage(bmpTarget, 20, 20);
}

In the same way, whether using the Icon.ToBitmap() or the Bitmap.FromHicon() method, you can access one of the Microsoft Windows built-in icons and use it.

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2010-2024, FunctionX Monday 20 May 2024 Next