34

縦書きのテキストを表示するマルチブラウザページがあります。

すべてのブラウザでテキストを垂直方向にレンダリングするための醜いハックとして、テキストが垂直方向に描画されたPNGを返すカスタムページハンドラーを作成しました。

これが私の基本的なコードです(C#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+'s 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+'s 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 );
    }
}

これでアルファは機能しているように見えますが、テキストはブロック状に見えます。まるでジャギーエッジが残っているかのように見えますが、背景は黒です。

これは.Net/GDI +のバグですか?gifのインデックスの透明度でも失敗することはすでにわかっているので、あまり自信がありません。

この画像は、これがうまくいかない2つの方法を示しています。

垂直方向のテキスト比較

上の画像は、白い背景やMakeTransparent呼び出しなしでそれを示しています。2つ目は、背景が白で塗りつぶされMakeTransparent、インデックスの透明度を追加するために呼び出されます。

これらはどちらも正しくありません。2番目の画像には、私が望まない白いエイリアシングジャギーがあり、最初の画像は黒に対してしっかりとエイリアシングされているように見えます。

4

9 に答える 9

14

テキストの「ブロックネス」を修正するには、どうすればよいでしょうか...

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

この行の後に...

Graphics g = Graphics.FromImage( (Image) image );
于 2009-05-04T14:44:05.483 に答える
6

BitmapでLockBitsメソッドを使用してBitmapDataオブジェクトを返し、各ピクセルのAlphaを自分で設定できます(GetPixelとSetPixelを使用することもできますが、これらのメソッドはめちゃくちゃ遅いです)。この回答を参照してください。

私が最初にテクニックを使い始めたとき、私はアルファ値を0に設定していたので、これが確実に機能することを知っています。そのため、設定した色はどれも見えませんでした。

編集:これは、完全に.NETで(LockBitsを使用して)行われた魚眼レンズ効果のサンプルです。

代替テキストhttp://www.freeimagehosting.net/uploads/21ca8300cc.jpg

于 2008-12-23T12:22:19.243 に答える
6

IIRCでは、ビットマップコンストラクターでPixelFormatを指定する必要があります。

于 2008-12-23T11:41:43.320 に答える
5

テキストのアンチエイリアスについては、Graphics.TextRenderingHintの値を試してみてください。ClearTypeは、LCDモニター(CRTではなく)でのみ表示され、回転が原因で機能しない可能性があるため、使用しないことをお勧めします。

PSそれはVilx-であり、Vlixではありません。:D

于 2008-12-23T12:49:06.070 に答える
1

申し訳ありませんが、私はあなたの質問を十分に注意深く読んでいませんでした。

例のエイリアシング効果を確認せずに、色付きの背景に回転したテキストを正常に描画できたことを知っています。コードを見に戻ったとき、Microsoft.WindowsCE.Forms名前空間にうまくラップされた論理フォントを使用して回転したテキストを描画していることに気付きました。この手法では、描画角度を論理フォントのプロパティとして設定します(したがって、TranslateTransformまたはRotateTransformを呼び出さないでください)。

Windows CEの世界以外では、論理フォントを作成するためにPInvokeを使用する必要があります(これを行ったことがなく、良い例をすぐに見つけることができませんでした)。これがどれほどうまく機能するかはわかりませんが、見ている奇妙なエイリアシング効果なしに回転したテキストを描画することは確かです。確かに、これはGDI +のバグ(または、誰もが実際に使用するとは思わなかったもの)だと思います。

論理フォントよりもパフォーマンスが優れている可能性がある別のアプローチは、通常は色付きの長方形の背景(テキストを保持するのに十分な大きさ)にテキストを描画してから、長方形を回転してメイン画像にコピーすることです。Graphics.DrawImageは回転を実行できないようですが、この効果はLockBitsを使用して簡単に実装できます。

于 2008-12-24T13:40:27.620 に答える
1

おそらく、この CodeProject 記事のソース コードで答えを見つけることができます。

C# のピクセルごとのアルファ ブレンド

于 2008-12-23T11:47:33.247 に答える
0

ビットマップを作成するときは、少なくとも 32 ビットのピクセル形式 (例: PixelFormat.Format32bppArgb) を指定する必要があります。そうしないと、GDI+ は透明度を管理できません。

保存時に結果のファイルを調整するには、Save を ImageCodecInfo および EncoderParameters と共に使用できます。

于 2008-12-24T12:39:55.213 に答える
0

Microsoft は、CodePlex の Asp.Net コンテンツの一部として、Web 用の新しい動的画像ライブラリを持っていることがわかりました。

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

残念ながら、それは私が望むものには少し多すぎます。安全でないコードを使用して独自のアルファ透明度をロールすることはできますが、このコードが使用頻度の高い Web アプリケーションの一部として使用されていることを考えると、これは遅すぎます。

これは MS の GDI+ .Net 実装の単なるバグですか?

于 2008-12-24T11:15:51.123 に答える
0

または、テキストを非透過の PNG にレンダリングして、セルの背景色と一致する背景色 (白ではなく) を使用することもできます。

于 2008-12-24T14:18:05.187 に答える