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を探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語での引数の省略方法
-
「指定されたキャストは有効で...
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語
-
return 1L
-
複数桁10進数の*桁目だけを抽出...
-
C言語のサイコロシミュレート
-
C++でvectorにテキストファイル...
-
「{ } で囲むだけ」は正しい?
-
C言語 エラーの原因がわからな...
-
C言語の配列をC++のvectorに高...
-
read関数をノンブロッキングで...
-
VB.NETからC++のdll連携(double)
-
ラップ関数とはどんなものですか?
-
困ってます…nCrを求めるC言語...
-
【C++】関数ポインタの使い方
-
PowerShellがうまくいかない
-
数字列を3桁ごとにカンマで区切...
-
Arduinoのプログラムにエラーが...
-
構造体の勉強中です 合計点の高...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
AtCoderABC135の問題Cについて
-
C言語 エラーの原因がわからな...
-
複数桁10進数の*桁目だけを抽出...
-
【C++】関数ポインタの使い方
-
実数の整数部,小数部の取得
-
ラップ関数とはどんなものですか?
-
if と配列の組み合わせ
-
return 1L
-
read関数をノンブロッキングで...
-
(int *)の意味
-
std::set<int> で、ある値が何...
-
Win32APIで作るコンボボックス...
-
C++でvectorにテキストファイル...
-
「{ } で囲むだけ」は正しい?
-
足して100になるような乱数のア...
-
Arduinoのプログラムにエラーが...
-
課題でつまってます・・・
おすすめ情報