diff --git a/czi-format/czi-parser/CMakeLists.txt b/czi-format/czi-parser/CMakeLists.txt
index 10703476e5ab74e285b6079a830e344ce9777b9a..4d8b5312434658ba235269cf4359b100b091a278 100644
--- a/czi-format/czi-parser/CMakeLists.txt
+++ b/czi-format/czi-parser/CMakeLists.txt
@@ -49,7 +49,11 @@ if (OPENMP_FOUND)
     message("ENABLED OpenMP")
 endif()
 
-include_directories("utilities/bsdiff")
+# add_library(BSDIFF "utilities/bsdiff/bsdiff.h" "utilities/bsdiff/bsdiff.c")
+# include_directories("utilities/bsdiff/")
+# target_link_libraries(czi-parser BSDIFF)
+
+# include_directories()
 
 set(CPACK_PROJECT_NAME ${PROJECT_NAME})
 set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
diff --git a/czi-format/czi-parser/compression/benchmark.cpp b/czi-format/czi-parser/compression/benchmark.cpp
index 2df8ae3d2e153d5c1fe25ae13f21f833a0171d63..e5aacca739ceee5949282a8b0faef3a2b7870e24 100644
--- a/czi-format/czi-parser/compression/benchmark.cpp
+++ b/czi-format/czi-parser/compression/benchmark.cpp
@@ -250,7 +250,7 @@ static void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cf
     }
 
     auto minMax = vecUtil::find_min_max(delta);
-    long maxRequiredValue = (minMax.first < 0) ? (abs(minMax.first) + minMax.second) : (minMax.second);
+    long maxRequiredValue = (minMax.min < 0) ? (abs(minMax.min) + minMax.max) : (minMax.max);
     bool canBeMappedToUShort = maxRequiredValue < USHORT_MAX;
 
     always_assert(canBeMappedToUShort && "Value can not be mapped into ushort.");
@@ -269,10 +269,56 @@ static void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cf
     cr = test_compression_method(ushortMappedDeltaBytes, cm, compLevel);
 }
 
-void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose, int level, CompressionMethod cm)
+static void _diff_from_frame_gray16_va_bit_count(const ByteArray &pfData, const ByteArray &cfData,
+                                                 const CompressionMethod cm, const int compLevel, CompressionResult &cr, size_t &bitsUsed)
+{
+
+    always_assert(pfData.size() == cfData.size());
+
+    std::vector<int> delta;
+
+    {
+        std::vector<ushort> pfUshortValues = bytes_to_ushort_array(pfData);
+        std::vector<ushort> cfUshortValues = bytes_to_ushort_array(cfData);
+        always_assert(pfUshortValues.size() == cfUshortValues.size());
+
+        delta = vecUtil::diff_vectors<ushort, int>(pfUshortValues, cfUshortValues);
+    }
+
+    auto minMax = vecUtil::find_min_max(delta);
+    long maxRequiredValue = (minMax.min < 0) ? (abs(minMax.min) + minMax.max) : (minMax.max);
+    bool canBeMappedToUShort = maxRequiredValue < USHORT_MAX;
+    always_assert(canBeMappedToUShort && "Value can not be mapped into ushort.");
+
+    // Here we map integers into ushort.
+    ByteArray diffBytes;
+    {
+        TypeMapper<int, ushort> typeMapper;
+        std::vector<ushort> ushortMappedDelta = typeMapper.map(delta);
+
+        ushort ushortMappedDeltaMax = vecUtil::find_max(ushortMappedDelta);
+        bitsUsed = bits_required(ushortMappedDeltaMax);
+
+        OutMemoryBitStream outMemoryBitStream(bitsUsed);
+        size_t requiredBitCount = bitsUsed * ushortMappedDelta.size();
+        size_t requiredSize = (requiredBitCount + 8 - 1) / 8;
+        outMemoryBitStream.resize_for_raw_write(requiredSize);
+
+        for (size_t i = 0; i < ushortMappedDelta.size(); i++)
+        {
+            outMemoryBitStream.write_value_no_alloc(ushortMappedDelta[i]);
+        }
+        diffBytes = outMemoryBitStream.get_flushed_buffer();
+    }
+
+    cr = test_compression_method(diffBytes, cm, compLevel);
+}
+
+void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose, int level, CompressionMethod cm, bool variableBitCount)
 {
     // NOTE: This benchmark works only for 16 bit pixels!
     printf("Compression method %s with compression level %i\n", compression_method_str(cm), level);
+    printf_if(variableBitCount, "Using variable bit count.\n");
     std::string fName = fs_wrapper::get_filename(cziFile.fileName);
     auto framesByChannels = cziFile.get_subblocks_grouped_by_channels();
 
@@ -296,10 +342,6 @@ void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &rep
             always_assert(prevEntry.pixelType == PixelType_Gray16);
             always_assert(currEntry.pixelType == PixelType_Gray16);
 
-            record.set_metadata(fName.c_str(), currFrameId, prevFrameId,
-                                cziFile.pixel_type_str(currEntry.pixelType), currEntry.width, currEntry.height,
-                                compression_method_str(cm), level, "PrevFrameDiff", 16, channelGroup.first);
-
             DimensionEntryDV1 prevDim = prevEntry.get_dimension(Dimension_Z);
             DimensionEntryDV1 currDim = currEntry.get_dimension(Dimension_Z);
             always_assert(!prevDim.isEmpty && !currDim.isEmpty);
@@ -311,21 +353,37 @@ void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &rep
 
             // pf => previous frame, cf => current frame.
             size_t originalSize = 0;
-            //std::thread(pfData,cfData, benchmarkRecord);
+            size_t bitsUsed = 16;
             {
                 auto pfData = cziFile.get_image_data(prevFrameId, false);
                 auto cfData = cziFile.get_image_data(currFrameId, false);
-                _diff_from_frame_gray16(pfData, cfData, cm, level, crN);
+
+                if (variableBitCount)
+                    _diff_from_frame_gray16_va_bit_count(pfData, cfData, cm, level, crN, bitsUsed);
+                else
+                    _diff_from_frame_gray16(pfData, cfData, cm, level, crN);
+
                 originalSize = pfData.size();
             }
             // Z order
             {
                 auto pfDataZ = cziFile.get_image_data(prevFrameId, true);
                 auto cfDataZ = cziFile.get_image_data(currFrameId, true);
-                _diff_from_frame_gray16(pfDataZ, cfDataZ, cm, level, crZ);
+
+                if (variableBitCount)
+                    _diff_from_frame_gray16_va_bit_count(pfDataZ, cfDataZ, cm, level, crZ, bitsUsed);
+                else
+                    _diff_from_frame_gray16(pfDataZ, cfDataZ, cm, level, crZ);
+
                 always_assert(pfDataZ.size() == originalSize);
             }
 
+            record.set_metadata(fName.c_str(), currFrameId, prevFrameId,
+                                cziFile.pixel_type_str(currEntry.pixelType), currEntry.width, currEntry.height,
+                                compression_method_str(cm), level, "PrevFrameDiff", bitsUsed, channelGroup.first);
+
+            //printf_if((variableBitCount && verbose), "Bits used for encoding: %lu\n", bitsUsed);
+
             record.originalSize = originalSize;
             record.compressedSize = crN.compressedSize;
             record.zOrderCompressedSize = crZ.compressedSize;
@@ -351,6 +409,8 @@ void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &rep
 
 void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose)
 {
+    always_assert(NOT_IMPLEMENTED_YET && "This has to fixed with proper version of bsdiff.");
+    /*
     std::string fName = fs_wrapper::get_filename(cziFile.fileName);
     printf("Difference from previuos frame by bsdiff unix tool.\n");
     auto framesByChannels = cziFile.get_subblocks_grouped_by_channels();
@@ -394,11 +454,13 @@ void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportF
                 auto cfData = cziFile.get_image_data(currFrameId, false);
                 originalSize = pfData.size();
 
-                size_t maxPatchSize = lib_bsdiff::bsdiff_patchsize_max(pfData.size(), cfData.size());
+                size_t maxPatchSize = 0; //lib_bsdiff::bsdiff_patchsize_max(pfData.size(), cfData.size());
                 ByteArray patchBuffer;
-                patchBuffer.resize(maxPatchSize);
+                //patchBuffer.resize(maxPatchSize);
+
+                lib_bsdiff::bsdiff_helper(pfData.data(), pfData.size(), cfData.data(), cfData.size(), patchBuffer);
 
-                off_t actualBufferSize = lib_bsdiff::bsdiff(pfData.data(), pfData.size(), cfData.data(), cfData.size(), patchBuffer.data(), maxPatchSize);
+                off_t actualBufferSize = patchBuffer.size(); //lib_bsdiff::bsdiff(pfData.data(), pfData.size(), cfData.data(), cfData.size(), patchBuffer.data(), maxPatchSize);
                 always_assert(actualBufferSize != -1 && "bsdiff error.");
                 patchSizeN = actualBufferSize;
             }
@@ -408,11 +470,11 @@ void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportF
                 auto cfDataZ = cziFile.get_image_data(currFrameId, true);
                 always_assert(pfDataZ.size() == originalSize);
 
-                size_t maxPatchSize = lib_bsdiff::bsdiff_patchsize_max(pfDataZ.size(), cfDataZ.size());
+                size_t maxPatchSize = 0; //lib_bsdiff::bsdiff_patchsize_max(pfDataZ.size(), cfDataZ.size());
                 ByteArray patchBuffer;
                 patchBuffer.resize(maxPatchSize);
 
-                off_t actualBufferSize = lib_bsdiff::bsdiff(pfDataZ.data(), pfDataZ.size(), cfDataZ.data(), cfDataZ.size(), patchBuffer.data(), maxPatchSize);
+                off_t actualBufferSize = 0; //lib_bsdiff::bsdiff(pfDataZ.data(), pfDataZ.size(), cfDataZ.data(), cfDataZ.size(), patchBuffer.data(), maxPatchSize);
                 always_assert(actualBufferSize != -1 && "bsdiff error.");
                 patchSizeZ = actualBufferSize;
             }
@@ -438,4 +500,5 @@ void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportF
     write_diff_report(benchmarkRecords, reportFile);
     printf("\rFinished %u/%u\n", iterCount, iterCount);
     printf("Report saved in %s\n", reportFile.c_str());
+    */
 }
