Resumé

GDIplus and C-Sharp Rating Image

Cristian Merighi () 0.00

How to create a runtime image, overlaying multiple objects and exploiting what the GDI+ classes of the .Net Framework can offer.
This article is obsolete. Some functionalities might not work anymore. Comments are disabled.

With this article I'll try to show how to use .Net GDI+ APIs to combine at runtime physical and virtual images.
There's abundance of help requests, in various forums, about how-to overlay multiple images exploiting .Net tools, I think that the following example could be helpful and clarifying.
As usual let's define a real world scenario to contextualize the theoretical stuff:

  • goal
    create an image to visualize, using the "classical" five stars, a variable rating between 0 and 5 (double type values)
  • instruments
    C#, GDI+ and Adobe® Photoshop, or similar (used to create base images)

The idea is to assemble a sandwich triple-layered image.

  1. On the lowest level we put a background image which will act as a placeholder for the "switched-off" stars. The following image is exactly the one used in this blog:
    PNG file
  2. on the intermediate level we will draw a golden rectangle of variable width, depending on the rating value;
  3. on the top level we set a masked and beveled - for aesthetical purposals - image:
    PNG file

Let's dive into the C# code:

// retrieving and normalizing rating value
float rating = Convert.ToSingle(Request.QueryString["Rating"], System.Globalization.CultureInfo.InvariantCulture)/5F;
// creating an instance of Pacem.Drawing.Image using the background image (see step 1)
// (I will illustrate the OverlayImage method next)
Pacem.Drawing.Image pacemimg = new Pacem.Drawing.Image(Server.MapPath("~/Images/CMerighi/Rating_Lower.png"));
Bitmap rect = new Bitmap(pacemimg.Width, pacemimg.Height);
Graphics graph = Graphics.FromImage(rect);
// creating a golden rectangle having the width as fraction related to the rating value 
graph.FillRectangle(Brushes.Gold, new RectangleF(0F, 0F, ((float)pacemimg.Width)*rating, (float)pacemimg.Height));

pacemimg.OverlayImage(rect, Pacem.Drawing.VerticalAnchor.Top, Pacem.Drawing.HorizontalAnchor.Left);
pacemimg.OverlayImage(Server.MapPath("~/Images/CMerighi/Rating_Upper.png"), Pacem.Drawing.VerticalAnchor.Top, Pacem.Drawing.HorizontalAnchor.Left);
rect.Dispose(); graph.Dispose();
Response.ContentType = "image/png";
pacemimg.Flush(Response.OutputStream, "image/png");              
pacemimg.Dispose(); 

Pacem.Drawing.Image is a class I developed myself to manipulate images. It contains scaling, canvas resizing and - above all - color manipulation methods Photoshop-style with algorithms that render results extremely close to those of the Adobe® software. If you know something better please let me know.

Now we go in depth into a form of the - overloaded - method OverlayImage showing how it works. Here's the code:

public void OverlayImage(  
System.Drawing.Image bmp, 
VerticalAnchor vAnchor, 
HorizontalAnchor hAnchor
)
{
    Graphics graph = Graphics.FromImage(bmp);

    int x, y;
    double W, w, H, h;
    // _Bitmap is the inner Bitmap base instance of the Pacem.Drawing.Image class
    W = (double)_Bitmap.Width; H = (double)_Bitmap.Height;
    w = (double)bmp.Width; h = (double)bmp.Height;
    switch (vAnchor)
    {
        case VerticalAnchor.Middle:
            y = (int)((H - h) / 2);
            break;
        case VerticalAnchor.Bottom:
            y = _Bitmap.Height - bmp.Height;
            break;
        default:
            y = 0;
    }
    switch (hAnchor)
    {
        case HorizontalAnchor.Center:
            x = (int)((W - w) / 2);
            break;
        case HorizontalAnchor.Right:
            x = _Bitmap.Width - bmp.Width;
            break;
        default:
            x = 0;
    }
    Rectangle destR = new Rectangle(x, y, bmp.Width, bmp.Height);

    Bitmap _Bmp = new Bitmap(_Bitmap.Width, _Bitmap.Height);
    Graphics _Graph = Graphics.FromImage(_Bmp);
    _Graph.DrawImage(_Bitmap, 0, 0, _Bitmap.Width, _Bitmap.Height);
    // key instruction for overlaying
    _Graph.DrawImage(bmp, destR, new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
    _Bitmap = _Bmp;
    // _Graphics is the inner Graphics base instance of the Pacem.Drawing.Image class
    _Graphics = Graphics.FromImage(_Bitmap);
    bmp.Dispose(); graph.Dispose(); _Graph.Dispose();
}
 

That's it.

Take care. Bye.

feedback
 

Syndicate

Author

Cristian Merighi facebook twitter google+ youtube

Latest articles

Top rated

Archive

Where am I?

Author

Cristian Merighi facebook twitter google+ youtube

I'm now reading

Feeds