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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# プログラミングを教えて欲しいです。 配列aは、int a[9]={7,6,12,8,3,5,10,9 4 2022/12/19 23:27
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数桁10進数の*桁目だけを抽出...
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
(int *)の意味
-
数字列を3桁ごとにカンマで区切...
-
比較回数と交換回数表示について
-
if と配列の組み合わせ
-
C言語で三目並べをするプログラ...
-
実数の整数部,小数部の取得
-
卒業研究でよく分からないとこ...
-
C言語で分からないところがあり...
-
C言語での奇数の和
-
アスタリスクで正方形
-
警告 W8065について。
-
入力された2つの整数の差を絶対...
-
【C++】関数ポインタの使い方
-
C言語 エラーの原因がわからな...
-
C言語
-
C言語初心者です、、、お助けく...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
#define _CRT_SECURE_NO_WARNIN...
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
実数の整数部,小数部の取得
-
std::set<int> で、ある値が何...
-
C言語 エラーの原因がわからな...
-
c言語
-
system関数がうまくいかない
-
C++でvectorにテキストファイル...
-
acceptをalarmでタイムアウトさ...
-
if と配列の組み合わせ
-
return 1L
-
「{ } で囲むだけ」は正しい?
-
(マルチスレッド)_beginthrea...
-
PowerShellがうまくいかない
-
このプログラミング誰か教えて...
おすすめ情報