塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/paint.pdfdim g 2s graphics with picdisp...

25
VS 2005 資料 【電脳梁山泊 烏賊塾】 -1- 塗り潰しのアルゴリズム 2PI 関数の ExtFloodFill 関数に依る塗り潰し ExtFloodFill 関数は塗り潰し描画を行う API 関数で有り、Visual basic 6.0 の時の様に簡単ではない が、.NET Framework 下でのプログラミングでも使用する事が出来る(詳細 )。 使用例として、ピクチャボックス(picDisp)に、赤と青で枠線を描画し(赤枠が上層)、ExtFloodFill 関数を使用して、赤枠で囲まれた分を塗り潰す、又は、枠線に囲まれた白地の分を塗り潰すプログ ラムを、下記に示す。 Visual Basic Imports System.Runtime.InteropServices Public Class Form1 ' 塗り潰しを行う 2PI 関数 <DllImport("gdi32.dll", SetLastError:=True)> _ Private Shared Function ExtFloodFill( _ ByVal Hdc 2s IntPtr, _ ByVal X 2s Integer, _ ByVal Y 2s Integer, _ ByVal Color 2s Integer, _ ByVal FillType 2s UInteger) 2s <Marshal2s(UnmanagedType.Bool)> Boolean End Function ' ブラシを生成する 2PI 関数 <DllImport("gdi32.dll", SetLastError:=True)> _ Private Shared Function CreateBrushIndirect( _ ByRef Brush 2s LOGBRUSH) 2s IntPtr End Function ' CreateBrushIndirect 関数の為の構体 Private Structure LOGBRUSH Dim Style 2s Integer Dim Color 2s Integer Dim Hatch 2s Integer End Structure ' オブジェクトを択する 2PI 関数 <DllImport("gdi32.dll", SetLastError:=True)> _ Private Shared Function SelectObject( _ ByVal Hdc 2s IntPtr, _ ByVal Obj 2s IntPtr) 2s IntPtr End Function

Upload: others

Post on 13-Jun-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-1-

■ 塗り潰しのアルゴリズム ■ ■ 2PI 関数の ExtFloodFill 関数に依る塗り潰し ExtFloodFill 関数は塗り潰し描画を行う API 関数で有り、Visual basic 6.0 の時の様に簡単ではない

が、.NET Framework 下でのプログラミングでも使用する事が出来る(詳細)。

使用例として、ピクチャボックス(picDisp)に、赤と青で枠線を描画し(赤枠が上層)、ExtFloodFill

関数を使用して、赤枠で囲まれた部分を塗り潰す、又は、枠線に囲まれた白地の部分を塗り潰すプログ

ラムを、下記に示す。

Visual Basic

Imports System.Runtime.InteropServices

Public Class Form1

' 塗り潰しを行う 2PI 関数

<DllImport("gdi32.dll", SetLastError:=True)> _

Private Shared Function ExtFloodFill( _

ByVal Hdc 2s IntPtr, _

ByVal X 2s Integer, _

ByVal Y 2s Integer, _

ByVal Color 2s Integer, _

ByVal FillType 2s UInteger) 2s <Marshal2s(UnmanagedType.Bool)> Boolean

End Function

' ブラシを生成する 2PI 関数

<DllImport("gdi32.dll", SetLastError:=True)> _

Private Shared Function CreateBrushIndirect( _

ByRef Brush 2s LOGBRUSH) 2s IntPtr

End Function

' CreateBrushIndirect 関数の為の構造体

Private Structure LOGBRUSH

Dim Style 2s Integer

Dim Color 2s Integer

Dim Hatch 2s Integer

End Structure

' オブジェクトを選択する 2PI 関数

<DllImport("gdi32.dll", SetLastError:=True)> _

Private Shared Function SelectObject( _

ByVal Hdc 2s IntPtr, _

ByVal Obj 2s IntPtr) 2s IntPtr

End Function

塗塗りり潰潰しし

Page 2: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-2-

' オブジェクトを削除する 2PI 関数

<DllImport("gdi32.dll")> _

Private Shared Function DeleteObject( _

hObject 2s IntPtr) 2s <Marshal2s(UnmanagedType.Bool)> Boolean

End Function

Private Const FLOODFILLBORDER 2s UInteger = 0UI ' 境界色指定

Private Const FLOODFILLSURF2CE 2s UInteger = 1UI ' 表面色指定

Private Sub btnExtFloodFill_Click(sender 2s System.Object, e 2s System.Event2rgs) _

Handles btnExtFloodFill.Click

' ピクチャボックスの Graphics オブジェクトのインスタンス生成

Dim G 2s Graphics

With picDisp

.Image = New Bitmap(.Width, .Height)

G = Graphics.FromImage(.Image)

End With

G.Clear(Color.White)

' 枠の描画

G.DrawRectangle(Pens.Blue, New Rectangle(100, 60, 100, 100))

G.DrawRectangle(Pens.Red, New Rectangle(50, 30, 100, 100))

picDisp.Refresh()

' ハンドルの取得

Dim Hdc 2s IntPtr = Graphics.FromHwnd(picDisp.Handle).GetHdc()

' 塗り潰しブラシの作成

Dim Bp 2s LOGBRUSH