\ No newline at end of file
diff --git a/czi-format/czi-parser/compression/benchmark.h b/czi-format/czi-parser/compression/benchmark.h
index c45fe338469926d09d58f44e87dff6ea0104a19a..64ce63198fe1658302506a023e42cdf0e353e6c1 100644
--- a/czi-format/czi-parser/compression/benchmark.h
+++ b/czi-format/czi-parser/compression/benchmark.h
@@ -2,31 +2,53 @@
 #include "compressors.h"
 #include "../czi_file.h"
 #include "../file_system.h"
+#include "../stream/memory_bit_stream.h"
 #include <iomanip>
 #include <thread>
 
 namespace lib_bsdiff
 {
-#include "../utilities/bsdiff/bsdiff.h"
-#include "../utilities/bsdiff/bsdiff.c"
+// #include "../utilities/bsdiff/bsdiff.h"
+
+// static int bs_write_imp(struct bsdiff_stream *stream, const void *buffer, int size)
+// {
+//     auto vectorBuffer = ((std::vector<unsigned char> *)stream->opaque);
+//     unsigned char *binDataToWrite = (unsigned char *)buffer;
+//     for (int i = 0; i < size; i++)
+//     {
+//         vectorBuffer->push_back(binDataToWrite[i]);
+//     }
+//     return 0;
+// }
+
+// static int bsdiff_helper(const uint8_t *old, int64_t oldsize, const uint8_t *_new, int64_t newsize, std::vector<unsigned char> &buffer)
+// {
+//     struct bsdiff_stream diff_stream;
+//     diff_stream.opaque = (void *)&buffer;
+//     diff_stream.malloc = malloc;
+//     diff_stream.free = free;
+//     diff_stream.write = bs_write_imp;
+
+//     return bsdiff(old, oldsize, _new, newsize, &diff_stream);
+// }
 }; // namespace lib_bsdiff
 
 struct BaseBenchmarkRecord
 {
-    const char *fileName;
-    size_t subblockId;
-    const char *pixelType;
-    size_t width;
-    size_t height;
-    const char *compressionMethod;
-    int compressionLevel;
-    size_t originalSize;
-    size_t compressedSize;
-    size_t zOrderCompressedSize;
-    float compressionRatio;
-    float zOrderCompressionRatio;
-    double compressionTime;
-    double zOrderCompressionTime;
+    const char *fileName = nullptr;
+    size_t subblockId = 0;
+    const char *pixelType = nullptr;
+    size_t width = 0;
+    size_t height = 0;
+    const char *compressionMethod = nullptr;
+    int compressionLevel = 0;
+    size_t originalSize = 0;
+    size_t compressedSize = 0;
+    size_t zOrderCompressedSize = 0;
+    float compressionRatio = 0.0f;
+    float zOrderCompressionRatio = 0.0f;
+    double compressionTime = 0.0;
+    double zOrderCompressionTime = 0.0;
 
     BaseBenchmarkRecord() {}
     BaseBenchmarkRecord(const CompressionResult &dataResult, const CompressionResult &dataZOrderResult)
@@ -66,10 +88,10 @@ struct BaseBenchmarkRecord
 
 struct DiffBenchmarkRecord : BaseBenchmarkRecord
 {
-    size_t refSubblockId;
-    uint channel;
-    const char *diffType;
-    uint bitsUsedForEncoding;
+    size_t refSubblockId = 0;
+    uint channel = 0;
+    const char *diffType = nullptr;
+    uint bitsUsedForEncoding = 0;
 
     void set_metadata(const char *fName, size_t subBlockId, size_t refSlubblockId, const char *pixelType, size_t width, size_t height, const char *cMethod, int cLevel,
                       const char *diffType, const uint bitsUsed, const uint channel)
@@ -100,8 +122,11 @@ void benchmark_continuos_compression(CziFile &cziFile, const std::string &report
 void benchmark_compression(CziFile &cziFile, const std::string &reportFile, bool verbose, int level = -1);
 
 // Frame difference benchmark stuff
-void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose, int level, CompressionMethod cm);
-void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose);
+void value_diff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile,
+                                        bool verbose, int level, CompressionMethod cm, bool variableBitCount);
+
+// void bsdiff_by_prev_frame_benchmark(CziFile &cziFile, const std::string &reportFile, bool verbose);
+
 static void write_diff_report(const std::vector<DiffBenchmarkRecord> &results, const std::string &reportFile);
 
 #include "benchmark.cpp"
\ No newline at end of file
diff --git a/czi-format/czi-parser/main.cpp b/czi-format/czi-parser/main.cpp
index 38278099c19b233a4b6587026b626149bdfbbc4a..06091f0414c1b589e4798e819f59847b5ec1248c 100644
--- a/czi-format/czi-parser/main.cpp
+++ b/czi-format/czi-parser/main.cpp
@@ -44,9 +44,12 @@ int main(int argc, char **argv)
     // Options
     args::Flag dontParseMetadataOption(optionsGroup, "no metadata", "Dont read metadata byte", {"no-metadata"});
     args::Flag verboseOption(optionsGroup, "verbose", "Extend output of method", {'v', "verbose"});
+    args::Flag variableBitCount(optionsGroup, "Variable bit count", "Use variable bit count for encoding difference value.", {"variable"});
+
     args::ValueFlag<int> compressionLevelOption(optionsGroup, "Compression level", "Compression level", {'l', "level"});
     args::ValueFlag<std::string> folderOption(optionsGroup, "Folder", "Folder to which save exported items.", {'f', "folder"});
     args::ValueFlag<std::string> reportFileOption(optionsGroup, "Report file", "File where to write report.", {'r', "report"});
+
     args::Flag gzipCompressionOption(compressionGroup, "GZIP", "gzip (zlib) compression", {"gzip"});
     args::Flag lzmaCompressionOption(compressionGroup, "LZMA", "lzma compression", {"lzma"});
     args::Flag bzip2CompressionOption(compressionGroup, "BZIP2", "bzip2 compression", {"bzip2"});
@@ -122,7 +125,7 @@ int main(int argc, char **argv)
 
         CompressionMethod cm = get_chosen_compression_method(gzipCompressionOption, lzmaCompressionOption, bzip2CompressionOption);
 
-        value_diff_by_prev_frame_benchmark(parsedFile, reportFileOption.Get(), verboseOption.Matched(), level, cm);
+        value_diff_by_prev_frame_benchmark(parsedFile, reportFileOption.Get(), verboseOption.Matched(), level, cm, variableBitCount.Matched());
 
         return 0;
     }
diff --git a/czi-format/czi-parser/stream/memory_bit_stream.cpp b/czi-format/czi-parser/stream/memory_bit_stream.cpp
index 4db2043e07e334816b00cd53b322db7ef391867d..04e2c5d20ae0590f49a5c3cfba86a6829f2f8889 100644
--- a/czi-format/czi-parser/stream/memory_bit_stream.cpp
+++ b/czi-format/czi-parser/stream/memory_bit_stream.cpp
@@ -3,24 +3,32 @@
 /******************************************************************************************************************************
   * OutMemoryBitStream implementation
   ****************************************************************************************************************************/
-OutMemoryBitStream::OutMemoryBitStream()
+OutMemoryBitStream::OutMemoryBitStream(size_t valueEncodeBitCount)
 {
     bitBuffer = 0;
     bitBufferSize = 0;
+    memoryBufferIndex = 0;
+    this->valueEncodeBitCount = valueEncodeBitCount;
 }
 
 OutMemoryBitStream::~OutMemoryBitStream()
 {
     flush_bit_buffer();
     bitBuffer = 0;
+    memoryBufferIndex = 0;
     bitBufferSize = 0;
 }
 
