既に他の場所で公開済みのImageCompressionのプロジェクトを取り込み。
@@ -0,0 +1,21 @@ | ||
1 | +// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または | |
2 | +// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル | |
3 | +// を記述します。 | |
4 | +// | |
5 | + | |
6 | +#pragma once | |
7 | + | |
8 | +#include "targetver.h" | |
9 | + | |
10 | +#include <stdio.h> | |
11 | +#include <tchar.h> | |
12 | + | |
13 | + | |
14 | +template <typename T> | |
15 | +__forceinline void OffsetPtr(T*& ptr, int offsetBytes) | |
16 | +{ | |
17 | + ptr = (T*) ((const char*)ptr + offsetBytes); | |
18 | +} | |
19 | + | |
20 | + | |
21 | +// TODO: プログラムに必要な追加ヘッダーをここで参照してください。 |
@@ -0,0 +1,145 @@ | ||
1 | +#include "stdafx.h" | |
2 | + | |
3 | +#include "IntraPrediction.h" | |
4 | + | |
5 | +namespace IntraPrediction { | |
6 | + | |
7 | +void Predictor8::vertical(const int original[8][8], int processed[8][8]) | |
8 | +{ | |
9 | + for (size_t x=0; x<8; ++x) { | |
10 | + processed[0][x] = original[0][x] - cols[1+x]; | |
11 | + } | |
12 | + for (size_t y=1; y<8; ++y) { | |
13 | + for (size_t x=0; x<8; ++x) { | |
14 | + processed[y][x] = original[y][x] - original[y-1][x]; | |
15 | + } | |
16 | + } | |
17 | +} | |
18 | + | |
19 | +void Predictor8::horizontal(const int original[8][8], int processed[8][8]) | |
20 | +{ | |
21 | + for (size_t y=0; y<8; ++y) { | |
22 | + processed[y][0] = original[y][0] - rows[1+y]; | |
23 | + for (size_t x=1; x<8; ++x) { | |
24 | + processed[y][x] = original[y][x] - original[y][x-1]; | |
25 | + } | |
26 | + } | |
27 | +} | |
28 | + | |
29 | +void Predictor8::dc(const int original[8][8], int processed[8][8]) | |
30 | +{ | |
31 | + for (size_t y=0; y<8; ++y) { | |
32 | + for (size_t x=0; x<8; ++x) { | |
33 | + processed[y][x] = original[y][x] - average; | |
34 | + } | |
35 | + } | |
36 | +} | |
37 | + | |
38 | +void Predictor8::diagonalDownLeft(const int original[8][8], int processed[8][8]) | |
39 | +{ | |
40 | + for (size_t x=0; x<8; ++x) { | |
41 | + processed[0][x] = original[0][x] - cols[1+x]; | |
42 | + } | |
43 | + for (size_t y=1; y<8; ++y) { | |
44 | + for (size_t x=0; x<7; ++x) { | |
45 | + processed[y][x] = original[y][x] - original[y-1][x+1]; | |
46 | + } | |
47 | + processed[y][7] = original[y][7] - cols[9+y]; | |
48 | + } | |
49 | +} | |
50 | + | |
51 | +void Predictor8::diagonalDownRight(const int original[8][8], int processed[8][8]) | |
52 | +{ | |
53 | + for (size_t x=0; x<8; ++x) { | |
54 | + processed[0][x] = original[0][x] - cols[x]; | |
55 | + } | |
56 | + for (size_t y=1; y<8; ++y) { | |
57 | + processed[y][0] = rows[y]; | |
58 | + for (size_t x=1; x=8; ++x) { | |
59 | + processed[y][x] = original[y][x] - original[y-1][x-1]; | |
60 | + } | |
61 | + } | |
62 | +} | |
63 | + | |
64 | +void Predictor8::verticalRight_Sub(size_t offset, const int original[8][8], int processed[8][8]) | |
65 | +{ | |
66 | + processed[offset][0] = original[offset][0] - rows[offset]; | |
67 | + for (size_t x=1; x<8; ++x) { | |
68 | + processed[offset][x] = original[offset][x] - original[offset-1][x-1]; | |
69 | + } | |
70 | + for (size_t x=0; x<8; ++x) { | |
71 | + processed[offset+1][x] = original[offset+1][x] - original[offset][x]; | |
72 | + } | |
73 | +} | |
74 | + | |
75 | +void Predictor8::verticalRight(const int original[8][8], int processed[8][8]) | |
76 | +{ | |
77 | + for (size_t x=0; x<8; ++x) { | |
78 | + processed[0][x] = original[0][x] - cols[x]; | |
79 | + } | |
80 | + for (size_t x=0; x<8; ++x) { | |
81 | + processed[1][x] = original[1][x] - original[0][x]; | |
82 | + } | |
83 | + verticalRight_Sub(2, original, processed); | |
84 | + verticalRight_Sub(4, original, processed); | |
85 | + verticalRight_Sub(6, original, processed); | |
86 | +} | |
87 | + | |
88 | +void Predictor8::horizontalDown(const int original[8][8], int processed[8][8]) | |
89 | +{ | |
90 | + for (size_t x=0; x<8; x+=2) { | |
91 | + processed[0][x] = original[0][x] - cols[x]; | |
92 | + processed[0][x+1] = original[0][x+1] - original[0][x]; | |
93 | + } | |
94 | + for (size_t y=1; y<8; ++y) { | |
95 | + processed[y][0] = original[y][0] - rows[y]; | |
96 | + processed[y][1] = original[y][1] - original[y][0]; | |
97 | + for (size_t x=2; x<8; x+=2) { | |
98 | + processed[y][x] = original[y][x] - original[y-1][x-1]; | |
99 | + processed[y][x+1] = original[y][x+1] - original[y][x]; | |
100 | + } | |
101 | + } | |
102 | +} | |
103 | + | |
104 | +void Predictor8::verticalLeft_Sub(size_t offset, const int original[8][8], int processed[8][8]) | |
105 | +{ | |
106 | + for (size_t x=0; x<7; ++x) { | |
107 | + processed[offset][x] = original[offset][x] - original[offset-1][x+1]; | |
108 | + processed[offset+1][x] = original[offset+1][x] - original[offset][x]; | |
109 | + } | |
110 | + processed[offset][7] = original[offset][7] - cols[8+offset]; | |
111 | + processed[offset+1][7] = original[offset+1][7] - original[offset][7]; | |
112 | +} | |
113 | + | |
114 | +void Predictor8::verticalLeft(const int original[8][8], int processed[8][8]) | |
115 | +{ | |
116 | + for (size_t x=0; x<8; ++x) { | |
117 | + processed[0][x] = original[0][x] - cols[x+2]; | |
118 | + } | |
119 | + for (size_t x=0; x<8; ++x) { | |
120 | + processed[1][x] = original[1][x] - original[0][x]; | |
121 | + } | |
122 | + verticalLeft_Sub(2, original, processed); | |
123 | + verticalLeft_Sub(4, original, processed); | |
124 | + verticalLeft_Sub(6, original, processed); | |
125 | +} | |
126 | + | |
127 | +void Predictor8::horizontalUp(const int original[8][8], int processed[8][8]) | |
128 | +{ | |
129 | + for (size_t y=0; y<7; ++y) { | |
130 | + processed[y][0] = original[y][0] - rows[2+y]; | |
131 | + processed[y][1] = original[y][1] - original[y][0]; | |
132 | + for (size_t x=2; x<8; x+=2) { | |
133 | + processed[y][x] = original[y][x] - rows[x]; | |
134 | + processed[y][x+1] = original[y][x+1] - original[y][x+1]; | |
135 | + } | |
136 | + } | |
137 | + for (size_t x=0; x<8; x+=2) { | |
138 | + processed[7][x] = original[7][x] - rows[7/*9+x>>1*/]; | |
139 | + processed[7][x+1] = original[7][x+1] - original[7][x]; | |
140 | + } | |
141 | + | |
142 | +} | |
143 | + | |
144 | +} // namespace namespace IntraPrediction | |
145 | + |
@@ -0,0 +1,726 @@ | ||
1 | + | |
2 | +template <typename T> | |
3 | +void gather( | |
4 | + const T* in, int lineOffsetBytes, | |
5 | + int values[8][8] | |
6 | + ) | |
7 | +{ | |
8 | + const T* src = in; | |
9 | + for (size_t i=0; i<8; ++i) { | |
10 | + for (size_t j=0; j<8; ++j) { | |
11 | + values[i][j] = src[j]; | |
12 | + } | |
13 | + OffsetPtr(src, lineOffsetBytes); | |
14 | + } | |
15 | +} | |
16 | + | |
17 | +template <typename T> | |
18 | +void scatter( | |
19 | + T* out, int lineOffsetBytes, | |
20 | + int values[8][8] | |
21 | + ) | |
22 | +{ | |
23 | + T* dest = out; | |
24 | + for (size_t i=0; i<8; ++i) { | |
25 | + for (size_t j=0; j<8; ++j) { | |
26 | + dest[j] = values[i][j]; | |
27 | + } | |
28 | + OffsetPtr(dest, lineOffsetBytes); | |
29 | + } | |
30 | +} | |
31 | + | |
32 | +int paethPredictor(int left, int above, int upperLeft) | |
33 | +{ | |
34 | + int initial = left + (above - upperLeft); | |
35 | + int diffLeft = std::abs(initial - left); | |
36 | + int diffAbove = std::abs(initial - above); | |
37 | + int diffUpperLeft = std::abs(initial - upperLeft); | |
38 | + if (diffLeft <= diffAbove && diffLeft <= diffUpperLeft) { | |
39 | + return left; | |
40 | + }else if (diffAbove <= diffUpperLeft) { | |
41 | + return above; | |
42 | + }else { | |
43 | + return upperLeft; | |
44 | + } | |
45 | +} | |
46 | + | |
47 | +class BitWriter | |
48 | +{ | |
49 | +public: | |
50 | + BitWriter(unsigned char* dest) | |
51 | + : | |
52 | + nBits_(0), | |
53 | + dest_(dest), | |
54 | + counter_(0) | |
55 | + { | |
56 | + *dest_ = 0; | |
57 | + } | |
58 | + void putBit(bool b) | |
59 | + { | |
60 | + int v = b ? 1 : 0; | |
61 | + (*dest_) |= (v << (7 - counter_)); | |
62 | + ++counter_; | |
63 | + if (counter_ == 8) { | |
64 | + ++dest_; | |
65 | + *dest_ = 0; | |
66 | + counter_ = 0; | |
67 | + } | |
68 | + ++nBits_; | |
69 | + } | |
70 | + size_t nBits() const { return nBits_; } | |
71 | +private: | |
72 | + size_t nBits_; | |
73 | + unsigned char counter_; | |
74 | + unsigned char* dest_; | |
75 | +}; | |
76 | + | |
77 | +class BitReader | |
78 | +{ | |
79 | +public: | |
80 | + BitReader(const unsigned char* src) | |
81 | + : | |
82 | + src_(src), | |
83 | + counter_(0) | |
84 | + { | |
85 | + } | |
86 | + | |
87 | + bool getBit() | |
88 | + { | |
89 | + bool ret = *src_ & (1 << (7-counter_)); | |
90 | + ++counter_; | |
91 | + if (counter_ == 8) { | |
92 | + counter_ = 0; | |
93 | + ++src_; | |
94 | + } | |
95 | + return ret; | |
96 | + } | |
97 | +private: | |
98 | + unsigned char counter_; | |
99 | + const unsigned char* src_; | |
100 | +}; | |
101 | + | |
102 | +class RiceCoder | |
103 | +{ | |
104 | +public: | |
105 | + RiceCoder(size_t shift) | |
106 | + : | |
107 | + shift_(shift) | |
108 | + { | |
109 | + } | |
110 | + | |
111 | + void Encode(size_t value, BitWriter& writer) | |
112 | + { | |
113 | + size_t p = value >> shift_; | |
114 | + for (size_t i=0; i<p; ++i) { | |
115 | + writer.putBit(false); | |
116 | + } | |
117 | + writer.putBit(true); | |
118 | + int v = 1; | |
119 | + for (size_t i=0; i<shift_; ++i) { | |
120 | + writer.putBit(value & v); | |
121 | + v <<= 1; | |
122 | + } | |
123 | + } | |
124 | + | |
125 | + size_t Decode(BitReader& reader) | |
126 | + { | |
127 | + size_t q = 0; | |
128 | + while (!reader.getBit()) ++q; | |
129 | + size_t ret = q << shift_; | |
130 | + for (size_t i=0; i<shift_; ++i) { | |
131 | + if (reader.getBit()) { | |
132 | + ret += 1 << i; | |
133 | + } | |
134 | + } | |
135 | + return ret; | |
136 | + } | |
137 | + | |
138 | +private: | |
139 | + size_t shift_; | |
140 | +}; | |
141 | + | |
142 | +enum RiceCoderFlag { | |
143 | + None = 0xFF, | |
144 | +}; | |
145 | + | |
146 | +size_t compressSub( | |
147 | + ICompressor& compressor, | |
148 | + int* src, size_t srcLen, | |
149 | + unsigned char* dest, size_t destLen, | |
150 | + unsigned char* tmp, size_t tmpLen | |
151 | + ) | |
152 | +{ | |
153 | + unsigned char* initialDest = dest; | |
154 | + | |
155 | + assert(destLen > 4); | |
156 | + | |
157 | + int mini = boost::integer_traits<int>::const_max; | |
158 | + int maxi = boost::integer_traits<int>::const_min; | |
159 | +// int table[4096] = {0}; | |
160 | + | |
161 | + BitWriter signFlags(dest+4); | |
162 | + for (size_t i=0; i<srcLen; ++i) { | |
163 | + int val = src[i]; | |
164 | + if (val == 0) { | |
165 | + }else if (val < 0) { | |
166 | + signFlags.putBit(false); | |
167 | + }else { | |
168 | + signFlags.putBit(true); | |
169 | + } | |
170 | + val = std::abs(val); | |
171 | + maxi = std::max(val, maxi); | |
172 | + src[i] = val; | |
173 | +// ++table[val]; | |
174 | + } | |
175 | + size_t signFlagCount = signFlags.nBits(); | |
176 | + size_t signFlagBytes = signFlagCount/8 + ((signFlagCount%8) ? 1 : 0); | |
177 | + *((size_t*)dest) = signFlagBytes; | |
178 | + dest += (4 + signFlagBytes); | |
179 | + destLen -= (4 + signFlagBytes); | |
180 | + | |
181 | + mini = 0; | |
182 | + size_t max = std::max(maxi, std::abs(mini)); | |
183 | + int b; | |
184 | + if (max > 2048) { | |
185 | + b = 7; | |
186 | + }else if (max > 1024) { | |
187 | + b = 6; | |
188 | + }else if (max > 512) { | |
189 | + b = 5; | |
190 | + }else if (max > 256) { | |
191 | + b = 4; | |
192 | + }else if (max > 128+64) { | |
193 | + b = 3; | |
194 | + }else if (max > 128) { | |
195 | + b = 2; | |
196 | + }else if (max > 64) { | |
197 | + b = 1; | |
198 | + }else { | |
199 | + b = 0; | |
200 | + } | |
201 | + | |
202 | + size_t initialCompressedLen = compressor.Compress((const unsigned char*)src, srcLen*4, tmp, tmpLen); | |
203 | + | |
204 | + BitWriter bitWriter(dest); | |
205 | + RiceCoder riceCoder(b); | |
206 | + for (size_t i=0; i<srcLen; ++i) { | |
207 | + riceCoder.Encode(src[i], bitWriter); | |
208 | + } | |
209 | + //BitReader bitReader(dest); | |
210 | + //for (size_t i=0; i<srcLen; ++i) { | |
211 | + // size_t val = riceCoder.Decode(bitReader); | |
212 | + // assert(src[i] == val); | |
213 | + //} | |
214 | + size_t bitsLen = bitWriter.nBits(); | |
215 | + size_t bytesLen = bitsLen / 8; | |
216 | + if (bitsLen % 8) ++bytesLen; | |
217 | + | |
218 | + memcpy(src, dest, bytesLen); | |
219 | + size_t compressedLen = compressor.Compress((const unsigned char*)src, bytesLen, dest+2+4, destLen-2-4); | |
220 | + | |
221 | + size_t len = 0; | |
222 | + if (initialCompressedLen < compressedLen && initialCompressedLen < bytesLen) { | |
223 | + *dest++ = 1; | |
224 | + *dest++ = RiceCoderFlag::None; | |
225 | + len = initialCompressedLen; | |
226 | + memcpy(dest+4, tmp, len); | |
227 | + }else if (compressedLen < bytesLen) { | |
228 | + *dest++ = 1; | |
229 | + *dest++ = b; | |
230 | + len = compressedLen; | |
231 | + }else { | |
232 | + *dest++ = 0; | |
233 | + *dest++ = b; | |
234 | + len = bytesLen; | |
235 | + memcpy(dest+4, src, len); | |
236 | + } | |
237 | + *((size_t*)dest) = len; | |
238 | + dest += 4; | |
239 | + dest += len; | |
240 | + | |
241 | +// printf("%d %d %d\n", max, b, len + signFlagBytes); | |
242 | + | |
243 | + return dest - initialDest; | |
244 | +} | |
245 | + | |
246 | +size_t compress( | |
247 | + ICompressor& compressor, | |
248 | + size_t hBlockCount, | |
249 | + size_t vBlockCount, | |
250 | + const int* src, | |
251 | + int* tmp, | |
252 | + unsigned char* tmp2, size_t tmp2Len, | |
253 | + unsigned char* dest, size_t destLen | |
254 | + ) | |
255 | +{ | |
256 | + const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
257 | + const size_t fromWidth = hBlockCount * 8; | |
258 | + const size_t fromWidth8 = fromWidth * 8; | |
259 | + | |
260 | + const int* from = src; | |
261 | + int* to = tmp; | |
262 | + | |
263 | + int readPos; | |
264 | + // DC0 | |
265 | + readPos = 0; | |
266 | + for (size_t y=0; y<vBlockCount; ++y) { | |
267 | + int fromPos = readPos; | |
268 | + for (size_t x=0; x<hBlockCount; ++x) { | |
269 | + *to++ = from[fromPos]; | |
270 | + fromPos += 8; | |
271 | + } | |
272 | + readPos += fromWidth8; | |
273 | + } | |
274 | + | |
275 | + // paeth prediction to DC0 | |
276 | + to -= totalBlockCount; | |
277 | + // first row | |
278 | + int left = *to; | |
279 | + int above = 0; | |
280 | + int upperLeft = 0; | |
281 | + int cur = 0; | |
282 | + ++to; | |
283 | + for (size_t i=1; i<hBlockCount; ++i) { | |
284 | + cur = *to; | |
285 | + *to = cur - left; | |
286 | + ++to; | |
287 | + left = cur; | |
288 | + } | |
289 | + int fromLineOffset = 0; | |
290 | + for (size_t y=1; y<vBlockCount; ++y) { | |
291 | + cur = *to; | |
292 | + above = from[fromLineOffset]; | |
293 | + *to = cur - paethPredictor(0, above, 0); | |
294 | + left = cur; | |
295 | + upperLeft = above; | |
296 | + ++to; | |
297 | + int fromPos = fromLineOffset + 8; | |
298 | + for (size_t x=1; x<hBlockCount; ++x) { | |
299 | + above = from[fromPos]; | |
300 | + cur = *to; | |
301 | + *to = cur - paethPredictor(left, above, upperLeft); | |
302 | + ++to; | |
303 | + left = cur; | |
304 | + upperLeft = above; | |
305 | + fromPos += 8; | |
306 | + } | |
307 | + fromLineOffset += fromWidth8; | |
308 | + } | |
309 | + | |
310 | + size_t progress = 0; | |
311 | + progress += compressSub(compressor, tmp, totalBlockCount, dest+progress, destLen-progress, tmp2, tmp2Len); | |
312 | + to = tmp; | |
313 | + | |
314 | + // AC1 | |
315 | + readPos = 0; | |
316 | + for (size_t y=0; y<vBlockCount; ++y) { | |
317 | + int fromPos = readPos; | |
318 | + for (size_t x=0; x<hBlockCount; ++x) { | |
319 | + *to++ = from[fromPos+fromWidth*0+1]; | |
320 | + *to++ = from[fromPos+fromWidth*1+0]; | |
321 | + *to++ = from[fromPos+fromWidth*1+1]; | |
322 | + fromPos += 8; | |
323 | + } | |
324 | + readPos += fromWidth8; | |
325 | + } | |
326 | + progress += compressSub(compressor, tmp, totalBlockCount*3, dest+progress, destLen-progress, tmp2, tmp2Len); | |
327 | + to = tmp; | |
328 | + | |
329 | + // AC2 | |
330 | + readPos = 0; | |
331 | + for (size_t y=0; y<vBlockCount; ++y) { | |
332 | + int fromPos = readPos; | |
333 | + for (size_t x=0; x<hBlockCount; ++x) { | |
334 | + *to++ = from[fromPos+fromWidth*0+2]; | |
335 | + *to++ = from[fromPos+fromWidth*1+2]; | |
336 | + *to++ = from[fromPos+fromWidth*2+0]; | |
337 | + *to++ = from[fromPos+fromWidth*2+1]; | |
338 | + *to++ = from[fromPos+fromWidth*2+2]; | |
339 | + fromPos += 8; | |
340 | + } | |
341 | + readPos += fromWidth8; | |
342 | + } | |
343 | + progress += compressSub(compressor, tmp, totalBlockCount*5, dest+progress, destLen-progress, tmp2, tmp2Len); | |
344 | + to = tmp; | |
345 | + | |
346 | + // AC3 | |
347 | + readPos = 0; | |
348 | + for (size_t y=0; y<vBlockCount; ++y) { | |
349 | + int fromPos = readPos; | |
350 | + for (size_t x=0; x<hBlockCount; ++x) { | |
351 | + *to++ = from[fromPos+fromWidth*0+3]; | |
352 | + *to++ = from[fromPos+fromWidth*1+3]; | |
353 | + *to++ = from[fromPos+fromWidth*2+3]; | |
354 | + *to++ = from[fromPos+fromWidth*3+0]; | |
355 | + *to++ = from[fromPos+fromWidth*3+1]; | |
356 | + *to++ = from[fromPos+fromWidth*3+2]; | |
357 | + *to++ = from[fromPos+fromWidth*3+3]; | |
358 | + fromPos += 8; | |
359 | + } | |
360 | + readPos += fromWidth8; | |
361 | + } | |
362 | + progress += compressSub(compressor, tmp, totalBlockCount*7, dest+progress, destLen-progress, tmp2, tmp2Len); | |
363 | + to = tmp; | |
364 | + | |
365 | + // AC4 | |
366 | + readPos = 0; | |
367 | + for (size_t y=0; y<vBlockCount; ++y) { | |
368 | + int fromPos = readPos; | |
369 | + for (size_t x=0; x<hBlockCount; ++x) { | |
370 | + *to++ = from[fromPos+fromWidth*0+4]; | |
371 | + *to++ = from[fromPos+fromWidth*1+4]; | |
372 | + *to++ = from[fromPos+fromWidth*2+4]; | |
373 | + *to++ = from[fromPos+fromWidth*3+4]; | |
374 | + *to++ = from[fromPos+fromWidth*4+0]; | |
375 | + *to++ = from[fromPos+fromWidth*4+1]; | |
376 | + *to++ = from[fromPos+fromWidth*4+2]; | |
377 | + *to++ = from[fromPos+fromWidth*4+3]; | |
378 | + *to++ = from[fromPos+fromWidth*4+4]; | |
379 | + fromPos += 8; | |
380 | + } | |
381 | + readPos += fromWidth8; | |
382 | + } | |
383 | + progress += compressSub(compressor, tmp, totalBlockCount*9, dest+progress, destLen-progress, tmp2, tmp2Len); | |
384 | + to = tmp; | |
385 | + | |
386 | + // AC5 | |
387 | + readPos = 0; | |
388 | + for (size_t y=0; y<vBlockCount; ++y) { | |
389 | + int fromPos = readPos; | |
390 | + for (size_t x=0; x<hBlockCount; ++x) { | |
391 | + *to++ = from[fromPos+fromWidth*0+5]; | |
392 | + *to++ = from[fromPos+fromWidth*1+5]; | |
393 | + *to++ = from[fromPos+fromWidth*2+5]; | |
394 | + *to++ = from[fromPos+fromWidth*3+5]; | |
395 | + *to++ = from[fromPos+fromWidth*4+5]; | |
396 | + *to++ = from[fromPos+fromWidth*5+0]; | |
397 | + *to++ = from[fromPos+fromWidth*5+1]; | |
398 | + *to++ = from[fromPos+fromWidth*5+2]; | |
399 | + *to++ = from[fromPos+fromWidth*5+3]; | |
400 | + *to++ = from[fromPos+fromWidth*5+4]; | |
401 | + *to++ = from[fromPos+fromWidth*5+5]; | |
402 | + fromPos += 8; | |
403 | + } | |
404 | + readPos += fromWidth8; | |
405 | + } | |
406 | + progress += compressSub(compressor, tmp, totalBlockCount*11, dest+progress, destLen-progress, tmp2, tmp2Len); | |
407 | + to = tmp; | |
408 | + | |
409 | + // AC6 | |
410 | + readPos = 0; | |
411 | + for (size_t y=0; y<vBlockCount; ++y) { | |
412 | + int fromPos = readPos; | |
413 | + for (size_t x=0; x<hBlockCount; ++x) { | |
414 | + *to++ = from[fromPos+fromWidth*0+6]; | |
415 | + *to++ = from[fromPos+fromWidth*1+6]; | |
416 | + *to++ = from[fromPos+fromWidth*2+6]; | |
417 | + *to++ = from[fromPos+fromWidth*3+6]; | |
418 | + *to++ = from[fromPos+fromWidth*4+6]; | |
419 | + *to++ = from[fromPos+fromWidth*5+6]; | |
420 | + *to++ = from[fromPos+fromWidth*6+0]; | |
421 | + *to++ = from[fromPos+fromWidth*6+1]; | |
422 | + *to++ = from[fromPos+fromWidth*6+2]; | |
423 | + *to++ = from[fromPos+fromWidth*6+3]; | |
424 | + *to++ = from[fromPos+fromWidth*6+4]; | |
425 | + *to++ = from[fromPos+fromWidth*6+5]; | |
426 | + *to++ = from[fromPos+fromWidth*6+6]; | |
427 | + fromPos += 8; | |
428 | + } | |
429 | + readPos += fromWidth8; | |
430 | + } | |
431 | + progress += compressSub(compressor, tmp, totalBlockCount*13, dest+progress, destLen-progress, tmp2, tmp2Len); | |
432 | + to = tmp; | |
433 | + | |
434 | + // AC7 | |
435 | + readPos = 0; | |
436 | + for (size_t y=0; y<vBlockCount; ++y) { | |
437 | + int fromPos = readPos; | |
438 | + for (size_t x=0; x<hBlockCount; ++x) { | |
439 | + *to++ = from[fromPos+fromWidth*0+7]; | |
440 | + *to++ = from[fromPos+fromWidth*1+7]; | |
441 | + *to++ = from[fromPos+fromWidth*2+7]; | |
442 | + *to++ = from[fromPos+fromWidth*3+7]; | |
443 | + *to++ = from[fromPos+fromWidth*4+7]; | |
444 | + *to++ = from[fromPos+fromWidth*5+7]; | |
445 | + *to++ = from[fromPos+fromWidth*6+7]; | |
446 | + *to++ = from[fromPos+fromWidth*7+0]; | |
447 | + *to++ = from[fromPos+fromWidth*7+1]; | |
448 | + *to++ = from[fromPos+fromWidth*7+2]; | |
449 | + *to++ = from[fromPos+fromWidth*7+3]; | |
450 | + *to++ = from[fromPos+fromWidth*7+4]; | |
451 | + *to++ = from[fromPos+fromWidth*7+5]; | |
452 | + *to++ = from[fromPos+fromWidth*7+6]; | |
453 | + *to++ = from[fromPos+fromWidth*7+7]; | |
454 | + fromPos += 8; | |
455 | + } | |
456 | + readPos += fromWidth8; | |
457 | + } | |
458 | + progress += compressSub(compressor, tmp, totalBlockCount*15, dest+progress, destLen-progress, tmp2, tmp2Len); | |
459 | + | |
460 | + return progress; | |
461 | +} | |
462 | + | |
463 | +size_t decompressSub(ICompressor& compressor, const unsigned char* src, unsigned char* tmp, int* dest, size_t destLen) | |
464 | +{ | |
465 | + size_t signFlagBytes = *(size_t*)src; | |
466 | + src += 4; | |
467 | + BitReader signFlags(src); | |
468 | + src += signFlagBytes; | |
469 | + | |
470 | + bool isCompressed = *src++ != 0; | |
471 | + unsigned char b = *src++; | |
472 | + size_t len = *(size_t*)src; | |
473 | + src += 4; | |
474 | + | |
475 | + size_t len2 = 0; | |
476 | + if (isCompressed) { | |
477 | + len2 = compressor.Decompress(src, len, tmp, destLen*4); | |
478 | + }else { | |
479 | + memcpy(tmp, src, len); | |
480 | + len2 = len; | |
481 | + } | |
482 | + | |
483 | + if (b == RiceCoderFlag::None) { | |
484 | + memcpy(dest, tmp, len2); | |
485 | + for (size_t i=0; i<len2/4; ++i) { | |
486 | + int val = dest[i]; | |
487 | + if (val != 0) { | |
488 | + if (!signFlags.getBit()) { | |
489 | + dest[i] = -val; | |
490 | + } | |
491 | + } | |
492 | + } | |
493 | + | |
494 | + }else { | |
495 | + RiceCoder riceCoder(b); | |
496 | + BitReader bitReader(tmp); | |
497 | + for (size_t i=0; i<destLen; ++i) { | |
498 | + int val = riceCoder.Decode(bitReader); | |
499 | + if (val != 0) { | |
500 | + if (!signFlags.getBit()) { | |
501 | + val = -val; | |
502 | + } | |
503 | + } | |
504 | + dest[i] = val; | |
505 | + } | |
506 | + } | |
507 | +// showMinus(dest, dest, destLen); | |
508 | + | |
509 | + return 4 + signFlagBytes + 6 + len; | |
510 | +} | |
511 | + | |
512 | +void decompress( | |
513 | + ICompressor& decompressor, | |
514 | + size_t hBlockCount, | |
515 | + size_t vBlockCount, | |
516 | + const unsigned char* src, size_t srcLen, | |
517 | + unsigned char* tmp, int* tmp2, | |
518 | + int* dest, size_t destLen | |
519 | + ) | |
520 | +{ | |
521 | + int* initialDest = dest; | |
522 | + const unsigned char* initialSrc = src; | |
523 | + | |
524 | + const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
525 | + const size_t toWidth = hBlockCount * 8; | |
526 | + const size_t toWidth8 = toWidth * 8; | |
527 | + | |
528 | + int* from = tmp2; | |
529 | + int* to = dest; | |
530 | + | |
531 | + int writePos; | |
532 | + | |
533 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount); | |
534 | + // DC0 | |
535 | + writePos = 0; | |
536 | + for (size_t y=0; y<vBlockCount; ++y) { | |
537 | + int toPos = writePos; | |
538 | + for (size_t x=0; x<hBlockCount; ++x) { | |
539 | + assert(toPos < destLen); | |
540 | + to[toPos] = *from++; | |
541 | + toPos += 8; | |
542 | + } | |
543 | + writePos += toWidth8; | |
544 | + } | |
545 | + | |
546 | + // paeth predictor to DC0 | |
547 | + // first row | |
548 | + int left = *to; | |
549 | + int above = 0; | |
550 | + int upperLeft = 0; | |
551 | + int cur = 0; | |
552 | + writePos = 8; | |
553 | + for (size_t i=1; i<hBlockCount; ++i) { | |
554 | + cur = to[writePos] + left; | |
555 | + assert(writePos < destLen); | |
556 | + to[writePos] = cur; | |
557 | + left = cur; | |
558 | + writePos += 8; | |
559 | + } | |
560 | + int toLineOffset = toWidth8; | |
561 | + int paeth = 0; | |
562 | + for (size_t y=1; y<vBlockCount; ++y) { | |
563 | + above = to[toLineOffset - toWidth8]; | |
564 | + paeth = to[toLineOffset]; | |
565 | + cur = paeth + paethPredictor(0, above, 0); | |
566 | + assert(toLineOffset < destLen); | |
567 | + to[toLineOffset] = cur; | |
568 | + writePos = toLineOffset + 8; | |
569 | + left = cur; | |
570 | + upperLeft = above; | |
571 | + for (size_t x=1; x<hBlockCount; ++x) { | |
572 | + above = to[writePos - toWidth8]; | |
573 | + paeth = to[writePos]; | |
574 | + cur = paeth + paethPredictor(left, above, upperLeft); | |
575 | + assert(writePos < destLen); | |
576 | + to[writePos] = cur; | |
577 | + left = cur; | |
578 | + upperLeft = above; | |
579 | + writePos += 8; | |
580 | + } | |
581 | + toLineOffset += toWidth8; | |
582 | + } | |
583 | + | |
584 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*3); | |
585 | + // AC1 | |
586 | + writePos = 0; | |
587 | + for (size_t y=0; y<vBlockCount; ++y) { | |
588 | + int toPos = writePos; | |
589 | + for (size_t x=0; x<hBlockCount; ++x) { | |
590 | + to[toPos+toWidth*0+1] = *from++; | |
591 | + to[toPos+toWidth*1+0] = *from++; | |
592 | + to[toPos+toWidth*1+1] = *from++; | |
593 | + assert(toPos+toWidth*1+1 < destLen); | |
594 | + toPos += 8; | |
595 | + } | |
596 | + writePos += toWidth8; | |
597 | + } | |
598 | + | |
599 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*5); | |
600 | + // AC2 | |
601 | + writePos = 0; | |
602 | + for (size_t y=0; y<vBlockCount; ++y) { | |
603 | + int toPos = writePos; | |
604 | + for (size_t x=0; x<hBlockCount; ++x) { | |
605 | + to[toPos+toWidth*0+2] = *from++; | |
606 | + to[toPos+toWidth*1+2] = *from++; | |
607 | + to[toPos+toWidth*2+0] = *from++; | |
608 | + to[toPos+toWidth*2+1] = *from++; | |
609 | + to[toPos+toWidth*2+2] = *from++; | |
610 | + toPos += 8; | |
611 | + } | |
612 | + writePos += toWidth8; | |
613 | + } | |
614 | + | |
615 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*7); | |
616 | + // AC3 | |
617 | + writePos = 0; | |
618 | + for (size_t y=0; y<vBlockCount; ++y) { | |
619 | + int toPos = writePos; | |
620 | + for (size_t x=0; x<hBlockCount; ++x) { | |
621 | + to[toPos+toWidth*0+3] = *from++; | |
622 | + to[toPos+toWidth*1+3] = *from++; | |
623 | + to[toPos+toWidth*2+3] = *from++; | |
624 | + to[toPos+toWidth*3+0] = *from++; | |
625 | + to[toPos+toWidth*3+1] = *from++; | |
626 | + to[toPos+toWidth*3+2] = *from++; | |
627 | + to[toPos+toWidth*3+3] = *from++; | |
628 | + toPos += 8; | |
629 | + } | |
630 | + writePos += toWidth8; | |
631 | + } | |
632 | + | |
633 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*9); | |
634 | + // AC4 | |
635 | + writePos = 0; | |
636 | + for (size_t y=0; y<vBlockCount; ++y) { | |
637 | + int toPos = writePos; | |
638 | + for (size_t x=0; x<hBlockCount; ++x) { | |
639 | + to[toPos+toWidth*0+4] = *from++; | |
640 | + to[toPos+toWidth*1+4] = *from++; | |
641 | + to[toPos+toWidth*2+4] = *from++; | |
642 | + to[toPos+toWidth*3+4] = *from++; | |
643 | + to[toPos+toWidth*4+0] = *from++; | |
644 | + to[toPos+toWidth*4+1] = *from++; | |
645 | + to[toPos+toWidth*4+2] = *from++; | |
646 | + to[toPos+toWidth*4+3] = *from++; | |
647 | + to[toPos+toWidth*4+4] = *from++; | |
648 | + toPos += 8; | |
649 | + } | |
650 | + writePos += toWidth8; | |
651 | + } | |
652 | + | |
653 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*11); | |
654 | + // AC5 | |
655 | + writePos = 0; | |
656 | + for (size_t y=0; y<vBlockCount; ++y) { | |
657 | + int toPos = writePos; | |
658 | + for (size_t x=0; x<hBlockCount; ++x) { | |
659 | + to[toPos+toWidth*0+5] = *from++; | |
660 | + to[toPos+toWidth*1+5] = *from++; | |
661 | + to[toPos+toWidth*2+5] = *from++; | |
662 | + to[toPos+toWidth*3+5] = *from++; | |
663 | + to[toPos+toWidth*4+5] = *from++; | |
664 | + to[toPos+toWidth*5+0] = *from++; | |
665 | + to[toPos+toWidth*5+1] = *from++; | |
666 | + to[toPos+toWidth*5+2] = *from++; | |
667 | + to[toPos+toWidth*5+3] = *from++; | |
668 | + to[toPos+toWidth*5+4] = *from++; | |
669 | + to[toPos+toWidth*5+5] = *from++; | |
670 | + toPos += 8; | |
671 | + } | |
672 | + writePos += toWidth8; | |
673 | + } | |
674 | + | |
675 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*13); | |
676 | + // AC6 | |
677 | + writePos = 0; | |
678 | + for (size_t y=0; y<vBlockCount; ++y) { | |
679 | + int toPos = writePos; | |
680 | + for (size_t x=0; x<hBlockCount; ++x) { | |
681 | + to[toPos+toWidth*0+6] = *from++; | |
682 | + to[toPos+toWidth*1+6] = *from++; | |
683 | + to[toPos+toWidth*2+6] = *from++; | |
684 | + to[toPos+toWidth*3+6] = *from++; | |
685 | + to[toPos+toWidth*4+6] = *from++; | |
686 | + to[toPos+toWidth*5+6] = *from++; | |
687 | + to[toPos+toWidth*6+0] = *from++; | |
688 | + to[toPos+toWidth*6+1] = *from++; | |
689 | + to[toPos+toWidth*6+2] = *from++; | |
690 | + to[toPos+toWidth*6+3] = *from++; | |
691 | + to[toPos+toWidth*6+4] = *from++; | |
692 | + to[toPos+toWidth*6+5] = *from++; | |
693 | + to[toPos+toWidth*6+6] = *from++; | |
694 | + toPos += 8; | |
695 | + } | |
696 | + writePos += toWidth8; | |
697 | + } | |
698 | + | |
699 | + src += decompressSub(decompressor, src, tmp, from, totalBlockCount*15); | |
700 | + // AC7 | |
701 | + writePos = 0; | |
702 | + for (size_t y=0; y<vBlockCount; ++y) { | |
703 | + int toPos = writePos; | |
704 | + for (size_t x=0; x<hBlockCount; ++x) { | |
705 | + to[toPos+toWidth*0+7] = *from++; | |
706 | + to[toPos+toWidth*1+7] = *from++; | |
707 | + to[toPos+toWidth*2+7] = *from++; | |
708 | + to[toPos+toWidth*3+7] = *from++; | |
709 | + to[toPos+toWidth*4+7] = *from++; | |
710 | + to[toPos+toWidth*5+7] = *from++; | |
711 | + to[toPos+toWidth*6+7] = *from++; | |
712 | + to[toPos+toWidth*7+0] = *from++; | |
713 | + to[toPos+toWidth*7+1] = *from++; | |
714 | + to[toPos+toWidth*7+2] = *from++; | |
715 | + to[toPos+toWidth*7+3] = *from++; | |
716 | + to[toPos+toWidth*7+4] = *from++; | |
717 | + to[toPos+toWidth*7+5] = *from++; | |
718 | + to[toPos+toWidth*7+6] = *from++; | |
719 | + to[toPos+toWidth*7+7] = *from++; | |
720 | + assert(toPos+toWidth*7+7 < destLen); | |
721 | + toPos += 8; | |
722 | + } | |
723 | + writePos += toWidth8; | |
724 | + } | |
725 | +} | |
726 | + |
@@ -0,0 +1,115 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +#include "IntraPrediction.h" | |
4 | + | |
5 | +void copy(int in[8][8], int out[8][8]) | |
6 | +{ | |
7 | + for (size_t i=0; i<8; ++i) | |
8 | + for (size_t j=0; j<8; ++j) | |
9 | + out[i][j] = in[i][j]; | |
10 | +} | |
11 | + | |
12 | +size_t sumOfAbsolutes(const int values[8][8]) | |
13 | +{ | |
14 | + size_t ret = 0; | |
15 | + for (size_t i=0; i<8; ++i) | |
16 | + for (size_t j=0; j<8; ++j) | |
17 | + ret += std::abs(values[i][j]); | |
18 | + return ret; | |
19 | +} | |
20 | + | |
21 | +template <typename T> | |
22 | +void encode( | |
23 | + Quantizer& quantizer, | |
24 | + size_t hBlocks, size_t vBlocks, | |
25 | + const T* in, int inLineOffsetBytes, | |
26 | + int* out, int outLineOffsetBytes | |
27 | + ) | |
28 | +{ | |
29 | + int values[8][8]; | |
30 | + int tmps[8][8]; | |
31 | + int tmps2[8][8]; | |
32 | + | |
33 | + IntraPrediction::Predictor8 predictor; | |
34 | + int cols[17]; | |
35 | + int rows[17]; | |
36 | + int predictionScores[9]; | |
37 | + | |
38 | + const T* src = in; | |
39 | + int* dest = out; | |
40 | + | |
41 | + // top | |
42 | + { | |
43 | + const T* srcLine = src; | |
44 | + int* destLine = dest; | |
45 | + | |
46 | + // top left | |
47 | + gather(srcLine, inLineOffsetBytes, values); | |
48 | + dct_8x8(values, tmps); | |
49 | + quantizer.quantize(values); | |
50 | + scatter(destLine, outLineOffsetBytes, values); | |
51 | + srcLine += 8; destLine += 8; | |
52 | + // top remain | |
53 | + for (size_t x=1; x<hBlocks; ++x) { | |
54 | +#if 0 | |
55 | + decodeRightMostColumn(quantizer, rows+1, values, tmps); | |
56 | +// predictor.rows[0] = predictor.rows[1] = | |
57 | + int sum = 0; | |
58 | + for (size_t i=1; i<9; ++i) { | |
59 | + sum += rows[i]; | |
60 | + } | |
61 | + std::copy(rows+1, rows+9, predictor.rows+1); | |
62 | + predictor.average = sum / 8; | |
63 | + gather(srcLine, inLineOffsetBytes, values); | |
64 | + predictor.horizontal(values, tmps); | |
65 | + sum = sumOfAbsolutes(tmps); | |
66 | + predictor.horizontalUp(values, tmps); | |
67 | + sum = sumOfAbsolutes(tmps); | |
68 | + predictor.dc(values, tmps); | |
69 | + sum = sumOfAbsolutes(tmps); | |
70 | + dct_8x8(tmps, tmps2); | |
71 | + quantizer.quantize(tmps); | |
72 | + scatter(destLine, outLineOffsetBytes, tmps); | |
73 | +#else | |
74 | + gather(srcLine, inLineOffsetBytes, values); | |
75 | + dct_8x8(values, tmps); | |
76 | + quantizer.quantize(values); | |
77 | + scatter(destLine, outLineOffsetBytes, values); | |
78 | +#endif | |
79 | + srcLine += 8; destLine += 8; | |
80 | + } | |
81 | + OffsetPtr(src, inLineOffsetBytes*8); | |
82 | + OffsetPtr(dest, outLineOffsetBytes*8); | |
83 | + } | |
84 | + | |
85 | + for (size_t y=1; y<vBlocks; ++y) { | |
86 | + | |
87 | + const T* srcLine = src; | |
88 | + int* destLine = dest; | |
89 | + | |
90 | + // left | |
91 | + gather(srcLine, inLineOffsetBytes, values); | |
92 | + dct_8x8(values, tmps); | |
93 | + quantizer.quantize(values); | |
94 | + scatter(destLine, outLineOffsetBytes, values); | |
95 | + srcLine += 8; destLine += 8; | |
96 | + // between | |
97 | + for (size_t x=1; x<hBlocks-1; ++x) { | |
98 | + gather(srcLine, inLineOffsetBytes, values); | |
99 | + dct_8x8(values, tmps); | |
100 | + quantizer.quantize(values); | |
101 | + scatter(destLine, outLineOffsetBytes, values); | |
102 | + srcLine += 8; destLine += 8; | |
103 | + } | |
104 | + // right | |
105 | + gather(srcLine, inLineOffsetBytes, values); | |
106 | + dct_8x8(values, tmps); | |
107 | + quantizer.quantize(values); | |
108 | + scatter(destLine, outLineOffsetBytes, values); | |
109 | + srcLine += 8; destLine += 8; | |
110 | + | |
111 | + OffsetPtr(src, inLineOffsetBytes*8); | |
112 | + OffsetPtr(dest, outLineOffsetBytes*8); | |
113 | + } | |
114 | +} | |
115 | + |
@@ -0,0 +1,31 @@ | ||
1 | +#include "stdafx.h" | |
2 | + | |
3 | +#include "BZip2Compressor.h" | |
4 | + | |
5 | +#include "bzlib.h" | |
6 | +#pragma comment(lib, "libbz2.lib") | |
7 | + | |
8 | +size_t BZip2Compressor::Compress( | |
9 | + const unsigned char* src, | |
10 | + size_t srcLen, | |
11 | + unsigned char* dest, | |
12 | + size_t destLen | |
13 | +) | |
14 | +{ | |
15 | + size_t compressedLen = destLen; | |
16 | + BZ2_bzBuffToBuffCompress((char*)dest, &compressedLen, (char*)src, srcLen, 9, 0, 30); | |
17 | + return compressedLen; | |
18 | +} | |
19 | + | |
20 | +size_t BZip2Compressor::Decompress( | |
21 | + const unsigned char* src, | |
22 | + size_t srcLen, | |
23 | + unsigned char* dest, | |
24 | + size_t destLen | |
25 | +) | |
26 | +{ | |
27 | + size_t decompressedLen = destLen; | |
28 | + BZ2_bzBuffToBuffDecompress((char*)dest, &decompressedLen, (char*)src, srcLen, 0, 0); | |
29 | + return decompressedLen; | |
30 | +} | |
31 | + |
@@ -0,0 +1,75 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +namespace IntraPrediction { | |
4 | + | |
5 | +enum Mode { | |
6 | + Mode_Vertical = 0, | |
7 | + Mode_Horizontal = 1, | |
8 | + Mode_DC = 2, | |
9 | + Mode_DiagonalDownLeft = 3, | |
10 | + Mode_DiagonalDownRight = 4, | |
11 | + Mode_VerticalRight = 5, | |
12 | + Mode_HorizontalDown = 6, | |
13 | + Mode_VerticalLeft = 7, | |
14 | + Mode_HorizontalUp = 8, | |
15 | +}; | |
16 | + | |
17 | +class Predictor8 | |
18 | +{ | |
19 | +public: | |
20 | + void predict(Mode mode, const int original[8][8], int processed[8][8]) | |
21 | + { | |
22 | + switch (mode) { | |
23 | + case Mode_Vertical: | |
24 | + vertical(original, processed); | |
25 | + break; | |
26 | + case Mode_Horizontal: | |
27 | + horizontal(original, processed); | |
28 | + break; | |
29 | + case Mode_DC: | |
30 | + dc(original, processed); | |
31 | + break; | |
32 | + case Mode_DiagonalDownLeft: | |
33 | + diagonalDownLeft(original, processed); | |
34 | + break; | |
35 | + case Mode_DiagonalDownRight: | |
36 | + diagonalDownRight(original, processed); | |
37 | + break; | |
38 | + case Mode_VerticalRight: | |
39 | + verticalRight(original, processed); | |
40 | + break; | |
41 | + case Mode_HorizontalDown: | |
42 | + horizontalDown(original, processed); | |
43 | + break; | |
44 | + case Mode_VerticalLeft: | |
45 | + verticalLeft(original, processed); | |
46 | + break; | |
47 | + case Mode_HorizontalUp: | |
48 | + horizontalUp(original, processed); | |
49 | + break; | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + void vertical(const int original[8][8], int processed[8][8]); | |
54 | + void horizontal(const int original[8][8], int processed[8][8]); | |
55 | + void dc(const int original[8][8], int processed[8][8]); | |
56 | + void diagonalDownLeft(const int original[8][8], int processed[8][8]); | |
57 | + void diagonalDownRight(const int original[8][8], int processed[8][8]); | |
58 | + | |
59 | + void verticalRight(const int original[8][8], int processed[8][8]); | |
60 | + void verticalRight_Sub(size_t offset, const int original[8][8], int processed[8][8]); | |
61 | + | |
62 | + void horizontalDown(const int original[8][8], int processed[8][8]); | |
63 | + | |
64 | + void verticalLeft(const int original[8][8], int processed[8][8]); | |
65 | + void verticalLeft_Sub(size_t offset, const int original[8][8], int processed[8][8]); | |
66 | + | |
67 | + void horizontalUp(const int original[8][8], int processed[8][8]); | |
68 | + | |
69 | + int cols[17]; // bottom row | |
70 | + int rows[17]; // right-most columns | |
71 | + int average; | |
72 | +}; | |
73 | + | |
74 | +} // namespace IntraPrediction | |
75 | + |
@@ -0,0 +1,13 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +// 以下のマクロは、最低限必要なプラットフォームを定義します。最低限必要なプラットフォームとは、 | |
4 | +// アプリケーションを実行するために必要な機能を備えた最も古いバージョンの Windows や Internet Explorer など | |
5 | +// をいいます。これらのマクロは、指定したバージョンと、それ以前のバージョンのプラットフォーム上で利用できるすべての機能を有効にすることによって | |
6 | +// 動作します。 | |
7 | + | |
8 | +// 下で指定された定義の前に対象プラットフォームを指定しなければならない場合、以下の定義を変更してください。 | |
9 | +// 異なるプラットフォームに対応する値に関する最新情報については、MSDN を参照してください。 | |
10 | +#ifndef _WIN32_WINNT // 最低限必要なプラットフォームが Windows Vista であることを指定します。 | |
11 | +#define _WIN32_WINNT 0x0600 // これを Windows の他のバージョン向けに適切な値に変更してください。 | |
12 | +#endif | |
13 | + |
@@ -0,0 +1,24 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +#include "ICompressor.h" | |
4 | + | |
5 | +class BZip2Compressor : public ICompressor | |
6 | +{ | |
7 | +public: | |
8 | + // overrides | |
9 | + size_t Compress( | |
10 | + const unsigned char* src, | |
11 | + size_t srcLen, | |
12 | + unsigned char* dest, | |
13 | + size_t destLen | |
14 | + ); | |
15 | + | |
16 | + size_t Decompress( | |
17 | + const unsigned char* src, | |
18 | + size_t srcLen, | |
19 | + unsigned char* dest, | |
20 | + size_t destLen | |
21 | + ); | |
22 | + | |
23 | +}; | |
24 | + |
@@ -0,0 +1,20 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +class ICompressor | |
4 | +{ | |
5 | +public: | |
6 | + virtual size_t Compress( | |
7 | + const unsigned char* src, | |
8 | + size_t srcLen, | |
9 | + unsigned char* dest, | |
10 | + size_t destLen | |
11 | + ) = 0; | |
12 | + | |
13 | + virtual size_t Decompress( | |
14 | + const unsigned char* src, | |
15 | + size_t srcLen, | |
16 | + unsigned char* dest, | |
17 | + size_t destLen | |
18 | + ) = 0; | |
19 | +}; | |
20 | + |
@@ -0,0 +1,306 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +// http://en.wikipedia.org/wiki/Hadamard_transform | |
4 | + | |
5 | +// integer 4x4 forward Discrete Hadamard Transform | |
6 | +inline void dht_4x4(short d[4][4], short t[4][4]) | |
7 | +{ | |
8 | + for (size_t i=0; i<4; ++i) { | |
9 | + int s01 = d[i][0] + d[i][1]; | |
10 | + int d01 = d[i][0] - d[i][1]; | |
11 | + int s23 = d[i][2] + d[i][3]; | |
12 | + int d23 = d[i][2] - d[i][3]; | |
13 | + | |
14 | + t[0][i] = s01 + s23; | |
15 | + t[1][i] = s01 - s23; | |
16 | + t[2][i] = d01 - d23; | |
17 | + t[3][i] = d01 + d23; | |
18 | + } | |
19 | + | |
20 | + for (size_t i=0; i<4; ++i) { | |
21 | + int s01 = t[i][0] + t[i][1]; | |
22 | + int d01 = t[i][0] - t[i][1]; | |
23 | + int s23 = t[i][2] + t[i][3]; | |
24 | + int d23 = t[i][2] - t[i][3]; | |
25 | + | |
26 | + d[i][0] = s01 + s23; | |
27 | + d[i][1] = s01 - s23; | |
28 | + d[i][2] = d01 - d23; | |
29 | + d[i][3] = d01 + d23; | |
30 | + } | |
31 | +} | |
32 | + | |
33 | +inline void dht_8x8(int d[8][8], int t[8][8]) | |
34 | +{ | |
35 | +/* | |
36 | + | |
37 | +1 ---------------- | |
38 | +2 --------________ | |
39 | +3 ----________---- | |
40 | +4 ----____----____ | |
41 | +5 --____----____-- | |
42 | +6 --____--__----__ | |
43 | +7 --__--____--__-- | |
44 | +8 --__--__--__--__ | |
45 | + | |
46 | +*/ | |
47 | + for (size_t i=0; i<8; ++i) { | |
48 | + int s01 = d[i][0] + d[i][1]; | |
49 | + int d01 = d[i][0] - d[i][1]; | |
50 | + int s23 = d[i][2] + d[i][3]; | |
51 | + int d23 = d[i][2] - d[i][3]; | |
52 | + int s45 = d[i][4] + d[i][5]; | |
53 | + int d45 = d[i][4] - d[i][5]; | |
54 | + int s67 = d[i][6] + d[i][7]; | |
55 | + int d67 = d[i][6] - d[i][7]; | |
56 | + | |
57 | + int a0 = s01 + s23; | |
58 | + int a1 = s01 - s23; | |
59 | + int a2 = d01 + d23; | |
60 | + int a3 = d01 - d23; | |
61 | + int a4 = s45 + s67; | |
62 | + int a5 = s45 - s67; | |
63 | + int a6 = d45 + d67; | |
64 | + int a7 = d45 - d67; | |
65 | + | |
66 | + t[0][i] = a0 + a4; | |
67 | + t[1][i] = a0 - a4; | |
68 | + t[2][i] = a1 - a5; | |
69 | + t[3][i] = a1 + a5; | |
70 | + t[4][i] = a3 + a7; | |
71 | + t[5][i] = a3 - a7; | |
72 | + t[6][i] = a2 - a6; | |
73 | + t[7][i] = a2 + a6; | |
74 | + } | |
75 | + for (size_t i=0; i<8; ++i) { | |
76 | + int s01 = t[i][0] + t[i][1]; | |
77 | + int d01 = t[i][0] - t[i][1]; | |
78 | + int s23 = t[i][2] + t[i][3]; | |
79 | + int d23 = t[i][2] - t[i][3]; | |
80 | + int s45 = t[i][4] + t[i][5]; | |
81 | + int d45 = t[i][4] - t[i][5]; | |
82 | + int s67 = t[i][6] + t[i][7]; | |
83 | + int d67 = t[i][6] - t[i][7]; | |
84 | + | |
85 | + int a0 = s01 + s23; | |
86 | + int a1 = s01 - s23; | |
87 | + int a2 = d01 + d23; | |
88 | + int a3 = d01 - d23; | |
89 | + int a4 = s45 + s67; | |
90 | + int a5 = s45 - s67; | |
91 | + int a6 = d45 + d67; | |
92 | + int a7 = d45 - d67; | |
93 | + | |
94 | + d[i][0] = a0 + a4; | |
95 | + d[i][1] = a0 - a4; | |
96 | + d[i][2] = a1 - a5; | |
97 | + d[i][3] = a1 + a5; | |
98 | + d[i][4] = a3 + a7; | |
99 | + d[i][5] = a3 - a7; | |
100 | + d[i][6] = a2 - a6; | |
101 | + d[i][7] = a2 + a6; | |
102 | + } | |
103 | +} | |
104 | + | |
105 | +// integer 8x8 forward Discrete Cosine Transform | |
106 | +inline void dct_8x8(int d[8][8], int t[8][8]) | |
107 | +{ | |
108 | + // horizontal | |
109 | + for (size_t i=0; i<8; ++i) { | |
110 | + int p0 = d[i][0]; | |
111 | + int p1 = d[i][1]; | |
112 | + int p2 = d[i][2]; | |
113 | + int p3 = d[i][3]; | |
114 | + int p4 = d[i][4]; | |
115 | + int p5 = d[i][5]; | |
116 | + int p6 = d[i][6]; | |
117 | + int p7 = d[i][7]; | |
118 | + | |
119 | + int a0 = p0 + p7; | |
120 | + int a1 = p1 + p6; | |
121 | + int a2 = p2 + p5; | |
122 | + int a3 = p3 + p4; | |
123 | + | |
124 | + int b0 = (a0 + a3) << 1; | |
125 | + int b1 = (a1 + a2) << 1; | |
126 | + int b2 = (a0 - a3) << 1; | |
127 | + int b3 = (a1 - a2) << 1; | |
128 | + | |
129 | + a0 = p0 - p7; | |
130 | + a1 = p1 - p6; | |
131 | + a2 = p2 - p5; | |
132 | + a3 = p3 - p4; | |
133 | + | |
134 | + int b4 = ((a1 + a2) << 1) + (a0 * 3); | |
135 | + int b5 = ((a0 - a3) << 1) - (a2 * 3); | |
136 | + int b6 = ((a0 + a3) << 1) - (a1 * 3); | |
137 | + int b7 = ((a1 - a2) << 1) + (a3 * 3); | |
138 | + | |
139 | + t[i][0] = (b0 + b1) << 2; | |
140 | + t[i][1] = (b4 << 2) + b7; | |
141 | + t[i][2] = (b2 << 2) + (b3 << 1); | |
142 | + t[i][3] = (b5 << 2) + b6; | |
143 | + t[i][4] = (b0 - b1) << 2; | |
144 | + t[i][5] = (b6 << 2) - b5; | |
145 | + t[i][6] = (b2 << 1) - (b3 << 2); | |
146 | + t[i][7] = b4 - (b7 << 2); | |
147 | + } | |
148 | + // vertical | |
149 | + for (size_t i=0; i<8; ++i) { | |
150 | + int p0 = t[0][i]; | |
151 | + int p1 = t[1][i]; | |
152 | + int p2 = t[2][i]; | |
153 | + int p3 = t[3][i]; | |
154 | + int p4 = t[4][i]; | |
155 | + int p5 = t[5][i]; | |
156 | + int p6 = t[6][i]; | |
157 | + int p7 = t[7][i]; | |
158 | + | |
159 | + int a0 = p0 + p7; | |
160 | + int a1 = p1 + p6; | |
161 | + int a2 = p2 + p5; | |
162 | + int a3 = p3 + p4; | |
163 | + | |
164 | + int b0 = (a0 + a3) << 1; | |
165 | + int b1 = (a1 + a2) << 1; | |
166 | + int b2 = (a0 - a3) << 1; | |
167 | + int b3 = (a1 - a2) << 1; | |
168 | + | |
169 | + a0 = p0 - p7; | |
170 | + a1 = p1 - p6; | |
171 | + a2 = p2 - p5; | |
172 | + a3 = p3 - p4; | |
173 | + | |
174 | + int b4 = ((a1 + a2) << 1) + (a0 * 3); | |
175 | + int b5 = ((a0 - a3) << 1) - (a2 * 3); | |
176 | + int b6 = ((a0 + a3) << 1) - (a1 * 3); | |
177 | + int b7 = ((a1 - a2) << 1) + (a3 * 3); | |
178 | + | |
179 | + d[0][i] = (b0 + b1) << 2; | |
180 | + d[1][i] = (b4 << 2) + b7; | |
181 | + d[2][i] = (b2 << 2) + (b3 << 1); | |
182 | + d[3][i] = (b5 << 2) + b6; | |
183 | + d[4][i] = (b0 - b1) << 2; | |
184 | + d[5][i] = (b6 << 2) - b5; | |
185 | + d[6][i] = (b2 << 1) - (b3 << 2); | |
186 | + d[7][i] = b4 - (b7 << 2); | |
187 | + } | |
188 | +} | |
189 | + | |
190 | +// integer 8x8 inverse Discrete Cosine Transform | |
191 | +inline void idct_8x8(int d[8][8], int t[8][8]) | |
192 | +{ | |
193 | + // horizontal | |
194 | + for (size_t i=0; i<8; ++i) { | |
195 | + int p0 = d[i][0]; | |
196 | + int p1 = d[i][1]; | |
197 | + int p2 = d[i][2]; | |
198 | + int p3 = d[i][3]; | |
199 | + int p4 = d[i][4]; | |
200 | + int p5 = d[i][5]; | |
201 | + int p6 = d[i][6]; | |
202 | + int p7 = d[i][7]; | |
203 | + | |
204 | + int a0 = (p0 + p4) << 3; | |
205 | + int a1 = (p0 - p4) << 3; | |
206 | + int a2 = (p6 << 3) - (p2 << 2); | |
207 | + int a3 = (p2 << 3) + (p6 << 2); | |
208 | + | |
209 | + int b0 = a0 + a3; | |
210 | + int b2 = a1 - a2; | |
211 | + int b4 = a1 + a2; | |
212 | + int b6 = a0 - a3; | |
213 | + | |
214 | + a0 = ((-p3 + p5 - p7) << 1) - p7; | |
215 | + a1 = (( p1 + p7 - p3) << 1) - p3; | |
216 | + a2 = ((-p1 + p7 + p5) << 1) + p5; | |
217 | + a3 = (( p3 + p5 + p1) << 1) + p1; | |
218 | + | |
219 | + int b1 = (a0 << 2) + a3; | |
220 | + int b3 = (a1 << 2) + a2; | |
221 | + int b5 = (a2 << 2) - a1; | |
222 | + int b7 = (a3 << 2) - a0; | |
223 | + | |
224 | + t[i][0] = b0 + b7; | |
225 | + t[i][1] = b2 - b5; | |
226 | + t[i][2] = b4 + b3; | |
227 | + t[i][3] = b6 + b1; | |
228 | + t[i][4] = b6 - b1; | |
229 | + t[i][5] = b4 - b3; | |
230 | + t[i][6] = b2 + b5; | |
231 | + t[i][7] = b0 - b7; | |
232 | + } | |
233 | + // vertical | |
234 | + for (size_t i=0; i<8; ++i) { | |
235 | + int p0 = t[0][i]; | |
236 | + int p1 = t[1][i]; | |
237 | + int p2 = t[2][i]; | |
238 | + int p3 = t[3][i]; | |
239 | + int p4 = t[4][i]; | |
240 | + int p5 = t[5][i]; | |
241 | + int p6 = t[6][i]; | |
242 | + int p7 = t[7][i]; | |
243 | + | |
244 | + int a0 = (p0 + p4) << 3; | |
245 | + int a1 = (p0 - p4) << 3; | |
246 | + int a2 = (p6 << 3) - (p2 << 2); | |
247 | + int a3 = (p2 << 3) + (p6 << 2); | |
248 | + | |
249 | + int b0 = a0 + a3; | |
250 | + int b2 = a1 - a2; | |
251 | + int b4 = a1 + a2; | |
252 | + int b6 = a0 - a3; | |
253 | + | |
254 | + a0 = ((-p3 + p5 - p7) << 1) - p7; | |
255 | + a1 = (( p1 + p7 - p3) << 1) - p3; | |
256 | + a2 = ((-p1 + p7 + p5) << 1) + p5; | |
257 | + a3 = (( p3 + p5 + p1) << 1) + p1; | |
258 | + | |
259 | + int b1 = (a0 << 2) + a3; | |
260 | + int b3 = (a1 << 2) + a2; | |
261 | + int b5 = (a2 << 2) - a1; | |
262 | + int b7 = (a3 << 2) - a0; | |
263 | + | |
264 | + d[0][i] = b0 + b7; | |
265 | + d[1][i] = b2 - b5; | |
266 | + d[2][i] = b4 + b3; | |
267 | + d[3][i] = b6 + b1; | |
268 | + d[4][i] = b6 - b1; | |
269 | + d[5][i] = b4 - b3; | |
270 | + d[6][i] = b2 + b5; | |
271 | + d[7][i] = b0 - b7; | |
272 | + } | |
273 | +} | |
274 | + | |
275 | +/* | |
276 | + Y = (R + 2G + B) >> 2 | |
277 | + Co = (R - B) >> 1 | |
278 | + Cg = (-R + 2G - B) >> 2 | |
279 | +*/ | |
280 | +inline void RGB_2_YCoCg(short r, short g, short b, short& y, short& co, short& cg) | |
281 | +{ | |
282 | + assert(r <= 255); | |
283 | + assert(g <= 255); | |
284 | + assert(b <= 255); | |
285 | + y = r + 2 * g + b; | |
286 | + co = r - b; | |
287 | + cg = -r + 2 * g -b; | |
288 | +} | |
289 | + | |
290 | +/* | |
291 | + R = Y + Co - Cg | |
292 | + G = Y + Cg | |
293 | + B = Y - Co - Cg | |
294 | +*/ | |
295 | +inline void YCoCg_2_RGB(short y, short co, short cg, short& r, short& g, short& b) | |
296 | +{ | |
297 | + short ymcg = y - cg; | |
298 | + short co2 = 2 * co; | |
299 | + r = (ymcg + co2) >> 2; | |
300 | + g = (y + cg) >> 2; | |
301 | + b = (ymcg - co2) >> 2; | |
302 | + assert(r <= 255); | |
303 | + assert(g <= 255); | |
304 | + assert(b <= 255); | |
305 | +} | |
306 | + |
@@ -0,0 +1,130 @@ | ||
1 | +#include "stdafx.h" | |
2 | +#include "Quantizer.h" | |
3 | + | |
4 | +static const int quant8_scan[16] = { | |
5 | + 0,3,4,3, 3,1,5,1, 4,5,2,5, 3,1,5,1 | |
6 | +}; | |
7 | + | |
8 | +static const int dequant8_scale[6][6] = { | |
9 | + { 20, 18, 32, 19, 25, 24 }, | |
10 | + { 22, 19, 35, 21, 28, 26 }, | |
11 | + { 26, 23, 42, 24, 33, 31 }, | |
12 | + { 28, 25, 45, 26, 35, 33 }, | |
13 | + { 32, 28, 51, 30, 40, 38 }, | |
14 | + { 36, 32, 58, 34, 46, 43 }, | |
15 | +}; | |
16 | +static const int quant8_scale[6][6] = { | |
17 | + { 13107, 11428, 20972, 12222, 16777, 15481 }, | |
18 | + { 11916, 10826, 19174, 11058, 14980, 14290 }, | |
19 | + { 10082, 8943, 15978, 9675, 12710, 11985 }, | |
20 | + { 9362, 8228, 14913, 8931, 11984, 11259 }, | |
21 | + { 8192, 7346, 13159, 7740, 10486, 9777 }, | |
22 | + { 7282, 6428, 11570, 6830, 9118, 8640 } | |
23 | +}; | |
24 | + | |
25 | +static const unsigned char quant8_intra_matrix[8][8] = { | |
26 | + 6, 10, 13, 16, 18, 23, 25, 27, | |
27 | + 10, 11, 16, 18, 23, 25, 27, 29, | |
28 | + 13, 16, 18, 23, 25, 27, 29, 31, | |
29 | + 16, 18, 23, 25, 27, 29, 31, 33, | |
30 | + 18, 23, 25, 27, 29, 31, 33, 36, | |
31 | + 23, 25, 27, 29, 31, 33, 36, 38, | |
32 | + 25, 27, 29, 31, 33, 36, 38, 40, | |
33 | + 27, 29, 31, 33, 36, 38, 40, 42, | |
34 | +}; | |
35 | + | |
36 | +static const unsigned char quant8_inter_matrix[8][8] = { | |
37 | + 9, 13, 15, 17, 19, 21, 22, 24, | |
38 | + 13, 13, 17, 19, 21, 22, 24, 25, | |
39 | + 15, 17, 19, 21, 22, 24, 25, 27, | |
40 | + 17, 19, 21, 22, 24, 25, 27, 28, | |
41 | + 19, 21, 22, 24, 25, 27, 28, 30, | |
42 | + 21, 22, 24, 25, 27, 28, 30, 32, | |
43 | + 22, 24, 25, 27, 28, 30, 32, 33, | |
44 | + 24, 25, 27, 28, 30, 32, 33, 35, | |
45 | +}; | |
46 | + | |
47 | +namespace { | |
48 | + | |
49 | +int div(int n, int d) | |
50 | +{ | |
51 | + return (n + (d>>1)) / d; | |
52 | +} | |
53 | + | |
54 | +} | |
55 | + | |
56 | +void Quantizer::init(size_t qp, size_t hBlockness, size_t vBlockness, bool useQuantMatrix) | |
57 | +{ | |
58 | + QP = qp; | |
59 | + QP_shift = QP / 6; | |
60 | + QP_remain = QP % 6; | |
61 | + | |
62 | + for (size_t i=0; i<64; ++i) { | |
63 | + int j = quant8_scan[((i>>1)&12) | (i&3)]; | |
64 | +// printf("%d,", j); | |
65 | + quant8_table[i] = quant8_scale[QP_remain][j]; | |
66 | + dequant8_table[i] = dequant8_scale[QP_remain][j] << QP_shift; | |
67 | + } | |
68 | + | |
69 | + // 量子化テーブル操作 | |
70 | + for (size_t i=0; i<8; ++i) { | |
71 | + if (i>=(8-hBlockness)) { | |
72 | + for (size_t j=0; j<8; ++j) { | |
73 | + quant8_table[j*8+i] = 0; | |
74 | + } | |
75 | + } | |
76 | + if (i>=(8-vBlockness)) { | |
77 | + for (size_t j=0; j<8; ++j) { | |
78 | + quant8_table[i*8+j] = 0; | |
79 | + } | |
80 | + } | |
81 | + } | |
82 | + | |
83 | + // 高周波を荒くする量子化マトリクスを適用 | |
84 | + if (useQuantMatrix) { | |
85 | + for (size_t i=0; i<8; ++i) { | |
86 | + for (size_t j=0; j<8; ++j) { | |
87 | + quant8_table[i*8+j] = div(quant8_table[i*8+j] << 4, quant8_intra_matrix[i][j]); | |
88 | + dequant8_table[i*8+j] *= quant8_intra_matrix[i][j]; | |
89 | + } | |
90 | + } | |
91 | + }else { | |
92 | + for (size_t i=0; i<8*8; ++i) { | |
93 | + quant8_table[i] = quant8_table[i]; | |
94 | + dequant8_table[i] <<= 4; | |
95 | + } | |
96 | + } | |
97 | + | |
98 | +} | |
99 | + | |
100 | +void Quantizer::quantize(int values[8][8]) | |
101 | +{ | |
102 | + for (size_t i=0; i<8; ++i) { | |
103 | + for (size_t j=0; j<8; ++j) { | |
104 | + int value = values[i][j]; | |
105 | + if (value == 0) { | |
106 | + continue; | |
107 | + }else if (value > 0) { | |
108 | + value += (1 << 5); | |
109 | + }else { | |
110 | + value -= (1 << 5); | |
111 | + } | |
112 | + value >>= 6; | |
113 | + value *= quant8_table[i*8+j]; | |
114 | + value += (1 << (11+QP_shift)); | |
115 | + value >>= (12+QP_shift); | |
116 | +// assert(value >= -32768 && value <= 32767); | |
117 | + values[i][j] = value; | |
118 | + } | |
119 | + } | |
120 | +} | |
121 | + | |
122 | +void Quantizer::dequantize(int values[8][8]) | |
123 | +{ | |
124 | + for (size_t i=0; i<8; ++i) { | |
125 | + for (size_t j=0; j<8; ++j) { | |
126 | + values[i][j] *= dequant8_table[i*8+j]; | |
127 | + } | |
128 | + } | |
129 | +} | |
130 | + |
@@ -0,0 +1,87 @@ | ||
1 | +#include "stdafx.h" | |
2 | + | |
3 | +#include <assert.h> | |
4 | + | |
5 | +#include "dct.h" | |
6 | +#include "Quantizer.h" | |
7 | + | |
8 | +#include <vector> | |
9 | +#include <algorithm> | |
10 | +#include <cmath> | |
11 | + | |
12 | +#include <boost/integer_traits.hpp> | |
13 | +#include "BZip2Compressor.h" | |
14 | +#include "misc.h" | |
15 | +#include "decode.h" | |
16 | +#include "encode.h" | |
17 | + | |
18 | +#include "ReadImage/ReadImage.h" | |
19 | +#include "ReadImage/File.h" | |
20 | + | |
21 | +int _tmain(int argc, _TCHAR* argv[]) | |
22 | +{ | |
23 | + if (argc < 2) { | |
24 | + _tprintf(_T("specify filename\n")); | |
25 | + return 1; | |
26 | + } | |
27 | + | |
28 | + FILE* f = _tfopen(argv[1], _T("rb")); | |
29 | + if (!f) { | |
30 | + _tprintf(_T("failed to open file : %s\n"), argv[1]); | |
31 | + return 1; | |
32 | + } | |
33 | + File fo(f); | |
34 | + ImageInfo imageInfo; | |
35 | + ReadImageInfo(fo, imageInfo); | |
36 | + | |
37 | + size_t width = imageInfo.width; | |
38 | + size_t height = imageInfo.height; | |
39 | + assert(imageInfo.bitsPerSample == 8 && imageInfo.samplesPerPixel == 1); | |
40 | + const size_t size = width * height; | |
41 | + std::vector<unsigned char> in(size); | |
42 | + std::vector<int> work(size); | |
43 | + std::vector<int> work2(size); | |
44 | + std::vector<unsigned char> out(size); | |
45 | + | |
46 | + unsigned char palettes[256 * 4]; | |
47 | + ReadImageData(fo, &in[0], width, palettes); | |
48 | + fclose(f); | |
49 | + | |
50 | + for (size_t i=0; i<size; ++i) { | |
51 | + in[i] = palettes[4 * in[i]]; | |
52 | + } | |
53 | + | |
54 | + Quantizer quantizer; | |
55 | + quantizer.init(6*8+0, 0, 0, true); | |
56 | + | |
57 | + const size_t hBlockCount = width / 8 + ((width % 8) ? 1 : 0); | |
58 | + const size_t vBlockCount = height / 8 + ((height % 8) ? 1 : 0); | |
59 | + const size_t totalBlockCount = hBlockCount * vBlockCount; | |
60 | + | |
61 | + encode(quantizer, hBlockCount, vBlockCount, &in[0], width, &work[0], width*sizeof(int)); | |
62 | + int* pWork = &work[0]; | |
63 | + | |
64 | + BZip2Compressor compressor; | |
65 | + size_t compressedLen = 0; | |
66 | + | |
67 | + size_t storageSize = work.size()*4*1.1+600; | |
68 | + std::vector<unsigned char> work3(storageSize); | |
69 | + std::vector<unsigned char> compressed(storageSize); | |
70 | + compressedLen = compress(compressor, hBlockCount, vBlockCount, &work[0], &work2[0], &work3[0], work3.size(), &compressed[0], compressed.size()); | |
71 | + | |
72 | + std::fill(work.begin(), work.end(), 0); | |
73 | + std::fill(work2.begin(), work2.end(), 0); | |
74 | + | |
75 | + std::vector<unsigned char> tmp(compressed.size()); | |
76 | + decompress(compressor, hBlockCount, vBlockCount, &compressed[0], compressedLen, &tmp[0], &work[0], &work2[0], work2.size()); | |
77 | + | |
78 | + decode(quantizer, hBlockCount, vBlockCount, &work2[0], width*sizeof(int), &out[0], width); | |
79 | + unsigned char* pOutput = &out[0]; | |
80 | + | |
81 | + //FILE* of = _tfopen(_T("out.raw"), _T("wb")); | |
82 | + //fwrite(pOutput, 1, size, of); | |
83 | + //fclose(of); | |
84 | + | |
85 | + _tprintf(_T("%f%% %d bytes"), (100.0 * compressedLen) / size, compressedLen); | |
86 | + return 0; | |
87 | +} |
@@ -0,0 +1,18 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +class Quantizer | |
4 | +{ | |
5 | +public: | |
6 | + void init(size_t qp, size_t hBlockness, size_t vBlockness, bool useQuantMatrix); | |
7 | + | |
8 | + void quantize(int values[8][8]); | |
9 | + void dequantize(int values[8][8]); | |
10 | +private: | |
11 | + int quant8_table[64]; | |
12 | + int dequant8_table[64]; | |
13 | + | |
14 | + size_t QP; | |
15 | + size_t QP_shift; | |
16 | + size_t QP_remain; | |
17 | +}; | |
18 | + |
@@ -0,0 +1,82 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +template <int shifts, typename T> | |
4 | +T div(T value) | |
5 | +{ | |
6 | + return (value + (1 << (shifts - 1))) >> shifts; | |
7 | +} | |
8 | + | |
9 | + | |
10 | +void decodeRightMostColumn(Quantizer& quantizer, int* rows, int values[8][8], int tmps[8][8]) | |
11 | +{ | |
12 | + quantizer.dequantize(values); | |
13 | + idct_8x8(values, tmps); | |
14 | + for (size_t i=0; i<8; ++i) { | |
15 | + rows[i] = div<22>(values[i][7]); | |
16 | + } | |
17 | +} | |
18 | + | |
19 | +void decodeBottomRow(Quantizer& quantizer, int* cols, int values[8][8], int tmps[8][8]) | |
20 | +{ | |
21 | + quantizer.dequantize(values); | |
22 | + idct_8x8(values, tmps); | |
23 | + for (size_t i=0; i<8; ++i) { | |
24 | + cols[i] = div<22>(values[7][i]); | |
25 | + } | |
26 | +} | |
27 | + | |
28 | +void decodeRightMostColumnAndBottomRow(Quantizer& quantizer, int* rows, int* cols, int values[8][8], int tmps[8][8]) | |
29 | +{ | |
30 | + quantizer.dequantize(values); | |
31 | + idct_8x8(values, tmps); | |
32 | + | |
33 | + for (size_t i=0; i<8; ++i) { | |
34 | + rows[i] = div<22>(values[i][7]); | |
35 | + } | |
36 | + for (size_t i=0; i<8; ++i) { | |
37 | + cols[i] = div<22>(values[7][i]); | |
38 | + } | |
39 | +} | |
40 | + | |
41 | +template <typename T> | |
42 | +void decode( | |
43 | + Quantizer& quantizer, | |
44 | + size_t hBlocks, size_t vBlocks, | |
45 | + const int* in, int inLineOffsetBytes, | |
46 | + T* out, int outLineOffsetBytes | |
47 | + ) | |
48 | +{ | |
49 | + int values[8][8]; | |
50 | + int tmps[8][8]; | |
51 | + | |
52 | + const int* src = in; | |
53 | + T* dest = out; | |
54 | + | |
55 | + for (size_t y=0; y<vBlocks; ++y) { | |
56 | + | |
57 | + const int* srcLine = src; | |
58 | + T* destLine = dest; | |
59 | + | |
60 | + for (size_t x=0; x<hBlocks; ++x) { | |
61 | + | |
62 | + gather(srcLine, inLineOffsetBytes, values); | |
63 | + | |
64 | + quantizer.dequantize(values); | |
65 | + idct_8x8(values, tmps); | |
66 | + for (size_t i=0; i<8; ++i) { | |
67 | + for (size_t j=0; j<8; ++j) { | |
68 | + values[i][j] = div<22>(values[i][j]); | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + scatter(destLine, outLineOffsetBytes, values); | |
73 | + | |
74 | + srcLine += 8; | |
75 | + destLine += 8; | |
76 | + } | |
77 | + | |
78 | + OffsetPtr(src, inLineOffsetBytes*8); | |
79 | + OffsetPtr(dest, outLineOffsetBytes*8); | |
80 | + } | |
81 | +} | |
82 | + |
@@ -0,0 +1,8 @@ | ||
1 | +// stdafx.cpp : 標準インクルード ImageCompression.pch のみを | |
2 | +// 含むソース ファイルは、プリコンパイル済みヘッダーになります。 | |
3 | +// stdafx.obj にはプリコンパイル済み型情報が含まれます。 | |
4 | + | |
5 | +#include "stdafx.h" | |
6 | + | |
7 | +// TODO: このファイルではなく、STDAFX.H で必要な | |
8 | +// 追加ヘッダーを参照してください。 |
@@ -0,0 +1,111 @@ | ||
1 | +#include "stdafx.h" | |
2 | + | |
3 | +#include "ReadImage.h" | |
4 | + | |
5 | +#define TRACE printf | |
6 | +#include <assert.h> | |
7 | + | |
8 | +#include <windows.h> | |
9 | + | |
10 | +bool Read_BITMAPINFOHEADER(IFile& file, BITMAPINFOHEADER& bmih) | |
11 | +{ | |
12 | + size_t fileSize = file.Size(); | |
13 | + if (fileSize <= 54) { | |
14 | + TRACE("file size <= 54 bytes."); | |
15 | + return false; | |
16 | + } | |
17 | + BITMAPFILEHEADER bmpFileHeader; | |
18 | + size_t readBytes = 0; | |
19 | + file.Read(&bmpFileHeader, 14, readBytes); | |
20 | + assert(readBytes == 14); | |
21 | + if (bmpFileHeader.bfType != 19778) { | |
22 | + TRACE("file hedear bfType != 19778"); | |
23 | + return false; | |
24 | + } | |
25 | + | |
26 | + file.Read(&bmih, 40, readBytes); | |
27 | + if (readBytes != 40) { | |
28 | + TRACE("bmih shortage."); | |
29 | + return false; | |
30 | + } | |
31 | + | |
32 | + return true; | |
33 | +} | |
34 | + | |
35 | +bool ReadImageInfo_BMP(IFile& file, ImageInfo& info) | |
36 | +{ | |
37 | + BITMAPINFOHEADER bmih; | |
38 | + if (!Read_BITMAPINFOHEADER(file, bmih)) { | |
39 | + return false; | |
40 | + } | |
41 | + info.width = bmih.biWidth; | |
42 | + info.height = bmih.biHeight; | |
43 | + info.bitsPerSample = 8; | |
44 | + info.samplesPerPixel = 1; | |
45 | + return true; | |
46 | +} | |
47 | + | |
48 | +bool ReadImageData_BMP(IFile& file, unsigned char* dest, int lineOffset, void* palettes) | |
49 | +{ | |
50 | + file.Seek(0, FILE_BEGIN); | |
51 | + BITMAPINFOHEADER bmih; | |
52 | + if (!Read_BITMAPINFOHEADER(file, bmih)) { | |
53 | + return false; | |
54 | + } | |
55 | + size_t bmiColorsLen = 0; | |
56 | + switch (bmih.biBitCount) { | |
57 | + case 1: | |
58 | + bmiColorsLen = 2; | |
59 | + break; | |
60 | + case 4: | |
61 | + bmiColorsLen = 16; | |
62 | + break; | |
63 | + case 8: | |
64 | + bmiColorsLen = 256; | |
65 | + break; | |
66 | + case 16: | |
67 | + TRACE("16 bit BMP not supported."); | |
68 | + return false; | |
69 | + break; | |
70 | + case 32: | |
71 | + if (bmih.biCompression == BI_BITFIELDS) { | |
72 | + bmiColorsLen = 3; | |
73 | + } | |
74 | + } | |
75 | + size_t readBytes = 0; | |
76 | + if (bmiColorsLen) { | |
77 | + size_t needBytes = /*sizeof(RGBQUAD)*/4*bmiColorsLen; | |
78 | + file.Read(palettes, needBytes, readBytes); | |
79 | + if (readBytes != needBytes) { | |
80 | + TRACE("bmiColors read failed."); | |
81 | + return false; | |
82 | + } | |
83 | + } | |
84 | + const int lineBytes = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3); | |
85 | + const int lineIdx = (bmih.biHeight < 0) ? 0 : (bmih.biHeight-1); | |
86 | + OffsetPtr(dest, lineOffset * lineIdx); | |
87 | + lineOffset *= (bmih.biHeight < 0) ? 1 : -1; | |
88 | + | |
89 | + const size_t height = abs(bmih.biHeight); | |
90 | + for (size_t y=0; y<height; ++y) { | |
91 | + file.Read(dest, lineBytes, readBytes); | |
92 | + if (readBytes != lineBytes) { | |
93 | + TRACE("read bytes != lineBytes."); | |
94 | + return false; | |
95 | + } | |
96 | + OffsetPtr(dest, lineOffset); | |
97 | + } | |
98 | + | |
99 | + return true; | |
100 | +} | |
101 | + | |
102 | +bool ReadImageInfo(IFile& file, ImageInfo& info) | |
103 | +{ | |
104 | + return ReadImageInfo_BMP(file, info); | |
105 | +} | |
106 | + | |
107 | +bool ReadImageData(IFile& file, unsigned char* dest, int lineOffset, void* palettes) | |
108 | +{ | |
109 | + return ReadImageData_BMP(file, dest, lineOffset, palettes); | |
110 | +} | |
111 | + |
@@ -0,0 +1,60 @@ | ||
1 | +#include "stdafx.h" | |
2 | +#include "File.h" | |
3 | + | |
4 | +#include <io.h> | |
5 | +#include <assert.h> | |
6 | +#include <memory.h> | |
7 | +#include <stdio.h> | |
8 | + | |
9 | +#include <windows.h> | |
10 | + | |
11 | +File::File(HANDLE hFile) | |
12 | + : | |
13 | + hFile_(hFile) | |
14 | +{ | |
15 | +} | |
16 | + | |
17 | +File::File(FILE* pFile) | |
18 | +{ | |
19 | + hFile_ = (HANDLE) _get_osfhandle(_fileno(pFile)); | |
20 | +} | |
21 | + | |
22 | +bool File::Read(void* pBuffer, size_t nNumberOfBytesToRead, size_t& nNumberOfBytesRead) | |
23 | +{ | |
24 | + return ReadFile(hFile_, pBuffer, nNumberOfBytesToRead, (LPDWORD)&nNumberOfBytesRead, NULL); | |
25 | +} | |
26 | + | |
27 | +bool File::Write(const void* pBuffer, size_t nNumberOfBytesToWrite, size_t& nNumberOfBytesWritten) | |
28 | +{ | |
29 | + return WriteFile(hFile_, pBuffer, nNumberOfBytesToWrite, (LPDWORD)&nNumberOfBytesWritten, NULL); | |
30 | +} | |
31 | + | |
32 | +size_t File::Seek(long lDistanceToMove, size_t dwMoveMethod) | |
33 | +{ | |
34 | + return SetFilePointer(hFile_, lDistanceToMove, NULL, dwMoveMethod); | |
35 | +} | |
36 | + | |
37 | +size_t File::Tell() const | |
38 | +{ | |
39 | + /* | |
40 | + -- Reference -- | |
41 | + http://nukz.net/reference/fileio/hh/winbase/filesio_3vhu.htm | |
42 | + */ | |
43 | + return SetFilePointer( | |
44 | + hFile_, // must have GENERIC_READ and/or GENERIC_WRITE | |
45 | + 0, // do not move pointer | |
46 | + NULL, // hFile is not large enough to need this pointer | |
47 | + FILE_CURRENT | |
48 | + ); // provides offset from current position | |
49 | +} | |
50 | + | |
51 | +size_t File::Size() const | |
52 | +{ | |
53 | + return GetFileSize(hFile_, NULL); | |
54 | +} | |
55 | + | |
56 | +bool File::Flush() | |
57 | +{ | |
58 | + return FlushFileBuffers(hFile_); | |
59 | +} | |
60 | + |
@@ -0,0 +1,15 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +#include "IFile.h" | |
4 | + | |
5 | +struct ImageInfo | |
6 | +{ | |
7 | + size_t width; | |
8 | + size_t height; | |
9 | + size_t bitsPerSample; | |
10 | + size_t samplesPerPixel; | |
11 | +}; | |
12 | + | |
13 | +bool ReadImageInfo(IFile& file, ImageInfo& info); | |
14 | +bool ReadImageData(IFile& file, unsigned char* dest, int lineOffset, void* palettes); | |
15 | + |
@@ -0,0 +1,33 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +#include "IFile.h" | |
4 | + | |
5 | +#include <windows.h> | |
6 | +#include <stdio.h> | |
7 | + | |
8 | +class File : public IFile | |
9 | +{ | |
10 | +public: | |
11 | + File(HANDLE hFile); | |
12 | + | |
13 | + File(FILE* pFile); | |
14 | + | |
15 | + bool Read(void* pBuffer, size_t nNumberOfBytesToRead, size_t& nNumberOfBytesRead); | |
16 | + | |
17 | + bool Write(const void* pBuffer, size_t nNumberOfBytesToWrite, size_t& nNumberOfBytesWritten); | |
18 | + | |
19 | + size_t Seek(long lDistanceToMove, size_t dwMoveMethod); | |
20 | + | |
21 | + size_t Tell() const; | |
22 | + | |
23 | + size_t Size() const; | |
24 | + | |
25 | + bool Flush(); | |
26 | + | |
27 | + bool HasBuffer() const { return false; } | |
28 | + virtual const void* GetBuffer() const { return 0; } | |
29 | + | |
30 | +private: | |
31 | + HANDLE hFile_; | |
32 | +}; | |
33 | + |
@@ -0,0 +1,33 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +/*! | |
4 | + | |
5 | +概要 | |
6 | + 画像の入出力用に仮想的にFileを扱えるようにする | |
7 | + | |
8 | +制限 | |
9 | + 非同期操作には対応しない | |
10 | + 2GBまで | |
11 | + | |
12 | +備考 | |
13 | + CxImage by Davide Pizzolato (http://www.xdp.it/cximage.htm) を参考にしました。 | |
14 | + | |
15 | + InterfaceをWindowsAPIのFile関数に似せています | |
16 | + | |
17 | +*/ | |
18 | + | |
19 | +class IFile | |
20 | +{ | |
21 | +public: | |
22 | + virtual bool Read(void* pBuffer, size_t nNumberOfBytesToRead, size_t& nNumberOfBytesRead) = 0; | |
23 | + virtual bool Write(const void* pBuffer, size_t nNumberOfBytesToWrite, size_t& nNumberOfBytesWritten) = 0; | |
24 | + virtual size_t Seek(long lDistanceToMove, size_t dwMoveMethod) = 0; | |
25 | + virtual size_t Tell() const = 0; | |
26 | + virtual size_t Size() const = 0; | |
27 | + virtual bool IsEof() const { return Tell() == Size(); } | |
28 | + virtual bool Flush() = 0; | |
29 | + | |
30 | + virtual bool HasBuffer() const = 0; | |
31 | + virtual const void* GetBuffer() const = 0; | |
32 | +}; | |
33 | + |