前回はウィンドウのドンガラをやりましたので、今回はボタン等のコントロールで呼び出されるイベント処理部分、特にイメージファイル形式の変換処理部分の解説をしましょう。
【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);
}
}
}
}
}
比較的短く、単純なプログラミングでしたが、出来上がりは結構使い勝手の良いツールとなりました。