+void OutMemoryBitStream::resize_for_raw_write(const size_t size)
+{
+    buffer.resize(size);
+}
+
 void OutMemoryBitStream::operator<<(const bool &bit)
 {
-    write_bit(bit);
+    internal_write_bit(bit, true);
 }
-void OutMemoryBitStream::write_bit(const bool &bit)
+void OutMemoryBitStream::internal_write_bit(const bool &bit, const bool &alloc)
 {
     ++bitBufferSize;
     if (bit)
@@ -30,15 +38,39 @@ void OutMemoryBitStream::write_bit(const bool &bit)
 
     if (bitBufferSize == 8)
     {
-        flush_bit_buffer();
+        internal_flush_bit_buffer(alloc);
     }
 }
 
+void OutMemoryBitStream::write_bit(const bool &bit)
+{
+    internal_write_bit(bit, true);
+}
+
+void OutMemoryBitStream::write_bit_no_alloc(const bool &bit)
+{
+    internal_write_bit(bit, false);
+}
+
 void OutMemoryBitStream::flush_bit_buffer()
+{
+    internal_flush_bit_buffer(true);
+}
+
+void OutMemoryBitStream::internal_flush_bit_buffer(const bool &alloc)
 {
     if (bitBufferSize > 0)
     {
-        buffer.push_back(bitBuffer);
+        if (alloc)
+        {
+            buffer.push_back(bitBuffer);
+            ++memoryBufferIndex;
+        }
+        else
+        {
+            buffer[memoryBufferIndex++] = bitBuffer;
+        }
+
         bitBuffer = 0;
         bitBufferSize = 0;
     }
@@ -51,7 +83,13 @@ ByteArray OutMemoryBitStream::get_buffer() const
 
 ByteArray OutMemoryBitStream::get_flushed_buffer()
 {
-    flush_bit_buffer();
+    internal_flush_bit_buffer(true);
+    return buffer;
+}
+
+ByteArray OutMemoryBitStream::get_flushed_buffer_no_alloc()
+{
+    internal_flush_bit_buffer(false);
     return buffer;
 }
 
@@ -59,12 +97,13 @@ ByteArray OutMemoryBitStream::get_flushed_buffer()
   * InMemoryBitStream implementation
   ****************************************************************************************************************************/
 
-InMemoryBitStream::InMemoryBitStream(const ByteArray *buffer, size_t bufferPosition)
+InMemoryBitStream::InMemoryBitStream(const ByteArray *buffer, size_t bufferPosition, size_t valueEncodeBitCount)
 {
     memoryBuffer = buffer;
     memoryBufferPosition = bufferPosition;
     bitBufferSize = 0;
     bitBuffer = 0;
+    this->valueEncodeBitCount = valueEncodeBitCount;
 }
 
 InMemoryBitStream::~InMemoryBitStream()
diff --git a/czi-format/czi-parser/stream/memory_bit_stream.h b/czi-format/czi-parser/stream/memory_bit_stream.h
index d4741cf82c73e040c1c279729bad24cf41560c5a..6ae92693c05315dc2d50a093177f708ae4fce65a 100644
--- a/czi-format/czi-parser/stream/memory_bit_stream.h
+++ b/czi-format/czi-parser/stream/memory_bit_stream.h
@@ -1,60 +1,134 @@
 #pragma once
 #include "../custom_types.h"
 
+constexpr size_t MAX_BIT_COUNT = 255;
+
 // Class allowing to write invidual bits to memory buffer.
 class OutMemoryBitStream
 {
-private:
-  // Memory buffer.
-  ByteArray buffer;
-  // Bit buffer.
-  byte bitBuffer;
-  // Actual size of bit buffer.
-  byte bitBufferSize = 0;
-
-public:
-  OutMemoryBitStream();
-  ~OutMemoryBitStream();
-
-  // Write bit to memory stream.
-  void write_bit(const bool &bit);
-  // Write bit to memory stream.
-  void operator<<(const bool &bit);
-
-  // If flush buffer is not flushed, flush it to main buffer and clear it.
-  void flush_bit_buffer();
-  // Get buffer of written bits, which may not be flushed.
-  ByteArray get_buffer() const;
-  // Get buffer of written bits, which is flushed.
-  ByteArray get_flushed_buffer();
+  private:
+    // Memory buffer.
+    ByteArray buffer;
+    // Index to the next write in memory buffer.
+    size_t memoryBufferIndex = 0;
+    // Bit buffer.
+    byte bitBuffer;
+    // Actual size of bit buffer.
+    byte bitBufferSize = 0;
+    // Number of bits to which value will be encoded when `write_value` is called.
+    size_t valueEncodeBitCount = 0;
+
+    void internal_write_bit(const bool &bit, const bool &alloc);
+    void internal_flush_bit_buffer(const bool &alloc);
+
+  public:
+    OutMemoryBitStream(size_t valueEncodeBitCount = 1);
+    ~OutMemoryBitStream();
+    // Resize the memory buffer for `write_value_no_alloc` and `write_bit_no_alloc`
+    void resize_for_raw_write(const size_t size);
+
+    // Write bit to memory stream.
+    void write_bit(const bool &bit);
+    // Write bit without resizing buffer. Buffer must be allocated using `resize_for_raw_write` !
+    void write_bit_no_alloc(const bool &bit);
+    // Write bit to memory stream.
+    void operator<<(const bool &bit);
+
+    // If flush buffer is not flushed, flush it to main buffer and clear it.
+    void flush_bit_buffer();
+    // Get buffer of written bits, which may not be flushed.
+    ByteArray get_buffer() const;
+    // Get buffer of written bits, which is flushed.
+    ByteArray get_flushed_buffer();
+    // Get buffer of written bits, which is flushed. For allocated buffer.
+    ByteArray get_flushed_buffer_no_alloc();
+
+    template <typename T>
+    void write_value(const T &value)
+    {
+        // Lets do it Little-Endian way, start with LSB and move to MSB.
+        bool bit;
+        for (size_t bitPos = 0; bitPos < valueEncodeBitCount; bitPos++)
+        {
+            bit = value & (1 << bitPos);
+            write_bit(bit);
+        }
+    }
+
+    // Write value without resizing buffer. Buffer must be allocated using `resize_for_raw_write` !
+    template <typename T>
+    void write_value_no_alloc(const T &value)
+    {
+        // Lets do it Little-Endian way, start with LSB and move to MSB.
+        bool bit;
+        for (size_t bitPos = 0; bitPos < valueEncodeBitCount; bitPos++)
+        {
+            bit = value & (1 << bitPos);
+            write_bit_no_alloc(bit);
+        }
+    }
 };
 
 // Class alowing to read invidual bits from memory buffer.
 class InMemoryBitStream
 {
-private:
-  // Memory buffer.
-  const ByteArray *memoryBuffer = nullptr;
-  // Position in memory buffer.
-  size_t memoryBufferPosition = 0;
-  // Bit buffer.
-  byte bitBuffer = 0;
-  // Current bit buffer size.
-  byte bitBufferSize = 0;
-
-  // Read byte into bit buffer.
-  void read_byte_to_bit_buffer();
-
-public:
-  InMemoryBitStream(const ByteArray *buffer, size_t bufferPosition = 0);
-  ~InMemoryBitStream();
-
-  // Read one bit from memory buffer.
-  bool read_bit();
-  // Read one bit from memory buffer.
-  void operator>>(bool &bit);
-  // Check wheter atleast one bit can be read.
-  bool can_read() const;
+  private:
+    // Memory buffer.
+    const ByteArray *memoryBuffer = nullptr;
+    // Position in memory buffer.
+    size_t memoryBufferPosition = 0;
+    // Bit buffer.
+    byte bitBuffer = 0;
+    // Current bit buffer size.
+    byte bitBufferSize = 0;
+    // Number of bits to consume when reading value by `read_value`.
+    size_t valueEncodeBitCount;
+
+    // Read byte into bit buffer.
+    void read_byte_to_bit_buffer();
+
+  public:
+    InMemoryBitStream(const ByteArray *buffer, size_t bufferPosition = 0, size_t valueEncodeBitCount = 1);
+    ~InMemoryBitStream();
+
+    // Read one bit from memory buffer.
+    bool read_bit();
+    // Read one bit from memory buffer.
+    void operator>>(bool &bit);
+    // Check wheter atleast one bit can be read.
+    bool can_read() const;
+
+    template <typename T>
+    T read_value()
+    {
+        bool bit;
+        T result = 0;
+        for (size_t bitPos = 0; bitPos < valueEncodeBitCount; bitPos++)
+        {
+            bit = read_bit();
+            result |= (bit << bitPos);
+        }
+        return result;
+    }
 };
 
+// Find number of bits required to encode value of `maxValue`.
+size_t bits_required(size_t maxValue)
+{
+    size_t maxValueForBitCount = 0;
+    for (size_t bitCount = 2; bitCount < MAX_BIT_COUNT; bitCount++)
+    {
+        maxValueForBitCount = 0;
+        for (size_t i = 0; i < bitCount; i++)
+        {
+            maxValueForBitCount |= 1 << i;
+        }
+        if (maxValue <= maxValueForBitCount)
+            return bitCount;
+    }
+
+    always_assert(false && "Max value is too large");
+    return 0;
+}
+
 #include "memory_bit_stream.cpp"
\ No newline at end of file
diff --git a/czi-format/czi-parser/utilities/bsdiff/bsdiff.c b/czi-format/czi-parser/utilities/bsdiff/bsdiff.c
index b90ebbf36a8d4187f22884ba45e301f3c8871e18..628f1c1a05b470e167d025e9fa99f379a81e67e2 100644
--- a/czi-format/czi-parser/utilities/bsdiff/bsdiff.c
+++ b/czi-format/czi-parser/utilities/bsdiff/bsdiff.c
@@ -1,10 +1,10 @@
 /*-
- * Copyright 2012-2013 Austin Seipp
  * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
+ * modification, are permitted providing that the following conditions 
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -25,474 +25,421 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#if 0
-__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
-#endif
+#include "bsdiff.h"
 
-#include <stdlib.h>
-#include <stdio.h>
+#include <limits.h>
 #include <string.h>
-#include <sys/types.h>
 
-#include "bsdiff.h"
+#define MIN(x,y) (((x)<(y)) ? (x) : (y))
 
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-
-/* Header is
-   0  8       BSDIFF_CONFIG_MAGIC (see minibsdiff-config.h)
-   8  8       length of bzip2ed ctrl block
-   16 8       length of bzip2ed diff block
-   24 8       length of new file */
-/* File is
-   0  32      Header
-   32 ??      ctrl block
-   ?? ??      diff block
-   ?? ??      extra block */
-
-static void
-split(off_t *I, off_t *V, off_t start, off_t len, off_t h)
+static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h)
 {
-  off_t i, j, k, x, tmp, jj, kk;
-
-  if (len < 16)
-  {
-    for (k = start; k < start + len; k += j)
-    {
-      j = 1;
-      x = V[I[k] + h];
-      for (i = 1; k + i < start + len; i++)
-      {
-        if (V[I[k + i] + h] < x)
-        {
-          x = V[I[k + i] + h];
-          j = 0;
-        };
-        if (V[I[k + i] + h] == x)
-        {
-          tmp = I[k + j];
-          I[k + j] = I[k + i];
-          I[k + i] = tmp;
-          j++;
-        };
-      };
-      for (i = 0; i < j; i++)
-        V[I[k + i]] = k + j - 1;
-      if (j == 1)
-        I[k] = -1;
-    };
-    return;
-  };
-
-  x = V[I[start + len / 2] + h];
-  jj = 0;
-  kk = 0;
-  for (i = start; i < start + len; i++)
-  {
-    if (V[I[i] + h] < x)
-      jj++;
-    if (V[I[i] + h] == x)
-      kk++;
-  };
-  jj += start;
-  kk += jj;
-
-  i = start;
-  j = 0;
-  k = 0;
-  while (i < jj)
-  {
-    if (V[I[i] + h] < x)
-    {
-      i++;
-    }
-    else if (V[I[i] + h] == x)
-    {
-      tmp = I[i];
-      I[i] = I[jj + j];
-      I[jj + j] = tmp;
-      j++;
-    }
-    else
-    {
-      tmp = I[i];
-      I[i] = I[kk + k];
-      I[kk + k] = tmp;
-      k++;
-    };
-  };
-
-  while (jj + j < kk)
-  {
-    if (V[I[jj + j] + h] == x)
-    {
-      j++;
-    }
-    else
-    {
-      tmp = I[jj + j];
-      I[jj + j] = I[kk + k];
-      I[kk + k] = tmp;
-      k++;
-    };
-  };
-
-  if (jj > start)
-    split(I, V, start, jj - start, h);
-
-  for (i = 0; i < kk - jj; i++)
-    V[I[jj + i]] = kk - 1;
-  if (jj == kk - 1)
-    I[jj] = -1;
-
-  if (start + len > kk)
-    split(I, V, kk, start + len - kk, h);
+	int64_t i,j,k,x,tmp,jj,kk;
+
+	if(len<16) {
+		for(k=start;k<start+len;k+=j) {
+			j=1;x=V[I[k]+h];
+			for(i=1;k+i<start+len;i++) {
+				if(V[I[k+i]+h]<x) {
+					x=V[I[k+i]+h];
+					j=0;
+				};
+				if(V[I[k+i]+h]==x) {
+					tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
+					j++;
+				};
+			};
+			for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
+			if(j==1) I[k]=-1;
+		};
+		return;
+	};
+
+	x=V[I[start+len/2]+h];
+	jj=0;kk=0;
+	for(i=start;i<start+len;i++) {
+		if(V[I[i]+h]<x) jj++;
+		if(V[I[i]+h]==x) kk++;
+	};
+	jj+=start;kk+=jj;
+
+	i=start;j=0;k=0;
+	while(i<jj) {
+		if(V[I[i]+h]<x) {
+			i++;
+		} else if(V[I[i]+h]==x) {
+			tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
+			j++;
+		} else {
+			tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	while(jj+j<kk) {
+		if(V[I[jj+j]+h]==x) {
+			j++;
+		} else {
+			tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
+			k++;
+		};
+	};
+
+	if(jj>start) split(I,V,start,jj-start,h);
+
+	for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
+	if(jj==kk-1) I[jj]=-1;
+
+	if(start+len>kk) split(I,V,kk,start+len-kk,h);
 }
 
-static void
-qsufsort(off_t *I, off_t *V, u_char *old, off_t oldsize)
+static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
 {
-  off_t buckets[256];
-  off_t i, h, len;
-
-  for (i = 0; i < 256; i++)
-    buckets[i] = 0;
-  for (i = 0; i < oldsize; i++)
-    buckets[old[i]]++;
-  for (i = 1; i < 256; i++)
-    buckets[i] += buckets[i - 1];
-  for (i = 255; i > 0; i--)
-    buckets[i] = buckets[i - 1];
-  buckets[0] = 0;
-
-  for (i = 0; i < oldsize; i++)
-    I[++buckets[old[i]]] = i;
-  I[0] = oldsize;
-  for (i = 0; i < oldsize; i++)
-    V[i] = buckets[old[i]];
-  V[oldsize] = 0;
-  for (i = 1; i < 256; i++)
-    if (buckets[i] == buckets[i - 1] + 1)
-      I[buckets[i]] = -1;
-  I[0] = -1;
-
-  for (h = 1; I[0] != -(oldsize + 1); h += h)
-  {
-    len = 0;
-    for (i = 0; i < oldsize + 1;)
-    {
-      if (I[i] < 0)
-      {
-        len -= I[i];
-        i -= I[i];
-      }
-      else
-      {
-        if (len)
-          I[i - len] = -len;
-        len = V[I[i]] + 1 - i;
-        split(I, V, i, len, h);
-        i += len;
-        len = 0;
-      };
-    };
-    if (len)
-      I[i - len] = -len;
-  };
-
-  for (i = 0; i < oldsize + 1; i++)
-    I[V[i]] = i;
+	int64_t buckets[256];
+	int64_t i,h,len;
+
+	for(i=0;i<256;i++) buckets[i]=0;
+	for(i=0;i<oldsize;i++) buckets[old[i]]++;
+	for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
+	for(i=255;i>0;i--) buckets[i]=buckets[i-1];
+	buckets[0]=0;
+
+	for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
+	I[0]=oldsize;
+	for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
+	V[oldsize]=0;
+	for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
+	I[0]=-1;
+
+	for(h=1;I[0]!=-(oldsize+1);h+=h) {
+		len=0;
+		for(i=0;i<oldsize+1;) {
+			if(I[i]<0) {
+				len-=I[i];
+				i-=I[i];
+			} else {
+				if(len) I[i-len]=-len;
+				len=V[I[i]]+1-i;
+				split(I,V,i,len,h);
+				i+=len;
+				len=0;
+			};
+		};
+		if(len) I[i-len]=-len;
+	};
+
+	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
 }
 
-static off_t
-matchlen(u_char *oldp, off_t oldsize, u_char *newp, off_t newsize)
+static int64_t matchlen(const uint8_t *old,int64_t oldsize,const uint8_t *new,int64_t newsize)
 {
-  off_t i;
+	int64_t i;
 
-  for (i = 0; (i < oldsize) && (i < newsize); i++)
-    if (oldp[i] != newp[i])
-      break;
+	for(i=0;(i<oldsize)&&(i<newsize);i++)
+		if(old[i]!=new[i]) break;
 
-  return i;
+	return i;
 }
 
-static off_t
-search(off_t *I, u_char *oldp, off_t oldsize,
-       u_char *newp, off_t newsize, off_t st, off_t en, off_t *pos)
+static int64_t search(const int64_t *I,const uint8_t *old,int64_t oldsize,
+		const uint8_t *new,int64_t newsize,int64_t st,int64_t en,int64_t *pos)
 {
-  off_t x, y;
-
-  if (en - st < 2)
-  {
-    x = matchlen(oldp + I[st], oldsize - I[st], newp, newsize);
-    y = matchlen(oldp + I[en], oldsize - I[en], newp, newsize);
-
-    if (x > y)
-    {
-      *pos = I[st];
-      return x;
-    }
-    else
-    {
-      *pos = I[en];
-      return y;
-    }
-  };
-
-  x = st + (en - st) / 2;
-  if (memcmp(oldp + I[x], newp, MIN(oldsize - I[x], newsize)) < 0)
-  {
-    return search(I, oldp, oldsize, newp, newsize, x, en, pos);
-  }
-  else
-  {
-    return search(I, oldp, oldsize, newp, newsize, st, x, pos);
-  };
+	int64_t x,y;
+
+	if(en-st<2) {
+		x=matchlen(old+I[st],oldsize-I[st],new,newsize);
+		y=matchlen(old+I[en],oldsize-I[en],new,newsize);
+
+		if(x>y) {
+			*pos=I[st];
+			return x;
+		} else {
+			*pos=I[en];
+			return y;
+		}
+	};
+
+	x=st+(en-st)/2;
+	if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
+		return search(I,old,oldsize,new,newsize,x,en,pos);
+	} else {
+		return search(I,old,oldsize,new,newsize,st,x,pos);
+	};
 }
 
-static void
-offtout(off_t x, u_char *buf)
+static void offtout(int64_t x,uint8_t *buf)
 {
-  off_t y;
-
-  if (x < 0)
-    y = -x;
-  else
-    y = x;
-
-  buf[0] = y % 256;
-  y -= buf[0];
-  y = y / 256;
-  buf[1] = y % 256;
-  y -= buf[1];
-  y = y / 256;
-  buf[2] = y % 256;
-  y -= buf[2];
-  y = y / 256;
-  buf[3] = y % 256;
-  y -= buf[3];
-  y = y / 256;
-  buf[4] = y % 256;
-  y -= buf[4];
-  y = y / 256;
-  buf[5] = y % 256;
-  y -= buf[5];
-  y = y / 256;
-  buf[6] = y % 256;
-  y -= buf[6];
-  y = y / 256;
-  buf[7] = y % 256;
-
-  if (x < 0)
-    buf[7] |= 0x80;
+	int64_t y;
+
+	if(x<0) y=-x; else y=x;
+
+	buf[0]=y%256;y-=buf[0];
+	y=y/256;buf[1]=y%256;y-=buf[1];
+	y=y/256;buf[2]=y%256;y-=buf[2];
+	y=y/256;buf[3]=y%256;y-=buf[3];
+	y=y/256;buf[4]=y%256;y-=buf[4];
+	y=y/256;buf[5]=y%256;y-=buf[5];
+	y=y/256;buf[6]=y%256;y-=buf[6];
+	y=y/256;buf[7]=y%256;
+
+	if(x<0) buf[7]|=0x80;
 }
 
-off_t bsdiff_patchsize_max(off_t newsize, off_t oldsize)
+static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
 {
-  return newsize + oldsize + BSDIFF_PATCH_SLOP_SIZE;
+	int64_t result = 0;
+
+	while (length > 0)
+	{
+		const int smallsize = (int)MIN(length, INT_MAX);
+		const int writeresult = stream->write(stream, buffer, smallsize);
+		if (writeresult == -1)
+		{
+			return -1;
+		}
+
+		result += writeresult;
+		length -= smallsize;
+		buffer = (uint8_t*)buffer + smallsize;
+	}
+
+	return result;
 }
 
-int bsdiff(u_char *oldp, off_t oldsize,
-           u_char *newp, off_t newsize,
-           u_char *patch, off_t patchsz)
+struct bsdiff_request
 {
-  off_t *I, *V;
-  off_t scan, pos, len;
-  off_t lastscan, lastpos, lastoffset;
-  off_t oldscore, scsc;
-  off_t s, Sf, lenf, Sb, lenb;
-  off_t overlap, Ss, lens;
-  off_t i;
-  off_t dblen, eblen;
-  u_char *db, *eb;
-  u_char buf[8];
-  u_char header[32];
-  u_char *fileblock;
-
-  off_t ctrllen;
-
-  /* Sanity checks */
-  if (oldp == NULL || newp == NULL || patch == NULL)
-    return -1;
-  if (oldsize < 0 || newsize < 0 || patchsz < 0)
-    return -1;
-  if (bsdiff_patchsize_max(oldsize, newsize) > patchsz)
-    return -1;
-
-  /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
-     that we never try to malloc(0) and get a NULL pointer */
-  if (((I = (off_t *)malloc((oldsize + 1) * sizeof(off_t))) == NULL) ||
-      ((V = (off_t *)malloc((oldsize + 1) * sizeof(off_t))) == NULL))
-  {
-    if (I)
-      free(I);
-    return -1;
-  }
-
-  qsufsort(I, V, oldp, oldsize);
-
-  free(V);
-
-  /* Allocate newsize+1 bytes instead of newsize bytes to ensure
-     that we never try to malloc(0) and get a NULL pointer */
-  if (((db = (u_char *)malloc(newsize + 1)) == NULL) ||
-      ((eb = (u_char *)malloc(newsize + 1)) == NULL))
-  {
-    if (db)
-      free(db);
-    free(I);
-    return -1;
-  }
-  dblen = 0;
-  eblen = 0;
-
-  /* Write initial header */
-  memcpy(header, BSDIFF_CONFIG_MAGIC, 8);
-  offtout(0, header + 8);
-  offtout(0, header + 16);
-  offtout(newsize, header + 24);
-  memcpy(patch, header, 32);
-
-  /* Set up initial pointers */
-  fileblock = patch + 32;
-  ctrllen = 0;
-
-  /* Compute the differences, writing ctrl as we go */
-  scan = 0;
-  len = 0;
-  pos = 0;
-  lastscan = 0;
-  lastpos = 0;
-  lastoffset = 0;
-  while (scan < newsize)
-  {
-    oldscore = 0;
-
-    for (scsc = scan += len; scan < newsize; scan++)
-    {
-      len = search(I, oldp, oldsize, newp + scan, newsize - scan,
-                   0, oldsize, &pos);
-
-      for (; scsc < scan + len; scsc++)
-        if ((scsc + lastoffset < oldsize) &&
-            (oldp[scsc + lastoffset] == newp[scsc]))
-          oldscore++;
-
-      if (((len == oldscore) && (len != 0)) ||
-          (len > oldscore + 8))
-        break;
-
-      if ((scan + lastoffset < oldsize) &&
-          (oldp[scan + lastoffset] == newp[scan]))
-        oldscore--;
-    };
-
-    if ((len != oldscore) || (scan == newsize))
-    {
-      s = 0;
-      Sf = 0;
-      lenf = 0;
-      for (i = 0; (lastscan + i < scan) && (lastpos + i < oldsize);)
-      {
-        if (oldp[lastpos + i] == newp[lastscan + i])
-          s++;
-        i++;
-        if (s * 2 - i > Sf * 2 - lenf)
-        {
-          Sf = s;
-          lenf = i;
-        };
-      };
-
-      lenb = 0;
-      if (scan < newsize)
-      {
-        s = 0;
-        Sb = 0;
-        for (i = 1; (scan >= lastscan + i) && (pos >= i); i++)
-        {
-          if (oldp[pos - i] == newp[scan - i])
-            s++;
-          if (s * 2 - i > Sb * 2 - lenb)
-          {
-            Sb = s;
-            lenb = i;
-          };
-        };
-      };
-
-      if (lastscan + lenf > scan - lenb)
-      {
-        overlap = (lastscan + lenf) - (scan - lenb);
-        s = 0;
-        Ss = 0;
-        lens = 0;
-        for (i = 0; i < overlap; i++)
-        {
-          if (newp[lastscan + lenf - overlap + i] ==
-              oldp[lastpos + lenf - overlap + i])
-            s++;
-          if (newp[scan - lenb + i] ==
-              oldp[pos - lenb + i])
-            s--;
-          if (s > Ss)
-          {
-            Ss = s;
-            lens = i + 1;
-          };
-        };
-
-        lenf += lens - overlap;
-        lenb -= lens;
-      };
-
-      for (i = 0; i < lenf; i++)
-        db[dblen + i] = newp[lastscan + i] - oldp[lastpos + i];
-      for (i = 0; i < (scan - lenb) - (lastscan + lenf); i++)
-        eb[eblen + i] = newp[lastscan + lenf + i];
-
-      dblen += lenf;
-      eblen += (scan - lenb) - (lastscan + lenf);
-
-      offtout(lenf, buf);
-      memcpy(fileblock, buf, 8);
-      fileblock += 8;
-      ctrllen += 8;
-
-      offtout((scan - lenb) - (lastscan + lenf), buf);
-      memcpy(fileblock, buf, 8);
-      fileblock += 8;
-      ctrllen += 8;
-
-      offtout((pos - lenb) - (lastpos + lenf), buf);
-      memcpy(fileblock, buf, 8);
-      fileblock += 8;
-      ctrllen += 8;
-
-      lastscan = scan - lenb;
-      lastpos = pos - lenb;
-      lastoffset = pos - scan;
-    };
-  };
-
-  /* Write size of ctrl data */
-  offtout(ctrllen, header + 8);
-
-  /* Write diff data */
-  memcpy(fileblock, db, dblen);
-  fileblock += dblen;
-  /* Write size of diff data */
-  offtout(dblen, header + 16);
-
-  /* Write extra data */
-  memcpy(fileblock, eb, eblen);
-
-  /* Write the final header */
-  memcpy(patch, header, 32);
-
-  /* Free the memory we used */
-  free(db);
-  free(eb);
-  free(I);
-
-  return (32 + ctrllen + dblen + eblen);
+	const uint8_t* old;
+	int64_t oldsize;
+	const uint8_t* new;
+	int64_t newsize;
+	struct bsdiff_stream* stream;
+	int64_t *I;
+	uint8_t *buffer;
+};
+
+static int bsdiff_internal(const struct bsdiff_request req)
+{
+	int64_t *I,*V;
+	int64_t scan,pos,len;
+	int64_t lastscan,lastpos,lastoffset;
+	int64_t oldscore,scsc;
+	int64_t s,Sf,lenf,Sb,lenb;
+	int64_t overlap,Ss,lens;
+	int64_t i;
+	uint8_t *buffer;
+	uint8_t buf[8 * 3];
+
+	if((V=req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1;
+	I = req.I;
+
+	qsufsort(I,V,req.old,req.oldsize);
+	req.stream->free(V);
+
+	buffer = req.buffer;
+
+	/* Compute the differences, writing ctrl as we go */
+	scan=0;len=0;pos=0;
+	lastscan=0;lastpos=0;lastoffset=0;
+	while(scan<req.newsize) {
+		oldscore=0;
+
+		for(scsc=scan+=len;scan<req.newsize;scan++) {
+			len=search(I,req.old,req.oldsize,req.new+scan,req.newsize-scan,
+					0,req.oldsize,&pos);
+
+			for(;scsc<scan+len;scsc++)
+			if((scsc+lastoffset<req.oldsize) &&
+				(req.old[scsc+lastoffset] == req.new[scsc]))
+				oldscore++;
+
+			if(((len==oldscore) && (len!=0)) || 
+				(len>oldscore+8)) break;
+
+			if((scan+lastoffset<req.oldsize) &&
+				(req.old[scan+lastoffset] == req.new[scan]))
+				oldscore--;
+		};
+
+		if((len!=oldscore) || (scan==req.newsize)) {
+			s=0;Sf=0;lenf=0;
+			for(i=0;(lastscan+i<scan)&&(lastpos+i<req.oldsize);) {
+				if(req.old[lastpos+i]==req.new[lastscan+i]) s++;
+				i++;
+				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
+			};
+
+			lenb=0;
+			if(scan<req.newsize) {
+				s=0;Sb=0;
+				for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
+					if(req.old[pos-i]==req.new[scan-i]) s++;
+					if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
+				};
+			};
+
+			if(lastscan+lenf>scan-lenb) {
+				overlap=(lastscan+lenf)-(scan-lenb);
+				s=0;Ss=0;lens=0;
+				for(i=0;i<overlap;i++) {
+					if(req.new[lastscan+lenf-overlap+i]==
+					   req.old[lastpos+lenf-overlap+i]) s++;
+					if(req.new[scan-lenb+i]==
+					   req.old[pos-lenb+i]) s--;
+					if(s>Ss) { Ss=s; lens=i+1; };
+				};
+
+				lenf+=lens-overlap;
+				lenb-=lens;
+			};
+
+			offtout(lenf,buf);
+			offtout((scan-lenb)-(lastscan+lenf),buf+8);
+			offtout((pos-lenb)-(lastpos+lenf),buf+16);
+
+			/* Write control data */
+			if (writedata(req.stream, buf, sizeof(buf)))
+				return -1;
+
+			/* Write diff data */
+			for(i=0;i<lenf;i++)
+				buffer[i]=req.new[lastscan+i]-req.old[lastpos+i];
+			if (writedata(req.stream, buffer, lenf))
+				return -1;
+
+			/* Write extra data */
+			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+				buffer[i]=req.new[lastscan+lenf+i];
+			if (writedata(req.stream, buffer, (scan-lenb)-(lastscan+lenf)))
+				return -1;
+
+			lastscan=scan-lenb;
+			lastpos=pos-lenb;
+			lastoffset=pos-scan;
+		};
+	};
+
+	return 0;
 }
+
+int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new, int64_t newsize, struct bsdiff_stream* stream)
+{
+	int result;
+	struct bsdiff_request req;
+
+	if((req.I=stream->malloc((oldsize+1)*sizeof(int64_t)))==NULL)
+		return -1;
+
+	if((req.buffer=stream->malloc(newsize+1))==NULL)
+	{
+		stream->free(req.I);
+		return -1;
+	}
+
+	req.old = old;
+	req.oldsize = oldsize;
+	req.new = new;
+	req.newsize = newsize;
+	req.stream = stream;
+
+	result = bsdiff_internal(req);
+
+	stream->free(req.buffer);
+	stream->free(req.I);
+
+	return result;
+}
+
+#if defined(BSDIFF_EXECUTABLE)
+
+#include <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size)
+{
+	int bz2err;
+	BZFILE* bz2;
+
+	bz2 = (BZFILE*)stream->opaque;
+	BZ2_bzWrite(&bz2err, bz2, (void*)buffer, size);
+	if (bz2err != BZ_STREAM_END && bz2err != BZ_OK)
+		return -1;
+
+	return 0;
+}
+
+int main(int argc,char *argv[])
+{
+	int fd;
+	int bz2err;
+	uint8_t *old,*new;
+	off_t oldsize,newsize;
+	uint8_t buf[8];
+	FILE * pf;
+	struct bsdiff_stream stream;
+	BZFILE* bz2;
+
+	memset(&bz2, 0, sizeof(bz2));
+	stream.malloc = malloc;
+	stream.free = free;
+	stream.write = bz2_write;
+
+	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[1]);
+
+
+	/* Allocate newsize+1 bytes instead of newsize bytes to ensure
+		that we never try to malloc(0) and get a NULL pointer */
+	if(((fd=open(argv[2],O_RDONLY,0))<0) ||
+		((newsize=lseek(fd,0,SEEK_END))==-1) ||
+		((new=malloc(newsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,new,newsize)!=newsize) ||
+		(close(fd)==-1)) err(1,"%s",argv[2]);
+
+	/* Create the patch file */
+	if ((pf = fopen(argv[3], "w")) == NULL)
+		err(1, "%s", argv[3]);
+
+	/* Write header (signature+newsize)*/
+	offtout(newsize, buf);
+	if (fwrite("ENDSLEY/BSDIFF43", 16, 1, pf) != 1 ||
+		fwrite(buf, sizeof(buf), 1, pf) != 1)
+		err(1, "Failed to write header");
+
+
+	if (NULL == (bz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)))
+		errx(1, "BZ2_bzWriteOpen, bz2err=%d", bz2err);
+
+	stream.opaque = bz2;
+	if (bsdiff(old, oldsize, new, newsize, &stream))
+		err(1, "bsdiff");
+
+	BZ2_bzWriteClose(&bz2err, bz2, 0, NULL, NULL);
+	if (bz2err != BZ_OK)
+		err(1, "BZ2_bzWriteClose, bz2err=%d", bz2err);
+
+	if (fclose(pf))
+		err(1, "fclose");
+
+	/* Free the memory we used */
+	free(old);
+	free(new);
+
+	return 0;
+}
+
+#endif
diff --git a/czi-format/czi-parser/utilities/bsdiff/bsdiff.h b/czi-format/czi-parser/utilities/bsdiff/bsdiff.h
index 84ccbc00bfbbeea032be6e074824d1b9da30faa5..ab6e880c981cb63f131c218fd3bd90bc09a2240a 100644
--- a/czi-format/czi-parser/utilities/bsdiff/bsdiff.h
+++ b/czi-format/czi-parser/utilities/bsdiff/bsdiff.h
@@ -1,10 +1,10 @@
 /*-
- * Copyright 2012-2013 Austin Seipp
  * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
+ * modification, are permitted providing that the following conditions 
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -24,48 +24,28 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef _MINIBSDIFF_H_
-#define _MINIBSDIFF_H_
 
-#include "minibsdiff-config.h"
+#ifndef BSDIFF_H
+#define BSDIFF_H
 
-#ifdef __cplusplus
-extern "C"
+#include <stddef.h>
+#include <stdint.h>
+
+#define new _new
+
+struct bsdiff_stream
 {
-#endif
+	void *opaque;
 
-   /* ------------------------------------------------------------------------- */
-   /* -- Public API ----------------------------------------------------------- */
+	void *(*malloc)(size_t size);
+	void (*free)(void *ptr);
+	int (*write)(struct bsdiff_stream *stream, const void *buffer, int size);
+};
 
