Other Posts in Image Editing

  1. Perlin Noise
  2. Fault Formation
  3. Cellular Textures
  4. Resizing an Image in C#
  5. Box Blur and Gaussian Blur... Sort of...
  6. Thermal Erosion
  7. Using Mid Point Displacement to Create Cracks
  8. Fluvial Erosion
  9. Creating Marble Like Textures Procedurally
  10. Procedural Textures and Dilation
  11. Converting Image to Black and White in C#
  12. Getting an HTML Based Color Palette from an Image in C#
  13. Adding Noise/Jitter to an Image in C#
  14. Creating Pixelated Images in C#
  15. Edge detection in C#
  16. Using Sin to Get What You Want... In C#...
  17. Noise Reduction of an Image in C# using Median Filters
  18. Image Dilation in C#
  19. Sepia Tone in C#
  20. Kuwahara Filter in C#
  21. Matrix Convolution Filters in C#
  22. Symmetric Nearest Neighbor in C#
  23. Bump Map Creation Using C#
  24. Normal Map Creation Using C#
  25. Creating Negative Images using C#
  26. Red, Blue, and Green Filters in C#
  27. Converting an Image to ASCII Art in C#
  28. Adjusting Brightness of an Image in C#
  29. Adding Noise to an Image in C#
  30. Adjusting the Gamma of an Image Using C#
  31. Adjusting Contrast of an Image in C#
  32. Drawing a Box With Rounded Corners in C#
  33. Anding Two Images Together Using C#
  34. Motion Detection in C#
  35. Creating Thermometer Chart in C#
  36. Colorizing a Black and White Image in C#
  37. Extracting an Icon From a File
  38. Setting the Pixel Format and Image Format of an Image in .Net
  39. Using Unsafe Code for Faster Image Manipulation
  40. Sobel Edge Detection and Laplace Edge Detection in C#

Drawing a Box With Rounded Corners in C#

5/5/2009

I've talked quite a bit about different algorithms for manipulating images in various ways. Everything from convolution filters to contrast manipulation to even some procedural image generation such as Perlin noise. However through all of that, I never really covered drawing your own images. Sure Perlin noise is a form of drawing, I guess, but what if all you need is a box drawn around something? Are we out of luck, having to draw that pixel by pixel?

The quick answer is no, within the GDI framework there are a set of classes within the System.Drawing and System.Drawing.Drawing2D that allows us to draw various objects by calling their functions. For instance within the Graphics class we can draw arcs, rectangles, lines, etc. Each function is well documented and easy to use (just remember that 0,0 is the upper left hand corner of an image). However other than circles, arcs, lines, etc. there really isn't anything complex that it can draw for us. For instance there is no way to tell it that we want rounded corners. So for items like that we have to cobble the object together from what we're given. So lets look at how we would draw a box with rounded corners.

   1: /*
   2: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
   3: 
   4: Permission is hereby granted, free of charge, to any person obtaining a copy
   5: of this software and associated documentation files (the "Software"), to deal
   6: in the Software without restriction, including without limitation the rights
   7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8: copies of the Software, and to permit persons to whom the Software is
   9: furnished to do so, subject to the following conditions:
  10: 
  11: The above copyright notice and this permission notice shall be included in
  12: all copies or substantial portions of the Software.
  13: 
  14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20: THE SOFTWARE.*/
  21:  
  22: #region Usings
  23: using System.Drawing;
  24: using System.Drawing.Drawing2D;
  25: #endregion
  26:  
  27: namespace Utilities.Media.Image
  28: {
  29:     /// <summary>
  30:     /// Class for drawing various shapes
  31:     /// </summary>
  32:     public static class Draw
  33:     {
  34:         #region Public Static Functions
  35:  
  36:         /// <summary>
  37:         /// Draws a rounded rectangle on a bitmap
  38:         /// </summary>
  39:         /// <param name="Image">Image to draw on</param>
  40:         /// <param name="BoxColor">The color that the box should be</param>
  41:         /// <param name="XPosition">The upper right corner's x position</param>
  42:         /// <param name="YPosition">The upper right corner's y position</param>
  43:         /// <param name="Height">Height of the box</param>
  44:         /// <param name="Width">Width of the box</param>
  45:         /// <param name="CornerRadius">Radius of the corners</param>
  46:         /// <returns>The bitmap with the rounded box on it</returns>
  47:         public static Bitmap DrawRoundedRectangle(Bitmap Image, Color BoxColor, int XPosition, int YPosition,
  48:             int Height, int Width, int CornerRadius)
  49:         {
  50:             Bitmap NewBitmap = new Bitmap(Image, Image.Width, Image.Height);
  51:             using (Graphics NewGraphics = Graphics.FromImage(NewBitmap))
  52:             {
  53:                 using (Pen BoxPen = new Pen(BoxColor))
  54:                 {
  55:                     using (GraphicsPath Path = new GraphicsPath())
  56:                     {
  57:                         Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition);
  58:                         Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90);
  59:                         Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2));
  60:                         Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90);
  61:                         Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height);
  62:                         Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90);
  63:                         Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius);
  64:                         Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90);
  65:                         Path.CloseFigure();
  66:                         NewGraphics.DrawPath(BoxPen, Path);
  67:                     }
  68:                 }
  69:             }
  70:             return NewBitmap;
  71:         }
  72:  
  73:         #endregion
  74:     }
  75: }

The code above takes in a number of variables including the height, width, upper left hand corner position of the box, and the radius of the corners. The function then creates a Pen as well as a Path object. The Pen object defines what color and thickness the lines will be when we draw them. The Path object actually draws the box. It does this by drawing a line for each side and an arc at each corner. Once the box is drawn, it closes the figure, and tell the Graphics object to actually draw it on the image (note that doing this allows you to create one path and reuse it on multiple images, so you're not recreating it each time). That's all there is to it. So take a look at the Path class, leave feedback, and happy coding.



Comments