Difference between revisions of "Developing with Graphics/ja"
m (Developing with Graphics) |
|||
Line 9: | Line 9: | ||
このページで、一般的なお知らせをすることがあります。 | このページで、一般的なお知らせをすることがあります。 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
__TOC__ | __TOC__ | ||
− | == | + | ==その他のグラフィックス== |
* [[GLScene]] - A port of the visual OpenGL graphics Library [http://www.glscene.org GLScene] | * [[GLScene]] - A port of the visual OpenGL graphics Library [http://www.glscene.org GLScene] | ||
* [[TAChart]] - Charting component for Lazarus | * [[TAChart]] - Charting component for Lazarus | ||
Line 24: | Line 19: | ||
==TBitmapの作業 == | ==TBitmapの作業 == | ||
− | |||
− | |||
まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。 | まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。 | ||
ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。 | ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。 | ||
− | + | たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。 | |
− | なぜなら、ScanlineはDevice Independant Bitmap(DIB) | + | なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。 |
− | |||
− | |||
− | |||
− | |||
− | + | [[doc:lcl/graphics/tbitmap.html|TBitmap]]にwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。 | |
Line 42: | Line 31: | ||
フェーディングするピクチャを作る場合、Delphiでは、このように書けます。 | フェーディングするピクチャを作る場合、Delphiでは、このように書けます。 | ||
− | |||
− | |||
<code> | <code> | ||
type | type | ||
Line 88: | Line 75: | ||
上の関数は、Lazarusでは、このように実装します: | 上の関数は、Lazarusでは、このように実装します: | ||
− | |||
<code> | <code> | ||
Line 128: | Line 114: | ||
このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 | このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 | ||
もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。 | もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。 | ||
− | |||
− | |||
− | |||
===色(が)透明なビットマップを描く=== | ===色(が)透明なビットマップを描く=== | ||
− | |||
Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 | Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 | ||
Line 140: | Line 122: | ||
次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。 | 次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。 | ||
− | |||
− | |||
− | |||
− | |||
<pre> | <pre> | ||
Line 180: | Line 158: | ||
それらは、読み込んだイメージを確実に操作するのに必要です。 | それらは、読み込んだイメージを確実に操作するのに必要です。 | ||
− | |||
== 動きのあるグラフィックス - チラツキを防止する方法 == | == 動きのあるグラフィックス - チラツキを防止する方法 == | ||
− | |||
多くのプログラムが、2D画像としてGUIを描画します。 | 多くのプログラムが、2D画像としてGUIを描画します。 | ||
Line 197: | Line 173: | ||
それでは、Canvasに描画するオプションを調べてみましょう。 | それでは、Canvasに描画するオプションを調べてみましょう。 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
* [[#Draw to a TImage|Draw to a TImage]] | * [[#Draw to a TImage|Draw to a TImage]] | ||
* [[#Draw on the OnPaint event|Draw on the OnPaint event of the form, a TPaintBox or another control]] | * [[#Draw on the OnPaint event|Draw on the OnPaint event of the form, a TPaintBox or another control]] | ||
Line 210: | Line 181: | ||
===TImageに描画する=== | ===TImageに描画する=== | ||
− | |||
TImageに描画するのにOnPaintイベントを使ってはいけません。 | TImageに描画するのにOnPaintイベントを使ってはいけません。 | ||
Line 217: | Line 187: | ||
この場合に、他の方法を試します。 | この場合に、他の方法を試します。 | ||
TImageに描画することは、ほかの方法よりも遅いのです。 | TImageに描画することは、ほかの方法よりも遅いのです。 | ||
− | |||
− | |||
− | |||
<code> | <code> | ||
Line 240: | Line 207: | ||
===OnPaintイベントで描画する=== | ===OnPaintイベントで描画する=== | ||
− | |||
この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。 | この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。 | ||
− | |||
− | |||
− | |||
===自分自身を描画するカスタムコントロールを作成する=== | ===自分自身を描画するカスタムコントロールを作成する=== | ||
− | |||
カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 | カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 | ||
この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。 | この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。 | ||
− | |||
− | |||
カスタムコントロールの例: | カスタムコントロールの例: | ||
− | |||
<code> | <code> | ||
Line 299: | Line 258: | ||
フォーム上で生成する方法は次のとおりです: | フォーム上で生成する方法は次のとおりです: | ||
− | |||
<code> | <code> | ||
procedure TMyForm.FormCreate(Sender: TObject); | procedure TMyForm.FormCreate(Sender: TObject); | ||
Line 330: | Line 288: | ||
"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 | "MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 | ||
(訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。) | (訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
===A.J.Venterのgamepackを使う=== | ===A.J.Venterのgamepackを使う=== | ||
− | |||
gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。 | gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。 | ||
Line 346: | Line 297: | ||
</code> | </code> | ||
− | + | ||
<code> | <code> | ||
svn co svn://silentcoder.co.za/lazarus/gamepack | svn co svn://silentcoder.co.za/lazarus/gamepack | ||
</code> | </code> |
Revision as of 12:01, 7 May 2006
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
italiano (it) │
日本語 (ja) │
한국어 (ko) │
Nederlands (nl) │
português (pt) │
русский (ru) │
slovenčina (sk) │
中文(中国大陆) (zh_CN) │
中文(台灣) (zh_TW) │
このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。 私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。 次の項目にリンクやページを追加して、Wikiを製作してください。
このページで、一般的なお知らせをすることがあります。
その他のグラフィックス
- GLScene - A port of the visual OpenGL graphics Library GLScene
- TAChart - Charting component for Lazarus
- PascalMagick - an easy to use API for interfacing with ImageMagick, a multiplatform free software suite to create, edit, and compose bitmap images.
- PlotPanel - A plotting and charting component for animated graphs
TBitmapの作業
まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。 ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。 たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。 なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。
TBitmapにwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
フェーディングの例
フェーディングするピクチャを作る場合、Delphiでは、このように書けます。
type
PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32767] of TRGBTriple;
procedure TForm1.FadeIn(aBitMap: TBitMap);
var
Bitmap, BaseBitmap: TBitmap;
Row, BaseRow: PRGBTripleArray;
x, y, step: integer;
begin
Bitmap := TBitmap.Create;
try
Bitmap.PixelFormat := pf32bit; // or pf24bit
Bitmap.Assign(aBitMap);
BaseBitmap := TBitmap.Create;
try
BaseBitmap.PixelFormat := pf32bit;
BaseBitmap.Assign(Bitmap);
for step := 0 to 32 do begin
for y := 0 to (Bitmap.Height - 1) do begin
BaseRow := BaseBitmap.Scanline[y];
Row := Bitmap.Scanline[y];
for x := 0 to (Bitmap.Width - 1) do begin
Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
end;
end;
Form1.Canvas.Draw(0, 0, Bitmap);
InvalidateRect(Form1.Handle, nil, False);
RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
end;
finally
BaseBitmap.Free;
end;
finally
Bitmap.Free;
end;
end;
上の関数は、Lazarusでは、このように実装します:
procedure TForm1.FadeIn(ABitMap: TBitMap);
var
SrcIntfImg, TempIntfImg: TLazIntfImage;
ImgHandle,ImgMaskHandle: HBitmap;
FadeStep: Integer;
px, py: Integer;
CurColor: TFPColor;
TempBitmap: TBitmap;
begin
SrcIntfImg:=TLazIntfImage.Create(0,0);
SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
TempIntfImg:=TLazIntfImage.Create(0,0);
TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
TempBitmap:=TBitmap.Create;
for FadeStep:=1 to 32 do begin
for py:=0 to SrcIntfImg.Height-1 do begin
for px:=0 to SrcIntfImg.Width-1 do begin
CurColor:=SrcIntfImg.Colors[px,py];
CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
TempIntfImg.Colors[px,py]:=CurColor;
end;
end;
TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
TempBitmap.Handle:=ImgHandle;
TempBitmap.MaskHandle:=ImgMaskHandle;
Canvas.Draw(0,0,TempBitmap);
end;
SrcIntfImg.Free;
TempIntfImg.Free;
TempBitmap.Free;
end;
このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
色(が)透明なビットマップを描く
Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 ビットマップファイル(*.BMP)は、透明性のどんな情報を持つことができません。しかし、ビットマップ上のある色を透明色と選択すれば、色透明ビットマップにすることができます。これは、Win32アプリケーションでよくつかわれてきたトリックです。
次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
procedure MyForm.MyButtonOnClick(Sender: TObject); var buffer: THandle; bmp: TBitmap; memstream: TMemoryStream; begin bmp := TBitmap.Create; buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID)); if (buffer = 0) then exit; // Error loading the bitmap bmp.Handle := buffer; memstream := TMemoryStream.create; try bmp.SaveToStream(memstream); memstream.position := 0; bmp.LoadFromStream(memstream); finally memstream.free; end; bmp.Transparent := True; bmp.TransparentColor := clFuchsia; MyCanvas.Draw(0, 0, bmp); bmp.Free; // Release allocated resource end;
TMemoryStreamでメモリ操作を行っていることに注意してください。 それらは、読み込んだイメージを確実に操作するのに必要です。
動きのあるグラフィックス - チラツキを防止する方法
多くのプログラムが、2D画像としてGUIを描画します。 それらの画像は、高速に変更する必要がある場合、すぐ次のような問題に直面します。高速に更新する画像は、しばしばスクリーン上でチラツキをおこします。 時々、全体的なイメージをユーザーが見ている時、ほんの一部分だけ描画される時、発生します。 それは、描画の作業に時間がかかるのでおこります。
しかし、どのようにしたらチラツキを防止し、最善の描画速度を得ることができるのでしょうか。もちろん、OpenGLを使ったハードウエアアクセラレーションを使うこともできます。しかし、この方法は小さなプログラムや古いコンピュータには、大変重いものです。 このチュートリアルでは、TCanvasに描画する方法に焦点をしぼります。 もし、OpenGLの助けが必要であれば、Lazarusについてくるサンプルを見てください。ほかにも、ダブルバッファをサポートしたcanvasや、スプライトコンポーネントのあるA.J.Venterのgamepackを使うこともできます。
それでは、Canvasに描画するオプションを調べてみましょう。
- Draw to a TImage
- Draw on the OnPaint event of the form, a TPaintBox or another control
- Create a custom control which draws itself
- Using A.J. Venter's gamepack
TImageに描画する
TImageに描画するのにOnPaintイベントを使ってはいけません。 TImageはバッファされていますので、あなたが一度描画したり変更しさえすれば、TImageはずっとそのイメージを持続します。 しかし、コンスタントに再描画をおこなえば、チラツキが発生するでしょう。 この場合に、他の方法を試します。 TImageに描画することは、ほかの方法よりも遅いのです。
procedure TForm1.BitBtn1Click(Sender: TObject);
var
x, y: Integer;
begin
// Draws the backgroung
MyImage.Canvas.Pen.Color := clWhite;
MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
// Draws squares
MyImage.Canvas.Pen.Color := clBlack;
for x := 1 to 8 do
for y := 1 to 8 do
MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
Round(x * Image.Width / 8), Round(y * Image.Height / 8));
end;
OnPaintイベントで描画する
この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
自分自身を描画するカスタムコントロールを作成する
カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
カスタムコントロールの例:
type
TMyDrawingControl = class(TCustomControl)
public
procedure Paint; override;
end;
implementation
procedure TMyDrawingControl.Paint;
var
x, y: Integer;
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
try
// Initializes the Bitmap Size
Bitmap.Height := Height;
Bitmap.Width := Width;
// Draws the background
Bitmap.Canvas.Pen.Color := clWhite;
Bitmap.Canvas.Rectangle(0, 0, Width, Height);
// Draws squares
Bitmap.Canvas.Pen.Color := clBlack;
for x := 1 to 8 do
for y := 1 to 8 do
Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
Round(x * Width / 8), Round(y * Height / 8));
Canvas.Draw(0, 0, Bitmap);
finally
Bitmap.Free;
end;
inherited Paint;
end;
フォーム上で生成する方法は次のとおりです:
procedure TMyForm.FormCreate(Sender: TObject);
begin
MyDrawingControl:= TMyDrawingControl.Create(Self);
MyDrawingControl.Height := 400;
MyDrawingControl.Width := 500;
MyDrawingControl.Top := 0;
MyDrawingControl.Left := 0;
MyDrawingControl.Parent := Self;
MyDrawingControl.DoubleBuffered := True;
end;
destroyを忘れてはいけない。
(訳注: CreateでFormのSelfを指定しているから、いらないのでは?)
just don´t forget to destroy it:
procedure TMyForm.FormDestroy(Sender: TObject);
begin
MyDrawingControl.Free;
end;
TopとLeftは、0が標準の位置なので、かならずしも設定する必要はありません。 しかし、これは、コントロールが置かれる位置を再設定します。
"MyDrawingControl.Parent := Self;"は、とても重要です。これを書かなくては、コントロールが表示されません。
"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 (訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。)
A.J.Venterのgamepackを使う
gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。
gamepackはsubversionを通して得ることができます。
svn co svn://silentcoder.co.za/lazarus/gamepack