-
Notifications
You must be signed in to change notification settings - Fork 0
/
dct.cpp
152 lines (114 loc) · 3.63 KB
/
dct.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// dct.cpp
// jpeg
//
// Created by Blake Johnson on 10/23/19.
// Copyright © 2019 Blake Johnson. All rights reserved.
//
#include "dct.hpp"
#include <iomanip>
void DCT::fdct(int xPix, int yPix, int chan, double *** colors){
//configure internal object parameters
i = xPix;
j = yPix;
channel = chan;
//orient every pixel value around zero
printBlock(colors);
levelShift(colors);
printBlock(colors);
/*
Take the dct of every pixel in the nxn block. This requires
iterating over every Suv value where u and v range from 0 to 8.
u and v correlate to an X and Y pixel in the colors array. (xPix, yPix)
is the top left pixel in the nxn block, essentially an offset. Add
i + u and and j + v to get a coordinate for the colors array. Because of
the repeating nature of the dct, a holding array to store the new Suv
values will be needed as not to overwrite the old colors values.
*/
//Initialize holding array
double Suv [8][8];
//fdctFunc(0, 0, Suv, colors);
// printBlock(Suv);
for (int v = 0; v < 8; v++){
for (int u = 0; u < 8; u++){
fdctFunc(u, v, Suv, colors);
}
}
printBlock(Suv);
//Store Suv values back into colors
for (int v = 0; v < 8; v++){
for (int u = 0; u < 8; u++){
colors[channel][v][u] = Suv[v][u];
}
}
//Now compute quantization values
printBlock(colors);
quantize(colors);
printBlock(colors);
}
void DCT::fdctFunc(int u, int v, double Suv [8][8], double *** colors){
double S = 0, Cu = 1, Cv = 1, inner = 0, outer = 0, theta = 0, sum = 0;
double coef [8][8];
if(u == 0) Cu = Cuv;
if(v == 0) Cv = Cuv;
S = 0.25 * Cu * Cv;
for (int y = 0; y < n; y++){
for(int x = 0; x < m; x++){
theta = ((2 * x) + 1) * u * Pi;
coef[y][x] = colors[channel][y + j][x + i] * std::cos(theta / 16);
theta = ((2 * y) + 1) * v * Pi;
coef[y][x] *= std::cos(theta / 16);
sum += coef[y][x];
}
}
S *= sum;
Suv [v][u] = S;
}
//Shift all values around zero before doing the dct.
//if there are 8 bits per channel, than the mid point is 128, so subtract that
void DCT::levelShift(double *** colors){
for (int y = i; y < n; y++){
for(int x = j; x < m; x++){
colors[channel][y][x] -= 128;
}
}
}
void DCT::quantize(double ***colors)
{
//luminance channel (0) has a different quantization table than chromance channels do (1 and 2)
//I didnt want a if statment 64 times, so I copied the code in an ugly way
if(channel == 0){
for (int y = i; y < n; y++){
for(int x = j; x < m; x++){
colors[channel][y][x] = std::round(colors[channel][y][x] / quantLumin[y][x]);
}
}
}
else {
for (int y = i; y < n; y++){
for(int x = j; x < m; x++){
colors[channel][y][x] = std::round(colors[channel][y][x] / quantChrom[y][x]);
}
}
}
}
//DEBUG
void DCT::printBlock(double ***colors){
std::cout << "\n";
for (int y = i; y < n; y++){
for(int x = j; x < m; x++){
std::cout << colors[channel][y][x] << " ";
}
std::cout << std::endl;
}
}
//DEBUG
void DCT::printBlock(double colors [8][8]){
std::cout <<std::setprecision(4) <<"\n";
for (int y = i; y < n; y++){
for(int x = j; x < m; x++){
std::cout << colors[y][x] << " ";
}
std::cout << std::endl;
}
}