こんにちは。
WMFのようなメタファイルの一部を拡大したいと思っています。
Meta := TMetafile.Create;
MetaCanvas := TMetafileCanvas.Create( Meta, 0 );
Meta.LoadFromFile('Map.wmf');
Image1.Canvas.CopyRect( Bounds(0,0,Image1.Width, Image1.Height),
MetaCanvas,
Bounds(100, 100,50, 50) );
MetaCanvas.Free;
Meta.Free;
今はこんな感じですが、Image1は真っ白になります。
いつもビットマップばかりだったので、苦戦しております。
どなたかご教授いただけると助かります。
よろしくお願いします。
TMetafileについてはあまり詳しくないのですが、
CopyRectのCanvas指定はTMetafileCanvasではダメなような
感じがするので、一度MetafileをBitmapにStretchDrawで描画して、
そのBitmapからImage1にコピーしたらいいと思いますよ。
var
CutRect :TRect;
Bitmap :TBitmap;
ZoomRect :=Bounds(100, 100, 50, 50);
Meta := TMetafile.Create;
Meta.LoadFromFile('Map.wmf');
Bitmap :=TBitmap.Create;
try
//2倍に拡大
Bitmap.Width :=Meta.Width * 2;
Bitmap.Height :=Meta.Height * 2;
Bitmap.Canvas.StretchDraw(Rect(0, 0, Bitmap.Width, Bitmap.Height), Meta);
Image1.Canvas.CopyRect(Rect(0,0,Image1.Width, Image1.Height),
Bitmap.Canvas,
Rect(ZoomRect.Left * 2, ZoomRect.Top * 2,
ZoomRect.Right * 2, ZoomRect.Bottom * 2));
finally
Bitmap.Free;
end;
Meta.Free;
ありがとうございます。
この方法だと拡大率によっては
かなり巨大なビットマップを用意しなければなりませんね。
メモリに取れないほどの大きさまで拡大するつもりだったので、
先に一部を切り取りたかったのですが、
何かよい方法はないでしょうか。
それでは、等倍サイズのBitmapにMetafileを描画しておいて
CopyRectで拡大コピーする方法ではどうでしょうか?
Bitmap :=TBitmap.Create;
try
Bitmap.Width :=Meta.Width;
Bitmap.Height :=Meta.Height;
Bitmap.Canvas.Draw(0, 0, Meta);
Image1.Canvas.CopyRect(Bounds(0, 0,Image1.Width, Image1.Height),
Bitmap.Canvas,
ZoomRect);
finally
Bitmap.Free;
end;
等倍サイズのBitmapも使えないとなると
かなり苦戦しそうな感じがします。
ご回答ありがとうございます。
試してみて、拡大することには成功しましたが、
これは結局単純なビットマップの拡大ですので、
メタファイルの売りであるところの
拡大でも画像劣化しない点が活きてきません。
元のWMFを分割するという方法も考えてはみたのですが、
これも拡大率によってはメモリを多量に消費しそうで……
> この方法だと拡大率によっては
> かなり巨大なビットマップを用意しなければなりませんね。
ん? コピーしたい範囲分のビットマップだけ用意すれば済むんじゃないですか?
たとば10倍に拡大して真ん中付近を切り取りたい場合
Bitmap.Width := Image1.Width;
Bitmap.Height := Image1.Height;
rc = Rect(0, 0, Meta.Width * 10, Meta.Height * 10);
OffsetRect(rc, (Bitmap.Width - Meta.Width * 10) div 2, (Bitmap.Height - Meta.Height * 10) div 2);
Bitmap.Canvas.StretchDraw(rc, Meta);
みたいにすれば必要な範囲だけ描画されると思うのですが。
メタファイルは拡大してもメモリのサイズは変わりません。
そのためメタファイルを一度全部拡大してしまい、
ほしいところだけ描画すれば目的の動作になります。
procedure TForm1.Button1Click(Sender: TObject);
var
str:string;
mFile :TMetafile;
mCanvas:TMetafileCanvas;
rate,left,right,top,bottom,rL,rT : Integer;
bmp: TBitmap;
begin
mFile := TMetafile.Create;
mFile.Width:=20;
mFile.Height:=20;
mCanvas:=TMetafileCanvas.Create(mFile,0);
mCanvas.Font.Height := 20;
str := '薔';
TextOut(mCanvas.Handle,0,0,@str[1],1);
mCanvas.Free;
//メタファイルサイズは H20 W20
//水平 5-15 を拡大して表示
//垂直 5-15 を拡大して表示
rate := 20; //20倍
left := 5;
right := 15;
top := 5;
bottom:= 15;
bmp:=TBitmap.Create;
bmp.Width := (right - left)*rate;
bmp.Height:= (bottom- top )*rate;
rL := left*rate*-1;
rT := top*rate*-1;
bmp.Canvas.StretchDraw(
Rect(rL,rT,
mFile.Width * rate + rL,
mFile.Height* rate + rT),mFile);
Canvas.Draw(0,0,bmp);
bmp.Free;
mFile.Free;
end;
あら、サンプル書いているうちに書き込みありましたね。
重複失礼しました。
1781x2203 の .WMF を
if OpenPictureDialog1.Execute = True then
begin
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
Image1.Width := Image1.Picture.Width * 10000;
Image1.Height := Image1.Picture.Height * 10000;
end;
で表示できるから別に部分拡大しなくても良い気がするけど?
たくさんのレスありがとうございます。
tocさまの方法でうまくいきました。
メタファイルは拡大してもメモリは使わないのですね。
勉強になりました。
Mr.XRAYです.解決済みというこですが,ついでに.
>メタファイルは拡大してもメモリは使わないのですね。
描画情報が格納されているだけですから,基本的にそうなります.
メタファイルをTImageに描画する際,DrawやStretchDrawの場合,TImgaeの拡大に伴い,
描画した画像はギザギザになります.これは内部での描画がビットマップだからです.
一方,Image1.Picture.Assigngならばなりません.
すぐに確認できるサンプルを用意してあります.もし必要なら試してください.
http://mrxray.on.coocan.jp/Delphi/plSamples/172_MetaFile_BasicTest.htm
それから,メタファイルの部分拡大したメタファイルの取得ですが,
マッピングという方法を利用すると可能です.
以下のコードでは,簡単のために,範囲指定ではなく,拡大して,その部分を保存
しています.
範囲指定するには,換算が必要です.
保存したメタファイルを,イメージを表示するアプリで開き,拡大してみてください.
まさにメタファイルであることが確認できます.
//=============================================================================
// メタファイルの一部を切取ったメタファイルを作成
//
// TImageを2つ.共にStretchをTrueに(画像が大きい時も確認可能にするため)
// TButtonを1つ
//
// 任意の範囲だけを取出すには,
// SetWindowExtExとSetViewPortOrgExの引数値に工夫が必要
// ここでは簡単にするため,倍率で設定
//=============================================================================
procedure TForm1.Button4Click(Sender: TObject);
Var
Meta : TMetafile;
MetaCanvas : TMetafileCanvas;
AWidth : Integer;
AHeight : Integer;
R : Integer;
begin
Image1.Stretch := True;
Image2.Stretch := True;
//拡大率
R := 3;
Meta := TMetafile.Create;
try
//対象のメタファイル画像
Meta.LoadFromFile('000.emf');
//元の画像を確認表示
Image1.Picture.Assign(Meta);
MetaCanvas := TMetafileCanvas.Create( Meta, 0 );
AWidth := Meta.Width;
AHeight := Meta.Height;
//マッピング設定
SetMapMode (MetaCanvas.Handle,MM_ANISOTROPIC);
SetWindowExtEx (MetaCanvas.Handle,AWidth div R, AHeight div R, nil);
SetViewPortExtEx (MetaCanvas.Handle,AWidth, AHeight, nil);
//描画原点を移動
//ここでは元の画像の右から30,上から50
SetViewPortOrgEx(MetaCanvas.Handle,-30*R,-50*R,nil);
//描画
MetaCanvas.Draw(0,0,Meta);;
//描画終了
MetaCanvas.Free;
//確認表示(このImage2に表示されている範囲が保存される
//ただし,Image2のStretchはTrueとしているので縦横比は正確でない
Image2.Picture.Assign(Meta);
//保存
Meta.SaveToFile('TestOut.emf');
finally
FreeAndNil(Meta);
end;
end;
Mr.XRAYです.
う〜ん.この方法には無理がありますね.
やはり,他の方のレスのやり方がいいでしょう.
迷わせてしまって,申し訳ありませんでした.
詳しくありがとうございます。
とても参考になります。
試してみましたが、
切り取ったメタファイルって
ほとんどファイルサイズ変わらないんですね
復活させることも可能なんでしょうか。
Mr.XRAYです.
メタファイルのサイズというのは,コードの Meta.Width 等のことでしょうか.
例えば,ビットマップのサイズ(幅)というと,
Bitmap.Width
のことを意味していると思いますが,これは,ピクセル数のことです.
メタファイルのサイズとは,意味が違います.
メタファイルというのは,
(0,0) から (200,500) まで,直線で,これこれの色と太さで描画せよ
というような情報が格納されています.
つまり,メタファイルのサイズというのは,そのような情報の格納サイズと考えてください.
これは,他のベクター方式の画像ファイルにも言えることです.
ビットマップでしたら,どこから,どこまでのピクセルを切取った画像とういことが可能です.
メタファイルの場合は,情報の格納サイズみたいなものですから,
通常のファイル等と同じで,ファイルのサイズの一部分を切取るということはできません.
(明らかに,意味不明ですよね?)
他の方のレスにあるように,ビットマップを介して,その一部を描画というのはできます.
メタファイルの一部分を取出しても,描画情報の格納サイズですから,それほど変化が
ない場合もあります.
>復活させることも可能なんでしょうか。
すみません.意味がわかりません.
>メタファイルの一部分を取出しても,描画情報の格納サイズですから,それほど変化が
>ない場合もあります.
ファイルそのもののサイズも同様です.
>そのような情報の格納サイズと考えてください.
本当は違います.格納サイズの一種です.
描画に関する長さと高さ関係の情報なんですが,
それは,ネット上や書籍で調べてみてください.
*私のサイトには,これに関しての説明記事はありません,あしからず.
ツイート | ![]() |