前回はウィンドウのドンガラをやりましたので、今回はボタン等のコントロールで呼び出されるイベント処理部分、特にイメージファイル形式の変換処理部分の解説をしましょう。

 

【ImageConverter.csの続き】

        //イメージを開く
        private void open_button_Click (object sender, System.EventArgs e)
        {
            //OpenFileDialogオブジェクトの生成
            OpenFileDialog openDlg = new OpenFileDialog();    //usingを使うと最後のDispose処理が不要になる
            openDlg.Filter = "pngファイル|*.png|jpeg/jpgファイル|*.jpeg;*.jpg|bmpファイル|*.bmp|gifファイル|*.gif|tiffファイル|*.tiff";   //解説:最初からGDI+で扱えるファイル種類で一般的なものに絞りました。
            openDlg.Multiselect = true;
            DialogResult result = openDlg.ShowDialog();
            if(result == DialogResult.OK)
            {
                //リストボックスにイメージファイル名を登録
                if(openDlg.FileNames != null)    //複数ファイル選択の場合
                {
                    listBox.BeginUpdate();
                    for(int i = 0; i < openDlg.FileNames.Length; i++ )
                        listBox.Items.Add(openDlg.FileNames[i]);
                    listBox.EndUpdate();
                }
                else                            //単一ファイル選択の場合
                    listBox.Items.Add(openDlg.FileName);
            }
            else if(result == DialogResult.Cancel)
                MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //オブジェクトを破棄する(解説:↑に書いたようにusingを使うと、これは不要となります。)
            openDlg.Dispose();
        }

        //リストボックスで指定したイメージの消去
        private void del_button_Click (object sender, System.EventArgs e)
        {
            if(listBox.SelectedIndex != -1)    //選択されている場合(-1は選択されていない場合)
            {
                listBox.Items.Remove(listBox.SelectedItem);            //リストボックスから消去
                pictureBox.Image = null;                            //pictureBoxの画面消去
                num_label.Text = "イメージ番号:";   //解説:ラベルの初期化もします。
            }
            else                            //-1は選択されていない場合
                MessageBox.Show("選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        //すべてのイメージの消去
        private void clr_button_Click (object sender, System.EventArgs e)
        {
            listBox.Items.Clear();                    //リストボックスから消去する
            pictureBox.Image = null;                //pictureBoxの画面消去
            num_label.Text = "イメージ番号:";
        }

        //イメージ型式変換
        private void cnvt_button_Click (object sender, System.EventArgs e)
        {
            //エラーチェック-変換対象イメージファイルない場合
            if(listBox.Items.Count == 0)
            {
                MessageBox.Show("変換対象ファイルがありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            //エラーチェック-「ファイルサイズを変更」がチェックされていて、有効な画像幅または画像高が入力されていない場合(解説:ここで同時に画像幅と高さを取得しておきます。)
            int new_width = 0, new_height = 0;        //入力画像幅と高さ
            if((resizing.CheckState == CheckState.Checked) &&
                !(Int32.TryParse(img_Width.Text, out new_width) && Int32.TryParse(img_Height.Text, out new_height)))
            {
                MessageBox.Show("画像幅または画像高の値が不正です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            //以下オプションに応じて指定画像ファイル形式で出力(同じ形式の場合、ファイル名を変更して出力))
            if(selected_only.CheckState == CheckState.Checked)    //単一ファイルの変換
            {
                //エラーチェック-変換対象ファイルが未選択の場合
                if(listBox.SelectedIndex == -1)
                {
                    MessageBox.Show("変換対象ファイルが選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                //出力ファイルパス・名の設定
                //1-ソースファイルパス・名の拡張子を変換対象のものに変更
                output_Name = Path.ChangeExtension(listBox.Text, img_ext[comBox.SelectedIndex]);
                //2-出力先指定があればそのパスと入れ替える
                if(output_Path != "")
                    output_Name = output_Path + "\\" + Path.GetFileName(output_Name);
                if(resizing.CheckState == CheckState.Checked)    //ファイルサイズを変更する
                {
                    //エラーチェック-ソースファイル拡張子と出力拡張子が同じ場合
                    if(Path.GetExtension(listBox.Text) == img_ext[comBox.SelectedIndex])
                    {   //解説:ファイルサイズを変更する場合にはエラーにせず、ファイル名に"_Rev"をつけて保存する。
                        output_Name = Path.GetDirectoryName(output_Name) + "\\" + Path.GetFileNameWithoutExtension(output_Name) + "_Rev" + img_ext[comBox.SelectedIndex];
                        MessageBox.Show("ソースと同じファイル形式の指定であり、ファイル名を変更しました。\r\n" + output_Name, "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }

                    //解説:↓のImageConversion関数二つ(オーバーロードしています)を参照して下さい。
                    Image_Conversion(listBox.Text, output_Name, new_width, new_height, asp_ratio.Checked);
                }
                else                                            //ファイルサイズを変更しない
                {
                    //エラーチェック-ソースファイル拡張子と出力拡張子が同じ場合(解説:エラー扱い)
                    if(Path.GetExtension(listBox.Text) == img_ext[comBox.SelectedIndex])
                    {
                        MessageBox.Show("ソースと同じファイル形式の指定であり、変換を中止します。\r\n" + output_Name, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    Image_Conversion(listBox.Text, output_Name);
                }
            }
            else                                                //ListBox表示のすべてのファイルの変換
            {
                foreach(object file in listBox.Items)
                {
                    //出力ファイルパス・名の設定
                    //1-ソースファイルパス・名の拡張子を変換対象のものに変更
                    output_Name = Path.ChangeExtension(file.ToString(), img_ext[comBox.SelectedIndex]);

                    //解説:単一ファイルと同じ処理ですが、ソースファイルがlistBox.Textかforeachのobjectかの違いがあります。
                    //2-出力先指定があればそのパスと入れ替える
                    if(output_Path != "")
                        output_Name = output_Path + "\\" + Path.GetFileName(output_Name);
                    if(resizing.CheckState == CheckState.Checked)    //ファイルサイズを変更する
                    {
                        //エラーチェック-ソースファイル拡張子と出力拡張子が同じ場合
                        if(Path.GetExtension(file.ToString()) == img_ext[comBox.SelectedIndex])
                        {
                            output_Name = Path.GetDirectoryName(output_Name) + "\\" + Path.GetFileNameWithoutExtension(output_Name) + "_Rev" + img_ext[comBox.SelectedIndex];
                            MessageBox.Show("ソースと同じファイル形式の指定であり、ファイル名を変更しました。\r\n" + output_Name, "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        }
                        Image_Conversion(file.ToString(), output_Name, new_width, new_height, asp_ratio.Checked);
                    }
                    else                                            //ファイルサイズを変更しない
                    {
                        //エラーチェック-ソースファイル拡張子と出力拡張子が同じ場合
                        if(Path.GetExtension(file.ToString()) == img_ext[comBox.SelectedIndex])
                        {
                            MessageBox.Show("ソースと同じファイル形式の指定であり、変換を中止します。\r\n" + output_Name, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            continue;
                        }
                        Image_Conversion(file.ToString(), output_Name);
                    }
                }
            }
            output_Path = "";        //出力し終えたので、出力先パスを初期化する
            output_Name = "";        //再初期化
        }

        //出力先(フォールダー)の指定
        private void sel_button_Click(object sender, EventArgs e)
        {    //解説:ヘルプが無いのでメッセージボックスで注意喚起します。
            MessageBox.Show("出力先を指定せず、「キャンセル」すればオリジナル画像と同じフォールダーに保存されます。", "出力先設定上の注意", MessageBoxButtons.OK, MessageBoxIcon.Information);
            FolderBrowserDialog fbDlg = new FolderBrowserDialog();    //usingを使うと最後のDispose処理が不要になる
            // ダイアログの説明文
            fbDlg.Description = "変換したイメージファイルの出力先(フォールダー)を選択してください。";
            // デフォルトのフォルダ(output_Pathにデータがあればそこ、なければ"C:\")
            fbDlg.SelectedPath = (output_Path == "") ? @"C:\" : output_Path;    //解説:C由来の条件文です。
            // 「新しいフォルダーの作成する」ボタンを表示する(デフォルトはtrue)
            fbDlg.ShowNewFolderButton = true;
            //フォルダを選択するダイアログを表示する
            if(fbDlg.ShowDialog() == DialogResult.OK)
            {
                output_Path = fbDlg.SelectedPath;
                MessageBox.Show(output_Path, "指定された出力先", MessageBoxButtons.OK, MessageBoxIcon.Information);
                tooltip.SetToolTip(sel_button, output_Path);    //sel_buttonにツールチップをつける
            }
            else
                MessageBox.Show("キャンセルされました。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            // オブジェクトを破棄する
            fbDlg.Dispose();
        }

        //フォームを閉じる
        private void exit_button_Click(object sender, EventArgs e)
        {
            Close();
        }

        //resizingチェックボックスの状態が変更された
        private void resizing_CheckedChanged(object sender, EventArgs e)
        {
            if(resizing.CheckState == CheckState.Checked)    //有効化
            {
                img_Width.Enabled = true;    //"画像幅"用ラベル
                img_Height.Enabled = true;    //"画像高"用ラベル
                asp_ratio.Enabled = true;    //"縦横比を維持"用ラベル
                asp_ratio.Checked = true;    //"縦横比を維持"用チェックボックス
            }
            else                                            //無効化
            {
                img_Width.Enabled = false;    //"画像幅"用ラベル
                img_Height.Enabled = false;    //"画像高"用ラベル
                asp_ratio.Enabled = false;    //"縦横比を維持"用ラベル
                asp_ratio.Checked = false;    //"縦横比を維持"用チェックボックス
            }
        }

        //同一サイズで変換
        private void Image_Conversion(string filename, string output_name)
        {
            //ソースImageオブジェクトの作成
            using(Image image = Image.FromFile(filename))    //自動的にDispose()が呼び出される
            {
                //変換コーデックのImageCodecInfoを作成
                ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo ici = null;
                for(int i = 0; i < encoders.Length; i++)
                    if(encoders[i].MimeType == comBox.SelectedItem.ToString())
                        ici = encoders[i];
                //画質パラメーターカテゴリー用EncoderオブジェクトをGUIDに基づいて作成
                //EncoderParameter配列であるEncoderParametersオブジェクトの作成

                EncoderParameters encoderParameters = new EncoderParameters(1);
                //出力用Imageをレベル100の画質で保存
                encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                image.Save(output_name, ici, encoderParameters);
            }
        }

        //サイズを変更して変換(オーバーロード関数-既定値:アスペクト比を維持)
        private void Image_Conversion(string filename, string output_name, int width, int height, bool aspectRatio = true)
        {
            //ソースImageオブジェクトの作成
            float scale;
            int new_width = width, new_height = height;
            using(Image image = Image.FromFile(filename))            //自動的にDispose()が呼び出される
            {
                //変更倍率を取得する
                if(aspectRatio)
                {
                    scale = Math.Min((float)width / (float)image.Width,
                                    (float)height / (float)image.Height);
                    //変更サイズを取得
                    new_width = (int)(image.Width * scale);
                    new_height = (int)(image.Height * scale);
                }
                //変換用Bitmapオブジェクトの作成
                using(Bitmap bmp = new Bitmap(width, height))        //自動的にDispose()が呼び出される
                using(Graphics graphics = Graphics.FromImage(bmp))    //自動的にDispose()が呼び出される
                {
                    //背景色(黒)
                    using(SolidBrush solidBrush = new SolidBrush(Color.Black))
                    {    //自動的にDispose()が呼び出される
                        graphics.FillRectangle(solidBrush, new RectangleF(0, 0, width, height));
                    }
                    //左上起点で変更画像を描画
                    graphics.DrawImage(image, 0, 0, new_width, new_height);
                    //変換コーデックのImageCodecInfoを作成
                    ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
                    ImageCodecInfo ici = null;
                    for(int i = 0; i < encoders.Length; i++)
                        if(encoders[i].MimeType == comBox.SelectedItem.ToString())
                            ici = encoders[i];
                    //画質パラメーターカテゴリー用EncoderオブジェクトをGUIDに基づいて作成
                    //EncoderParameter配列であるEncoderParametersオブジェクトの作成

                    EncoderParameters encoderParameters = new EncoderParameters(1);
                    //出力用Imageをレベル100の画質で保存
                    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                    bmp.Save(output_name, ici, encoderParameters);
                }
            }
        }
    }
}

 

比較的短く、単純なプログラミングでしたが、出来上がりは結構使い勝手の良いツールとなりました。