I am writing C# code in VS2010 to achieve the following.
I am trying to draw text on a transparent bitmap and running into ugly looking text. Below is the pic of three texts (i.e. A, B and C)
Note: A and C have transparent background, B has White as background.
Problem:A: I have a bitmap with ARGB pixel format. And I want to draw a text into it. The text drawn has sharp edges and it does not honor the transparency.
B: I write the exact same code, but only difference from A is that the pixels in bitmap are not transparent anymore. (I will fill in a rectangle). But if you notince the pixels of the text, you will see a smooth blend of black (text color) and white (background color).
开发者_如何学JAVAC: This is what I am expecting the text to look when I am drawing a text onto a bitmap with transparent pixels.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void UserControl1_Paint(object sender, PaintEventArgs e)
{
//e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(0, Color.Red)), e.ClipRectangle);
e.Graphics.DrawString("0123456789", new Font("Verdana", 20), Brushes.Red, new PointF(5, 10));
e.Graphics.DrawEllipse(Pens.Black, e.ClipRectangle);
}
// This is a public method, using which I want to save my usercontrol to an image to save to file later.
public Image ToImage(Size size, PixelFormat p)
{
Bitmap b = new Bitmap(Width, Height, p);
using (Graphics g = Graphics.FromImage(b))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
PaintEventArgs e = new PaintEventArgs(g, new Rectangle(0, 0, size.Width, size.Height));
base.OnPaint(e);
this.OnPaint(e);
}
return b;
}
How do I make A look like C with the transparent background. I am pretty sure this can be done, because softwares like photoshop, paint.net handle this very nicely.
Thanks a lot!
Datte
Drawing the text WON'T affect alpha channel on your target bitmap, and will always look like that if you draw to intermediate ARGB bitmap that you want to blend to some other bitmap.
What you need is to manipulate pixels of the bitmap after drawing the text, so you re-calculate alpha value for every pixel so it is equal to your grayscale text. You can do it either with GetPixel
/PutPixel
combination when traversing the bitmap (slow) or with unsafe
portion of the code (unsafe, pointers, fast).
What SmoothingMode are you using for your Graphics object?
If you haven't set it then try to change its value:
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.smoothingmode.aspx
Looks like GDI+ does not support this out of the box. What you can do is render black text on a white background and then modify the pixel data to convert all pixels to black with an alpha value based on the original brightness.
static void GrayscaleToAlpha(Bitmap image) {
var lockData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
unsafe {
// Pointer to the current pixel
uint* pPixel = (uint*)lockData.Scan0;
// Pointer value at which we terminate the loop (end of pixel data)
var pLastPixel = pPixel + image.Width * image.Height;
while (pPixel < pLastPixel) {
// Get pixel data
uint pixelValue = *pPixel;
// Average RGB
uint brightness = ((pixelValue & 0xFF) + ((pixelValue >> 8) & 0xFF) + ((pixelValue >> 16) & 0xFF)) / 3;
// Use brightness for alpha value, leave R, G, and B zero (black)
pixelValue = (255 - brightness) << 24;
// Copy back to image
*pPixel = pixelValue;
// Next pixel
pPixel++;
}
}
image.UnlockBits(lockData);
}
精彩评论