← |
2024年11月 |
→ |
日 |
月 |
火 |
水 |
木 |
金 |
土 |
|
|
|
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
|
26 |
27 |
28 |
29 |
30 |
|
JpegBitmapEncoderは画質が悪い。特に純色赤とか。 |
ちょっと、故あって、C#でJpegファイルを生成するプログラムを書いた。
C#には、JpegBitmapEncoderなる、素敵なクラスがあるから楽勝♪ とか思っていたら、どうも、できあがったJpegの画質が悪い。
もちろん、Jpegの品質値は100にしていているにもかかわらず、純色赤の線とかがくすむ。
いろいろ調べてみた結果どうやら、こういうことらしい。
つまり、Jpegというのは、乱暴な説明をすると、 DCT(離散コサイン変換)という演算をして、 人間の目には目立つ成分と、目立たない成分に分けて、 目立たない成分を削除することで、データ量を減らす画像形式なんだけど、 その、DCT計算したあとに、どれぐらい間引くかが、いわゆるJpegの品質値。
だけど、そもそも、そのDCT演算の前に、 Jpeg画像にはくいくつかの色モードがある。 モノクロとか、RGBフルカラーとか、CMYKフルカラーとか。
で、一般的なJpeg画像は、YCrCbの色で管理されている。 輝度と、赤の色差、青の色差ね。
ところで、人間の目は、輝度の変化には強いけど、 色の変化は結構鈍感なので、 なので、色差信号を間引くことで、画像の容量を減らすという手法がある。
で、話に戻って、JpegBitmapEncoderですが、 どうやら、輝度に対して色差の情報量を 1/4に減らす色成分(YCC=411)を採用で保存しているらしい。 なので、どうしても、純色の赤や青がくすんでしまうのが原因ということらしい。
じゃあ、色差を間引かない色成分(YCC=444)を使おうと思ったら、 JpegBitmapEncoderは、このあたりは変更できないらしい。
仕方がないので、前述のサイト同様に、libJpegを使うことに。
一部のExifも使いたかったり、なんやかんやしたかったので、 libJpegをラッピングするDLLをC++で書いて、 それを、C#から呼び出すという方法に落ち着いた。
手順をざっくりまとめるとこんな感じ: 1,libJpegを入手して、C++libの新規プロジェクトを作成して、libjpeg.libの生成。 2,C++DLLの新規プロジェクトを作成して、 libjpeg.libを使ってやりたいことをやるための関数を作て、DLL化する。 3,さらにC++コンソールの新規プロジェクトを作成して、 今作ったDLLのテストプログラムをC++で書く。で、テスト。 4,さらにC#の新規プロジェクトを作成して、 C#からC++のDLLを呼ぶ作法に基づいてC#からDLLのコール。
ちなみに、今回自分は、 foo(ストアファイル名(jpeg),ソースファイル名(bmp),品質,ExifのCreateDateTime…【必要なExif情報を引数で】); みたいな関数を持つDLLを用意した。 つまり、保存したい画像を、一度、BMPファイルにして それを経由で受け渡している。 このへんは、もっとスマートな方法があると思う。
それにしても、おかげで、C++でDLLやlibを生成する復習が出来たし、 C#からC++のDLLの呼び出しや、Exifのデータ構造等の良い勉強になった。
・・・でも、疲れた・・・
というのも、JpegBitmapEncoderで画質について調べると、 QAサイトに結構引っかかるけど、 「品質値を100にしろ」とか「Jpegなんだから劣化が当たり前」 という回答ばっかり。
質問者が「他のJpeg圧縮のソフトに比べて、 品質を100にしても画質が悪い原因を知りたい」 みたいなことを書いていても・・・だ。
かなり、今回の記事の情報は検索に引っかかりにくいので、 この記事が、誰かの参考になればと思う。
|
03:14, Saturday, Oct 09, 2010 ¦ 固定リンク
¦ 携帯
■コメント
■コメントを書く
※コメントの受け付けは終了しました
|
|