Delphi6です。初心者と中級者の間ぐらいのレベルです。
フォームにボタンとチェックボックスとイメージを用意します。
uses に Clipbrd を追加します。
procedure TForm1.Button1Click(Sender: TObject);
var
Metafile: TMetafile;
MetafileCanvas: TMetafileCanvas;
DispW, DispH, MMPerPixelW, MMPerPixelH: Integer;
Format: Word;
Data: THandle;
Palette: HPALETTE;
r: TRect;
begin
DispW := GetDeviceCaps( Canvas.Handle, HORZSIZE );
DispH := GetDeviceCaps( Canvas.Handle, VERTSIZE );
MMPerPixelW := Round( DispW * 100 / Screen.Width );
MMPerPixelH := Round( DispH * 100 / Screen.Height );
Metafile := TMetafile.Create;
try
with Metafile do
begin
Enhanced := True;
MMWidth := Image1.Width * MMPerPixelW;
MMHeight := Image1.Height * MMPerPixelH;
Width := Image1.Width;
Height := Image1.Height;
end;
MetafileCanvas := TMetafileCanvas.Create( Metafile, Canvas.Handle );
// 図形描画
MetafileCanvas.Ellipse(0, 0, 40, 40);
// 文字列描画
r := Rect(50,15,Image1.Width,Image1.Height);
if Checkbox1.Checked = true then
DrawText(MetafileCanvas.Handle, '文字列', -1, r, DT_LEFT );
MetafileCanvas.Free;
Image1.Picture.Assign(Metafile);
Metafile.SaveToClipboardFormat( Format, Data, Palette );
Clipboard.SetAsHandle( Format, Data );
finally
Metafile.Free;
end;
end;
ボタンをクリックするとクリップボードにコピーされます。
これをWORDに貼り付けると、チェックボックスの状態によってWORD
に貼り付けた図形のアンチエイリアスが、効いたり効かなかったりします。
チックボックスがOFFの時・・・図形にアンチエイリアスが働く
チックボックスがONの時・・・・図形にアンチエイリアスが働かない
文字列にアンチエイリアスが働く
つまり、図形だけの時はアンチエイリアスが働くのに、文字列を追加すると
図形のアンチエイリアスが解除されてしまいます。
この挙動の原因がつかめないで困っています。
メインの質問とは別件ですが、Imageコンポーネントの表示は常にアンチ
エイリアスが働かない状態ですが、これにアンチエイリアスを効かせる
ことはできるのでしょうか?
ご存知の方がいらっしゃいましたら、よろしくお願いいたします。
GDI+ のライブラリを使うしかないかもです。
[2010/12/28 及び 12/29 の雑談]
http://ht-deko.minim.ne.jp/ft1012.html#101228_01
素早いお返事ありがとうございます。
GDI+ですか。いきなり難しそうですね。まだまだ私には手の出せない領域です。
2010/12/29 の雑談より
> TImage では EMF+ (GDI+) の描画ができませんから、"GDI+ のコマンド" 部分は
> 正確に再生されません。
これはImageコンポーネントにアンチエイリアスが働かない原因ですね。
納得しました。
本題の方ですが、
> "Metafile を表示する" というのは "GDI コマンドを再生する" 事に他なりません。
とありますので、メタファイルにはアンチエイリアス処理のコマンドを含むことが
できるということですね。
つまり上記のプログラムでは、そもそもアンチエイリアス処理のコマンドが含まれて
いないので、WORDに貼り付けた時きれいに表示できないと。
うーん、文字列がないときにアンチエイリアスが働いている理由がよく分かりませんが、
なんとなくは納得できました。
ありがとうございました。
ぱっと見ですが、MS Wordはメタファイルを独自で描画しているみたいですね。
MS Word上で一度でも編集すると全てにアンチエイリアスがかかるみたいですよ。
MS ペイントに描かせるとやはりアンチエイリアスはかかりません。
どの環境でもアンチエイリアスをかけるのはDEKOさんの方法しか無いようですが、
せめて自分のアプリ内だけでも…というならそのままでもいける方法はあります。
メタファイルを2倍の大きさでBmpに出力後、1/2するとアンチエイリアスが掛かった描画になります。
手持ちソースの切り抜きですがよかったらどうぞ。
type
TByteARGB = record
B:Byte;
G:Byte;
R:Byte;
A:Byte;
end;
PByteARGB = ^TByteARGB;
procedure BmpHalf(SrcBmp,DestBmp:TBitmap);
var
aW,aH,x,y,p,step:Integer;
pS: array [0..1] of PByteARGB;
pD:PByteARGB;
R,G,B:Integer;
begin
aW := SrcBmp.Width div 2;
aH := SrcBmp.Height div 2;
step := SrcBmp.Width;
DestBmp.SetSize(aW,aH);
pS[0] := SrcBmp.ScanLine[SrcBmp.Height-1];
for p := 1 to 1 do
begin
pS[p] := pS[p-1];
inc(pS[p], SrcBmp.Width);
end;
pD := DestBmp.ScanLine[DestBmp.Height-1];
for y := 0 to aH-1 do
begin
for x := 0 to aW-1 do
begin
R:=0; G:=0; B:=0;
for p := 0 to 1 do
begin
R:=R+ps[p]^.R;
G:=G+ps[p]^.G;
B:=B+ps[p]^.B;
inc(pS[p]);
R:=R+ps[p]^.R;
G:=G+ps[p]^.G;
B:=B+ps[p]^.B;
inc(pS[p]);
end;
R := R shr 2;
G := G shr 2;
B := B shr 2;
pD^.R := R;
pD^.G := G;
pD^.B := B;
inc(pD);
end;
for p := 0 to 1 do
inc(pS[p], step);
end;
end;
procedure EMFToBMPwithAntialiasing(aMetafile: TMetafile; var aBmp:TBitmap);
var
aBmp2:TBitmap;
begin
aBmp.PixelFormat:=pf32bit;
aBmp.SetSize(aMetafile.Width,aMetafile.Height);
aBmp2:=TBitmap.Create;
aBmp2.PixelFormat:=pf32bit;
aBmp2.SetSize(aMetafile.Width*2,aMetafile.Height*2);
aBmp2.Canvas.StretchDraw(Rect(0,0,aBmp2.Width,aBmp2.Height),aMetafile);
BmpHalf(aBmp2,aBmp);
aBmp2.Free;
end;
//-----------------------------------------------------------------------
aBmp:=TBitmap.Create;
aBmp.SetSize(Metafile.Width,Metafile.Height);
EMFToBMPwithAntialiasing(Metafile,aBmp);
Image1.Picture.Assign(aBmp);
aBmp.Free;
//Image1.Picture.Assign(Metafile);
解決策とか関係ありませんが。。。
これとか?
TNkDIB
http://www.asahi-net.or.jp/~HA3T-NKMR/deldown.htm
これとか?
Graphics32 Project Homepage - Main.HomePage
http://graphics32.org/wiki/とか
monaaさん
> メタファイルを2倍の大きさでBmpに出力後、1/2するとアンチエイリアス
> が掛かった描画になります。
プログラムを作れるだけではなく、こういう発想ができるようにもならない
とダメですね。勉強になりました。
> 手持ちソースの切り抜きですがよかったらどうぞ。
なぜかSetSizeで未定義の識別子としてコンパイルが止まってしまいます。
原因を探し中です。
ライブラリさん
両方ともちょっと私には難しそうです。せっかく教えていただいたのに、
活用できないのが残念です。
D6でしたね、スミマセン。
TBitmap.Seisize(Width,Height)なので
TBitmap.Width := Width;
TBitmap.Height:= Height;
に書き換えてください。
できましたー。
これで自アプリだけでも綺麗に表示できます。
見た目だけの問題で実害はないのですが、やはりちょっとでも綺麗に見えると
気持ちがいいもんです。
ありがとうございました。
ツイート | ![]() |