あ~見つけてしまった!
つぶしきったと思っていたのだが、探して見るとあるもんだ。
ほぼ問題に遭遇する人はいないだろうし、
遭遇しても問題に気付くこともまず無いだろうが
気色悪いので直しておこう。
問題は量子化係数を指定Q値でスケーリングする部分にあった。
IJG推奨の量子化係数のスケーリング方法は
まず指定Q値をスケーリング係数Sに以下で変換する。
i) Q<50のとき S = 5000/Q
ii) 上記以外のとき S = 200 - 2xQ
次に輝度と色差のQ=50での量子化係数テーブルを以下として
この各成分にスケーリング係数Sを掛けて100で割り、
小数部を四捨五入で整数にする。
このスケーリング変換で結果がゼロになった場合に
「1」に置き換える処理は入れたのだが、
「255」を超えた時の処理は入れていなかった。
(ちなみにスケーリング元の最大値は輝度テーブルの121だから
指定Q値を23以下にすると255を超える成分が出て来る。
Qを23以下に指定することなんて…ある?)
で、255を超えた時にどうなってしまうかと言うと
下位8bitだけを抜き出してUnsigned Charにキャストするので
例えばQ=1でスケーリングすると量子化テーブルは
ALL 255ではなく
となってしまう。
具体的にどこをどう直すのかと言うと・・・
Adj_Head()ファンクションの以下の青文字部分を
/*****
Adjust Jpeg Header
*****/
void Adj_Head
(long *Pic_W, long *Pic_H, unsigned char *QC){
int i;
long N;
// ***** Apply Quantize Coefficient *****
if (*QC != 50) {
N = (*QC < 50) ? 5000 / *QC : 200 - (*QC * 2);
for (i = 0; i < 64; i++){
JPHead[25 + i] = (unsigned char)((N * JPHead[25 + i] + 50) / 100);
if (JPHead[25 + i] < 1) JPHead[25 + i] = 1;
JPHead[94 + i] = (unsigned char)((N * JPHead[94 + i] + 50) / 100);
if (JPHead[94 + i] < 1) JPHead[94 + i] = 1;
}
}
<以下省略>
下のように直す。
/*****
Adjust Jpeg Header
*****/
void Adj_Head
(long *Pic_W, long *Pic_H, unsigned char *QC){
int i;
long M, N;
// ***** Apply Quantize Coefficient *****
if (*QC != 50) {
N = (*QC < 50) ? 5000 / *QC : 200 - (*QC * 2);
for (i = 0; i < 64; i++){
M = (N * JPHead[25 + i] + 50) / 100;
if (M != 0 && M < 256) JPHead[25 + i] = (unsigned char)M;
else if (M == 0) JPHead[25 + i] = 1;
else JPHead[25 + i] = 255;
M = (N * JPHead[94 + i] + 50) / 100;
if (M != 0 && M < 256) JPHead[94 + i] = (unsigned char)M;
else if (M == 0) JPHead[94 + i] = 1;
else JPHead[94 + i] = 255;
}
}
<以下省略>
これでヨシっ!と思っていたら・・・
もう一箇所問題に気が付いた。
あぅ~ (ToT;
- つづく -
最新の画像[もっと見る]
- 勝手に何すんねん!? 6年前
- 勝手に何すんねん!? 6年前
- Jpeg保存dllのバグ修正 <長いものは、やはり長い> 6年前
- Jpeg保存dllのバグ修正 <長いものは、やはり長い> 6年前
- Jpeg保存dllのバグ修正 <長いものは、やはり長い> 6年前
- Jpeg保存dllのバグ修正 <長いものは、やはり長い> 6年前
- コンパイル&ビルド 7年前
- コンパイル&ビルド 7年前
- Huffman変換&圧縮処理のつづき 7年前
- ハフマン変換をLUTにする の続き 7年前