-   /*-
- * Determine the maximum size of a patch between two files. This function
- * should be used to allocate a buffer big enough for `bsdiff` to store
- * its output in.
- */
-   off_t bsdiff_patchsize_max(off_t oldsize, off_t newsize);
+int bsdiff(const uint8_t *old, int64_t oldsize, const uint8_t *new, int64_t newsize, struct bsdiff_stream *stream);
 
-   /*-
- * Create a binary patch from the buffers pointed to by oldp and newp (with
- * respective sizes,) and store the result in the buffer pointed to by 'patch'.
- *
- * The input pointer 'patch' must not be NULL, and the size of the buffer must
- * be at least 'bsdiff_patchsize_max(new,old)' in length.
- *
- * Returns -1 if `patch` is NULL, the 'patch' buffer is not large enough, or if
- * memory cannot be allocated.
- * Otherwise, the return value is the size of the patch that was put in the
- * 'patch' buffer.
- *
- * This function is memory-intensive, and requires max(17*n,9*n+m)+O(1) bytes
- * of memory, where n is the size of the new file and m is the size of the old
- * file. It runs in O((n+m) log n) time.
- */
-   int bsdiff(u_char *oldp, off_t oldsize,
-              u_char *newp, off_t newsize,
-              u_char *patch, off_t patchsize);
+//#include "bsdiff.c"
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
+#undef new
 
