EnhancedImage Project






4.94/5 (21 votes)
Sep 1, 2005
4 min read

70061

2896
An article about how to enhance current image characteristics
Introduction
As we all know, raster images cannot scale very well. If you try to scale the image, you will run into jagged pixelization. Of course, you can use vector images to overcome this problem. However, we still need to deal with raster images as well. Now, enter the EnhancedImage
project: it simply helps us to scale the image gracefully by introducing Insets concept.
I have been asked many times how to do scaling of raster images. I believe, programmers who have worked in web-based development have already run into similar cases like that. And probably, many times, they must have come up with quick and dirty solutions by writing custom code for a customized look and feel. I will use a well known technique to accomplish the desired effect. In this approach, the idea is quite simple: divide the picture into several regions and draw them separately. And here is the key: draw some of them as is, and let the others be stretched to satisfy the required image dimension.
Now, let's take a look at the following image. As you can see, the image is divided into 9 regions. I call them, NW, N, NE, W, Center, E, SW, S, and SE, where N: North, S: South, E: East and W: West.
In order to scale well, we will draw all corner images as-is. However, the regions in the middle (such as N, W, E, S, and Center) will be all scaled (stretched). Therefore L1, L3, L4 and L6 are constant, on the other side L2 and L5 should be calculated properly. At this point, let me introduce the Insets
class to you. It is a simple class that just holds the left, top, bottom and right values. In the previous image, the Insets
object required at the constructor of the EnhancedImage
class will be the borders of the center region. The following code provides a good detail of information about the usage of the Insets
.
In short, the EnhancedImage
class simply accomplishes this graceful scaling effect. Also, developers will be able to adjust the opacity of the image as well. A few things that I need to explain here. As you may know, the Image
in .NET is an abstract base
class. However, it is defined as an internal
class in the System.Drawing
namespace. That means, we cannot simply derive a new class based on it. It does provide functionality for System.Drawing.Bitmap
and System.Drawing.Imaging.Metafile
. Guess what? These two concrete classes are also sealed
and therefore cannot be extended! Wow! What are we going to do? All that means is that we cannot establish a 'IS-A' relationship, but there is nothing that can stop us establishing a 'HAS-A' relationship. And that's really what we are going to do here. In my implementation, I have a private
data member called mPeer
to represent a base image for me.
The most interesting part of the code is the PrepareRegions()
method:
//----------------- Regions -----------------
// 0,0 ----- L,0 -------------- R,0 ---- W,0
// | | | |
// | NW | N | NE |
// | | | |
// 0,T ----- L,T -------------- R,T ---- W,T
// | | | |
// | W | C | E |
// | | | |
// 0,B ----- L,B -------------- R,B ---- W,B
// | | | |
// | SW | S | SE |
// | | | |
// 0,H ----- L,H -------------- R,H ---- W,H
//--------------------------------------------
Insets sourceNW = new Insets(0, 0, L, T); // North West
Insets sourceN = new Insets(L, 0, R, T); // North
Insets sourceNE = new Insets(R, 0, W, T); // North East
Insets sourceW = new Insets(0, T, L, B); // West
Insets sourceC = new Insets(L, T, R, B); // Center
Insets sourceE = new Insets(R, T, W, B); // East
Insets sourceSW = new Insets(0, B, L, H); // South West
Insets sourceS = new Insets(L, B, R, H); // South
Insets sourceSE = new Insets(R, B, W, H); // South East
// Update values for destination regions
// (some values don't need to be changed!)
W = Width; // Width (EnhacedImage)
H = Height; // Height (EnhacedImage)
R = W - sourceSE.Width; // Right
B = H - sourceSE.Height; // Bottom
Insets destinationNW = new Insets(0, 0, L, T); // North West
Insets destinationN = new Insets(L, 0, R, T); // North
Insets destinationNE = new Insets(R, 0, W, T); // North East
Insets destinationW = new Insets(0, T, L, B); // West
Insets destinationC = new Insets(L, T, R, B); // Center
Insets destinationE = new Insets(R, T, W, B); // East
Insets destinationSW = new Insets(0, B, L, H); // South West
Insets destinationS = new Insets(L, B, R, H); // South
Insets destinationSE = new Insets(R, B, W, H); // South East
// Now, let's draw all regional pairs one by one...
DrawInsetsOn(g, sourceNW, destinationNW); // North West
DrawInsetsOn(g, sourceN, destinationN); // North
DrawInsetsOn(g, sourceNE, destinationNE); // North East
DrawInsetsOn(g, sourceW, destinationW); // West
DrawInsetsOn(g, sourceE, destinationE); // East
DrawInsetsOn(g, sourceSW, destinationSW); // South West
DrawInsetsOn(g, sourceS, destinationS); // South
DrawInsetsOn(g, sourceSE, destinationSE); // South East
// Should we draw the center piece?
if (mDrawCenter)
DrawInsetsOn(g, sourceC, destinationC); // Center
.
.
.
If you are interested in the details, I would recommend that you take a good look at that part of the code.
Using the Code
OK, how do we use the new class? Actually, it is quite simple. First, create your enhanced image based on a base image, provide the insets, the desired width and height of the your enhanced image, and of course, the opacity value. And voila! It is there for you to use. :)
Insets insets = new Insets(left, top, right, bottom);
EnhacedImage enhancedImage = new EnhancedImage(baseImage,
width, height, insets, opacity);
.
.
.
// Let's draw the image somewhere in our program
Graphics g; // Obtain a graphics object here
// We need to obtain the regular representation
// of the enhanced image here
Image reqularImage = enhancedImage.RegularImage;
// And draw it just like any other image.
g.DrawImage(regularImage, x, y); // Draw it as usual at x, y.
Points of Interest
Now it is time to take a look at the provided program. It has quite a few knobs for you to play with. You can change the inset points visually by using the Insets Adjuster. Opacity, width and height can be also changed on the fly by sliding the trackbars. You will realize that interesting effects can be accomplished by changing the insets. Also take a look at the scaling effect by toggling the check box called Scale
Properly. You will realize the regular vs. properly scale image differences right away. Also, don't forget to try different sample images provided in the application program.
History
I used similar techniques in my Java applications. Now, I added the same functionality to my C# library. You can always provide feedback and feature request so that we can make it even better.
Have fun! :)
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.