Sign in Join
Wiki copytemporary

Developing with Graphics/ja: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。 私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。 次の項目にリンクやページを追加して、Wikiを製作してください。
22
33このページで、一般的なお知らせをすることがあります。
44
55## その他のグラフィックス
66
77- [[GLScene/ja]] - OpenGL ライブラリの移植 [GLScene](http://www.glscene.org)
88- [[TAChart/ja]] - Lazarus用のチャートコンポーネント
99- [[PascalMagick/ja]] - インターフェース用の簡単なAPI [ImageMagick](http://www.imagemagick.org),マルチプラットホームでのビットマップを扱うフリーソフトウエア
1010- [[PlotPanel/ja]] - アニメーショングラフのためのチャートや描画コンポーネント
1111
1212## TBitmapの作業
1313
1414まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。 ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。 たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。 なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。
1515
1616[[doc:lcl/graphics/tbitmap.html|TBitmapにwidth]],heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
1717
1818### フェーディングの例
1919
2020フェーディングするピクチャを作る場合、Delphiでは、このように書けます。
2121
22-<code>
23-
2422`type`\
2523`  PRGBTripleArray = ^TRGBTripleArray;`\
2624`  TRGBTripleArray = array[0..32767] of TRGBTriple;`\
27-\
25+
2826`procedure TForm1.FadeIn(aBitMap: TBitMap);`\
2927`var`\
3028`  Bitmap, BaseBitmap: TBitmap;`\
3129`  Row, BaseRow: PRGBTripleArray;`\
3230`  x, y, step: integer;`\
3331`begin`\
3432`  Bitmap := TBitmap.Create;`\
3533`  try`\
3634`    Bitmap.PixelFormat := pf32bit;  //  or pf24bit`\
3735`    Bitmap.Assign(aBitMap);`\
3836`    BaseBitmap := TBitmap.Create;`\
3937`    try`\
4038`      BaseBitmap.PixelFormat := pf32bit;`\
4139`      BaseBitmap.Assign(Bitmap);`\
4240`      for step := 0 to 32 do begin`\
4341`        for y := 0 to (Bitmap.Height - 1) do begin`\
4442`          BaseRow := BaseBitmap.Scanline[y];`\
4543`          Row := Bitmap.Scanline[y];`\
4644`          for x := 0 to (Bitmap.Width - 1) do begin`\
4745`            Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;`\
4846`            Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading`\
4947`            Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;`\
5048`          end;`\
5149`        end;`\
5250`        Form1.Canvas.Draw(0, 0, Bitmap);`\
5351`        InvalidateRect(Form1.Handle, nil, False);`\
5452`        RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);`\
5553`      end;`\
5654`    finally`\
5755`      BaseBitmap.Free;`\
5856`    end;`\
5957`  finally`\
6058`    Bitmap.Free;`\
6159`  end;`\
6260`end;`
6361
64-</code>
65-
6662上の関数は、Lazarusでは、このように実装します:
6763
68-<code>
69-
7064`procedure TForm1.FadeIn(ABitMap: TBitMap);`\
7165`var`\
7266`  SrcIntfImg, TempIntfImg: TLazIntfImage;`\
7367`  ImgHandle,ImgMaskHandle: HBitmap;`\
7468`  FadeStep: Integer;`\
7569`  px, py: Integer;`\
7670`  CurColor: TFPColor;`\
7771`  TempBitmap: TBitmap;`\
7872`begin`\
7973`  SrcIntfImg:=TLazIntfImage.Create(0,0);`\
8074`  SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);`\
8175`  TempIntfImg:=TLazIntfImage.Create(0,0);`\
8276`  TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);`\
8377`  TempBitmap:=TBitmap.Create;`\
8478`  for FadeStep:=1 to 32 do begin`\
8579`    for py:=0 to SrcIntfImg.Height-1 do begin`\
8680`      for px:=0 to SrcIntfImg.Width-1 do begin`\
8781`        CurColor:=SrcIntfImg.Colors[px,py];`\
8882`        CurColor.Red:=(CurColor.Red*FadeStep) shr 5;`\
8983`        CurColor.Green:=(CurColor.Green*FadeStep) shr 5;`\
9084`        CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;`\
9185`        TempIntfImg.Colors[px,py]:=CurColor;`\
9286`      end;`\
9387`    end;`\
9488`    TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);`\
9589`    TempBitmap.Handle:=ImgHandle;`\
9690`    TempBitmap.MaskHandle:=ImgMaskHandle;`\
9791`    Canvas.Draw(0,0,TempBitmap);`\
9892`  end;`\
9993`  SrcIntfImg.Free;`\
10094`  TempIntfImg.Free;`\
10195`  TempBitmap.Free;`\
10296`end;`
10397
104-</code>
105-
10698このページのLazarusのコードは、 \$LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
10799
108100### 色(が)透明なビットマップを描く
109101
110102Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 ビットマップファイル(*.BMP)は、透明性のどんな情報を持つことができません。しかし、ビットマップ上のある色を透明色と選択すれば、色透明ビットマップにすることができます。これは、Win32アプリケーションでよくつかわれてきたトリックです。
111103
112104次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
113105
114106 procedure MyForm.MyButtonOnClick(Sender: TObject);
115107 var
116108 buffer: THandle;
117109 bmp: TBitmap;
118110 memstream: TMemoryStream;
119111 begin
120112 bmp := TBitmap.Create;
121113
122114 buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID));
123115
124116 if (buffer = 0) then exit; // Error loading the bitmap
125117
126118 bmp.Handle := buffer;
127119 memstream := TMemoryStream.create;
128120 try
129121 bmp.SaveToStream(memstream);
130122 memstream.position := 0;
131123 bmp.LoadFromStream(memstream);
132124 finally
133125 memstream.free;
134126 end;
135127
136128 bmp.Transparent := True;
137129 bmp.TransparentColor := clFuchsia;
138130
139131 MyCanvas.Draw(0, 0, bmp);
140132
141133 bmp.Free; // Release allocated resource
142134 end;
143135
144136[[doc:rtl/classes/tmemorystream.html|TMemoryStreamでメモリ]]操作を行っていることに注意してください。 それらは、読み込んだイメージを確実に操作するのに必要です。
145137
146138## 動きのあるグラフィックス - チラツキを防止する方法
147139
148140多くのプログラムが、2D画像としてGUIを描画します。 それらの画像は、高速に変更する必要がある場合、すぐ次のような問題に直面します。高速に更新する画像は、しばしばスクリーン上でチラツキをおこします。 時々、全体的なイメージをユーザーが見ている時、ほんの一部分だけ描画される時、発生します。 それは、描画の作業に時間がかかるのでおこります。
149141
150142しかし、どのようにしたらチラツキを防止し、最善の描画速度を得ることができるのでしょうか。もちろん、OpenGLを使ったハードウエアアクセラレーションを使うこともできます。しかし、この方法は小さなプログラムや古いコンピュータには、大変重いものです。 このチュートリアルでは、TCanvasに描画する方法に焦点をしぼります。 もし、OpenGLの助けが必要であれば、Lazarusについてくるサンプルを見てください。ほかにも、ダブルバッファをサポートしたcanvasや、スプライトコンポーネントのあるA.J.Venterのgamepackを使うこともできます。
151143
152144それでは、Canvasに描画するオプションを調べてみましょう。
153145
154146- Draw to a TImage
155147- Draw on the OnPaint event of the form, a TPaintBox or another control
156148- Create a custom control which draws itself
157149- Using A.J. Venter's gamepack
158150
159151### TImageに描画する
160152
161153TImageに描画するのにOnPaintイベントを使ってはいけません。 TImageはバッファされていますので、あなたが一度描画したり変更しさえすれば、TImageはずっとそのイメージを持続します。 しかし、コンスタントに再描画をおこなえば、チラツキが発生するでしょう。 この場合に、他の方法を試します。 TImageに描画することは、ほかの方法よりも遅いのです。
162154
163-<code>
164-
165155`procedure TForm1.BitBtn1Click(Sender: TObject);`\
166156`var`\
167157`  x, y: Integer;`\
168158`begin`\
169159`  // Draws the backgroung`\
170160`  MyImage.Canvas.Pen.Color := clWhite;`\
171161`  MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);`\
172162`  `\
173163`  // Draws squares`\
174164`  MyImage.Canvas.Pen.Color := clBlack;`\
175165`  for x := 1 to 8 do`\
176166`   for y := 1 to 8 do`\
177167`    MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),`\
178168`       Round(x * Image.Width / 8), Round(y * Image.Height / 8));`\
179169`end;`
180170
181-</code>
182-
183171### OnPaintイベントで描画する
184172
185173この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
186174
187175### 自分自身を描画するカスタムコントロールを作成する
188176
189177カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
190178
191179カスタムコントロールの例:
192180
193-<code>
194-
195181`type`\
196182`  TMyDrawingControl = class(TCustomControl)`\
197183`  public`\
198184`    procedure Paint; override;`\
199185`  end;`\
200-\
186+
201187`implementation`\
202-\
188+
203189`procedure TMyDrawingControl.Paint;`\
204190`var`\
205191`  x, y: Integer;`\
206192`  Bitmap: TBitmap;`\
207193`begin`\
208194`  Bitmap := TBitmap.Create;`\
209195`  try`\
210196`    // Initializes the Bitmap Size`\
211197`    Bitmap.Height := Height;`\
212198`    Bitmap.Width := Width;`\
213199` `\
214200`    // Draws the background`\
215201`    Bitmap.Canvas.Pen.Color := clWhite;`\
216202`    Bitmap.Canvas.Rectangle(0, 0, Width, Height);`\
217-\
203+
218204`    // Draws squares`\
219205`    Bitmap.Canvas.Pen.Color := clBlack;`\
220206`    for x := 1 to 8 do`\
221207`     for y := 1 to 8 do`\
222208`      Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),`\
223209`       Round(x * Width / 8), Round(y * Height / 8));`\
224210`      `\
225211`    Canvas.Draw(0, 0, Bitmap);`\
226212`  finally`\
227213`    Bitmap.Free;`\
228214`  end;`\
229-\
215+
230216`  inherited Paint;`\
231217`end;`
232218
233-</code>
234-
235-フォーム上で生成する方法は次のとおりです: <code>
219+フォーム上で生成する方法は次のとおりです:
236220
237221`procedure TMyForm.FormCreate(Sender: TObject);`\
238222`begin`\
239223`  MyDrawingControl:= TMyDrawingControl.Create(Self);`\
240224`  MyDrawingControl.Height := 400;`\
241225`  MyDrawingControl.Width := 500;`\
242226`  MyDrawingControl.Top := 0;`\
243227`  MyDrawingControl.Left := 0;`\
244228`  MyDrawingControl.Parent := Self;`\
245229`  MyDrawingControl.DoubleBuffered := True;`\
246230`end;`
247231
248-</code>
249-
250-destroyを忘れてはいけない。 (訳注: CreateでFormのSelfを指定しているから、いらないのでは?) just don´t forget to destroy it: <code>
232+destroyを忘れてはいけない。 (訳注: CreateでFormのSelfを指定しているから、いらないのでは?) just don´t forget to destroy it:
251233
252234`procedure TMyForm.FormDestroy(Sender: TObject);`\
253235`begin`\
254236`  MyDrawingControl.Free;`\
255237`end;`
256-
257-</code>
258238
259239TopとLeftは、0が標準の位置なので、かならずしも設定する必要はありません。 しかし、これは、コントロールが置かれる位置を再設定します。
260240
261241"MyDrawingControl.Parent := Self;"は、とても重要です。これを書かなくては、コントロールが表示されません。
262242
263243"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 (訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。)
264244
265245### A.J.Venterのgamepackを使う
266246
267247gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。 gamepackはsubversionを通して得ることができます。\
268248`svn co `[`svn://silentcoder.co.za/lazarus/gamepack`](svn://silentcoder.co.za/lazarus/gamepack)
269249
270250`svn co `[`svn://silentcoder.co.za/lazarus/gamepack`](svn://silentcoder.co.za/lazarus/gamepack)
271251
272252---
273253*From the Free Pascal wiki, page "Developing with Graphics/ja", as it stood on 2008-03-31 after a change by Saeka-jp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history