処理の分割、再配置
@@ -29,33 +29,6 @@ | ||
29 | 29 | } |
30 | 30 | } |
31 | 31 | |
32 | -void cutoff( | |
33 | - size_t hBlockCount, size_t vBlockCount, | |
34 | - int* data, int lineOffsetBytes, | |
35 | - const int table[8][8] | |
36 | - ) | |
37 | -{ | |
38 | - | |
39 | - int* srcLine = data; | |
40 | - for (size_t y=0; y<vBlockCount; ++y) { | |
41 | - int* workSrcLine = srcLine; | |
42 | - for (size_t yi=0; yi<8; ++yi) { | |
43 | - int* pWork = workSrcLine; | |
44 | - const int* tableLine = table[yi]; | |
45 | - for (size_t x=0; x<hBlockCount; ++x) { | |
46 | - for (size_t xi=0; xi<8; ++xi) { | |
47 | - int value = *pWork; | |
48 | - int newValue = std::min(tableLine[xi], std::abs(value)); | |
49 | - *pWork = (value < 0) ? -newValue : newValue; | |
50 | - ++pWork; | |
51 | - } | |
52 | - } | |
53 | - OffsetPtr(workSrcLine, lineOffsetBytes); | |
54 | - } | |
55 | - OffsetPtr(srcLine, lineOffsetBytes * 8); | |
56 | - } | |
57 | -} | |
58 | - | |
59 | 32 | int paethPredictor(int left, int above, int upperLeft) |
60 | 33 | { |
61 | 34 | int initial = left + (above - upperLeft); |
@@ -300,49 +273,15 @@ | ||
300 | 273 | |
301 | 274 | assert(destLen > 4); |
302 | 275 | |
303 | - int mini = boost::integer_traits<int>::const_max; | |
304 | - int maxi = boost::integer_traits<int>::const_min; | |
276 | + int mini = cinfo.mini; | |
277 | + int maxi = cinfo.maxi; | |
278 | + size_t max = std::max(maxi, std::abs(mini)); | |
305 | 279 | |
306 | 280 | int* hists = cinfo.hists; |
307 | 281 | int* phists = cinfo.phists; |
308 | 282 | int* mhists = cinfo.mhists; |
309 | - int zeroRepeat = 0; | |
310 | - int* zeroRepeatHist = cinfo.zeroRepeatHist; | |
311 | - BitWriter signFlags(dest+4); | |
312 | - for (size_t i=0; i<srcCount; ++i) { | |
313 | - int val = src[i]; | |
314 | - mini = std::min(val, mini); | |
315 | - maxi = std::max(val, maxi); | |
316 | - if (val == 0) { | |
317 | - ++zeroRepeat; | |
318 | - }else { | |
319 | - signFlags.putBit(val > 0); | |
320 | - ++zeroRepeatHist[zeroRepeat]; | |
321 | - zeroRepeat = 0; | |
322 | - } | |
323 | - if (val >= 0) { | |
324 | - ++phists[val]; | |
325 | - }else { | |
326 | - ++mhists[-val]; | |
327 | - } | |
328 | - val = std::abs(val); | |
329 | - src[i] = val; | |
330 | - | |
331 | - ++hists[val]; | |
332 | - } | |
333 | - if (zeroRepeat) { | |
334 | - ++zeroRepeatHist[zeroRepeat]; | |
335 | - zeroRepeat = 0; | |
336 | - } | |
337 | 283 | |
338 | - uint32_t signFlagsLen = signFlags.nBytes(); | |
339 | - *((size_t*)dest) = signFlagsLen; | |
340 | - | |
341 | - dest += (4 + signFlagsLen); | |
342 | - destLen -= (4 + signFlagsLen); | |
343 | - | |
344 | 284 | int b = 0; |
345 | - size_t max = std::max(maxi, std::abs(mini)); | |
346 | 285 | |
347 | 286 | if (max > 2048) { |
348 | 287 | b = 7; |
@@ -421,9 +360,8 @@ | ||
421 | 360 | dest += len; |
422 | 361 | |
423 | 362 | size_t destDiff = dest - initialDest; |
424 | - | |
363 | + | |
425 | 364 | cinfo.srcCount = srcCount; |
426 | - cinfo.signFlagsLen = signFlagsLen; | |
427 | 365 | cinfo.mini = mini; |
428 | 366 | cinfo.maxi = maxi; |
429 | 367 | cinfo.max = max; |
@@ -437,30 +375,18 @@ | ||
437 | 375 | return destDiff; |
438 | 376 | } |
439 | 377 | |
440 | -size_t compress( | |
441 | - ICompressor& compressor, | |
378 | +void paethPredictEncode( | |
442 | 379 | size_t hBlockCount, |
443 | 380 | size_t vBlockCount, |
444 | - const unsigned char* pZeroOneInfos, | |
445 | - size_t zeroOneLimit, | |
446 | - CompressInfo compressInfos[8], | |
447 | 381 | int* src, |
448 | - unsigned char* tmp1, | |
449 | - unsigned char* tmp2, | |
450 | - unsigned char* tmp3, | |
451 | - unsigned char* dest, size_t destLen | |
382 | + int* tmp | |
452 | 383 | ) |
453 | 384 | { |
454 | 385 | const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); |
455 | - | |
456 | - int* from = src; | |
457 | - | |
458 | - size_t progress = 0; | |
459 | 386 | |
460 | - // DC | |
461 | - | |
462 | 387 | // paeth prediction |
463 | - int* to = (int*) tmp3; | |
388 | + int* from = src; | |
389 | + int* to = tmp; | |
464 | 390 | std::copy(from, from+totalBlockCount, to); |
465 | 391 | // first row |
466 | 392 | int left = *to; |
@@ -494,20 +420,138 @@ | ||
494 | 420 | } |
495 | 421 | fromLineOffset += hBlockCount; |
496 | 422 | } |
423 | + std::copy(tmp, tmp+totalBlockCount, src); | |
424 | +} | |
425 | + | |
426 | +void paethPredictDecode( | |
427 | + size_t hBlockCount, | |
428 | + size_t vBlockCount, | |
429 | + int* src, | |
430 | + int* tmp | |
431 | + ) | |
432 | +{ | |
433 | + const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
497 | 434 | |
498 | - to -= totalBlockCount; | |
499 | - progress += compressSub(compressor, to, 0, totalBlockCount, 1, dest+progress, destLen-progress, tmp1, tmp2, compressInfos[0]); | |
500 | - from += totalBlockCount; | |
435 | + int* to = tmp; | |
436 | + std::copy(src,src+totalBlockCount, to); | |
501 | 437 | |
502 | - // zero one flags | |
503 | - BitWriter bw(dest+progress); | |
504 | - for (size_t i=0; i<totalBlockCount; ++i) { | |
505 | - bw.putBit(pZeroOneInfos[i]); | |
438 | + // paeth predictor to DC0 | |
439 | + // first row | |
440 | + int left = *to; | |
441 | + int above = 0; | |
442 | + int upperLeft = 0; | |
443 | + int cur = 0; | |
444 | + | |
445 | + int writePos; | |
446 | + writePos = 1; | |
447 | + for (size_t i=1; i<hBlockCount; ++i) { | |
448 | + cur = to[writePos] + left; | |
449 | + to[writePos] = cur; | |
450 | + left = cur; | |
451 | + ++writePos; | |
506 | 452 | } |
507 | - progress += bw.nBytes(); | |
453 | + int toLineOffset = hBlockCount; | |
454 | + int paeth = 0; | |
455 | + for (size_t y=1; y<vBlockCount; ++y) { | |
456 | + above = to[toLineOffset - hBlockCount]; | |
457 | + paeth = to[toLineOffset]; | |
458 | + cur = paeth + paethPredictor(0, above, 0); | |
459 | + to[toLineOffset] = cur; | |
460 | + writePos = toLineOffset + 1; | |
461 | + left = cur; | |
462 | + upperLeft = above; | |
463 | + for (size_t x=1; x<hBlockCount; ++x) { | |
464 | + above = to[writePos - hBlockCount]; | |
465 | + paeth = to[writePos]; | |
466 | + cur = paeth + paethPredictor(left, above, upperLeft); | |
467 | + to[writePos] = cur; | |
468 | + left = cur; | |
469 | + upperLeft = above; | |
470 | + ++writePos; | |
471 | + } | |
472 | + toLineOffset += hBlockCount; | |
473 | + } | |
474 | + | |
475 | + std::copy(to, to+totalBlockCount, src); | |
476 | + | |
477 | +} | |
478 | + | |
479 | +size_t collectInfos( | |
480 | + int* src, | |
481 | + size_t blockCount, | |
482 | + unsigned char* signFlags, | |
483 | + CompressInfo compressInfos[8] | |
484 | + ) | |
485 | +{ | |
486 | + size_t count = 0; | |
487 | + int* from = src; | |
488 | + for (size_t i=0; i<8; ++i) { | |
489 | + size_t blockSize = 1 + i * 2; | |
490 | + CompressInfo& ci = compressInfos[i]; | |
491 | + | |
492 | + int mini = boost::integer_traits<int>::const_max; | |
493 | + int maxi = boost::integer_traits<int>::const_min; | |
494 | + | |
495 | + int* hists = ci.hists; | |
496 | + int* phists = ci.phists; | |
497 | + int* mhists = ci.mhists; | |
498 | + int zeroRepeat = 0; | |
499 | + int* zeroRepeatHist = ci.zeroRepeatHist; | |
500 | + size_t srcCount = blockCount * blockSize; | |
501 | + for (size_t j=0; j<srcCount; ++j) { | |
502 | + int val = from[j]; | |
503 | + mini = std::min(val, mini); | |
504 | + maxi = std::max(val, maxi); | |
505 | + if (val == 0) { | |
506 | + ++zeroRepeat; | |
507 | + }else { | |
508 | + signFlags[count++] = (val > 0) ? 255 : 0; | |
509 | + ++zeroRepeatHist[zeroRepeat]; | |
510 | + zeroRepeat = 0; | |
511 | + } | |
512 | + if (val >= 0) { | |
513 | + ++phists[val]; | |
514 | + }else { | |
515 | + ++mhists[-val]; | |
516 | + } | |
517 | + val = std::abs(val); | |
518 | + from[j] = val; | |
519 | + | |
520 | + ++hists[val]; | |
521 | + } | |
522 | + if (zeroRepeat) { | |
523 | + ++zeroRepeatHist[zeroRepeat]; | |
524 | + zeroRepeat = 0; | |
525 | + } | |
526 | + ci.mini = mini; | |
527 | + ci.maxi = maxi; | |
528 | + ci.max = std::max(maxi, std::abs(mini)); | |
529 | + | |
530 | + from += srcCount; | |
531 | + } | |
532 | + return count; | |
533 | +} | |
534 | + | |
535 | +size_t compress( | |
536 | + ICompressor& compressor, | |
537 | + size_t hBlockCount, | |
538 | + size_t vBlockCount, | |
539 | + const unsigned char* pZeroOneInfos, | |
540 | + size_t zeroOneLimit, | |
541 | + CompressInfo compressInfos[8], | |
542 | + int* src, | |
543 | + unsigned char* tmp1, | |
544 | + unsigned char* tmp2, | |
545 | + unsigned char* tmp3, | |
546 | + unsigned char* dest, size_t destLen | |
547 | + ) | |
548 | +{ | |
549 | + const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
508 | 550 | |
509 | - // AC | |
510 | - for (size_t i=1; i<8; ++i) { | |
551 | + int* from = src; | |
552 | + size_t progress = 0; | |
553 | + | |
554 | + for (size_t i=0; i<8; ++i) { | |
511 | 555 | const unsigned char* p01 = (i < zeroOneLimit) ? 0 : pZeroOneInfos; |
512 | 556 | size_t blockSize = 1 + i * 2; |
513 | 557 | progress += compressSub(compressor, from, p01, totalBlockCount, blockSize, dest+progress, destLen-progress, tmp1, tmp2, compressInfos[i]); |
@@ -530,11 +574,6 @@ | ||
530 | 574 | |
531 | 575 | const unsigned char* initialSrc = src; |
532 | 576 | |
533 | - size_t signFlagBytes = *(size_t*)src; | |
534 | - src += 4; | |
535 | - BitReader signFlags(src); | |
536 | - src += signFlagBytes; | |
537 | - | |
538 | 577 | unsigned char compressFlag = *src++; |
539 | 578 | unsigned char b = *src++; |
540 | 579 | size_t len = *(size_t*)src; |
@@ -556,15 +595,6 @@ | ||
556 | 595 | |
557 | 596 | if (b == RiceCoderFlag::None) { |
558 | 597 | memcpy(dest, tmp, len2); |
559 | - for (size_t i=0; i<len2/4; ++i) { | |
560 | - int val = dest[i]; | |
561 | - if (val != 0) { | |
562 | - if (!signFlags.getBit()) { | |
563 | - dest[i] = -val; | |
564 | - } | |
565 | - } | |
566 | - } | |
567 | - | |
568 | 598 | }else { |
569 | 599 | RiceCoder riceCoder(b); |
570 | 600 | BitReader bitReader(tmp); |
@@ -588,16 +618,10 @@ | ||
588 | 618 | dest[i] = riceCoder.Decode(bitReader); |
589 | 619 | } |
590 | 620 | } |
591 | - for (size_t i=0; i<destLen; ++i) { | |
592 | - int val = dest[i]; | |
593 | - if (val != 0 && !signFlags.getBit()) { | |
594 | - dest[i] = -val; | |
595 | - } | |
596 | - } | |
597 | 621 | } |
598 | 622 | // showMinus(dest, dest, destLen); |
599 | 623 | |
600 | - return 4 + signFlagBytes + + 6 + len; | |
624 | + return 6 + len; | |
601 | 625 | } |
602 | 626 | |
603 | 627 | void reorderByFrequency( |
@@ -761,35 +785,25 @@ | ||
761 | 785 | |
762 | 786 | } |
763 | 787 | |
764 | - | |
765 | -void decompress( | |
766 | - ICompressor& decompressor, | |
788 | +void reorderByPosition( | |
767 | 789 | size_t hBlockCount, |
768 | 790 | size_t vBlockCount, |
769 | - const unsigned char* src, size_t srcLen, | |
770 | - unsigned char* tmp, int* tmp2, | |
771 | - int* dest, size_t destLen | |
791 | + const int* src, | |
792 | + int* dest | |
772 | 793 | ) |
773 | 794 | { |
774 | - int* initialDest = dest; | |
775 | - const unsigned char* initialSrc = src; | |
776 | - | |
777 | - const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
778 | 795 | const size_t toWidth = hBlockCount * 8; |
779 | - const size_t toWidth8 = toWidth * 8; | |
796 | + const size_t toWidth8 = toWidth * 8; | |
780 | 797 | |
781 | - int* from = tmp2; | |
798 | + const int* from = src; | |
782 | 799 | int* to = dest; |
783 | - | |
784 | - int writePos; | |
800 | + int writePos = 0; | |
785 | 801 | |
786 | - src += decompressSub(decompressor, src, 0, tmp, from, totalBlockCount, 1); | |
787 | 802 | // DC0 |
788 | 803 | writePos = 0; |
789 | 804 | for (size_t y=0; y<vBlockCount; ++y) { |
790 | 805 | int toPos = writePos; |
791 | 806 | for (size_t x=0; x<hBlockCount; ++x) { |
792 | - assert(toPos < destLen); | |
793 | 807 | to[toPos] = *from++; |
794 | 808 | toPos += 8; |
795 | 809 | } |
@@ -796,54 +810,6 @@ | ||
796 | 810 | writePos += toWidth8; |
797 | 811 | } |
798 | 812 | |
799 | - // paeth predictor to DC0 | |
800 | - // first row | |
801 | - int left = *to; | |
802 | - int above = 0; | |
803 | - int upperLeft = 0; | |
804 | - int cur = 0; | |
805 | - writePos = 8; | |
806 | - for (size_t i=1; i<hBlockCount; ++i) { | |
807 | - cur = to[writePos] + left; | |
808 | - assert(writePos < destLen); | |
809 | - to[writePos] = cur; | |
810 | - left = cur; | |
811 | - writePos += 8; | |
812 | - } | |
813 | - int toLineOffset = toWidth8; | |
814 | - int paeth = 0; | |
815 | - for (size_t y=1; y<vBlockCount; ++y) { | |
816 | - above = to[toLineOffset - toWidth8]; | |
817 | - paeth = to[toLineOffset]; | |
818 | - cur = paeth + paethPredictor(0, above, 0); | |
819 | - assert(toLineOffset < destLen); | |
820 | - to[toLineOffset] = cur; | |
821 | - writePos = toLineOffset + 8; | |
822 | - left = cur; | |
823 | - upperLeft = above; | |
824 | - for (size_t x=1; x<hBlockCount; ++x) { | |
825 | - above = to[writePos - toWidth8]; | |
826 | - paeth = to[writePos]; | |
827 | - cur = paeth + paethPredictor(left, above, upperLeft); | |
828 | - assert(writePos < destLen); | |
829 | - to[writePos] = cur; | |
830 | - left = cur; | |
831 | - upperLeft = above; | |
832 | - writePos += 8; | |
833 | - } | |
834 | - toLineOffset += toWidth8; | |
835 | - } | |
836 | - | |
837 | - // zero one flags | |
838 | - BitReader reader(src); | |
839 | - std::vector<unsigned char> zeroOneFlags(totalBlockCount); | |
840 | - unsigned char* pZeroOneFlags = &zeroOneFlags[0]; | |
841 | - for (size_t i=0; i<totalBlockCount; ++i) { | |
842 | - zeroOneFlags[i] = reader.getBit(); | |
843 | - } | |
844 | - src += reader.nBytes(); | |
845 | - | |
846 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 3); | |
847 | 813 | // AC1 |
848 | 814 | writePos = 0; |
849 | 815 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -852,13 +818,11 @@ | ||
852 | 818 | to[toPos+toWidth*0+1] = *from++; |
853 | 819 | to[toPos+toWidth*1+0] = *from++; |
854 | 820 | to[toPos+toWidth*1+1] = *from++; |
855 | - assert(toPos+toWidth*1+1 < destLen); | |
856 | 821 | toPos += 8; |
857 | 822 | } |
858 | 823 | writePos += toWidth8; |
859 | 824 | } |
860 | 825 | |
861 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 5); | |
862 | 826 | // AC2 |
863 | 827 | writePos = 0; |
864 | 828 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -874,7 +838,6 @@ | ||
874 | 838 | writePos += toWidth8; |
875 | 839 | } |
876 | 840 | |
877 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 7); | |
878 | 841 | // AC3 |
879 | 842 | writePos = 0; |
880 | 843 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -892,7 +855,6 @@ | ||
892 | 855 | writePos += toWidth8; |
893 | 856 | } |
894 | 857 | |
895 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 9); | |
896 | 858 | // AC4 |
897 | 859 | writePos = 0; |
898 | 860 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -912,7 +874,6 @@ | ||
912 | 874 | writePos += toWidth8; |
913 | 875 | } |
914 | 876 | |
915 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 11); | |
916 | 877 | // AC5 |
917 | 878 | writePos = 0; |
918 | 879 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -934,7 +895,6 @@ | ||
934 | 895 | writePos += toWidth8; |
935 | 896 | } |
936 | 897 | |
937 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 13); | |
938 | 898 | // AC6 |
939 | 899 | writePos = 0; |
940 | 900 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -958,7 +918,6 @@ | ||
958 | 918 | writePos += toWidth8; |
959 | 919 | } |
960 | 920 | |
961 | - src += decompressSub(decompressor, src, pZeroOneFlags, tmp, from, totalBlockCount, 15); | |
962 | 921 | // AC7 |
963 | 922 | writePos = 0; |
964 | 923 | for (size_t y=0; y<vBlockCount; ++y) { |
@@ -979,10 +938,36 @@ | ||
979 | 938 | to[toPos+toWidth*7+5] = *from++; |
980 | 939 | to[toPos+toWidth*7+6] = *from++; |
981 | 940 | to[toPos+toWidth*7+7] = *from++; |
982 | - assert(toPos+toWidth*7+7 < destLen); | |
983 | 941 | toPos += 8; |
984 | 942 | } |
985 | 943 | writePos += toWidth8; |
986 | 944 | } |
945 | + | |
987 | 946 | } |
988 | 947 | |
948 | +size_t decompress( | |
949 | + ICompressor& decompressor, | |
950 | + size_t hBlockCount, | |
951 | + size_t vBlockCount, | |
952 | + const unsigned char* pZeroOneInfos, | |
953 | + size_t zeroOneLimit, | |
954 | + const unsigned char* src, size_t srcLen, | |
955 | + unsigned char* tmp, int* tmp2, | |
956 | + int* dest, size_t destLen | |
957 | + ) | |
958 | +{ | |
959 | + const int totalBlockCount = static_cast<int>(hBlockCount * vBlockCount); | |
960 | + | |
961 | + const unsigned char* from = src; | |
962 | + int* to = dest; | |
963 | + | |
964 | + for (size_t i=0; i<8; ++i) { | |
965 | + const unsigned char* p01 = (i < zeroOneLimit) ? 0 : pZeroOneInfos; | |
966 | + size_t blockSize = 1 + i * 2; | |
967 | + from += decompressSub(decompressor, from, p01, tmp, to, totalBlockCount, blockSize); | |
968 | + to += totalBlockCount * blockSize; | |
969 | + } | |
970 | + | |
971 | + return from - src; | |
972 | +} | |
973 | + |
@@ -54,62 +54,135 @@ | ||
54 | 54 | in[i] = palettes[4 * in[i]]; |
55 | 55 | } |
56 | 56 | |
57 | - Quantizer quantizer; | |
58 | - quantizer.init(6*8+0, 0, 0, true); | |
59 | - | |
60 | 57 | const size_t hBlockCount = width / 8 + ((width % 8) ? 1 : 0); |
61 | 58 | const size_t vBlockCount = height / 8 + ((height % 8) ? 1 : 0); |
62 | 59 | const size_t totalBlockCount = hBlockCount * vBlockCount; |
63 | 60 | |
64 | - encode(quantizer, hBlockCount, vBlockCount, &in[0], width, &work[0], width*sizeof(int)); | |
65 | - | |
66 | - if (0) { | |
67 | - int cutoff_table[8][8] = { | |
68 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
69 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
70 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
71 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
72 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
73 | - -1,-1,-1,-1,-1,-1, 1, 1, | |
74 | - 1, 1, 1, 1, 1, 1, 1, 1, | |
75 | - 1, 1, 1, 1, 1, 1, 1, 1, | |
76 | - }; | |
77 | - for (size_t i=0; i<8; ++i) { | |
78 | - for (size_t j=0; j<8; ++j) { | |
79 | - if (cutoff_table[i][j] < 0) { | |
80 | - cutoff_table[i][j] = boost::integer_traits<int>::const_max; | |
81 | - } | |
82 | - } | |
83 | - } | |
84 | - cutoff(hBlockCount, vBlockCount, &work[0], width*sizeof(int), cutoff_table); | |
85 | - } | |
86 | - | |
87 | - int* pWork = &work[0]; | |
88 | - | |
89 | - reorderByFrequency(hBlockCount, vBlockCount, &work[0], &work2[0]); | |
90 | - | |
91 | - std::vector<unsigned char> zeroOneInfos(totalBlockCount); | |
92 | - unsigned char* pZeroOneInfos = &zeroOneInfos[0]; | |
93 | - size_t zeroOneLimit = 1; | |
94 | - findZeroOneInfos(hBlockCount, vBlockCount, &work2[0], &zeroOneInfos[0], zeroOneLimit); | |
95 | - | |
96 | 61 | BZip2Compressor compressor; |
97 | - size_t compressedLen = 0; | |
98 | 62 | |
99 | 63 | size_t storageSize = work.size()*4*1.1+600; |
100 | 64 | std::vector<unsigned char> work3(storageSize); |
101 | 65 | std::vector<unsigned char> work4(storageSize); |
102 | - std::vector<unsigned char> compressed(storageSize); | |
66 | + std::vector<unsigned char> encoded(storageSize); | |
103 | 67 | CompressInfo compressInfos[8] = {0}; |
104 | - compressedLen = compress(compressor, hBlockCount, vBlockCount, pZeroOneInfos, zeroOneLimit, compressInfos, &work2[0], (unsigned char*)&work[0], &work3[0], &work4[0], &compressed[0], compressed.size()); | |
105 | 68 | |
69 | + Quantizer quantizer; | |
70 | + quantizer.init(6*8+0, 0, 0, false); | |
71 | + | |
72 | + size_t zeroOneLimit = 1; | |
73 | + size_t totalLen = 0; | |
74 | + | |
75 | + // TODO: to design stream byte formats and various JYEIPEGYUU stream classes and implement serialize methods. | |
76 | + | |
77 | + // encode | |
78 | + { | |
79 | + unsigned char* dest = &encoded[0]; | |
80 | + unsigned char* initialDest = dest; | |
81 | + | |
82 | + // TODO: to record stream signature "jyeipegyuu\0" | |
83 | + // TODO: to record streams | |
84 | + | |
85 | + int* pWork = &work[0]; | |
86 | + int* pWork2 = &work2[0]; | |
87 | + | |
88 | + // TODO: to record quantizer parameter | |
89 | + | |
90 | + // TODO: to add encode options such as quantization table. | |
91 | + encode(quantizer, hBlockCount, vBlockCount, &in[0], width, pWork, width*sizeof(int)); | |
92 | + | |
93 | + reorderByFrequency(hBlockCount, vBlockCount, pWork, pWork2); | |
94 | + | |
95 | + // TODO: to add option to disable paeth prediction | |
96 | + paethPredictEncode(hBlockCount, vBlockCount, pWork2, pWork); | |
97 | + | |
98 | + std::vector<unsigned char> signFlags(totalBlockCount*64); | |
99 | + unsigned char* pSignFlags = &signFlags[0]; | |
100 | + size_t signFlagCount = collectInfos(pWork2, totalBlockCount, pSignFlags, compressInfos); | |
101 | + | |
102 | + std::vector<unsigned char> zeroOneInfos(totalBlockCount); | |
103 | + unsigned char* pZeroOneInfos = &zeroOneInfos[0]; | |
104 | + findZeroOneInfos(hBlockCount, vBlockCount, pWork2, &zeroOneInfos[0], zeroOneLimit); | |
105 | + | |
106 | + // TODO: to record quantizing zero one limit setting | |
107 | + | |
108 | + // quantizing zero one flags | |
109 | + BitWriter bw(dest+4); | |
110 | + for (size_t i=0; i<totalBlockCount; ++i) { | |
111 | + bw.putBit(pZeroOneInfos[i]); | |
112 | + } | |
113 | + *((uint32_t*)dest) = bw.nBytes(); | |
114 | + dest += 4; | |
115 | + dest += bw.nBytes(); | |
116 | + dest += compress(compressor, hBlockCount, vBlockCount, pZeroOneInfos, zeroOneLimit, compressInfos, pWork2, (unsigned char*)pWork, &work3[0], &work4[0], dest, encoded.size()); | |
117 | + | |
118 | + // TODO: to record DCT coefficients sign predictor setting | |
119 | + | |
120 | + BitWriter writer(dest+4); | |
121 | + for (size_t i=0; i<signFlagCount; ++i) { | |
122 | + writer.putBit(signFlags[i] != 0); | |
123 | + } | |
124 | + *((uint32_t*)dest) = writer.nBytes(); | |
125 | + dest += 4; | |
126 | + dest += writer.nBytes(); | |
127 | + | |
128 | + totalLen = dest - initialDest; | |
129 | + | |
130 | + } | |
131 | + | |
132 | + size_t compressedLen = totalLen; | |
133 | + | |
106 | 134 | std::fill(work.begin(), work.end(), 0); |
107 | 135 | std::fill(work2.begin(), work2.end(), 0); |
136 | + std::vector<unsigned char> tmp(encoded.size()); | |
108 | 137 | |
109 | - std::vector<unsigned char> tmp(compressed.size()); | |
110 | - decompress(compressor, hBlockCount, vBlockCount, &compressed[0], compressedLen, &tmp[0], &work[0], &work2[0], work2.size()); | |
111 | - | |
112 | - decode(quantizer, hBlockCount, vBlockCount, &work2[0], width*sizeof(int), &out[0], width); | |
138 | + // decode | |
139 | + { | |
140 | + unsigned char* src = &encoded[0]; | |
141 | + int* pWork = &work[0]; | |
142 | + int* pWork2 = &work2[0]; | |
143 | + size_t destLen = work2.size(); | |
144 | + | |
145 | + // zero one flags | |
146 | + uint32_t zeroOneFlagBytes = *(uint32_t*)src; | |
147 | + src += 4; | |
148 | + std::vector<unsigned char> zeroOneFlags(totalBlockCount); | |
149 | + unsigned char* pZeroOneFlags = &zeroOneFlags[0]; | |
150 | + { | |
151 | + BitReader reader(src); | |
152 | + assert(totalBlockCount <= zeroOneFlagBytes*8); | |
153 | + for (size_t i=0; i<zeroOneFlagBytes*8; ++i) { | |
154 | + zeroOneFlags[i] = reader.getBit(); | |
155 | + } | |
156 | + } | |
157 | + src += zeroOneFlagBytes; | |
158 | + | |
159 | + src += decompress(compressor, hBlockCount, vBlockCount, pZeroOneFlags, zeroOneLimit, src, compressedLen, &tmp[0], pWork, pWork2, destLen); | |
160 | + | |
161 | + // sign flags | |
162 | + uint32_t signFlagBytes = *(uint32_t*)src; | |
163 | + src += 4; | |
164 | + std::vector<unsigned char> signFlags(signFlagBytes * 8); | |
165 | + unsigned char* pSignFlags = &signFlags[0]; | |
166 | + { | |
167 | + BitReader reader(src); | |
168 | + for (size_t i=0; i<signFlagBytes*8; ++i) { | |
169 | + pSignFlags[i] = reader.getBit(); | |
170 | + } | |
171 | + size_t pos = 0; | |
172 | + for (size_t i=0; i<totalBlockCount*64; ++i) { | |
173 | + int& val = pWork2[i]; | |
174 | + if (val != 0) { | |
175 | + val = pSignFlags[pos++] ? val : -val; | |
176 | + } | |
177 | + } | |
178 | + } | |
179 | + | |
180 | + paethPredictDecode(hBlockCount, vBlockCount, pWork2, pWork); | |
181 | + | |
182 | + reorderByPosition(hBlockCount, vBlockCount, pWork2, pWork); | |
183 | + | |
184 | + decode(quantizer, hBlockCount, vBlockCount, pWork, width*sizeof(int), &out[0], width); | |
185 | + } | |
113 | 186 | unsigned char* pOutput = &out[0]; |
114 | 187 | |
115 | 188 | //FILE* of = _tfopen(_T("out.raw"), _T("wb")); |