画像への文字列描画(右から左にすると、文字列が入れ替わる)
投稿者 KOZ  (社会人)
投稿日時
2023/11/10 11:48:35
StringFormatFlags.DirectionRightToLeft は、アラビア語などの右から左に書く言語を表示するために使います。
右寄せの場合は次のように指定してください。
これでもいいんですが、文字を書くときは、TextRenderer を使ったほうがいいです。
右寄せの場合は次のように指定してください。
Dim sf As New StringFormat()
sf.Alignment = StringAlignment.Far
これでもいいんですが、文字を書くときは、TextRenderer を使ったほうがいいです。
Dim rct As New Rectangle(10, 10, cs.Width, cs.Height * 2)
Dim flags = TextFormatFlags.Right Or TextFormatFlags.NoPrefix Or TextFormatFlags.WordBreak
TextRenderer.DrawText(g, str, addFnt, rct, Color.Black, flags)
投稿者 sayama  (社会人)
投稿日時
2023/11/10 18:15:47
KOZ 様
解決しました。ありがとうございます。
StringFormatFlags.DirectionRightToLeftにこだわってしまったため、
sf.Alignment = StringAlignment.Farを利用することは頭にありませんでした。
誠に目から鱗がはがれる思いです。
> StringFormatFlags.DirectionRightToLeft は、アラビア語などの右から左に書く言語を表示するため
右から左に書く言語用とは、まったく知りませんでした。
>文字を書くときは、TextRenderer を使ったほうがいいです。
文字列計測の際、TextRenderer.MeasureTex を利用して DrawString() を利用しているのは、多少取得する大きさが変わっても
TextRenderer.DrawText を利用する際、小さいフォントを指定すると太字のようになってしまうので、対策として利用している次第です。
何か良い対策があれば、お暇なときにでも、ご教授ください。
今回は本当にありがとうございました。
解決しました。ありがとうございます。
StringFormatFlags.DirectionRightToLeftにこだわってしまったため、
sf.Alignment = StringAlignment.Farを利用することは頭にありませんでした。
誠に目から鱗がはがれる思いです。
> StringFormatFlags.DirectionRightToLeft は、アラビア語などの右から左に書く言語を表示するため
右から左に書く言語用とは、まったく知りませんでした。
>文字を書くときは、TextRenderer を使ったほうがいいです。
文字列計測の際、TextRenderer.MeasureTex を利用して DrawString() を利用しているのは、多少取得する大きさが変わっても
TextRenderer.DrawText を利用する際、小さいフォントを指定すると太字のようになってしまうので、対策として利用している次第です。
何か良い対策があれば、お暇なときにでも、ご教授ください。
今回は本当にありがとうございました。
投稿者 KOZ  (社会人)
投稿日時
2023/11/11 01:14:04
>TextRenderer.DrawText を利用する際、小さいフォントを指定すると太字のようになってしまうので、対策として利用している次第です。
Grapchis.TextRenderingHint を AntiAlias か AntiAliasGridFit にするといいかもしれません。
Grapchis.DrawString を使うのであれば、TextRenderer.MeasureText ではなく、Grapchis.MeasureString を使ったほうが良いです。
なぜ TextRenderer をお勧めするかというと、異体字が表示できるからです。
https://moji.or.jp/mojikiban/aboutivs/
Grapchis.TextRenderingHint を AntiAlias か AntiAliasGridFit にするといいかもしれません。
Grapchis.DrawString を使うのであれば、TextRenderer.MeasureText ではなく、Grapchis.MeasureString を使ったほうが良いです。
なぜ TextRenderer をお勧めするかというと、異体字が表示できるからです。
https://moji.or.jp/mojikiban/aboutivs/
投稿者 KOZ  (社会人)
投稿日時
2023/11/11 05:10:32
太く見えるのは、ハーフトーンで描画される部分が真っ黒に塗りつぶされているためだったみたいです。
ハーフトーンの品質を上げるとキレイに見えます。
こんなクラスを作って
このように実行してみてください。
結果は
画像を拡大するとよくわかります。
ハーフトーンの品質を上げるとキレイに見えます。
こんなクラスを作って
Imports System.Drawing
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Public Class GraphicsWrapper
Implements IDisposable
<DllImportAttribute("gdi32.dll")>
Private Shared Function SelectPalette(hdc As IntPtr,
htPalette As IntPtr, bForceBackground As Boolean) As IntPtr
End Function
<DllImportAttribute("gdi32.dll")>
Private Shared Function RealizePalette(hdc As IntPtr) As Integer
End Function
Private ReadOnly tmpGraphics As Graphics
Private ReadOnly hdc As IntPtr
Private ReadOnly oldPal As IntPtr
Private ReadOnly mainGraphics As Graphics
Public ReadOnly Property Graphics As Graphics
Get
Return mainGraphics
End Get
End Property
Public Sub New(img As Image, useHalftone As Boolean)
If useHalftone Then
tmpGraphics = Graphics.FromImage(img)
hdc = tmpGraphics.GetHdc()
oldPal = SetUpPalette(hdc, False, True)
mainGraphics = Graphics.FromHdc(hdc)
Else
mainGraphics = Graphics.FromImage(img)
End If
mainGraphics.TextRenderingHint = TextRenderingHint.AntiAlias
End Sub
Shared Function SetUpPalette(dc As IntPtr, force As Boolean, rp As Boolean) As IntPtr
Dim halftonePalette = Graphics.GetHalftonePalette()
Dim result = SelectPalette(dc, halftonePalette, force)
If rp Then
RealizePalette(dc)
End If
Return result
End Function
Private disposedValue As Boolean
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
disposedValue = True
mainGraphics.Dispose()
If tmpGraphics IsNot Nothing Then
If oldPal <> IntPtr.Zero Then
SelectPalette(hdc, oldPal, False)
End If
tmpGraphics.ReleaseHdc(hdc)
tmpGraphics.Dispose()
End If
End If
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
End Class
このように実行してみてください。
Dim str = "葛󠄀城市"
Using addFnt As New Font("メイリオ", 7.5, FontStyle.Regular, GraphicsUnit.Millimeter),
br = New SolidBrush(Color.Black)
Using img As New Bitmap(256, 256)
Using wrapper = New GraphicsWrapper(img, True)
wrapper.Graphics.Clear(Color.White)
TextRenderer.DrawText(wrapper.Graphics, str, addFnt, New Point(0, 0), Color.Black)
End Using
Using wrapper = New GraphicsWrapper(img, False)
TextRenderer.DrawText(wrapper.Graphics, str, addFnt, New Point(0, 32), Color.Black)
End Using
Using wrapper = New GraphicsWrapper(img, True)
wrapper.Graphics.DrawString(str, addFnt, br, New PointF(0, 64))
End Using
Using wrapper = New GraphicsWrapper(img, False)
wrapper.Graphics.DrawString(str, addFnt, br, New PointF(0, 96))
End Using
img.Save("z:\temp.bmp")
End Using
End Using
結果は
画像を拡大するとよくわかります。
新規作成した画像上で、決まったスペースに住所を右詰めで折り返して描画したいのですが、描画した文字列の一部が入れ替わってしまう現象が生じてしまい困っています。解決策があればご指導いただけますよう、よろしくお願いいたします。
’作成するイメージ
Img = New Bitmap(1050, 1500)
Dim g As Graphics = Graphics.FromImage(Img)
Dim Brs As SolidBrush
Brs = New SolidBrush(Color.White)
g.FillRectangle(Brs, 0, 0, Img.Width, Img.Height)
’このイメージに次の文字列を右詰めで折り返して描画したい
Dim addFnt As New Font("メイリオ", 7.5, FontStyle.Regular, GraphicsUnit.Millimeter)
Dim str As String = ""
Dim cs As Size
Dim sf As New StringFormat() 'StringFormatを作成
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft '右から左に表示する
str = "〒100-0001 東京都 新宿区 新宿 第一〇×ビル1階 108号室"
cs = TextRenderer.MeasureText(str, addFnt) ’文字列を描画した際の大きさを測定
str += "TEL:03-0000-0000"
Dim rct As New RectangleF(10, 10, cs.Width, cs.Height * 2) ’文字列2行分の大きさで描画スペースを作成
g.DrawString(str, addFnt, Brushes.Black, rct, sf) ’右から左に文字列を描画(右詰め)
’期待するイメージ
〒100-0001 東京都 新宿区 新宿 第一〇×ビル1階 108号室
TEL:03-0000-0000
’実際に出力されるイメージ
東京都 新宿区 新宿 第一〇×ビル1階 108号室 100-0001〒
TEL:03-0000-0000
’同様なことを単純な文字列 ”\20,000-”とやってみたのですが、
’出力されるイメージは ”-\20,000” と描画されてしまいます。
何がなんやら苦悶しています。。。。。お助けください。