Bp.Style = 0

Bp.Color = ColorTranslator.ToWin32(Color.Cyan)

Bp.Hatch = 0

Dim Br 2s IntPtr = CreateBrushIndirect(Bp)

' 塗り潰しブラシの適用

Dim Bo 2s IntPtr = SelectObject(Hdc, Br)

' 塗り潰し

If radBorder.Checked Then

ExtFloodFill(Hdc, 60, 60, ColorTranslator.ToWin32(Color.Red), FLOODFILLBORDER)

Else

ExtFloodFill(Hdc, 60, 60, ColorTranslator.ToWin32(Color.White), FLOODFILLSURF2CE)

End If

' 塗り潰しブラシの復元と開放

Br = SelectObject(Hdc, Bo)

Page 3: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-3-

DeleteObject(Br)

' ハンドルの開放

Hdc = Nothing

End Sub

End Class

C#

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace Graphics_ExtFloodFill { public partial class Form1 : Form { public Form1() { InitializeComponent(); } // 塗り潰しを行う 2PI 関数 [DllImport("gdi32.dll")] static extern bool ExtFloodFill(IntPtr hdc, int x, int y, int color, uint filltype); // 塗り潰し方法を指定する定数 private const uint FLOODFILLBORDER = 0; private const uint FLOODFILLSURF2CE = 1; // ブラシを生成する 2PI 関数 [DllImport("gdi32.dll")] static extern IntPtr CreateBrushIndirect([In] ref LOGBRUSH lplb); // CreateBrushIndirect 関数の為の構造体 private struct LOGBRUSH { internal int style; internal int color; internal int hatch; } // オブジェクトを選択する 2PI 関数 [DllImport("gdi32.dll", EntryPoint = "SelectObject")] public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj); // オブジェクトを削除する 2PI 関数 [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] [return: Marshal2s(UnmanagedType.Bool)]

Page 4: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-4-

public static extern bool DeleteObject([In] IntPtr hObject); private void btnExtFloodFill_Click(object sender, Event2rgs e) { // ピクチャボックスの Graphics オブジェクトのインスタンス生成 Graphics g; picDisp.Image = new Bitmap(picDisp.Width, picDisp.Height); g = Graphics.FromImage(picDisp.Image); g.Clear(Color.White); // 枠の描画 g.DrawRectangle(Pens.Blue, new Rectangle(100, 60, 100, 100)); g.DrawRectangle(Pens.Red, new Rectangle(50, 30, 100, 100)); picDisp.Refresh(); // ハンドルの取得 IntPtr hdc = Graphics.FromHwnd(picDisp.Handle).GetHdc(); // 塗り潰しブラシの作成 LOGBRUSH bp; bp.style = 0; bp.color = ColorTranslator.ToWin32(Color.Cyan); bp.hatch = 0; IntPtr br = CreateBrushIndirect(ref bp); // 塗り潰しブラシの適用 IntPtr bo = SelectObject(hdc, br); // 塗り潰し if (radBorder.Checked) { ExtFloodFill(hdc, 60, 60, ColorTranslator.ToWin32(Color.Red), FLOODFILLBORDER); } else { ExtFloodFill(hdc, 60, 60, ColorTranslator.ToWin32(Color.White), FLOODFILLSURF2CE); } // 塗り潰しブラシの復元と開放 br = SelectObject(hdc, bo); DeleteObject(br); // ハンドルの開放 hdc = IntPtr.Zero; } } }

但し、上記の例では、フォームを最小化する等すれば、塗り潰した部分は消失する(グラフィックスの

永続化が行われない)。 グラフィックスを永続化する例を、下記に示す。猶、色々なプログラムに組み込み易い様に、サブルー

チン化した。

Page 5: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-5-

Visual Basic

Imports System.Runtime.InteropServices

Public Class Form1

' 定数の宣言

Private Const SRCCOPY 2s Integer = &HCC0020

Private Const FLOODFILLBORDER 2s Integer = 0 ' 境界色指定

Private Const FLOODFILLSURF2CE 2s Integer = 1 ' 表面色指定

' 構造体の宣言

Private Structure BITM2PINFOHE2DER

Dim biSize 2s Integer

Dim biWidth 2s Integer

Dim biHeight 2s Integer

Dim biPlanes 2s Short

Dim biBitCount 2s Short

Dim biCompression 2s Integer

Dim biSizeImage 2s Integer

Dim biXPelsPerMeter 2s Integer

Dim biYPelsPerMeter 2s Integer

Dim biClrUsed 2s Integer

Dim biClrImportant 2s Integer

End Structure

<DllImport("gdi32.dll")> _

Private Shared Function CreateCompatibleDC( _

ByVal hdc 2s IntPtr) 2s IntPtr

End Function

<DllImport("gdi32.dll")> _

Private Shared Function CreateDIBSection( _

ByVal hdc 2s IntPtr, _

ByRef pBitmapInfo 2s BITM2PINFOHE2DER, _

ByVal un 2s Integer, _

ByRef lplpVoid 2s IntPtr, _

ByVal handle 2s Integer, _

ByVal dw 2s Integer) 2s IntPtr

End Function

<DllImport("gdi32.dll")> _

Private Shared Function BitBlt( _

ByVal hDestDC 2s IntPtr, _

ByVal x 2s Integer, _

ByVal y 2s Integer, _

ByVal nWidth 2s Integer, _

ByVal nHeight 2s Integer, _

ByVal hSrcDC 2s IntPtr, _

ByVal xSrc 2s Integer, _

Page 6: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-6-

ByVal ySrc 2s Integer, _

ByVal dwRop 2s Integer) 2s Integer

End Function

<DllImport("gdi32.dll")> _

Private Shared Function ExtFloodFill( _

ByVal hdc 2s IntPtr, _

ByVal X 2s Integer, _

ByVal Y 2s Integer, _

ByVal crColor 2s Integer, _

ByVal wFillType 2s Integer) 2s Integer

End Function

<DllImport("gdi32.dll")> _

Private Shared Function CreateSolidBrush( _

ByVal crColor 2s Integer) 2s IntPtr

End Function

<DllImport("gdi32.dll")> _

Private Shared Function GetPixel( _

ByVal hdc 2s IntPtr, _

ByVal X 2s Integer, _

ByVal Y 2s Integer) 2s Integer

End Function

<DllImport("gdi32.dll")> _

Private Shared Function SelectObject( _

ByVal hdc 2s IntPtr, _

ByVal hObject 2s IntPtr) 2s IntPtr

End Function

<DllImport("gdi32.dll")> _

Private Shared Function DeleteObject( _

ByVal hObject 2s IntPtr) 2s Integer

End Function

<DllImport("gdi32.dll")> _

Private Shared Function DeleteDC( _

ByVal hdc 2s IntPtr) 2s Integer

End Function

<DllImport("gdi32.dll")> _

Private Shared Function GdiFlush() 2s Integer

End Function

' N88B2SIC の Paint 機能(塗潰し)を実現するジェネラルプロシージャ

Public Sub N88Paint(ByRef Bmp 2s Bitmap, ByVal PaintColor 2s Color, _

ByVal TargetColor 2s Color, ByVal Pnt 2s Point, ByVal Border 2s Boolean)

Page 7: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-7-

' Bmp :描画対象と成る Image オブジェクト

' PaintColor :塗り潰し色

' TargetColor :境界色か表面色(Border 引数に依り決定)

' Pnt :描画開始位置

' Border :境界色で塗り潰す(True)か表面色で塗り潰す(False)かのフラグ

If Bmp Is Nothing Then Exit Sub

Dim SrcDC 2s IntPtr = CreateCompatibleDC(IntPtr.Zero)

Dim DstDC 2s IntPtr = CreateCompatibleDC(IntPtr.Zero)

Dim DstBMI 2s BITM2PINFOHE2DER

With DstBMI

.biBitCount = 24

.biHeight = Bmp.Height

.biSize = System.Runtime.InteropServices.Marshal.SizeOf(DstBMI)

.biWidth = Bmp.Width

.biPlanes = 1

End With

Dim DstBits 2s IntPtr

Dim Hbmp 2s IntPtr = Bmp.GetHbitmap

' HDC に Bitmap を選択

Dim Obmp 2s IntPtr = SelectObject(SrcDC, Hbmp)

' DIB の生成

Dim DstBMP 2s IntPtr = CreateDIBSection(DstDC, DstBMI, 0, DstBits, 0, 0)

Dim Obmp2 2s IntPtr = SelectObject(DstDC, DstBMP)

' Bitmap を DIB に格納

BitBlt(DstDC, 0, 0, Bmp.Width, Bmp.Height, SrcDC, 0, 0, SRCCOPY)

GdiFlush()

' 塗潰用ブラシの生成

Dim Br 2s IntPtr = CreateSolidBrush(System.Drawing.ColorTranslator.ToOle(PaintColor))

Dim Hmm 2s IntPtr = SelectObject(DstDC, Br)

' 塗潰し

If Border Then

ExtFloodFill(DstDC, Pnt.X, Pnt.Y, System.Drawing.ColorTranslator.ToOle(TargetColor), _

FLOODFILLBORDER)

Else

ExtFloodFill(DstDC, Pnt.X, Pnt.Y, GetPixel(DstDC, Pnt.X, Pnt.Y), _

FLOODFILLSURF2CE)

End If

' Bitmap の回収

Bmp = Bitmap.FromHbitmap(DstBMP)

' オブジェクトの開放(必須)

Page 8: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-8-

DeleteObject(Br)

DeleteObject(SelectObject(DstDC, Br))

DeleteObject(SelectObject(DstDC, DstBMP))

DeleteObject(SelectObject(SrcDC, Hbmp))

DeleteObject(Hmm)

DeleteObject(DstBits)

DeleteObject(Obmp2)

DeleteObject(Obmp)

DeleteObject(DstBMP)

DeleteDC(DstDC)

DeleteDC(SrcDC)

Hbmp = Nothing

Hmm = Nothing

DstBits = Nothing

Obmp2 = Nothing

Obmp = Nothing

DstBMP = Nothing

DstDC = Nothing

SrcDC = Nothing

DstBMI = Nothing

End Sub

Private Sub btnExtFloodFill_Click(ByVal sender 2s System.Object, _

ByVal e 2s System.Event2rgs) Handles btnExtFloodFill.Click

Dim Bmp 2s Bitmap = picDisp.Image

Dim Col 2s Color = Color.Cyan

Dim Pnt 2s Point = New Point(60, 60)

If radBorder.Checked Then

' 境界色で塗り潰し(境界色は赤)

N88Paint(picDisp.Image, Col, Color.Red, Pnt, True)

Else

' 表面色で塗り潰し(表面色は白)

N88Paint(picDisp.Image, Col, Color.White, Pnt, False)

End If

End Sub

End Class

C#

Page 9: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-9-

■ スキャンラインシードフィルのアルゴリズムに依る塗り潰し スキャンラインシードフィルアルゴリズム(Scanline Seed Fill 2lgorithm)に依り領域の塗り潰しを行

う手順を下記に示す。 1.シードピクセル(X,Y)から左右方向に走査し、塗り潰しの左右の境界を探す。然して、得られた

境界の x 座標を夫々XL(左端)と XR(右端)とする。 2.水平線分 (XL,Y)-(XR,Y) を塗り潰す。

Page 10: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-10-

3.描画した水平線分(上図黄色の部分)の上側の線分 (XL,Y + 1)-(XR,Y + 1) を左から走査して、塗

り潰す可きピクセルが横に連続して居る部分を総て探し、夫々の最も右側の座標をバッファに格納

する(但し、境界が見付からない内に画像の右端に達した場合は、画像の右端の座標をバッファに

格納する)。 4.描画した水平線分(上図黄色の部分)の下側の線分 (XL,Y - 1)-(XR,Y - 1) に対して上記3と同様の

処理を行う

Page 11: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-11-

5.以下、バッファから有効なシードを取り出しては 1~4 を繰り返す

バッファから*1 を取り出し、新たなシードとして処理を繰り返す

バッファから*2 を取り出し、新たなシードとして処理を繰り返す

Page 12: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-12-

バッファから*3 を取り出し、新たなシードとして処理を繰り返す

バッファから*4 を取り出し、新たなシードとして処理を繰り返す 6.バッファが空に成った時点で塗り潰しは完了して居る。

Page 13: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-13-

使用例として、ピクチャボックス(picDisp)の黒線で囲まれた領域をクリックすると、ラジオボタン

で選択された色で、スキャンラインシードフィルアルゴリズムを使用して、同じ領域色の領域を塗り潰

すプログラムを、下記に示す。

Visual Basic Imports System.IO Public Class N88Paint '==================================================== ' 下記は、スキャンラインシードフィルのアルゴリズムを使用して ' N88B2SIC の Paint 機能(塗潰し)を実現する物で有る。 '==================================================== ' N88B2SIC の Paint 機能(塗潰し)を実現するジェネラルプロシージャ Public Sub N88Paint(ByRef Bmp 2s Bitmap, ByVal Col 2s Color, ByVal Pnt 2s Point) If Bmp Is Nothing Then Exit Sub Dim Bgc 2s Color = Bmp.GetPixel(Pnt.X, Pnt.Y) Dim Buf 2s New Queue(Of Point) Buf.Enqueue(Pnt) Using G 2s Graphics = Graphics.FromImage(Bmp) Using Pen 2s New Pen(Col) Do While Buf.Count > 0 Dim P 2s Point = Buf.Dequeue If Bmp.GetPixel(P.X, P.Y) = Bgc Then Dim Rx 2s Integer = P.X Dim Lx 2s Integer = P.X Do While Rx < Bmp.Width - 1 If Bmp.GetPixel(Rx + 1, P.Y) <> Bgc Then Exit Do End If Rx += 1 Loop Do While Lx > 0 If Bmp.GetPixel(Lx - 1, P.Y) <> Bgc Then Exit Do End If Lx -= 1 Loop G.DrawLine(Pen, Lx, P.Y, Rx, P.Y) Me.Refresh() If P.Y > 0 Then ScanLine(Bmp, Buf, Lx, Rx, P.Y - 1, Bgc) End If If P.Y < Bmp.Height - 1 Then ScanLine(Bmp, Buf, Lx, Rx, P.Y + 1, Bgc) End If End If Loop End Using End Using End Sub ' 上記の N88Paint で使用する行をスキャンするジェネラルプロシージャ

Page 14: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-14-

Private Sub ScanLine(ByRef Bmp 2s Bitmap, ByVal Buf 2s Queue(Of Point), _ ByVal Lx 2s Integer, ByVal Rx 2s Integer, ByVal Y 2s Integer, ByVal C 2s Color) Do While Lx < Rx Do While Lx < Rx If Bmp.GetPixel(Lx + 1, Y) = C Then Exit Do End If Lx += 1 Loop Do While Lx < Rx If Not Bmp.GetPixel(Lx + 1, Y) = C Then Exit Do End If Lx += 1 Loop Buf.Enqueue(New Point(Lx, Y)) Lx += 1 Loop End Sub '==================================================== ' 以上、N88_Paint メソッド '==================================================== Private Col 2s Color = Color.Red ' フォームが読み込まれた時の処理 Private Sub N88Paint_Load(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles MyBase.Load dlgOpen.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|" & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" dlgSave.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|! & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" End Sub ' ピクチャボックスでマウスボタンが押し下げられた時の処理 Private Sub picDisp_MouseUp(ByVal sender 2s System.Object, _ ByVal e 2s System.Windows.Forms.MouseEvent2rgs) Handles picDisp.MouseUp N88Paint(picDisp.Image, Col, New Point(e.X, e.Y)) End Sub ' ラジオボタンがクリックされた時の処理 Private Sub radColor_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles radWhite.Click, radRed.Click, radGreen.Click, _ radCustom.Click, radBlue.Click, radBlack.Click Dim R 2s RadioButton = DirectCast(sender, RadioButton) Dim N 2s Integer = Integer.Parse(R.Tag) Select Case N Case 0 : Col = Color.Red Case 1 : Col = Color.Green Case 2 : Col = Color.Blue

Page 15: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-15-

Case 3 : Col = Color.Black Case 4 : Col = Color.White Case 5 If dlgColor.ShowDialog = Windows.Forms.DialogResult.OK Then Col = dlgColor.Color radCustom.BackColor = Col End If End Select End Sub ' ボタン(LO2D)がクリックされた時の処理 Private Sub btnLoad_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnLoad.Click If dlgOpen.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgOpen.FileName picDisp.Image = Image.FromFile(F) ' 下記の様に FileStream を使用しても良い。 ' Using Fs 2s FileStream = New FileStream(F, FileMode.Open, File2ccess.Read) ' picDisp.Image = Image.FromStream(Fs) ' Fs.Close() ' End Using End If End Sub ' ボタン(S2VE)がクリックされた時の処理 Private Sub btnSave_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnSave.Click If dlgSave.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgSave.FileName Select Case Path.GetExtension(F).ToLower() Case ".bmp" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Bmp) Case ".jpg" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Jpeg) Case ".gif" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Gif) Case ".tif", ".tiff" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Tiff) Case ".png" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Png) Case ".wmf" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Wmf) End Select MessageBox.Show("Saved !") End If End Sub End Class C#

上記の例は、アルゴリズムの動作を確認するには良いが、実際の塗り潰しの作業を頻繁に行うアプリケ

ーションでは、速度的に問題が有る。其処で、動作の遅い Bitmap クラスの GetPixel メソッドを使用

せずに画像イメージを Byte 配列で操作する例を、下記に示す。

Page 16: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-16-

Visual Basic Imports System.IO Public Class N88Paint '==================================================== ' 下記は、スキャンラインシードフィルのアルゴリズムを使用して ' N88B2SIC の Paint 機能(塗潰し)を実現する物で有る。 '==================================================== Private Buf 2s Queue(Of Point) Private Bd 2s Imaging.BitmapData Private Bs() 2s Byte ' 作業用 Byte 配列 Private Bgr, Bgg, Bgb 2s Byte ' N88B2SIC の Paint 機能(塗潰し)を実現するジェネラルプロシージャ Public Sub N88_Paint(ByRef Bmp 2s Bitmap, ByVal Col 2s Color, ByVal Pnt 2s Point) If Bmp Is Nothing Then Exit Sub Dim Bgc 2s Color = Bmp.GetPixel(Pnt.X, Pnt.Y) Bgr = Bgc.R : Bgg = Bgc.G : Bgb = Bgc.B ' 指定点の色 Dim Ptr, Ptg, Ptb 2s Byte Ptr = Col.R : Ptg = Col.G : Ptb = Col.B ' 塗り潰し色 Buf = New Queue(Of Point) Dim P 2s Point Dim M 2s Integer Buf.Enqueue(Pnt) Bd = Bmp.LockBits(New Rectangle(0, 0, Bmp.Width, Bmp.Height), _ Imaging.ImageLockMode.ReadWrite, _ Bmp.PixelFormat) ReDim Bs(Bd.Stride * Bmp.Height - 1) System.Runtime.InteropServices.Marshal.Copy(Bd.Scan0, Bs, 0, Bd.Stride * Bmp.Height) Using G 2s Graphics = Graphics.FromImage(Bmp) Do While Buf.Count > 0 P = Buf.Dequeue M = P.X * 3 + P.Y * Bd.Stride If Bs(M) = Bgb 2nd2lso Bs(M + 1) = Bgg 2nd2lso Bs(M + 2) = Bgr Then Dim Rx 2s Integer = P.X Dim Lx 2s Integer = P.X Do While Rx < Bmp.Width - 1 M = Rx * 3 + P.Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr Then Exit Do End If Rx += 1 Loop Do While Lx > 0 M = Lx * 3 + P.Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr Then Exit Do End If

Page 17: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-17-

Lx -= 1 Loop For I 2s Integer = (Lx + 1) To (Rx - 1) M = I * 3 + P.Y * Bd.Stride Bs(M) = Ptb : Bs(M + 1) = Ptg : Bs(M + 2) = Ptr Next If P.Y > 0 Then ScanLine(Lx, Rx, P.Y - 1) End If If P.Y < Bmp.Height - 1 Then ScanLine(Lx, Rx, P.Y + 1) End If End If Loop End Using System.Runtime.InteropServices.Marshal.Copy(Bs, 0, Bd.Scan0, Bd.Stride * Bmp.Height) Bmp.UnlockBits(Bd) picDisp.Image = Bmp picDisp.Refresh() End Sub ' MSX の P2INT ステートメントで使用する行をスキャンするジェネラルプロシージャ Private Sub ScanLine(ByVal Lx 2s Integer, ByVal Rx 2s Integer, ByVal Y 2s Integer) Dim M 2s Integer Do While Lx + 1 < Rx Do While Lx + 1 < Rx M = (Lx + 1) * 3 + Y * Bd.Stride If Bs(M) = Bgb 2nd2lso Bs(M + 1) = Bgg 2nd2lso Bs(M + 2) = Bgr Then Exit Do End If Lx += 1 Loop Do While Lx + 1 < Rx M = (Lx + 1) * 3 + Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr Then Exit Do End If Lx += 1 Loop Buf.Enqueue(New Point(Lx, Y)) Lx += 1 Loop End Sub '==================================================== ' 以上、N88_Paint メソッド '==================================================== Private Col 2s Color = Color.Red ' フォームが読み込まれた時の処理 Private Sub N88Paint_Load(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles MyBase.Load dlgOpen.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _

Page 18: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-18-

"Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|" & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" dlgSave.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|! & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" End Sub ' ピクチャボックスでマウスボタンが押し下げられた時の処理 Private Sub picDisp_MouseUp(ByVal sender 2s System.Object, _ ByVal e 2s System.Windows.Forms.MouseEvent2rgs) Handles picDisp.MouseUp N88_Paint(picDisp.Image, Col, New Point(e.X, e.Y)) End Sub ' ラジオボタンがクリックされた時の処理 Private Sub radColor_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles radWhite.Click, radRed.Click, radGreen.Click, radCustom.Click, _ radBlue.Click, radBlack.Click Dim R 2s RadioButton = DirectCast(sender, RadioButton) Dim N 2s Integer = Integer.Parse(R.Tag) Select Case N Case 0 : Col = Color.Red Case 1 : Col = Color.Green Case 2 : Col = Color.Blue Case 3 : Col = Color.Black Case 4 : Col = Color.White Case 5 If dlgColor.ShowDialog = Windows.Forms.DialogResult.OK Then Col = dlgColor.Color radCustom.BackColor = Col End If End Select End Sub ' ボタン(LO2D)がクリックされた時の処理 Private Sub btnLoad_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnLoad.Click If dlgOpen.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgOpen.FileName picDisp.Image = Image.FromFile(F) ' 下記の様に FileStream を使用しても良い。 ' Using Fs 2s FileStream = New FileStream(F, FileMode.Open, File2ccess.Read) ' picDisp.Image = Image.FromStream(Fs) ' Fs.Close() ' End Using End If End Sub ' ボタン(S2VE)がクリックされた時の処理 Private Sub btnSave_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnSave.Click If dlgSave.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgSave.FileName

Page 19: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-19-

Select Case Path.GetExtension(F).ToLower() Case ".bmp" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Bmp) Case ".jpg" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Jpeg) Case ".gif" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Gif) Case ".tif", ".tiff" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Tiff) Case ".png" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Png) Case ".wmf" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Wmf) End Select MessageBox.Show("Saved !") End If End Sub End Class C#

