Difference between revisions of "Developing with Graphics/ja"

From Lazarus wiki
Jump to navigationJump to search
m (Developing with Graphics)
Line 9: Line 9:
 
このページで、一般的なお知らせをすることがあります。
 
このページで、一般的なお知らせをすることがあります。
  
(英文による 原文)
 
 
This page will be the start of tutorials with regard to manipulating Bitmaps and other graphics. As I am not a graphics programmer, I invite all who are to share their expertise! Just add a link to the next section, add a page and create your own WiKi article.
 
 
On this page some general information will be given.
 
  
 
__TOC__
 
__TOC__
  
==Other graphics articles==  
+
==その他のグラフィックス==  
 
* [[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の作業 ==
 
==Working with TBitmap==
 
  
 
まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。
 
まず覚えていただきたいことは、Lazarusはプラットホームに対して独立しているということです。
 
ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。
 
ですから、WindowsAPIの機能を使うメソッドは言うまでもなく、つかわないでください。
Scanlineを使うメソッドは、Lazarusではサポートしません。
+
たとえば、Scanlineのようなメソッドは、Lazarusではサポートしません。
なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、GDI32.dllを使うことになるからです。
+
なぜなら、ScanlineはDevice Independant Bitmap(DIB)を扱い、結局GDI32.dllを使うことになるから(プラットホーム独立ではなくなるから)です。
 
 
また、[[doc:lcl/graphics/tbitmap.html|TBitmap]]にwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
 
 
 
The first thing to remember is that Lazarus is meant to be platform independent, so any methods using Windows API functionality are out of the question. So a method like ScanLine is not supported by Lazarus because it is intended for Device Independant Bitmap and uses functions from the GDI32.dll.
 
  
Be careful that if you do not specify the width and height of your [[doc:lcl/graphics/tbitmap.html|TBitmap]] it will have the standard one, which is quite small.
+
[[doc:lcl/graphics/tbitmap.html|TBitmap]]にwidth,heightを特定しないなら、デフォルトはかなり小さいものになっているので、気をつけてください。
  
  
Line 42: Line 31:
 
フェーディングするピクチャを作る場合、Delphiでは、このように書けます。
 
フェーディングするピクチャを作る場合、Delphiでは、このように書けます。
  
===A fading example===
 
Say you want to make a Fading picture. In Delphi you could do something like:
 
 
<code>
 
<code>
 
  type
 
  type
Line 88: Line 75:
  
 
上の関数は、Lazarusでは、このように実装します:
 
上の関数は、Lazarusでは、このように実装します:
This function in Lazarus could be implemented like:
 
  
 
<code>
 
<code>
Line 128: Line 114:
 
このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。
 
このページのLazarusのコードは、 $LazarusPath/examples/lazintfimage/fadein1.lpi のプロジェクトから取ってきたものです。
 
もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
 
もし、あなたが画像処理プログラムで早いスタートをしたいなら、この例を良く読みましょう。
 
The Lazarus code on this page has been taken from the $LazarusPath/examples/lazintfimage/fadein1.lpi project. So if you want a flying start with graphics programming take a closer look at this example.
 
 
  
  
 
===色(が)透明なビットマップを描く===
 
===色(が)透明なビットマップを描く===
===Drawing color transparent bitmaps===
 
  
 
Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。
 
Lazarus 0.9.11で実装された新しい機能で、色透明ビットマップを描画することができます。
Line 140: Line 122:
  
 
次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
 
次のサンプルはWindowsのリソースからビットマップをロードし、透明となる色(clFuchsia)を指定し、canvasに描画します。
 
A new feature, implemented on Lazarus 0.9.11, is color transparent bitmaps. Bitmap files (*.BMP) cannot store any information about transparency, but they can work as they had if you select a color on them to represent the transparent area. This is a common trick used on Win32 applications.
 
 
The following example loads a bitmap from a Windows resource, selects a color to be transparent (clFuchsia) and then draws it to a canvas.
 
  
 
<pre>
 
<pre>
Line 180: Line 158:
 
それらは、読み込んだイメージを確実に操作するのに必要です。
 
それらは、読み込んだイメージを確実に操作するのに必要です。
  
Notice the memory operations performed with the [[doc:rtl/classes/tmemorystream.html|TMemoryStream]]. They are necessary to ensure the correct loading of the image.
 
  
  
 
== 動きのあるグラフィックス - チラツキを防止する方法 ==
 
== 動きのあるグラフィックス - チラツキを防止する方法 ==
==Motion Graphics - How to Avoid flickering==
 
  
 
多くのプログラムが、2D画像としてGUIを描画します。
 
多くのプログラムが、2D画像としてGUIを描画します。
Line 197: Line 173:
 
それでは、Canvasに描画するオプションを調べてみましょう。
 
それでは、Canvasに描画するオプションを調べてみましょう。
  
Many programs draw their output to the GUI as 2D graphics. If those graphics need to change quickly you will soon face a problem: quickly changing graphics often flicker on the screen. This happens when the users sometimes sees the hole images and sometimes sees it when it is only partially drawn. It occurs because the painting process requires time.
 
 
But how can I avoid the flickering and get the best drawing speed? Of course you could work with hardware acceleration using OpenGL, but this approach is quite heavy for small programs or old computers. This tutorial will focus on drawing to a TCanvas. If you need help with OpenGL, take a look at the example that comes with Lazarus. You can also use A.J. Venter's gamepack, witch provides a double-buffered canvas and a sprite component.
 
 
Now we will examine the options we have for drawing to a 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に描画する===
===Draw to a TImage===
 
  
 
TImageに描画するのにOnPaintイベントを使ってはいけません。
 
TImageに描画するのにOnPaintイベントを使ってはいけません。
Line 217: Line 187:
 
この場合に、他の方法を試します。
 
この場合に、他の方法を試します。
 
TImageに描画することは、ほかの方法よりも遅いのです。
 
TImageに描画することは、ほかの方法よりも遅いのです。
 
 
Never use the OnPaint event to draw to a TImage. A TImage is buffered so all you need to do is draw to it from anywhere and the change is there forever. However, if you are constantly redrawing, the image will flicker. In this case you can try the other options. Drawing to a TImage is considered slower then the other approaches.
 
  
 
<code>
 
<code>
Line 240: Line 207:
  
 
===OnPaintイベントで描画する===
 
===OnPaintイベントで描画する===
===Draw on the OnPaint event===
 
  
 
この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
 
この場合、フォームのOnPaintイベントで、すべての描画が終了しなければなりません。この方法ではTImageのように、バッファには残りません。
 
In this case all the drawing has to be done on the OnPaint event of the form. It doesn't remain on the buffer, like on the TImage.
 
 
  
 
===自分自身を描画するカスタムコントロールを作成する===
 
===自分自身を描画するカスタムコントロールを作成する===
===Create a custom control which draws itself===
 
  
 
カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。
 
カスタムコントロールを作成することは、あなたのコードを構造化し、そのコントロールを再利用できる、という利点があります。
 
この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
 
この方法はとても高速ですが、まず、TBitmapに描画して、canvasにそれを転送しなければ、チラツキを発生することがあります。この方法では、コントロールのOnPaintイベントを必要としません。
 
Creating a custom control has the advantage of structuring your code and you can reuse the control. This approach is very fast, but it can still generate flickering if you don't draw to a TBitmap first and then draw to the canvas. On this case there is no need to use the OnPaint event of the control.
 
  
 
カスタムコントロールの例:
 
カスタムコントロールの例:
Here is an example custom control:
 
  
 
<code>
 
<code>
Line 299: Line 258:
  
 
フォーム上で生成する方法は次のとおりです:
 
フォーム上で生成する方法は次のとおりです:
and how we create it on the form:
 
 
<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を指定する必要がないのか?どっちだろう。)
 
Setting Top and Left to zero is not necessary, since this is the standard position, but is done so to reinforce where the control will be put.
 
 
"MyDrawingControl.Parent := Self;" is very important and you won't see your control if you don't do so.
 
 
"MyDrawingControl.DoubleBuffered := True;" is required to avoid flickering on Windows. It has no effect on gtk.
 
  
 
===A.J.Venterのgamepackを使う===
 
===A.J.Venterのgamepackを使う===
===Using A.J. Venter's 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>
  
The gamepack approach is to draw everything to one double-buffered canvas, which only gets updated to the visible canvas when you are ready. This takes quite a bit of code, but it has the advantage of being able to do large rapidly changing scenes with multiple sprites on them. If you wish to use this approach, you may be interested in A.J. Venter's gamepack, a set of components for game development in Lazarus, which provides a double-buffered display area component as well as a sprite component, designed to integrate well with one another. You can get gamepack via subversion:<br />
+
 
 
<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)

日本語版メニュー
メインページ - Lazarus Documentation日本語版 - 翻訳ノート - 日本語障害情報

このページは、どのようにビットマップや、その他のグラフィックスを扱うかのチュートリアルの最初のページになるでしょう。 私はグラフィクスに携わっていないので、専門的な経験を披露してくれる皆さんを招待します。 次の項目にリンクやページを追加して、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に描画するオプションを調べてみましょう。


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


svn co svn://silentcoder.co.za/lazarus/gamepack