投稿者 るきお  (社会人) 投稿日時 2021/7/22 11:02:27
続き

Private Function Mosaic(sourceImage As Image, mosaicSize As IntegerAs Image

        '▼色情報の取得 
        'sourceImageの画像の色情報を配列 rgbBits にコピーします。 
        Dim bmp As Bitmap = CType(sourceImage.Clone, Bitmap)

        Dim bmpData As Imaging.BitmapData = bmp.LockBits(
            New Rectangle(0, 0, bmp.Width, bmp.Height),
            Imaging.ImageLockMode.ReadOnly,
            bmp.PixelFormat)

        Dim bitCount As Integer = Math.Abs(bmpData.Stride) * bmp.Height
        Dim rgbBits(bitCount - 1) As Byte

        'rgbBitsは 赤・青・緑の情報を持つので、画像のピクセル数 × 3 の数の長さになります。 
        System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbBits, 0, bitCount)


        '縦・横いくつのモザイクに分割されるか計算します。 
        Dim mosaicCountX As Integer = CInt(Math.Ceiling(bmp.Width / mosaicSize))
        Dim mosaicCountY As Integer = CInt(Math.Ceiling(bmp.Height / mosaicSize))


        '▼モザイクごとに色を設定 
        For mosaicIndexY = 0 To mosaicCountY - 1
            For mosaicIndexX = 0 To mosaicCountX - 1

                '現在のモザイクの画像上の座標 
                Dim pointLeft As Integer = mosaicIndexX * mosaicSize
                Dim pointRight As Integer = pointLeft + mosaicSize - 1
                Dim pointTop As Integer = mosaicIndexY * mosaicSize
                Dim pointBottom As Integer = pointTop + mosaicSize - 1

                Dim sumR As Integer = 0
                Dim sumG As Integer = 0
                Dim sumB As Integer = 0

                'このモザイク内のすべての色を赤・青・緑それぞれで合計します。 
                For pointScanY As Integer = pointTop To pointBottom

                    'ここでの処理は計算は1行ごとに行います。(つまりモザイクのサイズが20であればこのForは20回実行されます。) 
                    'このモザイクの現在の行の色情報が配列 rgbBitsのどの位置にあるか計算します。 
                    Dim bitStartIndex As Integer = pointScanY * bmpData.Stride + pointLeft * 3
                    Dim bitEndIndex As Integer = pointScanY * bmpData.Stride + pointRight * 3

                    For bitIndex As Integer = bitStartIndex To bitEndIndex Step 3
                        If rgbBits.Length > bitIndex Then
                            sumR += rgbBits(bitIndex)
                            sumG += rgbBits(bitIndex + 1)
                            sumB += rgbBits(bitIndex + 2)
                        End If
                    Next
                Next

                'このモザイクの赤・青・緑の平均値を算出します。 
                Dim aveR As Double = sumR / (mosaicSize * mosaicSize)
                Dim aveG As Double = sumG / (mosaicSize * mosaicSize)
                Dim aveB As Double = sumB / (mosaicSize * mosaicSize)


                '算出した平均値をこのモザイク内に等しくセットします。 
                For pointScanY As Integer = pointTop To pointBottom
                    Dim bitStartIndex As Integer = pointScanY * bmpData.Stride + pointLeft * 3
                    Dim bitEndIndex As Integer = pointScanY * bmpData.Stride + pointRight * 3

                    For bitIndex As Integer = bitStartIndex To bitEndIndex Step 3
                        If rgbBits.Length > bitIndex Then
                            rgbBits(bitIndex) = CByte(aveR)
                            rgbBits(bitIndex + 1) = CByte(aveG)
                            rgbBits(bitIndex + 2) = CByte(aveB)
                        End If
                    Next
                Next

            Next

        Next

        '▼色情報の書き込み 
        '算出した色情報を画像に書き込みます。 
        System.Runtime.InteropServices.Marshal.Copy(rgbBits, 0, bmpData.Scan0, bitCount)
        bmp.UnlockBits(bmpData)

        '▼画像の作成(メモリ上で) 
        '新しい色情報を画像 resultImage に書き込みます。 
        Dim resultImage As New Bitmap(bmp.Width, bmp.Height)
        Dim g As Graphics = Graphics.FromImage(resultImage)

        g.DrawImage(bmp, 0, 0)


        Return resultImage

    End Function

End Class