-#endif /* _MINIBSDIFF_H_ */
+#endif
diff --git a/czi-format/czi-parser/utilities/bsdiff/bspatch.c b/czi-format/czi-parser/utilities/bsdiff/bspatch.c
index e51d85a7c48055561fd535c38ebf3045d800e6f0..b5449147f624b2fa8c53191024167a270c0822d3 100644
--- a/czi-format/czi-parser/utilities/bsdiff/bspatch.c
+++ b/czi-format/czi-parser/utilities/bsdiff/bspatch.c
@@ -1,10 +1,10 @@
 /*-
- * Copyright 2012-2013 Austin Seipp
  * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
+ * modification, are permitted providing that the following conditions 
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -25,141 +25,167 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#if 0
-__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
 #include "bspatch.h"
 
-/*
-  Patch file format:
-  0        8       BSDIFF_CONFIG_MAGIC (see minibsdiff-config.h)
-  8        8       X
-  16       8       Y
-  24       8       sizeof(newfile)
-  32       X       control block
-  32+X     Y       diff block
-  32+X+Y   ???     extra block
-  with control block a set of triples (x,y,z) meaning "add x bytes
-  from oldfile to x bytes from the diff block; copy y bytes from the
-  extra block; seek forwards in oldfile by z bytes".
-*/
-
-static off_t
-offtin(u_char *buf)
+static int64_t offtin(uint8_t *buf)
 {
-  off_t y;
+	int64_t y;
 
-  y=buf[7]&0x7F;
-  y=y*256;y+=buf[6];
-  y=y*256;y+=buf[5];
-  y=y*256;y+=buf[4];
-  y=y*256;y+=buf[3];
-  y=y*256;y+=buf[2];
-  y=y*256;y+=buf[1];
-  y=y*256;y+=buf[0];
+	y=buf[7]&0x7F;
+	y=y*256;y+=buf[6];
+	y=y*256;y+=buf[5];
+	y=y*256;y+=buf[4];
+	y=y*256;y+=buf[3];
+	y=y*256;y+=buf[2];
+	y=y*256;y+=buf[1];
+	y=y*256;y+=buf[0];
 
-  if(buf[7]&0x80) y=-y;
+	if(buf[7]&0x80) y=-y;
 
-  return y;
+	return y;
 }
 
