Opacity(アルファ値)の足し算と引き算もできるようにした、OpaOpaOpasity
OpaOpaOpasity1.0.2
ダウンロード先
ここのOpaOpaOpasity1.0.2.7z
github.com
追加、変更点
テスト用画像
テスト用画像で使われている色とその数をCountColorで見てみると
ほとんどがアルファ値128(不透明度0.5)の半透明画像
足し算
指定不透明度を0.2(アルファ値52)にして、これを足してみる
期待する結果は
不透明度だと0.5+0.2=0.7
アルファ値だと128+52=180
になればいい
結果
アルファ値は128から180になった
不透明度に直してみると
128/255=0.50196078
から
180/255=0.70588235
0.2増えている、いいね!
引き算
同様に0.2(アルファ値52)を引いてみた結果
アルファ値:128-52=76
不透明度:76/255=0.29803922
期待通り
マルチスレッド処理で速度向上
ファイルごとの処理をマルチスレッドにしたことで、複数ファイル処理の速度が上がったはず
結果は
CPU:Ryzen 5 2400Gで
ファイル数:426
ファイル合計サイズ:142MBの処理時間が
40秒から8秒になった
2400Gは4コア8スレッドのAPU
これで約5倍速くなって、これは期待以上だった
コード変更箇所
最初は画像処理の部分をマルチスレッド(並列化)にしようとしたけど、うまくできなかったので、ファイルごとの処理をマルチスレッドにした
/// <summary> /// 実行 /// 対象フォルダにopaフォルダ作成、そこにAlpha値を変換した画像を /// png形式で保存 /// <param name="files">対象画像ファイルリスト</param> /// <param name="ope">アルファ値の計算方法</param> /// </summary> private void MyExe(IEnumerable<string> files, MyOpe ope) { try { if (!string.IsNullOrEmpty(MyDirectory)) { string dir = System.IO.Path.Combine(MyDirectory, MY_FOlDER_NAME); _ = Directory.CreateDirectory(dir); foreach (var file in files) { SaveExe(file, dir + "\\" + System.IO.Path.GetFileName(file), (byte)MySlider.Value, ope); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } /// <summary> /// 画像ファイルを指定Alphaに変換して保存 /// </summary> /// <param name="bmpPath"></param> /// <param name="savePath"></param> /// <param name="alpha"></param> /// <returns></returns> private bool SaveExe(string bmpPath, string savePath, byte alpha, MyOpe ope) { if (GetBitmap(bmpPath) is BitmapSource bmp) { switch (ope) { case MyOpe.Replace: bmp = AlphaReplace(bmp, alpha); break; case MyOpe.Add: bmp = AlphaAdd(bmp, alpha); break; case MyOpe.Subtract: bmp = AlphaSubtract(bmp, alpha); break; default: break; } SaveBitmapToPng(savePath, bmp); return true; } return false; }
↑前回、シングルスレッド処理
↓今回、マルチスレッド処理
/// <summary> /// 対象フォルダにopaopaopasityフォルダ作成、そこにAlpha値を変換した画像をpng形式で保存 /// </summary> /// <param name="files">対象画像ファイルリスト</param> /// <param name="ope">アルファ値の計算方法</param> private void MyExe(List<string> files, MyOpe ope) { try { if (!string.IsNullOrEmpty(MyDirectory)) { string dir = System.IO.Path.Combine(MyDirectory, MY_FOlDER_NAME); _ = Directory.CreateDirectory(dir); byte alpha = (byte)MySlider.Value; Parallel.For(0, files.Count, async ii => { await SaveExe(files[ii], dir + "\\" + System.IO.Path.GetFileName(files[ii]), alpha, ope); }); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } /// <summary> /// 画像ファイルを指定Alphaと計算して保存 /// </summary> /// <param name="bmpPath">画像ファイルパス</param> /// <param name="savePath">保存パス</param> /// <param name="alpha">アルファ値指定</param> /// <param name="ope">アルファ値の計算方法指定</param> /// <returns></returns> private async Task<bool> SaveExe(string bmpPath, string savePath, byte alpha, MyOpe ope) { if (GetBitmap(bmpPath) is BitmapSource bmp) { switch (ope) { case MyOpe.Replace: bmp = AlphaReplace(bmp, alpha); break; case MyOpe.Add: bmp = AlphaAdd(bmp, alpha); break; case MyOpe.Subtract: bmp = AlphaSubtract(bmp, alpha); break; default: break; } await Task.Run(() => { SaveBitmapToPng(savePath, bmp); }); return true; } return false; }
MyExeのforeachでファイルリスト(files)のファイルを一個づつ処理していたところをParallel.Forでマルチスレッドに変更
foreach (var file in files){SaveExe()}
から
Parallel.For(0, files.Count, async ii =>{await SaveExe()}
これだけだとエラー表示だったので
SaveExeも変更
private bool SaveExe() SaveBitmapToPng();
をそれぞれ
private async Task<bool> SaveExe() await Task.Run(() =>{SaveBitmapToPng();});
に変更したら動いてくれた
このへんはよくわかっていない
asyncとawaitは対になっている感じで両方必要、これでエラー表示ならそれっぽいところにTask.Ran()、これで動いた
変換中のCPU使用率
今回100%使い切っているのは期待通り、いいねえ
でも、今気づいたのがメモリの使用量が多い!3GBも多く使っている!
いくらなんでも多すぎる、なんで?
感想
前回使っていて不満だったところの一部が直せてよかった、と同時にメモリ使用量っていう不満が出てきたけど、これは直せそうにないなあ
関連記事
次のOpaOpaOpasityは1週間後
gogowaten.hatenablog.com
前回の記事は昨日
gogowaten.hatenablog.com
画像に使われている色の詳細とその個数を表示するアプリCountColorの記事
画像の使用色数とその色のピクセル数を表示するアプリその6 - 午後わてんのブログ
gogowaten.hatenablog.com
画像の使用色数を表示するアプリ作ってみた - 午後わてんのブログ
gogowaten.hatenablog.com