
jpeg の DCT 変換がうまくいきません。
jpegを作りたいのですが、DCT変換で詰まってしまいました。
よろしければ、ご教授いただけませんでしょうか?
http://www.ann.hi-ho.ne.jp/jiro/assyuku2.htm
のDCT変換の例を見て、プログラムを作ってみましたが、
変換例と同じ値に変換されませんでした。
作ってみたプログラムです。
#include <iostream>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
using namespace std;
void main(int argc, char** argv)
{
double cu = 1.0;
double cv = 1.0;
double long sum = 0.0;
int before[8][8] ={
{57,49,44,39,33,28,23,22},
{55,45,39,33,28,21,21,19},
{55,44,37,31,20,17,17,16},
{58,44,37,29,17,15,16,14},
{66,46,31,22,16,14,12,10},
{71,49,32,24,14,12,21,19},
{69,50,30,22,12,4,-1,-2},
{62,42,25,17,7,1,-16,-16}
};
int after[8][8];
ZeroMemory(after,sizeof(int)*64);
for(int v =0; v < 8; v++)
{
if(v) cv =1.0;
if(!v) cv = 1 / sqrt(2.0);
for(int u = 0; u < 8; u++)
{
if(u) cu =1.0;
if(!u) cu = 1 / sqrt(2.0);
sum = 0.0;
for(int y = 0; y < 8; y++)
{
for(int x = 0; x < 8; x++)
{
double long a = cos((2 * x + 1)*u*M_PI/16) * cos(( 2 * y + 1)*v*M_PI/16);
double long d = before[x][y];
sum += d * a;
}
}
after[u][v] = int(cu*cv*sum/4);
}
}
for(int j = 0; j < 8; j++)
{
for(int i = 0; i < 8; i++)
{
cout << after[i][j] << ",";
}
cout << endl;
}
int b;
cin >> b ;
}
No.3ベストアンサー
- 回答日時:
ちょっとだけ補足しておきます。
> int(floor(cu*cv*sum/4+0.5));
floor は「引数値を超えない最大の整数」を返す関数であり、
それに0.5足した値を入れることで、四捨五入になります。
修正前> double long d = before[x][y];
修正後> double long d = before[y][x];
修正前> after[u][v] = int(cu*cv*sum/4);
修正後> after[v][u] = int(floor(cu*cv*sum/4+0.5));
修正前> cout << after[i][j] << ",";
修正後> cout << after[j][i] << ",";
この3行の修正で、質問者さんが挙げたリンク先の実行例と同じ結果になることは確認済です。
No.2
- 回答日時:
浮動小数点数を整数化するときの問題じゃないですかね。
int にキャストすると切り捨てになってしまいいますので、
> floor(cu*cv*sum/4+0.5)
としましょう。
それと、
before の初期化値の57,49,44,39,…が、y=0で、x=0,1,2,3…に対応するのなら、
配列アクセスは before[y][x] になります。
(このように、C言語で二次元配列を使うときは、yの方を最初の添え字に使う場合が多いです。)
それにあわせて、配列アクセスは全て
> double long d = before[y][x];
> after[v][u] = int(floor(cu*cv*sum/4+0.5));
> cout << after[j][i] << ",";
のようにするべきでしょう。
No.1
- 回答日時:
浮動小数点数を整数化するときの問題じゃないですかね。
int にキャストすると切り捨てになってしまいいますので、
> floor(cu*cv*sum/4+0.5)
としましょう。
それと、
before の初期化値の57,49,44,39,…が、y=0で、x=0,1,2,3…に対応するのなら、
配列アクセスは before[y][x] になります。
(このように、C言語で二次元配列を使うときは、yの方を最初の添え字に使う場合が多いです。)
それにあわせて、配列アクセスは全て
> double long d = before[y][x];
> after[v][u] = int(floor(cu*cv*sum/4+0.5));
> cout << after[j][i] << ",";
のようにするべきでしょう。
doubleの切捨てに問題があるということですね?
私もそこは気になっていました。
その観点でもう少しプログラムいじってみます。
ご解答ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数桁10進数の*桁目だけを抽出...
-
#define _CRT_SECURE_NO_WARNIN...
-
acceptをalarmでタイムアウトさ...
-
C言語での引数の省略方法
-
構造体の勉強中です 合計点の高...
-
C言語の関数で戻り値を返す必要...
-
C言語 エラーの原因がわからな...
-
return 1L
-
プログラムがうまく動作しない
-
C#のコンパイルエラーCS0120に...
-
【C++】関数ポインタの使い方
-
インライン展開されているか確...
-
ColorをRGBで指定する方法
-
「指定されたキャストは有効で...
-
C言語 プログラミング
-
Windowsでインターバル・タイマ...
-
DirectX ~テクスチャに値を書...
-
式は定数値が必要です」という...
-
read関数をノンブロッキングで...
-
以下のプログラムをnumber.txt...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
複数桁10進数の*桁目だけを抽出...
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語 エラーの原因がわからな...
-
ラップ関数とはどんなものですか?
-
【C++】関数ポインタの使い方
-
if と配列の組み合わせ
-
(int *)の意味
-
ColorをRGBで指定する方法
-
未解決の外部シンボル _printf...
-
構造体の勉強中です 合計点の高...
-
商と剰余を同時に求める(C言語)
-
C言語で分からないところがあり...
-
式は定数値が必要です」という...
-
C言語での奇数の和
-
std::set<int> で、ある値が何...
-
課題でつまってます・・・
-
int16_t の _t は何?
-
比較回数と交換回数表示について
おすすめ情報