猶、上記の例は 24 ビット(RGB)用で、透明度が加わる 32 ビット(2RGB)では、下記の様に成る。 Visual Basic Imports System.IO Public Class N88Paint '==================================================== ' 下記は、スキャンラインシードフィルのアルゴリズムを使用して ' N88B2SIC の Paint 機能(塗潰し)を実現する物で有る。 '==================================================== Private Buf 2s Queue(Of Point) Private Bd 2s Imaging.BitmapData Private Bs() 2s Byte ' 作業用 Byte 配列 Private Bga, Bgr, Bgg, Bgb 2s Byte ' N88B2SIC の Paint 機能(塗潰し)を実現するジェネラルプロシージャ Public Sub N88_Paint(ByRef Bmp 2s Bitmap, ByVal Col 2s Color, ByVal Pnt 2s Point) If Bmp Is Nothing Then Exit Sub Dim Bgc 2s Color = Bmp.GetPixel(Pnt.X, Pnt.Y) Bga = Bgc.2 : Bgr = Bgc.R : Bgg = Bgc.G : Bgb = Bgc.B ' 指定点の色 Dim Pta, Ptr, Ptg, Ptb 2s Byte Pta = Col.2 : Ptr = Col.R : Ptg = Col.G : Ptb = Col.B ' 塗り潰し色 Buf = New Queue(Of Point) Dim P 2s Point Dim M 2s Integer Buf.Enqueue(Pnt) Bd = Bmp.LockBits(New Rectangle(0, 0, Bmp.Width, Bmp.Height), _ Imaging.ImageLockMode.ReadWrite, _

Page 20: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-20-

Bmp.PixelFormat) ReDim Bs(Bd.Stride * Bmp.Height - 1) System.Runtime.InteropServices.Marshal.Copy(Bd.Scan0, Bs, 0, Bd.Stride * Bmp.Height) Using G 2s Graphics = Graphics.FromImage(Bmp) Do While Buf.Count > 0 P = Buf.Dequeue M = P.X * 4 + P.Y * Bd.Stride If Bs(M) = Bgb 2nd2lso Bs(M + 1) = Bgg 2nd2lso Bs(M + 2) = Bgr 2nd2lso _ Bs(M + 3) = Bga Then Dim Rx 2s Integer = P.X Dim Lx 2s Integer = P.X Do While Rx < Bmp.Width - 1 M = Rx * 4 + P.Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr OrElse _ Bs(M + 3) <> Bga Then Exit Do End If Rx += 1 Loop Do While Lx > 0 M = Lx * 4 + P.Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr OrElse _ Bs(M + 3) <> Bga Then Exit Do End If Lx -= 1 Loop For I 2s Integer = (Lx + 1) To (Rx - 1) M = I * 4 + P.Y * Bd.Stride Bs(M) = Ptb : Bs(M + 1) = Ptg : Bs(M + 2) = Ptr : Bs(M + 3) = Pta Next If P.Y > 0 Then ScanLine(Lx, Rx, P.Y - 1) End If If P.Y < Bmp.Height - 1 Then ScanLine(Lx, Rx, P.Y + 1) End If End If Loop End Using System.Runtime.InteropServices.Marshal.Copy(Bs, 0, Bd.Scan0, Bd.Stride * Bmp.Height) Bmp.UnlockBits(Bd) picDisp.Image = Bmp picDisp.Refresh() End Sub ' MSX の P2INT ステートメントで使用する行をスキャンするジェネラルプロシージャ Private Sub ScanLine(ByVal Lx 2s Integer, ByVal Rx 2s Integer, ByVal Y 2s Integer) Dim M 2s Integer Do While Lx + 1 < Rx Do While Lx + 1 < Rx M = (Lx + 1) * 4 + Y * Bd.Stride If Bs(M) = Bgb 2nd2lso Bs(M + 1) = Bgg 2nd2lso Bs(M + 2) = Bgr 2nd2lso _