-bool
-bspatch_valid_header(u_char* patch, ssize_t patchsz)
+int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream)
 {
-  ssize_t newsize, ctrllen, datalen;
+	uint8_t buf[8];
+	int64_t oldpos,newpos;
+	int64_t ctrl[3];
+	int64_t i;
+
+	oldpos=0;newpos=0;
+	while(newpos<newsize) {
+		/* Read control data */
+		for(i=0;i<=2;i++) {
+			if (stream->read(stream, buf, 8))
+				return -1;
+			ctrl[i]=offtin(buf);
+		};
+
+		/* Sanity-check */
+		if(newpos+ctrl[0]>newsize)
+			return -1;
+
+		/* Read diff string */
+		if (stream->read(stream, new + newpos, ctrl[0]))
+			return -1;
+
+		/* Add old data to diff string */
+		for(i=0;i<ctrl[0];i++)
+			if((oldpos+i>=0) && (oldpos+i<oldsize))
+				new[newpos+i]+=old[oldpos+i];
+
+		/* Adjust pointers */
+		newpos+=ctrl[0];
+		oldpos+=ctrl[0];
+
+		/* Sanity-check */
+		if(newpos+ctrl[1]>newsize)
+			return -1;
+
+		/* Read extra string */
+		if (stream->read(stream, new + newpos, ctrl[1]))
+			return -1;
+
+		/* Adjust pointers */
+		newpos+=ctrl[1];
+		oldpos+=ctrl[2];
+	};
+
+	return 0;
+}
 
