fc2ブログ

8bitのPNGへ変換するには

emotionサイトトップ >C#/.NET初心者メモ
emotionサイトトップ > C#/.NET初心者メモ >8bitのPNGへ変換するには

24bitまたは32bitのPNGを8bitのPNGにエンコードするには・・・
結論から言うと簡単に出来ない。
α付きのPNGは他画像ファイルと比べて構造が想像以上に複雑なので、これをやったら簡単に変換できるものは無い。
参考ブログ:Convert 32 bit PNGs to high quality 8 bit PNGs with C#
http://www.hurryupandwait.io/blog/convert-32-bit-pngs-to-high-quality-8-bit-pngs-with-c


頻繁に変換する必要が無い人はフリーソフトのIrfanViewを使って一括変換を実行すれば良いのですが、
頻繁に変換したり、更新時間が新しい物だけ変換したいアプリを自作したい人は違う方法を検討した方がタイパが良い。

一応EncoderParameterを使えばtiffファイル限定で8bit色深度へエンコードする事は可能。
https://learn.microsoft.com/ja-jp/dotnet/api/system.drawing.imaging.encoder.compression?view=netframework-4.8
ただし、IrfanViewで8bit-PNG変換した画像と比べると遥かに品質が悪い。
8bitのtiffへエンコードしてから、それをpngへエンコードすると一応8bit色深度のpngファイルは作成出来るもののかなり品質が悪い。

αが不要なら無理にpngを使わずに大人しくjpgを使った方が無難。

私が8bit-PNGを使用したかった理由は、jpgでファイルサイズを減らす為に低品質へ変換したら、文字が潰れて見え難くなってしまったので、8bit-PNGを使っていたのですが、自前アプリでjpgエンコードで文字が潰れないギリギリの品質へ一括変換するものを作ったら、8bit-PNGと同じファイルサイズになる事が分かったので、jpgを使う事にしましたw

ちなみにjpgの品質は60程度が無難。
50にすると文字がボヤけ始める。
40にするとノイズが入る。

OutOfMemoryExceptionエラーが発生するので0x64アプリにした時の注意

emotionサイトトップ >C#/.NET初心者メモ
emotionサイトトップ > C#/.NET初心者メモ >OutOfMemoryExceptionエラーが発生するので0x64アプリにした時の注意

アプリのメモリ使用量が3.5GBに到達して、OutOfMemoryExceptionエラーが発生して落ちる事が発生。
確かに大量のデータを取り扱うアプリだけど3.5GBに到達する程データは無い。
起動直後は800MBで、3時間経過すると3.5GBまで膨らむ。

パフォーマンスプロファイラーでどのデータが沢山メモリを消費しているのは特定しましたが、
処理が複雑過ぎて、具体的な原因を特定するには時間がかかりそう。
自分が使うアプリなのでとりあえずエラーが出る原因はメモリ不足なので、
単純に32bitアプリから64bitアプリでビルドし直して対応します。
いずれはデータが膨らんでいる原因をちゃんと特定しなければならないのですが、今はとりあえずこれで。

vs_0x64_05.jpg
Visual Studioを起動して、Any CPUのプルダウンリストをクリックして、構成マネージャーを選択

vs_0x64_05.jpg
アクティブソリューションプラットフォームで新規作成を選択

vs_0x64_05.jpg
新しいプラットフォームを入力の所に「0x64」を入力してOKボタンを押す。

vs_0x64_05.jpg
Any CPUのプルダウンリストで0x64を選択。
ちなみに同様の手順で0x86も作成可能。

vs_0x64_05.jpg
Any CPUでは実行ファイルがobjフォルダに作成されますが、
0x64の構成マネージャーを選択すると、objフォルダの下に0x64フォルダが作成されます。
これによりソースコードで相対アドレスを使用シている場合は調整が必要になります。



