Ответ 1
Чтобы исправить текст "блочность", вы не можете просто сделать...
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
после этой строки...
Graphics g = Graphics.FromImage( (Image) image );
У меня есть страница с несколькими браузерами, которая показывает вертикальный текст.
Как уродливое взломать текст для рендеринга по вертикали во всех браузерах, я создал обработчик пользовательской страницы, который возвращает PNG с текстом, нарисованным вертикально.
Вот мой базовый код (С# 3, но небольшие изменения в любой другой версии до 1):
Font f = GetSystemConfiguredFont();
//this sets the text to be rotated 90deg clockwise (i.e. down)
StringFormat stringFormat = new StringFormat { FormatFlags = StringFormatFlags.DirectionVertical };
SizeF size;
// creates 1Kx1K image buffer and uses it to find out how bit the image needs to be to fit the text
using ( Image imageg = (Image) new Bitmap( 1000, 1000 ) )
size = Graphics.FromImage( imageg ).
MeasureString( text, f, 25, stringFormat );
using ( Bitmap image = new Bitmap( (int) size.Width, (int) size.Height ) )
{
Graphics g = Graphics.FromImage( (Image) image );
g.FillRectangle( Brushes.White, 0f, 0f, image.Width, image.Height );
g.TranslateTransform( image.Width, image.Height );
g.RotateTransform( 180.0F ); //note that we need the rotation as the default is down
// draw text
g.DrawString( text, f, Brushes.Black, 0f, 0f, stringFormat );
//make be background transparent - this will be an index (rather than an alpha) transparency
image.MakeTransparent( Color.White );
//note that this image has to be a PNG, as GDI+ gif handling renders any transparency as black.
context.Response.AddHeader( "ContentType", "image/png" );
using ( MemoryStream memStream = new MemoryStream() )
{
image.Save( memStream, ImageFormat.Png );
memStream.WriteTo( context.Response.OutputStream );
}
}
Это создает образ, который выглядит так, как я хочу, за исключением того, что прозрачность основана на индексе. Когда я возвращаю PNG, он может поддерживать надлежащую альфа-прозрачность.
Есть ли способ сделать это в .net?
Благодаря Vlix (см. комментарии) я внес некоторые изменения, хотя это все еще неправильно:
using ( Bitmap image = new Bitmap( (int) size.Width, (int) size.Height, PixelFormat.Format32bppArgb ) )
{
Graphics g = Graphics.FromImage( (Image) image );
g.TranslateTransform( image.Width, image.Height );
g.RotateTransform( 180.0F ); //note that we need the rotation as the default is down
// draw text
g.DrawString( text, f, Brushes.Black, 0f, 0f, stringFormat );
//note that this image has to be a PNG, as GDI+ gif handling renders any transparency as black.
context.Response.AddHeader( "ContentType", "image/png" );
using ( MemoryStream memStream = new MemoryStream() )
{
//note that context.Response.OutputStream doesn't support the Save, but does support WriteTo
image.Save( memStream, ImageFormat.Png );
memStream.WriteTo( context.Response.OutputStream );
}
}
Теперь альфа, похоже, работает, но текст кажется блочным - как будто он все еще имеет края jaggie, но на черном фоне.
Является ли это некоторой ошибкой с .Net/GDI +? Я уже обнаружил, что он не работает даже для прозрачных индексов для gif, поэтому я не уверен в этом.
На этом изображении показаны два способа: это не так:
Верхнее изображение показывает его без белого фона или вызова MakeTransparent
. Второй с фоном, заполненным белым, а затем MakeTransparent
, вызываемым для добавления прозрачности индекса.
Ни одно из них не является правильным - на втором изображении есть белые сглаживающие jaggies, которые я не хочу, первый, похоже, прочно сглажен с черным.
Чтобы исправить текст "блочность", вы не можете просто сделать...
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
после этой строки...
Graphics g = Graphics.FromImage( (Image) image );
IIRC вам нужно указать PixelFormat в конструкторе растрового изображения.
Вы можете использовать метод LockBits на вашем Bitmap, чтобы вернуть объект BitmapData, и настроить Alpha для каждого пикселя самостоятельно (вы также можете использовать GetPixel и SetPixel, но эти методы безумно медленны). См. этот ответ.
Я знаю, что это работает точно, потому что, когда я впервые начал использовать технику, я установил значение альфа-значения в 0, поэтому ни один из цветов, которые я устанавливал, не был виден.
Изменить: вот образец эффекта линзы с рыбий глаз, выполненный полностью в .NET(с использованием LockBits):
alt text http://www.freeimagehosting.net/uploads/21ca8300cc.jpg
Для текстового сглаживания играйте со значениями в Graphics.TextRenderingHint. Я бы посоветовал не использовать ClearType, потому что это будет отображаться только на ЖК-мониторах (не CRT) и может не работать из-за поворота.
P.S. Это Vilx-, а не Vlix.: D
Возможно, вы можете найти ответ в исходном коде этой статьи CodeProject:
Извините, я недостаточно внимательно прочитал ваш вопрос.
Я знаю, что я успешно нарисовал повернутый текст на цветном фоне, не видя ни одного из эффектов сглаживания в ваших примерах. Когда я вернулся, чтобы посмотреть на свой код, я понял, что рисую вращающийся текст с использованием логического шрифта, который хорошо переносится в пространство имен Microsoft.WindowsCE.Forms. Этот метод устанавливает угол рисования как свойство логического шрифта (поэтому вы не называете TranslateTransform или RotateTransform).
Вне мира Windows CE вам нужно PInvoke создать логический шрифт (я этого никогда не делал, и я не мог быстро найти хороший пример). Я не знаю, как это будет хорошо, но я точно знаю, что он будет рисовать повернутый текст без каких-либо странных эффектов сглаживания, которые вы видите. Я уверен, что это ошибка в GDI + (или просто то, что они не думали, что кто-нибудь когда-либо действительно будет использовать).
Альтернативный подход, который может даже работать лучше, чем логический шрифт, - это рисовать текст на цветном фоне прямоугольника (достаточно большой, чтобы удерживать текст), а затем поворачивать и копировать прямоугольник на основное изображение. Graphics.DrawImage, похоже, не в состоянии сделать вращение, но этот эффект легко реализовать с помощью LockBits.
Оказывается, Microsoft имеет новую динамическую библиотеку изображений для Интернета как часть содержимого Asp.Net в CodePlex:
http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449
К сожалению, это немного для того, чего я хочу. Используя небезопасный код, я могу свернуть собственную альфа-прозрачность, но это слишком медленно, учитывая, что этот код используется как часть веб-приложения с высоким уровнем использования.
Это просто ошибка в реализации MS GDI +.Net?
При создании растрового изображения вы должны хотя бы указать формат 32-битного пикселя (например: PixelFormat.Format32bppArgb), иначе GDI + не сможет управлять прозрачностью.
Чтобы настроить полученный файл при сохранении, вы можете использовать Save с ImageCodecInfo и EncoderParameters.
Или вы можете просто визуализировать текст непрозрачным PNG, но используйте цвет фона (вместо белого), который соответствует цвету фона ячейки.