• R/O
  • SSH
  • HTTPS

jyeipegyuu: Commit


Commit MetaInfo

Revision4 (tree)
Time2009-04-05 21:08:23
Authorberupon

Log Message

既に他の場所で公開済みのImageCompressionのプロジェクトを取り込み。

Change Summary

Incremental Difference

--- stdafx.h (nonexistent)
+++ stdafx.h (revision 4)
@@ -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: プログラムに必要な追加ヘッダーをここで参照してください。
--- IntraPrediction.cpp (nonexistent)
+++ IntraPrediction.cpp (revision 4)
@@ -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+
--- misc.h (nonexistent)
+++ misc.h (revision 4)
@@ -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+
--- encode.h (nonexistent)
+++ encode.h (revision 4)
@@ -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+
--- BZip2Compressor.cpp (nonexistent)
+++ BZip2Compressor.cpp (revision 4)
@@ -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+
--- IntraPrediction.h (nonexistent)
+++ IntraPrediction.h (revision 4)
@@ -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+
--- targetver.h (nonexistent)
+++ targetver.h (revision 4)
@@ -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+
--- BZip2Compressor.h (nonexistent)
+++ BZip2Compressor.h (revision 4)
@@ -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+
--- ICompressor.h (nonexistent)
+++ ICompressor.h (revision 4)
@@ -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+
--- dct.h (nonexistent)
+++ dct.h (revision 4)
@@ -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+
--- Quantizer.cpp (nonexistent)
+++ Quantizer.cpp (revision 4)
@@ -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+
--- main.cpp (nonexistent)
+++ main.cpp (revision 4)
@@ -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+}
--- Quantizer.h (nonexistent)
+++ Quantizer.h (revision 4)
@@ -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+
--- decode.h (nonexistent)
+++ decode.h (revision 4)
@@ -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+
--- stdafx.cpp (nonexistent)
+++ stdafx.cpp (revision 4)
@@ -0,0 +1,8 @@
1+// stdafx.cpp : 標準インクルード ImageCompression.pch のみを
2+// 含むソース ファイルは、プリコンパイル済みヘッダーになります。
3+// stdafx.obj にはプリコンパイル済み型情報が含まれます。
4+
5+#include "stdafx.h"
6+
7+// TODO: このファイルではなく、STDAFX.H で必要な
8+// 追加ヘッダーを参照してください。
--- ReadImage/ReadImage.cpp (nonexistent)
+++ ReadImage/ReadImage.cpp (revision 4)
@@ -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+
--- ReadImage/File.cpp (nonexistent)
+++ ReadImage/File.cpp (revision 4)
@@ -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+
--- ReadImage/ReadImage.h (nonexistent)
+++ ReadImage/ReadImage.h (revision 4)
@@ -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+
--- ReadImage/File.h (nonexistent)
+++ ReadImage/File.h (revision 4)
@@ -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+
--- ReadImage/IFile.h (nonexistent)
+++ ReadImage/IFile.h (revision 4)
@@ -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+
Show on old repository browser