public Form1()
{
InitializeComponent();

string rel_path = @"..\..\obj\test\temp.txt";
bool rel_bool = File.Exists(rel_path);
string conv_path = Path.GetFullPath(rel_path);

Console.WriteLine("{0} {1}", rel_path, rel_bool);
Console.WriteLine("{0}", conv_path);

// 相対アドレスNGの場合
if (rel_bool == false )
{
rel_path = RemakeRelPath(rel_path);
rel_bool = File.Exists(rel_path);
conv_path = Path.GetFullPath(rel_path);
Console.WriteLine("{0} {1}", rel_path, rel_bool);
Console.WriteLine("{0}", conv_path);
}
}

// ―――――――――――――――――――――――――――――――――
// 相対アドレス補正
// ―――――――――――――――――――――――――――――――――
public static string RemakeRelPath(string in_path)
{
string temp_path = in_path;
if (File.Exists(temp_path) == false)
{
// AnyCpuとそれ以外ではパスが違う
temp_path = String.Format(@"..\{0}", temp_path);
}
return temp_path;

}


■結果

..\..\obj\test\temp.txt False
C:\Users\MSI_Z490\source\repos\TestX64\TestX64\bin\obj\test\temp.txt
..\..\..\obj\test\temp.txt True
C:\Users\MSI_Z490\source\repos\TestX64\TestX64\obj\test\temp.txt


C#でString文字列を正規表現を使って単語検索置換する

emotionサイトトップ >C#/.NET初心者メモ
emotionサイトトップ > C#/.NET初心者メモ >C#でString文字列を正規表現を使って単語検索置換する

テキストエディターで単語検索する場合は、単純に「単語の検索」というオプションを使えばいいだけですが、 C#の文字列検索で単語検索のオプションが見つかりませんでした。
なので正規表現を使って単語検索をします。

とりあえずテキストエディターの正規表現で単語検索をするには
HidemaruUnitReplace.png
\<は単語の先頭。
\>は単語の末尾。
なので単語を\<と\>で囲めば可能です。

でもこれ・・・C#では機能しませんでした。
なのでC#では違う方法を使いました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace RegexTest
{
	class Program
	{
		static void Main(string[] args)
		{

			string base_str = "Test AAATestBBB Test ABC.Test. _Test _Test_ TestTest Test";

			// 正規表現置換
			Regex temp_regx = new Regex(String.Format(@"[^\w.]{0}[^\w.]", "Test"));

			string ret_str = temp_regx.Replace(base_str, "■"); // 単語のTestを■に置換する

			Console.WriteLine(ret_str);
		}
	}
}

[^]は[]内のもの以外。
\wはすべての半角英数字とアンダースコア
.はピリオド

なので[^w.]はすべての半角英数字とアンダースコアとピリオド以外の文字になります。
これを実行すると

"Test AAATestBBB■ABC.Test. _Test _Test_ TestTest Test"
アレ?先頭と末尾が変換されていない・・・前後に文字が無いと駄目でしたorz
半角スペースも置換されていません。
ピリオドに挟まれた単語も置換されていません。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace RegexTest
{
	class Program
	{
		static void Main(string[] args)
		{

			string base_str = "Test AAATestBBB Test ABC.Test. _Test _Test_ TestTest Test";

			// 正規表現置換
			Regex temp_regx = new Regex(String.Format(@"\b{0}\b", "Test"));

			string ret_str = temp_regx.Replace(base_str, "■"); // 単語のTestを■に置換する

			Console.WriteLine(ret_str);
		}
	}
}

"■ AAATestBBB ■ ABC.■. _Test _Test_ TestTest ■"

単語のTestだけが置換されている事が確認できました。
ちなみに\bは文字列の先頭または末尾です。
難しい事を考えずに\bを付けるだけでしたwww

System.Runtime.InteropServices.ExternalException: '要求されたクリップボード操作に成功しませんでした。'

emotionサイトトップ >C#/.NET初心者メモ
emotionサイトトップ > C#/.NET初心者メモ >System.Runtime.InteropServices.ExternalException: '要求されたクリップボード操作に成功しませんでした。'

