Wednesday, April 13, 2011

Create Rounded Corners And Gradient Images On The Fly!

I am often tasked with taking a mockup and branding a site. This usually involves a custom master page with tweaks to the CSS for the layout and color scheme. It also involves the creation of images used to compliment the UI, the holy grail for some being gradient images and rounded corners. For the amateur graphic designer like myself, this often becomes a tedious task that involves repetitive tweaks to an image. I once had a client tell me that I had the wrong shade of “pumpkin”. (Depending on your disposition, this could result in an act of either running full speed into a brick wall or rocking yourself to sleep every night.)
Enter the poorly named Web Designer Tool! After some experimentation with the System.Drawing and System.Drawing.Drawing2D .NET 2.0 classes, I figured out a way to generate these images on the fly. Now I can rapidly create rounded corners and gradients and don't have to sweat it if a client needs a color or hue adjusted. The rounded corners include many options, including width, height, gradient and solid colors, radius corner size, and border. I also provide a preview feature that integrates the images into a sample html page and launches it in your default browser. I have successfully tested this in IE 6.0 ~ 8.0, Chrome 10.0, and Firefox 4.0.
Note: Although this will fly in the face of CSS purists, I have decided to use a simple table based layout for the preview html. I do make an effort to use DIV based layouts for web design, but in this case I have yet to find approach that works flawlessly across browsers types and versions or that integrates nicely with SharePoint. If you are that CSS guru, I welcome you to take these images and come up with a better approach. If you are successful, I would love to try out your code. You are also welcome to use my Shapes.cs class below and build your own tool. Life will be much easier once CSS 3 has reached enough market penetration and we can simply use the border-radius property.



Download Here
Screenshots
Rounded Corner Generator
image

Rounded Corner Generator (Fit To Screen)
image
Gradient Generatorimage

Sample Generated Images using Default Settings:(Note: A folder is created using the top gradient color.)
image

Rounded Corners with Default Colors:
clip_image001
Rounded Corners with Border Only

clip_image002
Rounded Corners with Header, Footer, and Content using the same background color. Header and Content with the same text color.
clip_image003
Rounded Corners with Footer using the same color as content
clip_image004
Rounded Corners only on the Top Left and Bottom Right
image

Gradient using default colors. Example uses the following html: <html><body style="background-image:url('gradient.png');background-repeat:x"></body></html>
image
Shapes Source Code:This is the Shapes class I created to generate the rounded corners and gradient.
using System.Drawing;
using System.Drawing.Drawing2D;

namespace WebDesignerTool
{
    public class Shapes
    {
        public enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight }
        public enum MiddleType { Top, Bottom }

        public static Bitmap GetRectangleCorner(int width, int height, Color startColor, Color endColor, 
            int radius, Color outlineColor, int outlineThickness, CornerType cornerType)
        {
            Bitmap bitmap = GetRectangle(width * 2, height * 2, startColor, endColor, radius, 
                outlineColor, outlineThickness);
            switch (cornerType)
            {
                case CornerType.TopLeft:
                    bitmap = bitmap.Clone(new Rectangle(0, 0, width, height), bitmap.PixelFormat);
                    break;
                case CornerType.TopRight:
                    bitmap = bitmap.Clone(new Rectangle(width, 0, width, height), bitmap.PixelFormat);
                    break;
                case CornerType.BottomLeft:
                    bitmap = bitmap.Clone(new Rectangle(0, height, width, height), bitmap.PixelFormat);
                    break;
                case CornerType.BottomRight:
                    bitmap = bitmap.Clone(new Rectangle(width, height, width, height), bitmap.PixelFormat);
                    break;
            }
            return bitmap;
        }

        public static Bitmap GetRectangleMiddle(int width, int height, Color startColor, Color endColor, 
            int radius, Color outlineColor, int outlineThickness, MiddleType middleType)
        {
            Bitmap bitmap = GetRectangle((width + outlineThickness + radius) * 4, height * 2, 
                startColor, endColor, 20, outlineColor, outlineThickness);
            int z = width + outlineThickness;
            switch (middleType)
            {
                case MiddleType.Top:
                    bitmap = bitmap.Clone(new Rectangle(bitmap.Width / 2 - width / 2, 0, width, height),
                        bitmap.PixelFormat);
                    break;
                case MiddleType.Bottom:
                    bitmap = bitmap.Clone(new Rectangle(bitmap.Width / 2 - width / 2, height, width, height), 
                        bitmap.PixelFormat);
                    break;
            }
            return bitmap;
        }

        public static Bitmap GetRectangle(int width, int height, Color startColor, Color endColor, int radius, 
            Color outlineColor, int outlineThickness)
        {
            Pen pen = new System.Drawing.Pen(outlineColor, outlineThickness);
            Rectangle originalRectangle = new System.Drawing.Rectangle(0, 0, width, height);
            Rectangle rectangle = new System.Drawing.Rectangle(0, 0, width, height);
            Bitmap bitmap = new Bitmap(width, height);
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                if (radius > 0)
                {
                    graphics.SmoothingMode = SmoothingMode.HighQuality;
                    rectangle = new Rectangle(0, 0, width - (int)pen.Width, height - (int)pen.Width);

                    if (rectangle.Width < 1)
                        rectangle.Width = 1;
                    if (rectangle.Height < 1)
                        rectangle.Height = 1;
                    if (rectangle.Width / 2 < radius)
                        radius = rectangle.Width / 2;
                    if (rectangle.Height / 2 < radius)
                        radius = rectangle.Height / 2;
                    pen.EndCap = pen.StartCap = LineCap.Round;
                    LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, rectangle.Width, 
                        rectangle.Height + (int)pen.Width), startColor, endColor, LinearGradientMode.Vertical);
                    GraphicsPath graphicsPath = new GraphicsPath();
                    graphicsPath.AddArc(rectangle.X, rectangle.Y, radius, radius, 180, 90);
                    graphicsPath.AddArc(rectangle.X + rectangle.Width - radius, rectangle.Y, radius, radius, 270, 90);
                    graphicsPath.AddArc(rectangle.X + rectangle.Width - radius, 
                        rectangle.Y + rectangle.Height - radius, radius, radius, 0, 90);
                    graphicsPath.AddArc(rectangle.X, rectangle.Y + rectangle.Height - radius, radius, radius, 90, 90);
                    graphicsPath.CloseAllFigures();
                    graphics.FillPath(brush, graphicsPath);
                    if (outlineThickness > 0)
                    {
                        graphics.DrawPath(pen, graphicsPath);
                    }
                }
                else
                {
                    LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, rectangle.Width, 
                        rectangle.Height + (int)pen.Width), startColor, endColor, LinearGradientMode.Vertical);
                    graphics.FillRectangle(brush, new Rectangle(0, 0, width, height));
                    if (outlineThickness > 0)
                    {
                        graphics.DrawRectangle(pen, rectangle);
                    }
                }
            }
            return bitmap;
        }
    }
}

1 comment:

  1. Alas, methinks CSS3 will solve most of these problems.

    ReplyDelete