Sign in Join
Wiki copytemporary

Developing with Graphics/ja: what changed

Revision 2 to 3. 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-`type`\
23-`  PRGBTripleArray = ^TRGBTripleArray;`\
24-`  TRGBTripleArray = array[0..32767] of TRGBTriple;`\
22+``` pascal
23+type
24+ PRGBTripleArray = ^TRGBTripleArray;
25+ TRGBTripleArray = array[0..32767] of TRGBTriple;
2526
26-`procedure TForm1.FadeIn(aBitMap: TBitMap);`\
27-`var`\
28-`  Bitmap, BaseBitmap: TBitmap;`\
29-`  Row, BaseRow: PRGBTripleArray;`\
30-`  x, y, step: integer;`\
31-`begin`\
32-`  Bitmap := TBitmap.Create;`\
33-`  try`\
34-`    Bitmap.PixelFormat := pf32bit;  //  or pf24bit`\
35-`    Bitmap.Assign(aBitMap);`\
36-`    BaseBitmap := TBitmap.Create;`\
37-`    try`\
38-`      BaseBitmap.PixelFormat := pf32bit;`\
39-`      BaseBitmap.Assign(Bitmap);`\
40-`      for step := 0 to 32 do begin`\
41-`        for y := 0 to (Bitmap.Height - 1) do begin`\
42-`          BaseRow := BaseBitmap.Scanline[y];`\
43-`          Row := Bitmap.Scanline[y];`\
44-`          for x := 0 to (Bitmap.Width - 1) do begin`\
45-`            Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;`\
46-`            Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading`\
47-`            Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;`\
48-`          end;`\
49-`        end;`\
50-`        Form1.Canvas.Draw(0, 0, Bitmap);`\
51-`        InvalidateRect(Form1.Handle, nil, False);`\
52-`        RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);`\
53-`      end;`\
54-`    finally`\
55-`      BaseBitmap.Free;`\
56-`    end;`\
57-`  finally`\
58-`    Bitmap.Free;`\
59-`  end;`\
60-`end;`
27+procedure TForm1.FadeIn(aBitMap: TBitMap);
28+var
29+ Bitmap, BaseBitmap: TBitmap;
30+ Row, BaseRow: PRGBTripleArray;
31+ x, y, step: integer;
32+begin
33+ Bitmap := TBitmap.Create;
34+ try
35+ Bitmap.PixelFormat := pf32bit; // or pf24bit
36+ Bitmap.Assign(aBitMap);
37+ BaseBitmap := TBitmap.Create;
38+ try
39+ BaseBitmap.PixelFormat := pf32bit;
40+ BaseBitmap.Assign(Bitmap);
41+ for step := 0 to 32 do begin
42+ for y := 0 to (Bitmap.Height - 1) do begin
43+ BaseRow := BaseBitmap.Scanline[y];
44+ Row := Bitmap.Scanline[y];
45+ for x := 0 to (Bitmap.Width - 1) do begin
46+ Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
47+ Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
48+ Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
49+ end;
50+ end;
51+ Form1.Canvas.Draw(0, 0, Bitmap);
52+ InvalidateRect(Form1.Handle, nil, False);
53+ RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
54+ end;
55+ finally
56+ BaseBitmap.Free;
57+ end;
58+ finally
59+ Bitmap.Free;
60+ end;
61+end;
62+```
6163
6264上の関数は、Lazarusでは、このように実装します:
6365
64-`procedure TForm1.FadeIn(ABitMap: TBitMap);`\
65-`var`\
66-`  SrcIntfImg, TempIntfImg: TLazIntfImage;`\
67-`  ImgHandle,ImgMaskHandle: HBitmap;`\
68-`  FadeStep: Integer;`\
69-`  px, py: Integer;`\
70-`  CurColor: TFPColor;`\
71-`  TempBitmap: TBitmap;`\
72-`begin`\
73-`  SrcIntfImg:=TLazIntfImage.Create(0,0);`\
74-`  SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);`\
75-`  TempIntfImg:=TLazIntfImage.Create(0,0);`\
76-`  TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);`\
77-`  TempBitmap:=TBitmap.Create;`\
78-`  for FadeStep:=1 to 32 do begin`\
79-`    for py:=0 to SrcIntfImg.Height-1 do begin`\
80-`      for px:=0 to SrcIntfImg.Width-1 do begin`\
81-`        CurColor:=SrcIntfImg.Colors[px,py];`\
82-`        CurColor.Red:=(CurColor.Red*FadeStep) shr 5;`\
83-`        CurColor.Green:=(CurColor.Green*FadeStep) shr 5;`\
84-`        CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;`\
85-`        TempIntfImg.Colors[px,py]:=CurColor;`\
86-`      end;`\
87-`    end;`\
88-`    TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);`\
89-`    TempBitmap.Handle:=ImgHandle;`\
90-`    TempBitmap.MaskHandle:=ImgMaskHandle;`\
91-`    Canvas.Draw(0,0,TempBitmap);`\
92-`  end;`\
93-`  SrcIntfImg.Free;`\
94-`  TempIntfImg.Free;`\
95-`  TempBitmap.Free;`\
96-`end;`
66+``` pascal
67+procedure TForm1.FadeIn(ABitMap: TBitMap);
68+var
69+ SrcIntfImg, TempIntfImg: TLazIntfImage;
70+ ImgHandle,ImgMaskHandle: HBitmap;
71+ FadeStep: Integer;
72+ px, py: Integer;
73+ CurColor: TFPColor;
74+ TempBitmap: TBitmap;
75+begin
76+ SrcIntfImg:=TLazIntfImage.Create(0,0);
77+ SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
78+ TempIntfImg:=TLazIntfImage.Create(0,0);
79+ TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
80+ TempBitmap:=TBitmap.Create;
81+ for FadeStep:=1 to 32 do begin
82+ for py:=0 to SrcIntfImg.Height-1 do begin
83+ for px:=0 to SrcIntfImg.Width-1 do begin
84+ CurColor:=SrcIntfImg.Colors[px,py];
85+ CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
86+ CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
87+ CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
88+ TempIntfImg.Colors[px,py]:=CurColor;
89+ end;
90+ end;
91+ TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
92+ TempBitmap.Handle:=ImgHandle;
93+ TempBitmap.MaskHandle:=ImgMaskHandle;
94+ Canvas.Draw(0,0,TempBitmap);
95+ end;
96+ SrcIntfImg.Free;
97+ TempIntfImg.Free;
98+ TempBitmap.Free;
99+end;
100+```
97101
98102このページのLazarusのコードは、 \$LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。 もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
99103
100104### 色(が)透明なビットマップを描く
101105
102106Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。 ビットマップファイル(*.BMP)は、透明性のどんな情報を持つことができません。しかし、ビットマップ上のある色を透明色と選択すれば、色透明ビットマップにすることができます。これは、Win32アプリケーションでよくつかわれてきたトリックです。
103107
104108次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
105109
106110 procedure MyForm.MyButtonOnClick(Sender: TObject);
107111 var
108112 buffer: THandle;
109113 bmp: TBitmap;
110114 memstream: TMemoryStream;
111115 begin
112116 bmp := TBitmap.Create;
113117
114118 buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID));
115119
116120 if (buffer = 0) then exit; // Error loading the bitmap
117121
118122 bmp.Handle := buffer;
119123 memstream := TMemoryStream.create;
120124 try
121125 bmp.SaveToStream(memstream);
122126 memstream.position := 0;
123127 bmp.LoadFromStream(memstream);
124128 finally
125129 memstream.free;
126130 end;
127131
128132 bmp.Transparent := True;
129133 bmp.TransparentColor := clFuchsia;
130134
131135 MyCanvas.Draw(0, 0, bmp);
132136
133137 bmp.Free; // Release allocated resource
134138 end;
135139
136140[[doc:rtl/classes/tmemorystream.html|TMemoryStreamでメモリ]]操作を行っていることに注意してください。 それらは、読み込んだイメージを確実に操作するのに必要です。
137141
138142## 動きのあるグラフィックス - チラツキを防止する方法
139143
140144多くのプログラムが、2D画像としてGUIを描画します。 それらの画像は、高速に変更する必要がある場合、すぐ次のような問題に直面します。高速に更新する画像は、しばしばスクリーン上でチラツキをおこします。 時々、全体的なイメージをユーザーが見ている時、ほんの一部分だけ描画される時、発生します。 それは、描画の作業に時間がかかるのでおこります。
141145
142146しかし、どのようにしたらチラツキを防止し、最善の描画速度を得ることができるのでしょうか。もちろん、OpenGLを使ったハードウエアアクセラレーションを使うこともできます。しかし、この方法は小さなプログラムや古いコンピュータには、大変重いものです。 このチュートリアルでは、TCanvasに描画する方法に焦点をしぼります。 もし、OpenGLの助けが必要であれば、Lazarusについてくるサンプルを見てください。ほかにも、ダブルバッファをサポートしたcanvasや、スプライトコンポーネントのあるA.J.Venterのgamepackを使うこともできます。
143147
144148それでは、Canvasに描画するオプションを調べてみましょう。
145149
146150- Draw to a TImage
147151- Draw on the OnPaint event of the form, a TPaintBox or another control
148152- Create a custom control which draws itself
149153- Using A.J. Venter's gamepack
150154
151155### TImageに描画する
152156
153157TImageに描画するのにOnPaintイベントを使ってはいけません。 TImageはバッファされていますので、あなたが一度描画したり変更しさえすれば、TImageはずっとそのイメージを持続します。 しかし、コンスタントに再描画をおこなえば、チラツキが発生するでしょう。 この場合に、他の方法を試します。 TImageに描画することは、ほかの方法よりも遅いのです。
154158
155-`procedure TForm1.BitBtn1Click(Sender: TObject);`\
156-`var`\
157-`  x, y: Integer;`\
158-`begin`\
159-`  // Draws the backgroung`\
160-`  MyImage.Canvas.Pen.Color := clWhite;`\
161-`  MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);`\
162-`  `\
163-`  // Draws squares`\
164-`  MyImage.Canvas.Pen.Color := clBlack;`\
165-`  for x := 1 to 8 do`\
166-`   for y := 1 to 8 do`\
167-`    MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),`\
168-`       Round(x * Image.Width / 8), Round(y * Image.Height / 8));`\
169-`end;`
159+``` pascal
160+procedure TForm1.BitBtn1Click(Sender: TObject);
161+var
162+ x, y: Integer;
163+begin
164+ // Draws the backgroung
165+ MyImage.Canvas.Pen.Color := clWhite;
166+ MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
167+
168+ // Draws squares
169+ MyImage.Canvas.Pen.Color := clBlack;
170+ for x := 1 to 8 do
171+ for y := 1 to 8 do
172+ MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
173+ Round(x * Image.Width / 8), Round(y * Image.Height / 8));
174+end;
175+```
170176
171177### OnPaintイベントで描画する
172178
173179この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
174180
175181### 自分自身を描画するカスタムコントロールを作成する
176182
177183カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。 この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
178184
179185カスタムコントロールの例:
180186
181-`type`\
182-`  TMyDrawingControl = class(TCustomControl)`\
183-`  public`\
184-`    procedure Paint; override;`\
185-`  end;`\
187+``` pascal
188+type
189+ TMyDrawingControl = class(TCustomControl)
190+ public
191+ procedure Paint; override;
192+ end;
186193
187-`implementation`\
194+implementation
188195
189-`procedure TMyDrawingControl.Paint;`\
190-`var`\
191-`  x, y: Integer;`\
192-`  Bitmap: TBitmap;`\
193-`begin`\
194-`  Bitmap := TBitmap.Create;`\
195-`  try`\
196-`    // Initializes the Bitmap Size`\
197-`    Bitmap.Height := Height;`\
198-`    Bitmap.Width := Width;`\
199-` `\
200-`    // Draws the background`\
201-`    Bitmap.Canvas.Pen.Color := clWhite;`\
202-`    Bitmap.Canvas.Rectangle(0, 0, Width, Height);`\
196+procedure TMyDrawingControl.Paint;
197+var
198+ x, y: Integer;
199+ Bitmap: TBitmap;
200+begin
201+ Bitmap := TBitmap.Create;
202+ try
203+ // Initializes the Bitmap Size
204+ Bitmap.Height := Height;
205+ Bitmap.Width := Width;
206+
207+ // Draws the background
208+ Bitmap.Canvas.Pen.Color := clWhite;
209+ Bitmap.Canvas.Rectangle(0, 0, Width, Height);
203210
204-`    // Draws squares`\
205-`    Bitmap.Canvas.Pen.Color := clBlack;`\
206-`    for x := 1 to 8 do`\
207-`     for y := 1 to 8 do`\
208-`      Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),`\
209-`       Round(x * Width / 8), Round(y * Height / 8));`\
210-`      `\
211-`    Canvas.Draw(0, 0, Bitmap);`\
212-`  finally`\
213-`    Bitmap.Free;`\
214-`  end;`\
211+ // Draws squares
212+ Bitmap.Canvas.Pen.Color := clBlack;
213+ for x := 1 to 8 do
214+ for y := 1 to 8 do
215+ Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
216+ Round(x * Width / 8), Round(y * Height / 8));
217+
218+ Canvas.Draw(0, 0, Bitmap);
219+ finally
220+ Bitmap.Free;
221+ end;
215222
216-`  inherited Paint;`\
217-`end;`
223+ inherited Paint;
224+end;
225+```
218226
219227フォーム上で生成する方法は次のとおりです:
220228
221-`procedure TMyForm.FormCreate(Sender: TObject);`\
222-`begin`\
223-`  MyDrawingControl:= TMyDrawingControl.Create(Self);`\
224-`  MyDrawingControl.Height := 400;`\
225-`  MyDrawingControl.Width := 500;`\
226-`  MyDrawingControl.Top := 0;`\
227-`  MyDrawingControl.Left := 0;`\
228-`  MyDrawingControl.Parent := Self;`\
229-`  MyDrawingControl.DoubleBuffered := True;`\
230-`end;`
229+``` pascal
230+procedure TMyForm.FormCreate(Sender: TObject);
231+begin
232+ MyDrawingControl:= TMyDrawingControl.Create(Self);
233+ MyDrawingControl.Height := 400;
234+ MyDrawingControl.Width := 500;
235+ MyDrawingControl.Top := 0;
236+ MyDrawingControl.Left := 0;
237+ MyDrawingControl.Parent := Self;
238+ MyDrawingControl.DoubleBuffered := True;
239+end;
240+```
231241
232242destroyを忘れてはいけない。 (訳注: CreateでFormのSelfを指定しているから、いらないのでは?) just don´t forget to destroy it:
233243
234-`procedure TMyForm.FormDestroy(Sender: TObject);`\
235-`begin`\
236-`  MyDrawingControl.Free;`\
237-`end;`
244+``` pascal
245+procedure TMyForm.FormDestroy(Sender: TObject);
246+begin
247+ MyDrawingControl.Free;
248+end;
249+```
238250
239251TopとLeftは、0が標準の位置なので、かならずしも設定する必要はありません。 しかし、これは、コントロールが置かれる位置を再設定します。
240252
241253"MyDrawingControl.Parent := Self;"は、とても重要です。これを書かなくては、コントロールが表示されません。
242254
243255"MyDrawingControl.DoubleBuffered := True;" は、Windows上でチラツキを防止するためのものです。gtk上では何の効果もありません。 (訳注:gtk上では、効果がないのか、そもそも、DoubleBufferdを指定する必要がないのか?どっちだろう。)
244256
245257### A.J.Venterのgamepackを使う
246258
247259gamepackによる方法は、すべてのものを、1つのダブルバッファされたcanvasに描画してしまおう、というものです。あなたが更新を準備できた時点で、、見えるcanvasの変更をおこなうことができます。多少コードを必要としますが、多くのスプライトをもつ"シーン"を、大幅に高速に描画更新できる、という利点があります。もし、このアプローチを使いたくなったら、Lazarusのゲーム開発コンポーネントセットであるA.J.Venterのgamepackに興味をもったでしょう。gamepackは、スプライト同様にダブルバッファを表示するエリアを提供してくれますし、ひとつひとつが、大変上手く統合されています。 gamepackはsubversionを通して得ることができます。\
248-`svn co `[`svn://silentcoder.co.za/lazarus/gamepack`](svn://silentcoder.co.za/lazarus/gamepack)
249260
250-`svn co `[`svn://silentcoder.co.za/lazarus/gamepack`](svn://silentcoder.co.za/lazarus/gamepack)
261+```text
262+svn co svn://silentcoder.co.za/lazarus/gamepack
263+```
264+
265+```text
266+svn co svn://silentcoder.co.za/lazarus/gamepack
267+```
251268
252269---
253270*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