Google Chromeの現在表示URLをコピペ使用としてClipboard.GetText();を使うと、
System.Runtime.InteropServices.ExternalException: '要求されたクリップボード操作に成功しませんでした。'
というエラーが100%表示されて少しハマったのでメモ書き。

エラーが出る理由は誰かがクリップボードを使用していて、
ファイルアクセスで言う所のファイルハンドラホールド中みたいな状態な時に出るみたい。

なので単純にスリープで1秒待ちしてみたものの、相変わらずエラーが発生する。
一瞬Chrome側でブロックされているのかも疑ってみたのですが、そんな感じはなかった。

Clipboard.Clear();
で一度クリップボードを消してから、try-catchでエラーが出たら100msecスリープを入れて、
100回ぐらいループさせてみる事に。
700msecぐらいで取得出来ました。
これは使えないorz

ただ
IDataObject temp_clip = Clipboard.GetDataObject();
if (temp_clip.GetDataPresent(DataFormats.Text) == true)
{
get_url = (string)temp_clip.GetData(DataFormats.Text);
}
でやったら一発で取れました。
どうやらClipboard.GetText()は時間がかかるみたいです。
Clipboard.GetText()は使用禁止ですねw

無駄に時間を取られたorz
スクレイピングを全自動化しようとしてこの不具合に1時間くらい時間を取られたorz
まあでもこれで全自動化出来たので、手動でやったら1週間じゃ済まないレベルのデータ収集が1日で終わるようになります♪

Seleniumを使えばいいのですが、未だ使った事が無いのでSeleniumの使い方を学習するのに時間がかかりそうだったし、
単純にURLだけ取得して、後はWebquestと分解処理で自動化出来るので、Seleniumは時間がある時に学習します。

古いWindowsFormからWPFへ移行しようか迷った結果

emotionサイトトップ >C#/.NET初心者メモ
emotionサイトトップ > C#/.NET初心者メモ >古いWindowsFormからWPFへ移行しようか迷った結果

今作成しているビジネス向けアプリを最適化して一から作り直して高速化を図っている途中なのですが、
ついでに古いWindowsFormからWPFへ移行してGPUの恩恵を受けて描画処理部分を高速化出来ないかな~?
と思ったのですが、ビジネス向けアプリは大して恩恵を受けないみたいなので、直感的に作成出来るWindowsFormの方が良さそうです。
WPFはどちからと言ったらマルチメディア系のアプリ開発なら使った方が良いみたいですけど、WPFに関する情報がかなり少ない。
WPFって実はそれほど浸透していないんじゃ・・・みんな古いけど使い易くて情報が多いWindowsFormを使ってるんじゃ・・・

という事でWindowsFormを使い続けますw
まぁデータ処理部分と描画処理部分を完全に分けて作り直しているので、いざとなったらWPFへ移植し易いようにもしているので、
とりあえずWindowsFormで色々と最適化ですね。
あとCore i7 4770の相場価格が3000円くらいまで落ち込んでいるので、3000円くらいなら買ってもいいかな~?
並列処理でもCPUに余裕があるので8コアあったほうが多少速くなるし。
まぁとりあえず最適化でどこまで速く出来るかですね、
バックグラウンド処理も上手く活用して体感的に重さを感じ難いようにして、
並列処理とバックグラウンド処理で上手くスレッドを使い分けて使用感だけはサクサク動作するように作り直し中。

スポンサーリンク
カテゴリ
OS (5)
Web (7)
CPU (16)
GPU (35)
GA2 (2)
GTA5 (18)
リンク
Unreal Engine
UE4_logo.png

無料化したゲームエンジンです。ミドルレンジクラスのGPUが必須ですが、GTX750Tiでも軽快に動作します。
ueHow
unityHow
Steam
steam.png
Valve Corporationが運営しているプラットフォームで、PCゲームをダウンロード購入出来ます。 不定期ながらだいたい四半期毎と10月の米国感謝祭と年末に大幅割引セールが行われるので、セール中に購入するのがおススメ。
RSSリンクの表示


スポンサーリンク