-  if (patchsz < 32) return false;
+#if defined(BSPATCH_EXECUTABLE)
 
-  /* Make sure magic and header fields are valid */
-  if(memcmp(patch, BSDIFF_CONFIG_MAGIC, 8) != 0) return false;
+#include <bzlib.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static int bz2_read(const struct bspatch_stream* stream, void* buffer, int length)
+{
+	int n;
+	int bz2err;
+	BZFILE* bz2;
 
-  ctrllen=offtin(patch+8);
-  datalen=offtin(patch+16);
-  newsize=offtin(patch+24);
-  if((ctrllen<0) || (datalen<0) || (newsize<0))
-    return false;
+	bz2 = (BZFILE*)stream->opaque;
+	n = BZ2_bzRead(&bz2err, bz2, buffer, length);
+	if (n != length)
+		return -1;
 
-  return true;
+	return 0;
 }
 
-ssize_t
-bspatch_newsize(u_char* patch, ssize_t patchsz)
+int main(int argc,char * argv[])
 {
-  if (!bspatch_valid_header(patch, patchsz)) return -1;
-  return offtin(patch+24);
+	FILE * f;
+	int fd;
+	int bz2err;
+	uint8_t header[24];
+	uint8_t *old, *new;
+	int64_t oldsize, newsize;
+	BZFILE* bz2;
+	struct bspatch_stream stream;
+	struct stat sb;
+
+	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+	/* Open patch file */
+	if ((f = fopen(argv[3], "r")) == NULL)
+		err(1, "fopen(%s)", argv[3]);
+
+	/* Read header */
+	if (fread(header, 1, 24, f) != 24) {
+		if (feof(f))
+			errx(1, "Corrupt patch\n");
+		err(1, "fread(%s)", argv[3]);
+	}
+
+	/* Check for appropriate magic */
+	if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
+		errx(1, "Corrupt patch\n");
+
+	/* Read lengths from header */
+	newsize=offtin(header+16);
+	if(newsize<0)
+		errx(1,"Corrupt patch\n");
+
+	/* Close patch file and re-open it via libbzip2 at the right places */
+	if(((fd=open(argv[1],O_RDONLY,0))<0) ||
+		((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+		((old=malloc(oldsize+1))==NULL) ||
+		(lseek(fd,0,SEEK_SET)!=0) ||
+		(read(fd,old,oldsize)!=oldsize) ||
+		(fstat(fd, &sb)) ||
+		(close(fd)==-1)) err(1,"%s",argv[1]);
+	if((new=malloc(newsize+1))==NULL) err(1,NULL);
+
+	if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0)))
+		errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err);
+
+	stream.read = bz2_read;
+	stream.opaque = bz2;
+	if (bspatch(old, oldsize, new, newsize, &stream))
+		errx(1, "bspatch");
+
+	/* Clean up the bzip2 reads */
+	BZ2_bzReadClose(&bz2err, bz2);
+	fclose(f);
+
+	/* Write the new file */
+	if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,sb.st_mode))<0) ||
+		(write(fd,new,newsize)!=newsize) || (close(fd)==-1))
+		err(1,"%s",argv[2]);
+
+	free(new);
+	free(old);
+
+	return 0;
 }
 