Page 21: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-21-

Bs(M + 3) = Bga Then Exit Do End If Lx += 1 Loop Do While Lx + 1 < Rx M = (Lx + 1) * 4 + Y * Bd.Stride If Bs(M) <> Bgb OrElse Bs(M + 1) <> Bgg OrElse Bs(M + 2) <> Bgr OrElse _ Bs(M + 3) <> Bga Then Exit Do End If Lx += 1 Loop Buf.Enqueue(New Point(Lx, Y)) Lx += 1 Loop End Sub '==================================================== ' 以上、N88_Paint メソッド '==================================================== Private Col 2s Color = Color.Red ' フォームが読み込まれた時の処理 Private Sub N88Paint_Load(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles MyBase.Load dlgOpen.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|" & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" dlgSave.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|! & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" End Sub ' ピクチャボックスでマウスボタンが押し下げられた時の処理 Private Sub picDisp_MouseUp(ByVal sender 2s System.Object, _ ByVal e 2s System.Windows.Forms.MouseEvent2rgs) Handles picDisp.MouseUp N88_Paint(picDisp.Image, Col, New Point(e.X, e.Y)) End Sub ' ラジオボタンがクリックされた時の処理 Private Sub radColor_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles radWhite.Click, radRed.Click, radGreen.Click, radCustom.Click, _ radBlue.Click, radBlack.Click Dim R 2s RadioButton = DirectCast(sender, RadioButton) Dim N 2s Integer = Integer.Parse(R.Tag) Select Case N Case 0 : Col = Color.Red Case 1 : Col = Color.Green Case 2 : Col = Color.Blue Case 3 : Col = Color.Black Case 4 : Col = Color.White

Page 22: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-22-

Case 5 If dlgColor.ShowDialog = Windows.Forms.DialogResult.OK Then Col = dlgColor.Color radCustom.BackColor = Col End If End Select End Sub ' ボタン(LO2D)がクリックされた時の処理 Private Sub btnLoad_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnLoad.Click If dlgOpen.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgOpen.FileName picDisp.Image = Image.FromFile(F) ' 下記の様に FileStream を使用しても良い。 ' Using Fs 2s FileStream = New FileStream(F, FileMode.Open, File2ccess.Read) ' picDisp.Image = Image.FromStream(Fs) ' Fs.Close() ' End Using End If End Sub ' ボタン(S2VE)がクリックされた時の処理 Private Sub btnSave_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnSave.Click If dlgSave.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgSave.FileName Select Case Path.GetExtension(F).ToLower() Case ".bmp" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Bmp) Case ".jpg" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Jpeg) Case ".gif" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Gif) Case ".tif", ".tiff" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Tiff) Case ".png" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Png) Case ".wmf" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Wmf) End Select MessageBox.Show("Saved !") End If End Sub End Class C#

Page 23: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-23-

■ 周囲の出発点と同じ色のドットに色を付ける処理を再帰的に行うアルゴリズムに依る塗り潰し 使用例として、ピクチャボックス(picDisp)の黒線で囲まれた領域をクリックすると、ラジオボタン

で選択された色で、スキャンラインシードフィルアルゴリズムを使用して、同じ領域色の領域を塗り潰

すプログラムを、下記に示す(スキャンラインシードフィルアルゴリズムと同じ)。

但し、下記では、40×40 の領域を塗り潰すのに、1316 回の再帰呼出を行った処でスタック領域不足の

エラーが発生した。因みに、35×35 の領域を塗り潰すには、1156 回の再帰呼出を行い塗り潰しに成功

した。 従って、比較的小さな領域を塗り潰す場合には有効で有るが、大きな領域を塗り潰す場合には、工夫が

必要と成り、亦、再帰呼出は速度的にも問題が有り、余り有効な手段ではない。 Visual Basic Imports System.IO Public Class N88Paint '======================================================================= ' 下記は、周囲の出発点と同じ色のドットに色を付ける処理を ' 再帰的に行うアルゴリズムを使用して ' N88B2SIC の Paint 機能(塗潰し)を実現する物で有る。 '======================================================================= ' N88B2SIC の Paint 機能(塗潰し)を実現するジェネラルプロシージャ Private Sub N88_Paint(ByVal X 2s Integer, ByVal Y 2s Integer) ' 指定点を塗る Cnt += 1 Bmp.SetPixel(X, Y, Pcolor) ' 上の点 If Bmp.GetPixel(X, Y - 1) = Ccolor Then N88_Paint(X, Y - 1) End If ' 右の点 If Bmp.GetPixel(X + 1, Y) = Ccolor Then N88_Paint(X + 1, Y) End If ' 下の点 If Bmp.GetPixel(X, Y + 1) = Ccolor Then N88_Paint(X, Y + 1) End If ' 左の点 If Bmp.GetPixel(X - 1, Y) = Ccolor Then N88_Paint(X - 1, Y) End If End Sub '====================================== ' 以上、N88_Paint メソッド '======================================

Page 24: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-24-

Private Bmp 2s Bitmap Private Pcolor 2s Color = Color.Red Private Ccolor 2s Color = Color.White Private Cnt 2s Long = 0 ' フォームが読み込まれた時の処理 Private Sub N88Paint_Load(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles MyBase.Load dlgOpen.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|" & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" dlgSave.Filter = "Supported Image Formats|*.bmp;*.jpg;*.gif;*.tif;*.tiff;*.png;*.wmf|" & _ "Bitmap (*.bmp)|*.bmp|JPEG image (*.jpg)|*.jpg|Gif image (*.gif)|*.gif|" & _ "Tif image (*.tif;*.tiff)|*.tif;*.tiff|PNG image (*.png)|*.png|! & _ "Windows metafile (*.wmf)|*.wmf|2ll Files (*.*)|*.*" End Sub ' ピクチャボックスでマウスボタンが押し下げられた時の処理 Private Sub picDisp_MouseUp(ByVal sender 2s System.Object, _ ByVal e 2s System.Windows.Forms.MouseEvent2rgs) Handles picDisp.MouseUp Bmp = picDisp.Image Ccolor = Bmp.GetPixel(e.X, e.Y) N88_Paint(e.X, e.Y) picDisp.Refresh() End Sub ' ラジオボタンがクリックされた時の処理 Private Sub radColor_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles radWhite.Click, radRed.Click, radGreen.Click, radCustom.Click, _ radBlue.Click, radBlack.Click Dim R 2s RadioButton = DirectCast(sender, RadioButton) Dim N 2s Integer = Integer.Parse(R.Tag) Select Case N Case 0 : Pcolor = Color.Red Case 1 : Pcolor = Color.Green Case 2 : Pcolor = Color.Blue Case 3 : Pcolor = Color.Black Case 4 : Pcolor = Color.White Case 5 If dlgColor.ShowDialog = Windows.Forms.DialogResult.OK Then Pcolor = dlgColor.Color radCustom.BackColor = Pcolor End If End Select End Sub ' ボタン(LO2D)がクリックされた時の処理 Private Sub btnLoad_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnLoad.Click If dlgOpen.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgOpen.FileName picDisp.Image = Image.FromFile(F)

Page 25: 塗り潰し - xdomainjunko036.html.xdomain.jp/pdf2/graphics/Paint.pdfDim G 2s Graphics With picDisp .Image = New Bitmap(.Width, .Height) G = Graphics.FromImage(.Image) End With G.Clear(Color.White)

VS 2005 資料 【電脳梁山泊 烏賊塾】

-25-

' 下記の様に FileStream を使用しても良い。 ' Using Fs 2s FileStream = New FileStream(F, FileMode.Open, File2ccess.Read) ' picDisp.Image = Image.FromStream(Fs) ' Fs.Close() ' End Using End If End Sub ' ボタン(S2VE)がクリックされた時の処理 Private Sub btnSave_Click(ByVal sender 2s System.Object, ByVal e 2s System.Event2rgs) _ Handles btnSave.Click If dlgSave.ShowDialog = Windows.Forms.DialogResult.OK Then Dim F 2s String = dlgSave.FileName Select Case Path.GetExtension(F).ToLower() Case ".bmp" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Bmp) Case ".jpg" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Jpeg) Case ".gif" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Gif) Case ".tif", ".tiff" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Tiff) Case ".png" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Png) Case ".wmf" picDisp.Image.Save(F, System.Drawing.Imaging.ImageFormat.Wmf) End Select MessageBox.Show("Saved !") End If End Sub End Class C#