【C#】Bitmap画像データの拡大縮小

シェアする

  • このエントリーをはてなブックマークに追加
最近の記事
  • 10/21 【C#】寸法線の描画
  • 10/21 【C#】GraphicsPathの領域取得
  • 10/20 【C#】GraphicsPathの描画
  • 10/18 【C#】GraphicsPath
  • 10/17 【C#】Bitmap画像データの拡大縮小
  • 10/15 【C#】画像の座標系
  • 10/14 【C#】画像の上下左右反転、90,180,270度回転
  • 10/3 【C#】SplitContainerのPanel固定方法
  • 9/7 【Neural Network Console】学習データの出力方法
  • 9/3 Deep Learning向け学習画像撮り込みソフト公開
  • 9/1 【Neural Network Console】新規画像のDataset作成方法
  • 8/28 【Neural Network Console】GUI表示スケールの変更
  • 8/22 【Neural Network Console】CPU/GPU処理の設定切替
  • 8/21 【Neural Network Console】Learning Rate(学習率)の設定
  • 8/20 ソニーの無償AIソフト Neural Network Consoleの入手ダウンロード、インストール
  • 8/20 Deep Learning
  • 8/20
  • 8/19 古いバージョンのVisual Studio Community/Expressの入手ダウンロード
  • 8/19 CUDAの入手、ダウンロード、インストール方法
  • 8/17 【C#.NET】マイクロソフト仕様のアフィン変換
  • 8/5 【C#】ファイルを開くダイアログボックスの表示
  • 8/2 キャノンプリンターのCDトレイはどこ?!
  • 7/6 【参考書籍】画像処理・機械学習プログラミング OpenCV 3対応
  • 6/20 【Python,matplotlib】動くグラフをAnimationGifに保存する方法
  • 6/17 シグモイド関数の微分
  • 6/15 シグモイド関数
  • 6/13 合成関数の微分
  • 6/12 WordPressで数式エディタ風に数式を入力したい
  • 6/11 PythonをVisual Studioでインストールする方法
  • 6/9 【Python】OpenCVをAnacondaでインストール(Windows編)
  • 6/6 【Python】Anacondaで複数バージョンの環境切り替え
  • 6/6 画像センシング展2017に出展します。
  • 6/1 【Office365】Web版Outlookのフォントサイズ変更
  • 6/1 【Anaconda】モジュールのアップデートでエラー発生
  • 6/1 【Anaconda】コマンドリストの表示
  • 5/29 Windows10パソコン購入
  • 5/24 Anacondaのアンインストール
  • 5/24 【Jupyter Notebook】新規プログラムの作成
  • 5/23 【Python】開発環境の構築
  • 5/23 Pythonはじめました
  • 4/6 【Office365】Web版Outlookのスレッド表示を解除する方法
  • 4/5 【Excel】フーリエ解析(FFT)
  • 3/20 Canny edge detection
  • 3/20 【Excel2016】分析ツールの表示
  • 3/5 【Visual Studio】黒い背景色を白に変更する方法
  • 2/8 【Windows10】拡張モニタに表示されたウィンドウを元に戻す
  • 2/7 複素数の計算
  • 1/18 【Excel】棒グラフの横軸の目盛を0始まりにする
  • 1/16 【Excel】フーリエ変換
  • 1/6 【OpenCV】疑似カラー(カラーマップ)

  • Bitmap画像を拡大縮小するには、Bitmapクラスのコンストラクタで、

    Bitmap bmpOrijinal = new Bitmap("sample.bmp");
    
    int scale = 50;
    Bitmap bmpResize = new Bitmap(
        bmpOrijinal,
        bmpOrijinal.Width * scale,
        bmpOrijinal.Height * scale
        );
    
    pictureBox1.Image = bmpResize;
    

    (処理結果)

    C# Bitmap画像の拡大縮小

    のようにすると簡単に画像を拡大縮小をすることができますが、このやり方では、いくつか不都合があります。

    ●モノクロ8bit画像に対応していない。

    ●補間モードを指定できない。

    ●画像を拡大すると、0.5画素分、位置がズレている。

    ●リサイズ後のBitmapは32bitになってしまう。

    ということで、これらに対応したメソッドを作ってみました。

    /// <summary>
    /// Bitmap画像データのリサイズ
    /// </summary>
    /// <param name="original">元のBitmapクラスオブジェクト</param>
    /// <param name="width">リサイズ後の幅</param>
    /// <param name="height">リサイズ後の高さ</param>
    /// <param name="interpolationMode">補間モード</param>
    /// <returns>リサイズされたBitmap</returns>
    private Bitmap ResizeBitmap(Bitmap original, int width, int height, System.Drawing.Drawing2D.InterpolationMode interpolationMode)
    {
        Bitmap bmpResize;
        Bitmap bmpResizeColor;
        Graphics graphics = null;
    
        try
        {
            System.Drawing.Imaging.PixelFormat pf = original.PixelFormat;
    
            if (original.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
            {
                // モノクロの時は仮に24bitとする
                pf = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
            }
    
            bmpResizeColor = new Bitmap(width, height, pf);
            var dstRect = new RectangleF(0, 0, width, height);
            var srcRect = new RectangleF(-0.5f, -0.5f, original.Width, original.Height);
            graphics = Graphics.FromImage(bmpResizeColor);
            graphics.Clear(Color.Transparent);
            graphics.InterpolationMode = interpolationMode;
            graphics.DrawImage(original, dstRect, srcRect, GraphicsUnit.Pixel);
    
        }
        finally
        {
            if (graphics != null)
            {
                graphics.Dispose();
            }
        }
    
        if (original.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
        {
            // モノクロ画像のとき、24bit→8bitへ変換
    
            // モノクロBitmapを確保
            bmpResize = new Bitmap(
                bmpResizeColor.Width, 
                bmpResizeColor.Height, 
                System.Drawing.Imaging.PixelFormat.Format8bppIndexed
                );
    
            var pal = bmpResize.Palette;
            for (int i = 0; i < bmpResize.Palette.Entries.Length; i++)
            {
                pal.Entries[i] = original.Palette.Entries[i];
            }
            bmpResize.Palette = pal;
    
            // カラー画像のポインタへアクセス
            var bmpDataColor = bmpResizeColor.LockBits(
                    new Rectangle(0, 0, bmpResizeColor.Width, bmpResizeColor.Height),
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bmpResizeColor.PixelFormat
                    );
    
            // モノクロ画像のポインタへアクセス
            var bmpDataMono = bmpResize.LockBits(
                    new Rectangle(0, 0, bmpResize.Width, bmpResize.Height),
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bmpResize.PixelFormat
                    );
    
            int colorStride = bmpDataColor.Stride;
            int monoStride = bmpDataMono.Stride;
    
            unsafe
            {
                var pColor = (byte*)bmpDataColor.Scan0;
                var pMono = (byte*)bmpDataMono.Scan0;
                for (int y = 0; y < bmpDataColor.Height; y++)
                {
                    for (int x = 0; x < bmpDataColor.Width; x++)
                    {
                        // R,G,B同じ値のため、Bの値を代表してモノクロデータへ代入
                        pMono[x + y * monoStride] = pColor[x * 3 + y * colorStride];    
                    }
                }
            }
    
            bmpResize.UnlockBits(bmpDataMono);
            bmpResizeColor.UnlockBits(bmpDataColor);
    
            // 解放
            bmpResizeColor.Dispose();
        }
        else
        {
            // カラー画像のとき
            bmpResize = bmpResizeColor;
        }
    
        return bmpResize;
    }
    

    このResizeBitmapメソッドを使って、このようなプログラムを書くと

    Bitmap bmpOrijinal = new Bitmap("sample.bmp");
    
    int scale = 50;
    Bitmap bmpResize = ResizeBitmap(
        bmpOrijinal,
        bmpOrijinal.Width * scale,
        bmpOrijinal.Height * scale,
        System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor
        );
    
    pictureBox1.Image = bmpResize;
    

    (処理結果)

    C# Bitmap画像の拡大縮小

    となります。

    モノクロの処理は少しまどろっこしい感じもしますが、画像データのリサイズや補間の部分を自前で書くよりは簡単!?

    画像処理のためのC#へ戻る