Link to home
Start Free TrialLog in
Avatar of sexyrexy
sexyrexy

asked on

GDI+ text looks bad

I have written a "textimage.aspx" page that returns an image/jpeg formatted according to the following parameters:
text string, font name, font size, font color, back color
The output usually looks fine but when using certain colors a degraded quality becomes apparent. (see http://beta.s3m.net/gdi_test.jpg)
I really need to figure out how to improve the quality... any change that would move me closer to the photoshop/fireworks-rendered text would be very helpful.

Here is the code, stripped down to the necessary parts:

////////////////////

Response.Clear();
Response.ContentType = "image/jpeg";

Bitmap myBmp = TextToImage(str,fName,fSize,fColor,bColor,trim);
EncoderParameters eps = new EncoderParameters(1);
eps.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
ImageCodecInfo[] objEncoders = ImageCodecInfo.GetImageDecoders();

for(int i=0;i<objEncoders.Length;i++)
{
      if(objEncoders[i].MimeType==Response.ContentType)
      {
            myBmp.Save(Response.OutputStream,objEncoders[i],eps);
            myBmp.Dispose();
            break;
      }
}

private Bitmap CreateImage(strText, strFontName, intFontSize, strForeColor, strBackColor)
{
      Color clrForeColor = ColorTranslator.FromHtml("#"+strForeColor);
      Color clrBackColor = ColorTranslator.FromHtml("#"+strBackColor);                  

      //get font path from DB of custom fonts

      PrivateFontCollection pfc = new PrivateFontCollection();
      pfc.AddFontFile(strFontPath);

      FontStyle myStyle = FontStyle.Regular;
      if(strFontName.ToLower().IndexOf("bold")>-1){myStyle = FontStyle.Bold;}
      if(strFontName.ToLower().IndexOf("italic")>-1){myStyle = FontStyle.Italic;}

      Font font=new Font(new FontFamily(strFontName,pfc),intFontSize, myStyle);

      Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format24bppRgb);
      Graphics g = Graphics.FromImage(bmp);

      SizeF imageSize = g.MeasureString(strText,font);
      int intWidth = (int)imageSize.Width;
      int intHeight = (int)imageSize.Height;

      bmp = new Bitmap(intWidth, intHeight, PixelFormat.Format24bppRgb);
      g = Graphics.FromImage(bmp);
      g.Clear(clrBackColor);
      g.TextRenderingHint = TextRenderingHint.AntiAlias;
      g.DrawString(strText, font, new SolidBrush(clrForeColor),new PointF(0,0));
      g.CompositingQuality = CompositingQuality.HighQuality;
      pfc.Dispose();                  
      g.Flush();
      g.Dispose();
                  
      return bmp;
}
Avatar of sexyrexy
sexyrexy

ASKER

Sorry the function names and overloads don't match up I just mistyped when stripping it down. The necessary functionality is still obvious.
ASKER CERTIFIED SOLUTION
Avatar of mmarinov
mmarinov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes, I've had unreliable results with GDI's gif output... it seems to be using a preset websafe 256 palette when downconverting the Bitmap to 8-bit GIF, rather than building a palette based on the colors found in the bitmap. This makes the output splotchy and rough. (http://beta.s3m.net/gdi_gif.gif)
mmarinov,
Thanks for suggesting a GIF type again. It prompted me to think about the fact that GDI uses a default palette and wonder whether a custom palette could be constructed based on the given bitmap, just like photoshop might. The following two articles were very helpful:

http://dotnetjunkies.com/WebLog/bsblog/archive/2004/01/26/6103.aspx
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp

There are warnings that generating the palette on the fly has alot of overhead, but by using pointers (and also in my case my images have very few colors since they are just text) the CPU load is minimized.