Discovered the “Code Golf” in StackExchange from the people I follow in twitter (for the #codechallenge hashtag).
The question to generate the StackOverflow logo in code was particularly interesting to me and naturally I wanted to try generating the logo using C# (GDI+ code). Because nobody had a C# solution listed there, I also put the code there as an answer (Look for the answer titled “C#/GDI+”)
I initially recreated the logo in GDI+ without a for loop (every rectangle had a hardcoded value for its locations and size). Using that approach, its possible to recreate the logo almost identical to the original. But I was not happy with doing it that way.
Also because they say → “The image is not required to be identical to the logo, however it must be recognizable as it” in the description, I used a for loop to minimize the number of lines written and to just generate a logo that looks like the StackOverflow logo, but not identical.
This is no “ingenious” code. I would be really happy to see anyone generating the same logo with GDI+ in a more efficient and accurate manner, using a formula to represent the exact curve that the original logo has (without hard-coding each and every position and size of the overflowing elements)
Here’s the difference between my generated logo and the original StackOverflow logo →
Click here to download the code (zip file)
Here’s the code listing:
using System.Drawing; using System.Drawing.Drawing2D; namespace StackOverflowLogoCodeChallenge { public class SOLogo { private float _rotateValue; private float _xValueForTransformation; private float _yValueForTransformation; int _containerWidth; int _containerHeight; float _lineThickness; int _paddingWithinContainer; int _elementStartY; public SOLogo( float rotateValue, float xValueForTransformation, float yValueForTransformation) { // Values used to position and rotate the overflowing elements. _rotateValue = rotateValue; _xValueForTransformation = xValueForTransformation; _yValueForTransformation = yValueForTransformation; } public void DrawLogo(Graphics g, int startX, int startY) { // Backup the current smoothing mode to apply later. var SmoothingMoodBackup = g.SmoothingMode; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // Values for the container box. _containerWidth = 94; _containerHeight = 61; _lineThickness = 11f; _paddingWithinContainer = 15; // Y value of the position where the 1st overflowing element starts. _elementStartY = 0; // Starting point of the 'container': // Top point of the line on the left-> |_| Point pointContainerLineStart = new Point(startX, startY); Point pointContainer1stLineEnd =new Point( pointContainerLineStart.X, pointContainerLineStart.Y); // Start with the previous pointContainer1stLineEnd.Offset(0, _containerHeight); // Offset "Y" Point pointContainer2ndLineEnd = new Point( pointContainer1stLineEnd.X, pointContainer1stLineEnd.Y); // Start with the previous pointContainer2ndLineEnd.Offset(_containerWidth, 0); // Offset "X" Point pointContainer3rdLineEnd = new Point( pointContainer2ndLineEnd.X, pointContainer2ndLineEnd.Y); // Start with the previous pointContainer3rdLineEnd.Offset(0, 0 - _containerHeight); // Offset "Y" (negative) GraphicsPath pathOfBox = new GraphicsPath(); pathOfBox.AddLine( pointContainerLineStart, pointContainer1stLineEnd); // Left line. Top to bottom pathOfBox.AddLine( pointContainer1stLineEnd, pointContainer2ndLineEnd); // Bottom line. Left to right pathOfBox.AddLine( pointContainer2ndLineEnd, pointContainer3rdLineEnd); // Right line. Bottom to top Pen thickPen = new Pen(Brushes.Gray, _lineThickness); Color elementColor = Color.FromKnownColor(KnownColor.Gray); // Draw the 'container' g.DrawPath(thickPen, pathOfBox); // Increase the size of the pen to draw the elements inside the container thickPen.Width = _lineThickness += 3; // "Y" - position of the 1st element _elementStartY = startY + 38; // The following section draws the overflowing elements Point pointElement1Left = new Point( startX + _paddingWithinContainer, _elementStartY); Point pointElement1Right = new Point( (startX + _containerWidth) - _paddingWithinContainer, _elementStartY); // Six colors of the overflowing elements var colors = new Color[] { Color.Gray, Color.FromArgb(-6911615), Color.FromArgb(-4417693), Color.FromArgb(-2848227), Color.FromArgb(-554957), Color.FromArgb(-688847) }; for (int x = 0; x < 6; x++) { thickPen.Color = colors[x]; pointElement1Left = new Point( startX + _paddingWithinContainer, _elementStartY); pointElement1Right = new Point( (startX + _containerWidth) - _paddingWithinContainer, _elementStartY); g.DrawLine(thickPen, pointElement1Left, pointElement1Right); g.RotateTransform(_rotateValue); g.TranslateTransform(_xValueForTransformation, _yValueForTransformation); } pathOfBox.Dispose(); thickPen.Dispose(); // Restore the smoothing mood that was backed up before we started this method. g.SmoothingMode = SmoothingMoodBackup; } } } |
Happy coding.
3 replies on “StackOverflow logo using C# and GDI+”
Have you considered adding some type of bookmarking buttons or links to your web page?
Real Nice.
The colors are correct.
I guess you presumed that the bars are equally spaced.
A simple modification would do the trick
Keep up the good work
Thanks for the feedback! 🙂