-int
-bspatch(u_char* oldp,  ssize_t oldsz,
-        u_char* patch, ssize_t patchsz,
-        u_char* newp,  ssize_t newsz)
-{
-  ssize_t newsize,ctrllen,datalen;
-  u_char *ctrlblock, *diffblock, *extrablock;
-  off_t oldpos,newpos;
-  off_t ctrl[3];
-  off_t i;
-
-  /* Sanity checks */
-  if (oldp == NULL || patch == NULL || newp == NULL) return -1;
-  if (oldsz < 0    || patchsz < 0   || newsz < 0)    return -1;
-  if (!bspatch_valid_header(patch, patchsz)) return -2;
-
-  /* Read lengths from patch header */
-  ctrllen=offtin(patch+8);
-  datalen=offtin(patch+16);
-  newsize=offtin(patch+24);
-  if (newsize > newsz) return -1;
-
-  /* Get pointers into the header metadata */
-  ctrlblock  = patch+32;
-  diffblock  = patch+32+ctrllen;
-  extrablock = patch+32+ctrllen+datalen;
-
-  /* Apply patch */
-  oldpos=0;newpos=0;
-  while(newpos<newsize) {
-    /* Read control block */
-    ctrl[0] = offtin(ctrlblock);
-    ctrl[1] = offtin(ctrlblock+8);
-    ctrl[2] = offtin(ctrlblock+16);
-    ctrlblock += 24;
-
-    /* Sanity check */
-    if(newpos+ctrl[0]>newsize)
-      return -3; /* Corrupt patch */
-
-    /* Read diff string */
-    memcpy(newp + newpos, diffblock, ctrl[0]);
-    diffblock += ctrl[0];
-
-    /* Add old data to diff string */
-    for(i=0;i<ctrl[0];i++)
-      if((oldpos+i>=0) && (oldpos+i<oldsz))
-        newp[newpos+i]+=oldp[oldpos+i];
-
-    /* Adjust pointers */
-    newpos+=ctrl[0];
-    oldpos+=ctrl[0];
-
-    /* Sanity check */
-    if(newpos+ctrl[1]>newsize)
-      return -3; /* Corrupt patch */
-
-    /* Read extra string */
-    memcpy(newp + newpos, extrablock, ctrl[1]);
-    extrablock += ctrl[1];
-
-    /* Adjust pointers */
-    newpos+=ctrl[1];
-    oldpos+=ctrl[2];
-  };
-
-  return 0;
-}
+#endif
diff --git a/czi-format/czi-parser/utilities/bsdiff/bspatch.h b/czi-format/czi-parser/utilities/bsdiff/bspatch.h
index d55919e83a8ccfe99bccd8c9e66b4228bf0cd44c..099c36e48e118df19261d2862f56264df7f7b4a6 100644
--- a/czi-format/czi-parser/utilities/bsdiff/bspatch.h
+++ b/czi-format/czi-parser/utilities/bsdiff/bspatch.h
@@ -1,10 +1,10 @@
 /*-
- * Copyright 2012-2013 Austin Seipp
  * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
+ * modification, are permitted providing that the following conditions 
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -24,55 +24,19 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef _MINIBSPATCH_H_
-#define _MINIBSPATCH_H_
 
-#include "minibsdiff-config.h"
+#ifndef BSPATCH_H
+# define BSPATCH_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ------------------------------------------------------------------------- */
-/* -- Public API ----------------------------------------------------------- */
+# include <stdint.h>
 
-/*-
- * Determine if the buffer pointed to by `patch` of a given `size` is
- * a valid patch.
- */
-bool bspatch_valid_header(u_char* patch, ssize_t patchsz);
-
-/*-
- * Determine the size of the new file that will result from applying
- * a patch. Returns -1 if the patch header is invalid, otherwise returns
- * the size of the new file.
- */
-ssize_t bspatch_newsize(u_char* patch, ssize_t patchsize);
+struct bspatch_stream
+{
+	void* opaque;
+	int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
+};
 
-/*-
- * Apply a patch stored in 'patch' to 'oldp', result in 'newp', and store the
- * result in 'newp'.
- *
- * The input pointers must not be NULL.
- *
- * The size of 'newp', represented by 'newsz', must be at least
- * 'bspatch_newsize(oldsz,patchsz)' bytes in length.
- *
- * Returns -1 if memory can't be allocated, or the input pointers are NULL.
- * Returns -2 if the patch header is invalid. Returns -3 if the patch itself is
- * corrupt.
- * Otherwise, returns 0.
- *
- * This function requires n+m+O(1) bytes of memory, where n is the size of the
- * old file and m is the size of the new file. It does no allocations.
- * It runs in O(n+m) time.
- */
-int bspatch(u_char* oldp,  ssize_t oldsz,
-            u_char* patch, ssize_t patchsz,
-            u_char* newp,  ssize_t newsz);
+int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream);
 
-#ifdef __cplusplus
-} /* extern "C" */
 #endif
 
-#endif /* _MINIBSPATCH_H_ */
diff --git a/czi-format/czi-parser/utilities/bsdiff/minibsdiff-config.h b/czi-format/czi-parser/utilities/bsdiff/minibsdiff-config.h
deleted file mode 100644
index 3bf5607a4621b53ed5a50b19e2eb24ba689b72e9..0000000000000000000000000000000000000000
--- a/czi-format/czi-parser/utilities/bsdiff/minibsdiff-config.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-
- * Copyright 2012-2013 Austin Seipp
- * Copyright 2003-2005 Colin Percival
- * All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _MINIBSDIFF_CONFIG_H_
-#define _MINIBSDIFF_CONFIG_H_
-
-#ifdef _MSC_VER
-#include <Windows.h>
-#include "stdint-msvc.h"
-#include "stdbool-msvc.h"
-#else
-#include <stdint.h>
-#include <stdbool.h>
-#endif /* _MSC_VER */
-
-/* ------------------------------------------------------------------------- */
-/* -- Patch file magic number ---------------------------------------------- */
-
-/** MUST be 8 bytes long! */
-/** TODO FIXME: we should static_assert this */
-#define BSDIFF_CONFIG_MAGIC "MBSDIF43"
-
-/* ------------------------------------------------------------------------- */
-/* -- Slop size for temporary patch buffer --------------------------------- */
-
-#define BSDIFF_PATCH_SLOP_SIZE 102400
-
-/* ------------------------------------------------------------------------- */
-/* -- Type definitions ----------------------------------------------------- */
-
-/* Duplicated to keep code small. Keep in sync with bspatch.h! */
-#ifndef _MINIBSDIFF_U_CHAR_T_
-#define _MINIBSDIFF_U_CHAR_T_
-typedef uint8_t u_char;
-#endif /* _MINIBSDIFF_U_CHAR_T_ */
-
-#ifdef _MSC_VER
-typedef SSIZE_T ssize_t;
-#endif /* _MSC_VER */
-
-#endif /* _MINIBSDIFF_CONFIG_H_ */
diff --git a/czi-format/czi-parser/utilities/type_mapper.h b/czi-format/czi-parser/utilities/type_mapper.h
index a7f40875bd0153e95b6a6fb85cd77a3fd041eb4b..4784f77f99ef8ddb9a360869ff9ad7ec594b39f7 100644
--- a/czi-format/czi-parser/utilities/type_mapper.h
+++ b/czi-format/czi-parser/utilities/type_mapper.h
@@ -12,8 +12,8 @@ class TypeMapper
     std::vector<TargetType> map(std::vector<SourceType> &data)
     {
         auto limits = vecUtil::find_min_max(data);
-        SourceType min = limits.first;
-        SourceType max = limits.second;
+        SourceType min = limits.min;
+        SourceType max = limits.max;
 
         TargetType targetMaxValue = std::numeric_limits<TargetType>::max();
         always_assert(max < targetMaxValue);
diff --git a/czi-format/czi-parser/utilities/vector_utilities.h b/czi-format/czi-parser/utilities/vector_utilities.h
index bbc1ecd479d78a94a73bce2433a332a89f4a65c5..81edd9ef24a50819010c7ec29a8bf9d522fb1528 100644
--- a/czi-format/czi-parser/utilities/vector_utilities.h
+++ b/czi-format/czi-parser/utilities/vector_utilities.h
@@ -3,6 +3,14 @@
 #include <algorithm>
 #include <limits>
 
+template <typename T>
+struct MinMax
+{ // Minimum value.
+    T min;
+    // Maximum value.
+    T max;
+};
+
 namespace vecUtil
 {
 
@@ -89,24 +97,24 @@ T find_min(const std::vector<T> &data)
 }
 
 template <typename T>
-std::pair<T, T> find_min_max(const std::vector<T> &data)
+MinMax<T> find_min_max(const std::vector<T> &data)
 {
-    T min = std::numeric_limits<T>::max();
-    T max = std::numeric_limits<T>::min();
+    MinMax<T> result;
+    result.min = std::numeric_limits<T>::max();
+    result.max = std::numeric_limits<T>::min();
 
     for (size_t i = 0; i < data.size(); i++)
     {
-        if (data[i] < min)
+        if (data[i] < result.min)
         {
-            min = data[i];
+            result.min = data[i];
         }
 
-        if (data[i] > max)
+        if (data[i] > result.max)
         {
-            max = data[i];
+            result.max = data[i];
         }
     }
-    return std::make_pair(min, max);
+    return result;
 }
-
 }; // namespace vecUtil