diff --git a/CMakeLists.txt b/CMakeLists.txt index 69ea523..a9a6263 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(dwt53 CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address") +#set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address") if(CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-D_ITERATOR_DEBUG_LEVEL=0) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") diff --git a/bitstream.hpp b/bitstream.hpp index 20506bc..9a7e4a9 100644 --- a/bitstream.hpp +++ b/bitstream.hpp @@ -1,10 +1,10 @@ -//https://raw.githubusercontent.com/vovach777/BitStream/main/bitstream.hpp #pragma once #include #include #include #include #include +#include class BitWriter { @@ -42,17 +42,17 @@ class BitWriter { inline void writeBit(bool value) { put_bits(1,value);} inline void writeBit0() { writeBit(true);} inline void writeBit1() { writeBit(false);} - auto data() const { - return reinterpret_cast( vec.data()); + auto data() const { + return reinterpret_cast( vec.data()); } - auto data() { - return reinterpret_cast( vec.data()); + auto data() { + return reinterpret_cast( vec.data()); } auto size_in_bits() const { return size_*32 + (32-bit_left_); } - auto size() const { + auto size() const { return (size_in_bits() + 7) >> 3; } - + void flush() { if (bit_left_ == 32) return; @@ -60,7 +60,7 @@ class BitWriter { vec.resize(size_+1); } vec[size_] = 0; - auto byte_by_byte = reinterpret_cast( &vec[size_] ); + auto byte_by_byte = reinterpret_cast( &vec[size_] ); auto bit_left = bit_left_; auto bit_buf = bit_buf_; if (bit_left < 32) @@ -95,7 +95,7 @@ class BitWriter { }; class BitReader { - + inline unsigned int get_bits1() { size_t _index = index; @@ -118,7 +118,7 @@ class BitReader { if (n == 0) return 0; if (index+n > size_in_bits) { throw std::out_of_range("(index+n > size_in_bits)!!!"); - } + } union unaligned_32 { uint32_t l; } __attribute__((packed)) __attribute__((may_alias)); diff --git a/bitstream_helper.hpp b/bitstream_helper.hpp new file mode 100644 index 0000000..fbc20e3 --- /dev/null +++ b/bitstream_helper.hpp @@ -0,0 +1,56 @@ +#pragma once + +class ValueWriter { + +inline int ilog2_32(uint32_t v) +{ + if (v == 0) + return 1; + return 32-__builtin_clz(v); +} + + public: + ValueWriter() = delete; + ValueWriter(BitWriter &ref) : ref(ref) {}; + void encode( int n, int value) + { + auto base = (1 << n)-1; + if (value >= base) + { + value -= base; + auto n_ = std::max(n, ilog2_32(value)); + base = (1 << n_)-1; + n = n_+1+n_; + if (n > 32) { + ref.writeBits(n_,base); + ref.writeBits(1, 0); + ref.writeBits(n_, value); + return; + } + value = (base << (n_+1)) | value; + } + ref.writeBits(n,value); + } + private: + BitWriter&ref; +}; + +class ValueReader { + public: + ValueReader() = delete; + ValueReader(BitReader& ref) : ref(ref) {} + int decode( int n ) + { + + auto v = ref.readBits(n); + if (v == ((1 << n)-1)) { + + while (ref.readBit()) ++n; + v += ref.readBits(n); + } + + return v; + } + private: + BitReader& ref; +}; diff --git a/huffman.hpp b/huffman.hpp index d4e4777..ef47369 100644 --- a/huffman.hpp +++ b/huffman.hpp @@ -16,6 +16,7 @@ #include #include "bitstream.hpp" #include "utils.hpp" +#include "bitstream_helper.hpp" namespace pack { namespace impl { @@ -72,11 +73,12 @@ namespace pack { void encodeHuffmanTree(BitWriter& dest) { if (DHT.size() == 0) throw std::domain_error("No DHT found!"); - + ValueWriter vv(dest); - dest.writeBits(8,DHT.size()); + vv.encode(4,DHT.size()); for (int i = 0; i < DHT.size(); i++) { - dest.writeBits(8, DHT[i].size()); + ///dest.writeBits(8, DHT[i].size()); + vv.encode(8, DHT[i].size()); for (auto symbol : DHT[i]) { auto catindex = symbol_to_catindex(symbol); dest.writeBits(4, catindex & 0xf); @@ -88,11 +90,13 @@ namespace pack { void decodeHuffmanTree(BitReader& src) { // decode huffman table + ValueReader vr(src); DHT.clear(); - DHT.resize(src.readBits(8)); - + //DHT.resize(src.readBits(8)); + DHT.resize(vr.decode(4)); for (int i = 0; i < DHT.size(); i++) { - DHT[i].resize(src.readBits(8)); + //DHT[i].resize(src.readBits(8)); + DHT[i].resize(vr.decode(8)); if (DHT[i].size() == 0) continue; cout << i << " (" << DHT[i].size() << ") :"; // cout << "DHT_" << i << ":" << DHT[i].size() << endl;