Подтвердить что ты не робот

Можете ли вы сделать альфа-прозрачный PNG с С#?

У меня есть страница с несколькими браузерами, которая показывает вертикальный текст.

Как уродливое взломать текст для рендеринга по вертикали во всех браузерах, я создал обработчик пользовательской страницы, который возвращает 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, поэтому я не уверен в этом.

На этом изображении показаны два способа: это не так:

vertical text comparison

Верхнее изображение показывает его без белого фона или вызова MakeTransparent. Второй с фоном, заполненным белым, а затем MakeTransparent, вызываемым для добавления прозрачности индекса.

Ни одно из них не является правильным - на втором изображении есть белые сглаживающие jaggies, которые я не хочу, первый, похоже, прочно сглажен с черным.

4b9b3361

Ответ 1

Чтобы исправить текст "блочность", вы не можете просто сделать...

g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

после этой строки...

Graphics g = Graphics.FromImage( (Image) image );

Ответ 2

IIRC вам нужно указать PixelFormat в конструкторе растрового изображения.

Ответ 3

Вы можете использовать метод LockBits на вашем Bitmap, чтобы вернуть объект BitmapData, и настроить Alpha для каждого пикселя самостоятельно (вы также можете использовать GetPixel и SetPixel, но эти методы безумно медленны). См. этот ответ.

Я знаю, что это работает точно, потому что, когда я впервые начал использовать технику, я установил значение альфа-значения в 0, поэтому ни один из цветов, которые я устанавливал, не был виден.

Изменить: вот образец эффекта линзы с рыбий глаз, выполненный полностью в .NET(с использованием LockBits):

alt text http://www.freeimagehosting.net/uploads/21ca8300cc.jpg

Ответ 4

Для текстового сглаживания играйте со значениями в Graphics.TextRenderingHint. Я бы посоветовал не использовать ClearType, потому что это будет отображаться только на ЖК-мониторах (не CRT) и может не работать из-за поворота.

P.S. Это Vilx-, а не Vlix.: D

Ответ 5

Возможно, вы можете найти ответ в исходном коде этой статьи CodeProject:

Per Pixel Alpha Blend в С#

Ответ 6

Извините, я недостаточно внимательно прочитал ваш вопрос.

Я знаю, что я успешно нарисовал повернутый текст на цветном фоне, не видя ни одного из эффектов сглаживания в ваших примерах. Когда я вернулся, чтобы посмотреть на свой код, я понял, что рисую вращающийся текст с использованием логического шрифта, который хорошо переносится в пространство имен Microsoft.WindowsCE.Forms. Этот метод устанавливает угол рисования как свойство логического шрифта (поэтому вы не называете TranslateTransform или RotateTransform).

Вне мира Windows CE вам нужно PInvoke создать логический шрифт (я этого никогда не делал, и я не мог быстро найти хороший пример). Я не знаю, как это будет хорошо, но я точно знаю, что он будет рисовать повернутый текст без каких-либо странных эффектов сглаживания, которые вы видите. Я уверен, что это ошибка в GDI + (или просто то, что они не думали, что кто-нибудь когда-либо действительно будет использовать).

Альтернативный подход, который может даже работать лучше, чем логический шрифт, - это рисовать текст на цветном фоне прямоугольника (достаточно большой, чтобы удерживать текст), а затем поворачивать и копировать прямоугольник на основное изображение. Graphics.DrawImage, похоже, не в состоянии сделать вращение, но этот эффект легко реализовать с помощью LockBits.

Ответ 7

Оказывается, Microsoft имеет новую динамическую библиотеку изображений для Интернета как часть содержимого Asp.Net в CodePlex:

http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449

К сожалению, это немного для того, чего я хочу. Используя небезопасный код, я могу свернуть собственную альфа-прозрачность, но это слишком медленно, учитывая, что этот код используется как часть веб-приложения с высоким уровнем использования.

Это просто ошибка в реализации MS GDI +.Net?

Ответ 8

При создании растрового изображения вы должны хотя бы указать формат 32-битного пикселя (например: PixelFormat.Format32bppArgb), иначе GDI + не сможет управлять прозрачностью.

Чтобы настроить полученный файл при сохранении, вы можете использовать Save с ImageCodecInfo и EncoderParameters.

Ответ 9

Или вы можете просто визуализировать текст непрозрачным PNG, но используйте цвет фона (вместо белого), который соответствует цвету фона ячейки.