diff --git a/czi/source_code/CMakeLists.txt b/czi/source_code/CMakeLists.txt
index 6aba4f5372b740d5691ee2f8bc373d5d7fecfb84..0e69240453625fae2b331c3ce39e0c7f4462f021 100644
--- a/czi/source_code/CMakeLists.txt
+++ b/czi/source_code/CMakeLists.txt
@@ -1,63 +1,6 @@
-cmake_minimum_required(VERSION 3.8.0)
-project(czi-parser VERSION 0.1.0)
+cmake_minimum_required(VERSION 3.0.0)
 
-add_executable(${PROJECT_NAME} main.cpp)
+project(semestral-project)
 
-set(CMAKE_CXX_FLAGS "-Wall -DBZ_NO_STDIO")
-
-# set(Boost_USE_STATIC_LIBS OFF) 
-set(Boost_USE_MULTITHREADED ON)  
-set(Boost_USE_STATIC_RUNTIME OFF) 
-find_package(Boost REQUIRED COMPONENTS filesystem locale)
-if(Boost_FOUND)
-    include_directories(${Boost_INCLUDE_DIRS}) 
-    target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})
-    message("LINKED BOOST")
-endif()
-
-find_package (Threads)
-    target_link_libraries (${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
-
-find_package(ZLIB)
-if(ZLIB_FOUND)
-    target_link_libraries(${PROJECT_NAME} ${ZLIB_LIBRARIES})
-    message("LINKED ZLIB")    
-endif(ZLIB_FOUND)
-
-find_package(LibLZMA)
-if (LIBLZMA_FOUND)
-    include_directories(${LIBLZMA_INCLUDE_DIRS}) 
-    target_link_libraries(${PROJECT_NAME} ${LIBLZMA_LIBRARIES})
-    message("LINKED LIBLZMA")
-endif()
-
-find_package(BZip2)
-if(BZIP2_FOUND)
-    include_directories(${BZIP2_INCLUDE_DIRS})
-    target_link_libraries(${PROJECT_NAME} ${BZIP2_LIBRARIES})
-    message("LINKED BZIP2")
-endif(BZIP2_FOUND)
-
-find_package(OpenMP)
-if (OPENMP_FOUND)
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
-    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
-    set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
-    message("ENABLED OpenMP")
-endif()
-
-# add_subdirectory(azgra_lib)
-target_link_libraries(${PROJECT_NAME} PUBLIC 
-    azgra_lib)
-
-
-
-# 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})
-include(CPack)
\ No newline at end of file
+add_subdirectory(azgra_lib)
+add_subdirectory(app)
\ No newline at end of file
diff --git a/czi/source_code/root/app/CMakeLists.txt b/czi/source_code/app/CMakeLists.txt
similarity index 82%
rename from czi/source_code/root/app/CMakeLists.txt
rename to czi/source_code/app/CMakeLists.txt
index 1dff09c9b25733ddd7c4b808bafe6a0a7fef4db9..c5dcb4526dda959a9792b3efc69ec9d0a28e2425 100644
--- a/czi/source_code/root/app/CMakeLists.txt
+++ b/czi/source_code/app/CMakeLists.txt
@@ -3,10 +3,20 @@ cmake_minimum_required(VERSION 3.8.0)
 project(czi)
 
 add_executable(${PROJECT_NAME} main.cpp
+    src/bsdiff/bspatch.c    
     src/czi/czi_file.cpp
     src/czi/czi_parser.cpp
+    src/czi/czi_parts/dimension.cpp
+    src/czi/czi_parts/pyramid_type.cpp
+    src/czi/czi_parts/pixel_type.cpp
+    src/czi/czi_parts/compression_type.cpp
+    src/filesystem/file_system.cpp
     src/image/image_matrix.cpp
+    src/image/pixel_parse_functions.cpp
     src/compression/benchmark.cpp
+    src/compression/compressors.cpp
+    src/bsdiff/api_bsdiff.cpp
+    src/bsdiff/bsdiff.c
     )
 
 include_directories(${PROJECT_SOURCE_DIR}/include)
diff --git a/czi/source_code/app/include/bsdiff/api_bsdiff.h b/czi/source_code/app/include/bsdiff/api_bsdiff.h
new file mode 100644
index 0000000000000000000000000000000000000000..7cbdd4cd4b879205b9e61b4031deaf8b4a573a6f
--- /dev/null
+++ b/czi/source_code/app/include/bsdiff/api_bsdiff.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "../custom_types.h"
+
+#define new _new
+#include "bsdiff.h"
+#include "bspatch.h"
+#undef new
+
+struct bsdiff_read_info
+{
+    ByteArray readBuffer;
+    size_t readPos = 0;
+};
+
+int bsdiff_write_impl(bsdiff_stream *stream, const void *buffer, int size);
+int bsdiff_read_impl(const struct bspatch_stream *stream, void *buffer, int length);
+
+/**
+ * @brief 
+ */
+constexpr int BSDIFF_API_SUCCESS = 0;
+constexpr int BSDIFF_API_FAILURE = -1;
+
+/**
+ * @brief Create binary patch, which can be used to create current buffer from reference buffer. Patch is not compressed.
+ * @param reference Reference data buffer.
+ * @param current Current data buffer.
+ * @param patchBuffer Patch buffer.
+ * @return int BSDIFF_API_SUCCESS on success.
+ */
+int bsdiff_create_patch(const ByteArray &reference, const ByteArray &current, ByteArray &patchBuffer);
+
+/**
+ * @brief Apply binary patch to create current data buffer from reference buffer. 
+ * 
+ * @param reference Reference buffer.
+ * @param patch Bsdiff patch buffer.
+ * @param current Buffer to which data will be written.
+ * @return int BSDIFF_API_SUCCESS on success.
+ */
+int bsdiff_apply_patch(const ByteArray &reference, const ByteArray &patch, ByteArray &current);
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/bsdiff/bsdiff.h b/czi/source_code/app/include/bsdiff/bsdiff.h
similarity index 80%
rename from czi/source_code/root/app/include/bsdiff/bsdiff.h
rename to czi/source_code/app/include/bsdiff/bsdiff.h
index eab71b582927e4e1fa42fd30a6671c68fba54c98..3fd285b72412dcce50639eef4d2a8f5d3294849d 100644
--- a/czi/source_code/root/app/include/bsdiff/bsdiff.h
+++ b/czi/source_code/app/include/bsdiff/bsdiff.h
@@ -31,17 +31,24 @@
 #include <stddef.h>
 #include <stdint.h>
 
-
-struct bsdiff_stream
+#ifdef __cplusplus
+extern "C"
 {
-	void *opaque;
+#endif
 
-	void *(*malloc)(size_t size);
-	void (*free)(void *ptr);
-	int (*write)(struct bsdiff_stream *stream, const void *buffer, int size);
-};
+	struct bsdiff_stream
+	{
+		void *opaque;
 
-int bsdiff(const uint8_t *old, int64_t oldsize, const uint8_t *new, int64_t newsize, struct bsdiff_stream *stream);
+		void *(*malloc)(size_t size);
+		void (*free)(void *ptr);
+		int (*write)(struct bsdiff_stream *stream, const void *buffer, int size);
+	};
 
+	int bsdiff(const uint8_t *old, int64_t oldsize, const uint8_t *new, int64_t newsize, struct bsdiff_stream *stream);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/czi/source_code/root/app/include/bsdiff/bspatch.h b/czi/source_code/app/include/bsdiff/bspatch.h
similarity index 80%
rename from czi/source_code/root/app/include/bsdiff/bspatch.h
rename to czi/source_code/app/include/bsdiff/bspatch.h
index 099c36e48e118df19261d2862f56264df7f7b4a6..6af330907e8b1b98e1756f748131344d1e8ae280 100644
--- a/czi/source_code/root/app/include/bsdiff/bspatch.h
+++ b/czi/source_code/app/include/bsdiff/bspatch.h
@@ -26,17 +26,25 @@
  */
 
 #ifndef BSPATCH_H
-# define BSPATCH_H
+#define BSPATCH_H
 
-# include <stdint.h>
+#include <stdint.h>
 
-struct bspatch_stream
+#ifdef __cplusplus
+extern "C"
 {
-	void* opaque;
-	int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
-};
+#endif
+
+	struct bspatch_stream
+	{
+		void *opaque;
+		int (*read)(const struct bspatch_stream *stream, void *buffer, int length);
+	};
 
-int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream);
+	int bspatch(const uint8_t *old, int64_t oldsize, uint8_t *new, int64_t newsize, struct bspatch_stream *stream);
 
+#ifdef __cplusplus
+}
 #endif
 
+#endif
diff --git a/czi/source_code/root/app/include/cli/args.hxx b/czi/source_code/app/include/cli/args.hxx
similarity index 100%
rename from czi/source_code/root/app/include/cli/args.hxx
rename to czi/source_code/app/include/cli/args.hxx
diff --git a/czi/source_code/root/app/include/compression/benchmark.h b/czi/source_code/app/include/compression/benchmark.h
similarity index 95%
rename from czi/source_code/root/app/include/compression/benchmark.h
rename to czi/source_code/app/include/compression/benchmark.h
index c5b1bba6840e577ffb9df0dcbe1b4abd82a4fccb..d03daa92379909f48b70b308fa90e2d06217ef1f 100644
--- a/czi/source_code/root/app/include/compression/benchmark.h
+++ b/czi/source_code/app/include/compression/benchmark.h
@@ -2,7 +2,7 @@
 #include "compressors.h"
 
 #include <czi/czi_file.h>
-#include <filesystem/file_system.h>
+//#include <filesystem/file_system.h>
 #include <azgra/stream/memory_bit_stream.h>
 #include <bsdiff/api_bsdiff.h>
 #include <iomanip>
@@ -92,7 +92,7 @@ struct DiffBenchmarkRecord : BaseBenchmarkRecord
 // Raw Compression benchmark functions.
 void write_compression_report(const std::vector<BaseBenchmarkRecord> &results, const std::string &reportFile);
 void compression_thread_work(const ByteArray &data, CompressionMethod method, int compressionLevel, CompressionResult &result, const char *info);
-static std::vector<BaseBenchmarkRecord> benchmark_continuos_compression_one_level(const ByteArray &data, const ByteArray &zOrderedData, int compressionLevel);
+std::vector<BaseBenchmarkRecord> benchmark_continuos_compression_one_level(const ByteArray &data, const ByteArray &zOrderedData, int compressionLevel);
 void benchmark_continuos_compression(CziFile &cziFile, const std::string &reportFile, bool verbose, int level = -1);
 void benchmark_compression(CziFile &cziFile, const std::string &reportFile, bool verbose, int level = -1);
 
diff --git a/czi/source_code/app/include/compression/compressors.h b/czi/source_code/app/include/compression/compressors.h
new file mode 100644
index 0000000000000000000000000000000000000000..5def2e315cc60a99d8904761a397bc50cc42e419
--- /dev/null
+++ b/czi/source_code/app/include/compression/compressors.h
@@ -0,0 +1,69 @@
+#pragma once
+#include <azgra/utilities/vector_utilities.h>
+#include <azgra/utilities/z_order.h>
+#include <azgra/utilities/Stopwatch.h>
+#include <custom_types.h>
+
+namespace library_zlib
+{
+#include <zlib.h>
+};
+
+namespace library_lzma
+{
+#include <lzma.h>
+};
+
+namespace library_bzip2
+{
+#include <bzlib.h>
+};
+
+enum CompressionMethod
+{
+    CompressionMethod_GZIP,
+    CompressionMethod_LZMA,
+    CompressionMethod_BZIP2,
+};
+
+const char *compression_method_str(const CompressionMethod cm);
+
+struct CompressionResult
+{
+    size_t originalSize;
+    size_t compressedSize;
+    float compressionRatio;
+    float ratioToOriginalSize;
+    double compressionTimeMS;
+
+    CompressionResult()
+    {
+        originalSize = 0;
+        compressedSize = 0;
+        compressionRatio = 0.0f;
+        compressionTimeMS = 0;
+        ratioToOriginalSize = 0;
+    }
+
+    void divide(float x)
+    {
+        originalSize /= x;
+        compressedSize /= x;
+        compressionRatio /= x;
+        ratioToOriginalSize /= x;
+    }
+};
+
+constexpr size_t MAX_LITERAL_COUNT = 255;
+constexpr size_t MAX_RUN_COUNT = 255;
+constexpr size_t MAX_LOOKBACK_COUNT = 255;
+
+inline float compression_ratio(float uncompressedSize, float compressedSize)
+{
+    return (uncompressedSize / compressedSize);
+}
+
+ByteArray gzip_encode(const ByteArray &data, int compressionLevel, CompressionResult &info);
+ByteArray lzma_encode(const ByteArray &data, int compressionLevel, CompressionResult &info);
+ByteArray bzip2_encode(const ByteArray &data, int compressionLevel, CompressionResult &info);
+CompressionResult test_compression_method(const ByteArray &data, CompressionMethod method, int compressionLevel);
diff --git a/czi/source_code/root/app/include/custom_types.h b/czi/source_code/app/include/custom_types.h
similarity index 100%
rename from czi/source_code/root/app/include/custom_types.h
rename to czi/source_code/app/include/custom_types.h
diff --git a/czi/source_code/root/app/include/czi/czi_file.h b/czi/source_code/app/include/czi/czi_file.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_file.h
rename to czi/source_code/app/include/czi/czi_file.h
diff --git a/czi/source_code/root/app/include/czi/czi_parser.h b/czi/source_code/app/include/czi/czi_parser.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parser.h
rename to czi/source_code/app/include/czi/czi_parser.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/attachment_directory_segment.h b/czi/source_code/app/include/czi/czi_parts/attachment_directory_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/attachment_directory_segment.h
rename to czi/source_code/app/include/czi/czi_parts/attachment_directory_segment.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/attachment_entry_a1.h b/czi/source_code/app/include/czi/czi_parts/attachment_entry_a1.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/attachment_entry_a1.h
rename to czi/source_code/app/include/czi/czi_parts/attachment_entry_a1.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/attachment_segment.h b/czi/source_code/app/include/czi/czi_parts/attachment_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/attachment_segment.h
rename to czi/source_code/app/include/czi/czi_parts/attachment_segment.h
diff --git a/czi/source_code/app/include/czi/czi_parts/compression_type.h b/czi/source_code/app/include/czi/czi_parts/compression_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..099d89c2399968a82b8705d8b159854654eecb36
--- /dev/null
+++ b/czi/source_code/app/include/czi/czi_parts/compression_type.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <azgra/azgra.h>
+
+enum CompressionType
+{
+    // Uncompressed pixels.
+    CompressionType_Uncompressed = 0,
+    CompressionType_JpgFile = 1,
+    CompressionType_LZW = 2,
+    CompressionType_JpegXrFile = 4,
+    // Camera specific RAW data.
+    CompressionType_Camera,
+    // System specific RAW data.
+    CompressionType_System
+};
+
+const char *compression_type_str(const CompressionType ct);
\ No newline at end of file
diff --git a/czi/source_code/app/include/czi/czi_parts/dimension.h b/czi/source_code/app/include/czi/czi_parts/dimension.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c8ddce8098d8b2ebe7ba3a6a864a9a5878a55fe
--- /dev/null
+++ b/czi/source_code/app/include/czi/czi_parts/dimension.h
@@ -0,0 +1,32 @@
+#pragma once
+
+enum Dimension
+{
+    // Pixel index / offset in the X direction. Used for tiled images.
+    Dimension_X = 'X',
+    // Pixel index / offset in the Y direction. Used for tiled images.
+    Dimension_Y = 'Y',
+    // Channel in a Multi-Channel data set.
+    Dimension_C = 'C',
+    // Slice index (Z – direction).
+    Dimension_Z = 'Z',
+    // Time point in a sequentially acquired series of data.
+    Dimension_T = 'T',
+    // Rotation – used in acquisition modes where the data is recorded from various angles.
+    Dimension_R = 'R',
+    // Scene – for clustering items in X/Y direction (data belonging to contiguous regions of interests in a mosaic image).
+    Dimension_S = 'S',
+    // Illumination - illumination direction index (e.g. from left=0, from right=1).
+    Dimension_I = 'I',
+    // (Acquisition) Block index in segmented experiments. Note: This index has been dropped. Instead of the B index multiple single CZI images will be generated when saving segmented experiments.
+    Dimension_B = 'B',
+    // Mosaic tile index – this index uniquely identifies all tiles in a  specific plane.
+    Dimension_M = 'M',
+    // Phase index – for specific acquisition methods.
+    Dimension_H = 'H',
+    // View index (for multi – view images, e.g. SPIM)
+    Dimension_V = 'V'
+};
+
+const char *dimension_type_str(const Dimension &d);
+const char *dimension_char(const Dimension &d);
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/czi/czi_parts/dimension_entry_dv1.h b/czi/source_code/app/include/czi/czi_parts/dimension_entry_dv1.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/dimension_entry_dv1.h
rename to czi/source_code/app/include/czi/czi_parts/dimension_entry_dv1.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/directory_entry_dv.h b/czi/source_code/app/include/czi/czi_parts/directory_entry_dv.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/directory_entry_dv.h
rename to czi/source_code/app/include/czi/czi_parts/directory_entry_dv.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/file_header_segment.h b/czi/source_code/app/include/czi/czi_parts/file_header_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/file_header_segment.h
rename to czi/source_code/app/include/czi/czi_parts/file_header_segment.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/metadata_segment.h b/czi/source_code/app/include/czi/czi_parts/metadata_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/metadata_segment.h
rename to czi/source_code/app/include/czi/czi_parts/metadata_segment.h
diff --git a/czi/source_code/app/include/czi/czi_parts/pixel_type.h b/czi/source_code/app/include/czi/czi_parts/pixel_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..f080f2948106767ccdd039cdb7a9faaf7e12a589
--- /dev/null
+++ b/czi/source_code/app/include/czi/czi_parts/pixel_type.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <azgra/azgra.h>
+
+enum PixelType
+{
+    // 8 bit unsigned.
+    PixelType_Gray8 = 0,
+    // 16 bit unsigned
+    PixelType_Gray16 = 1,
+    // 32 bit IEEE float.
+    PixelType_Gray32Float = 2,
+    // 8 bit for each color channel (blue, green, red).
+    PixelType_Bgr24 = 3,
+    // 16 bit for each color channel (blue, green, red).
+    PixelType_Bgr48 = 4,
+    // 32 bit IEEE float for each color channel.
+    PixelType_Bgr96Float = 8,
+    // 8 bit for each color channel (blue, green, red) and alpha channel.
+    PixelType_Bgra32 = 9,
+    // 2 x 32 bit IEEE float for real and imaginary part of complex number.
+    PixelType_Gray64ComplexFloat = 10,
+    // 32 bit IEEE float for real and imaginary part of each color channel.
+    PixelType_Bgr192ComplexFloat = 11,
+    // [Planned] 32 bit integer.
+    PixelType_Gray32 = 12,
+    // [Planned] Double precision floating point.
+    PixelType_Gray64 = 13,
+    // For internal usage.
+    PixelType_None
+};
+
+// Get number of bytes needed to encode specific `PixelType`
+int get_bytes_per_pixel_type(const PixelType &pt);
+// Get number of bytes, by which ByteArray can be reordered in Z-Order.
+uint get_component_size_of_pixel(const PixelType &pt);
+// Get number of separable components in specific `PixelType`.
+uint get_count_of_components_of_pixel(const PixelType &pt);
\ No newline at end of file
diff --git a/czi/source_code/app/include/czi/czi_parts/pyramid_type.h b/czi/source_code/app/include/czi/czi_parts/pyramid_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9c99bbaa6b78947150b77b4d9cac55f80326ec2
--- /dev/null
+++ b/czi/source_code/app/include/czi/czi_parts/pyramid_type.h
@@ -0,0 +1,10 @@
+#pragma once
+
+enum PyramidType
+{
+    PyramidType_None = 0,
+    PyramidType_SingleSubBlock = 1,
+    PyramidType_MultiSubBlock = 2
+};
+
+const char *pyramid_type_str(const PyramidType pt);
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/czi/czi_parts/segment_header.h b/czi/source_code/app/include/czi/czi_parts/segment_header.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/segment_header.h
rename to czi/source_code/app/include/czi/czi_parts/segment_header.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/segments.h b/czi/source_code/app/include/czi/czi_parts/segments.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/segments.h
rename to czi/source_code/app/include/czi/czi_parts/segments.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/subblock_directory_segment.h b/czi/source_code/app/include/czi/czi_parts/subblock_directory_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/subblock_directory_segment.h
rename to czi/source_code/app/include/czi/czi_parts/subblock_directory_segment.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/subblock_segment.h b/czi/source_code/app/include/czi/czi_parts/subblock_segment.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/subblock_segment.h
rename to czi/source_code/app/include/czi/czi_parts/subblock_segment.h
diff --git a/czi/source_code/root/app/include/czi/czi_parts/version.h b/czi/source_code/app/include/czi/czi_parts/version.h
similarity index 100%
rename from czi/source_code/root/app/include/czi/czi_parts/version.h
rename to czi/source_code/app/include/czi/czi_parts/version.h
diff --git a/czi/source_code/app/include/filesystem/file_system.h b/czi/source_code/app/include/filesystem/file_system.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb9de1eff6bc624661fed70b6a36ff2ab9650e38
--- /dev/null
+++ b/czi/source_code/app/include/filesystem/file_system.h
@@ -0,0 +1,41 @@
+#pragma once
+
+/*
+* Copyright Moravec Vojtech 2019.
+* Distributed under the Boost Software License, Version 1.0.
+* (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <azgra/azgra.h>
+#include "boost/filesystem.hpp"
+#include "boost/algorithm/string.hpp"
+
+namespace fs_wrapper
+{
+constexpr char CziExtUpperCase[] = ".CZI";
+
+struct SmallFileInfo
+{
+    // Name of the file.
+    std::string name;
+    // Whole path to file.
+    std::string path;
+};
+
+// Check if given path points to file.
+bool is_file(const std::string &pathToCheck);
+// Check if given path points to directory.
+bool is_directory(const std::string &pathToCheck);
+// Create all missing directories in path.
+bool create_directory_path(const std::string &desiredPath);
+// Get name of the file, specified by its path.
+std::string get_filename(const std::string &selectedPath);
+// Get name, without extension, of the file, specified by its path.
+std::string get_filename_without_extension(const std::string &selectedPath);
+// Get files, whose names begin with prefix.
+std::vector<SmallFileInfo> get_files_with_same_prefix(const std::vector<SmallFileInfo> &files, const std::string &prefix);
+// Get all regular files from directory.
+std::vector<SmallFileInfo> get_files_in_directory(const std::string &directoryPath, const bool onlyCziFiles);
+std::string get_parent_directory(const std::string &filePath);
+// Get all regular files from parent directory of given file.
+std::vector<SmallFileInfo> get_files_in_parent_directory(const std::string &filePath, const bool onlyCziFiles);
+}; // namespace fs_wrapper
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/image/CImg.h b/czi/source_code/app/include/image/CImg.h
similarity index 99%
rename from czi/source_code/root/app/include/image/CImg.h
rename to czi/source_code/app/include/image/CImg.h
index 4d535e722e0725fa13cee3cdbe66bbe58c16379c..eeb402468c5d778dbddb11ab943bc6a2cb05609f 100644
--- a/czi/source_code/root/app/include/image/CImg.h
+++ b/czi/source_code/app/include/image/CImg.h
@@ -5840,7 +5840,7 @@ namespace cimg_library_suffixed {
     inline unsigned int srand() {
       const unsigned int t = (unsigned int)cimg::time();
 #if cimg_OS==1 || defined(__BORLANDC__)
-      std::srand(t + (unsigned int)getpid());
+      std::srand(t + (unsigned int)99); //getpid() HACK: for now.
 #elif cimg_OS==2
       std::srand(t + (unsigned int)_getpid());
 #else
diff --git a/czi/source_code/root/app/include/image/cimg_wrapper.h b/czi/source_code/app/include/image/cimg_wrapper.h
similarity index 87%
rename from czi/source_code/root/app/include/image/cimg_wrapper.h
rename to czi/source_code/app/include/image/cimg_wrapper.h
index e1784f6ac234f65b14ab451b954ca2f2c547251e..e2aab8afc27908d8eb478c67ffd4f5ab25b383cb 100644
--- a/czi/source_code/root/app/include/image/cimg_wrapper.h
+++ b/czi/source_code/app/include/image/cimg_wrapper.h
@@ -34,7 +34,7 @@ inline Gray8Pixel get_grayscale_pixel(cimg_library::CImg<byte> &img, const uint
 }
 
 // Create grayscale image. `Gray8`
-cimg_library::CImg<byte> create_grayscale_image(const uint width, const uint height)
+inline cimg_library::CImg<byte> create_grayscale_image(const uint width, const uint height)
 {
     cimg_library::CImg<byte> image(width, height, 1, 1);
     image.fill(0);
@@ -42,7 +42,7 @@ cimg_library::CImg<byte> create_grayscale_image(const uint width, const uint hei
 }
 
 // Create color image. `Bgr24`
-cimg_library::CImg<byte> create_color_image(const uint width, const uint height)
+inline cimg_library::CImg<byte> create_color_image(const uint width, const uint height)
 {
     cimg_library::CImg<byte> image(width, height, 1, 3);
     image.fill(0);
diff --git a/czi/source_code/root/app/include/image/image_matrix.h b/czi/source_code/app/include/image/image_matrix.h
similarity index 100%
rename from czi/source_code/root/app/include/image/image_matrix.h
rename to czi/source_code/app/include/image/image_matrix.h
diff --git a/czi/source_code/app/include/image/pixel_parse_functions.h b/czi/source_code/app/include/image/pixel_parse_functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..90c83368a372b548a557fe3d647d5d974d6055fe
--- /dev/null
+++ b/czi/source_code/app/include/image/pixel_parse_functions.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <azgra/stream/binary_converter.h>
+#include "pixel_structures.h"
+#include <custom_types.h>
+#include <czi/czi_parts/pixel_type.h>
+
+std::shared_ptr<Gray8Pixel> bytes_to_Gray8Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Gray16Pixel> bytes_to_Gray16Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Bgr24Pixel> bytes_to_Bgr24Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Gray32FloatPixel> bytes_to_Gray32FloatPixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Bgr48Pixel> bytes_to_Bgr48Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Bgr96FloatPixel> bytes_to_Bgr96FloatPixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Bgra32Pixel> bytes_to_Bgra32Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Gray64ComplexFloatPixel> bytes_to_Gray64ComplexFloatPixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Bgr192ComplexFloatPixel> bytes_to_Bgr192ComplexFloatPixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Gray32Pixel> bytes_to_Gray32Pixel(const ByteArray &bytes, ulong &index);
+std::shared_ptr<Gray64Pixel> bytes_to_Gray64Pixel(const ByteArray &bytes, ulong &index);
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/image/pixel_structures.h b/czi/source_code/app/include/image/pixel_structures.h
similarity index 100%
rename from czi/source_code/root/app/include/image/pixel_structures.h
rename to czi/source_code/app/include/image/pixel_structures.h
diff --git a/czi/source_code/root/app/main.cpp b/czi/source_code/app/main.cpp
similarity index 100%
rename from czi/source_code/root/app/main.cpp
rename to czi/source_code/app/main.cpp
diff --git a/czi/source_code/app/src/bsdiff/api_bsdiff.cpp b/czi/source_code/app/src/bsdiff/api_bsdiff.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3874bd0df8ae81dfd108afd61a99ed961e1b6243
--- /dev/null
+++ b/czi/source_code/app/src/bsdiff/api_bsdiff.cpp
@@ -0,0 +1,50 @@
+#include <bsdiff/api_bsdiff.h>
+
+int bsdiff_write_impl(bsdiff_stream *stream, const void *buffer, int size)
+{
+    ByteArray *vectorBuffer = (ByteArray *)stream->opaque;
+    byte *dataBuffer = (byte *)buffer;
+
+    vectorBuffer->insert(vectorBuffer->end(), dataBuffer, (dataBuffer + size));
+    return 0;
+}
+
+int bsdiff_read_impl(const struct bspatch_stream *stream, void *buffer, int length)
+{
+    bsdiff_read_info *readInfo = (bsdiff_read_info *)stream->opaque;
+    byte *dataBuffer = (byte *)buffer;
+
+    for (int i = 0; i < length; i++)
+    {
+        dataBuffer[i] = readInfo->readBuffer[readInfo->readPos + i];
+    }
+    readInfo->readPos += length;
+
+    return 0;
+}
+
+int bsdiff_create_patch(const ByteArray &reference, const ByteArray &current, ByteArray &patchBuffer)
+{
+    struct bsdiff_stream patchStream;
+    patchStream.free = free;
+    patchStream.malloc = malloc;
+    patchStream.opaque = (void *)&patchBuffer;
+    patchStream.write = bsdiff_write_impl;
+
+    int result = bsdiff(reference.data(), reference.size(), current.data(), current.size(), &patchStream);
+    return result;
+}
+
+int bsdiff_apply_patch(const ByteArray &reference, const ByteArray &patch, ByteArray &current)
+{
+    bsdiff_read_info readInfo = {};
+    readInfo.readPos = 0;
+    readInfo.readBuffer = patch;
+
+    struct bspatch_stream patchStream;
+    patchStream.opaque = (void *)&readInfo;
+    patchStream.read = bsdiff_read_impl;
+
+    int result = bspatch(reference.data(), reference.size(), current.data(), current.size(), &patchStream);
+    return result;
+}
diff --git a/czi/source_code/app/src/bsdiff/bsdiff.c b/czi/source_code/app/src/bsdiff/bsdiff.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe51439eec79b9ac73f6bb3b56d1d865b06a5cdb
--- /dev/null
+++ b/czi/source_code/app/src/bsdiff/bsdiff.c
@@ -0,0 +1,559 @@
+/*-
+ * 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 
+ * 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.
+ */
+
+#include <bsdiff/bsdiff.h>
+
+#include <limits.h>
+#include <string.h>
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+static void split(int64_t *I, int64_t *V, int64_t start, int64_t len, int64_t 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(int64_t *I, int64_t *V, const uint8_t *old, int64_t oldsize)
+{
+	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 int64_t matchlen(const uint8_t *old, int64_t oldsize, const uint8_t *new, int64_t newsize)
+{
+	int64_t i;
+
+	for (i = 0; (i < oldsize) && (i < newsize); i++)
+		if (old[i] != new[i])
+			break;
+
+	return i;
+}
+
+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)
+{
+	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(int64_t x, uint8_t *buf)
+{
+	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;
+}
+
+static int64_t writedata(struct bsdiff_stream *stream, const void *buffer, int64_t length)
+{
+	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;
+}
+
+struct bsdiff_request
+{
+	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 = (int64_t *)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 = (int64_t *)stream->malloc((oldsize + 1) * sizeof(int64_t))) == NULL)
+		return -1;
+
+	if ((req.buffer = (uint8_t *)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/source_code/root/app/include/bsdiff/bspatch.c b/czi/source_code/app/src/bsdiff/bspatch.c
similarity index 66%
rename from czi/source_code/root/app/include/bsdiff/bspatch.c
rename to czi/source_code/app/src/bsdiff/bspatch.c
index b5449147f624b2fa8c53191024167a270c0822d3..77855584b5331df56822722c3615be4a1b6f98eb 100644
--- a/czi/source_code/root/app/include/bsdiff/bspatch.c
+++ b/czi/source_code/app/src/bsdiff/bspatch.c
@@ -25,44 +25,55 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "bspatch.h"
+#include <bsdiff/bspatch.h>
 
 static int64_t offtin(uint8_t *buf)
 {
 	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];
-
-	if(buf[7]&0x80) y=-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];
+
+	if (buf[7] & 0x80)
+		y = -y;
 
 	return y;
 }
 
-int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream)
+int bspatch(const uint8_t *old, int64_t oldsize, uint8_t *new, int64_t newsize, struct bspatch_stream *stream)
 {
 	uint8_t buf[8];
-	int64_t oldpos,newpos;
+	int64_t oldpos, newpos;
 	int64_t ctrl[3];
 	int64_t i;
 
-	oldpos=0;newpos=0;
-	while(newpos<newsize) {
+	oldpos = 0;
+	newpos = 0;
+	while (newpos < newsize)
+	{
 		/* Read control data */
-		for(i=0;i<=2;i++) {
+		for (i = 0; i <= 2; i++)
+		{
 			if (stream->read(stream, buf, 8))
 				return -1;
-			ctrl[i]=offtin(buf);
+			ctrl[i] = offtin(buf);
 		};
 
 		/* Sanity-check */
-		if(newpos+ctrl[0]>newsize)
+		if (newpos + ctrl[0] > newsize)
 			return -1;
 
 		/* Read diff string */
@@ -70,16 +81,16 @@ int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize,
 			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];
+		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];
+		newpos += ctrl[0];
+		oldpos += ctrl[0];
 
 		/* Sanity-check */
-		if(newpos+ctrl[1]>newsize)
+		if (newpos + ctrl[1] > newsize)
 			return -1;
 
 		/* Read extra string */
@@ -87,8 +98,8 @@ int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize,
 			return -1;
 
 		/* Adjust pointers */
-		newpos+=ctrl[1];
-		oldpos+=ctrl[2];
+		newpos += ctrl[1];
+		oldpos += ctrl[2];
 	};
 
 	return 0;
@@ -107,13 +118,13 @@ int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize,
 #include <unistd.h>
 #include <fcntl.h>
 
-static int bz2_read(const struct bspatch_stream* stream, void* buffer, int length)
+static int bz2_read(const struct bspatch_stream *stream, void *buffer, int length)
 {
 	int n;
 	int bz2err;
-	BZFILE* bz2;
+	BZFILE *bz2;
 
-	bz2 = (BZFILE*)stream->opaque;
+	bz2 = (BZFILE *)stream->opaque;
 	n = BZ2_bzRead(&bz2err, bz2, buffer, length);
 	if (n != length)
 		return -1;
@@ -121,26 +132,28 @@ static int bz2_read(const struct bspatch_stream* stream, void* buffer, int lengt
 	return 0;
 }
 
-int main(int argc,char * argv[])
+int main(int argc, char *argv[])
 {
-	FILE * f;
+	FILE *f;
 	int fd;
 	int bz2err;
 	uint8_t header[24];
 	uint8_t *old, *new;
 	int64_t oldsize, newsize;
-	BZFILE* bz2;
+	BZFILE *bz2;
 	struct bspatch_stream stream;
 	struct stat sb;
 
-	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+	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 (fread(header, 1, 24, f) != 24)
+	{
 		if (feof(f))
 			errx(1, "Corrupt patch\n");
 		err(1, "fread(%s)", argv[3]);
@@ -151,19 +164,21 @@ int main(int argc,char * argv[])
 		errx(1, "Corrupt patch\n");
 
 	/* Read lengths from header */
-	newsize=offtin(header+16);
-	if(newsize<0)
-		errx(1,"Corrupt patch\n");
+	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) ||
+	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);
+		(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);
@@ -178,9 +193,9 @@ int main(int argc,char * argv[])
 	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]);
+	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);
diff --git a/czi/source_code/root/app/src/compression/benchmark.cpp b/czi/source_code/app/src/compression/benchmark.cpp
similarity index 95%
rename from czi/source_code/root/app/src/compression/benchmark.cpp
rename to czi/source_code/app/src/compression/benchmark.cpp
index 9ae8969f007b835ad9c607374aa68b6d9b686532..205bf40ee00b624cdbd87265e3670475eb34e9e2 100644
--- a/czi/source_code/root/app/src/compression/benchmark.cpp
+++ b/czi/source_code/app/src/compression/benchmark.cpp
@@ -13,7 +13,7 @@ void save_histogram(const std::map<T, size_t> &histogram, const char *fileName)
     oStream.close();
 }
 
-static void write_compression_report(const std::vector<BaseBenchmarkRecord> &results, const std::string &reportFile)
+void write_compression_report(const std::vector<BaseBenchmarkRecord> &results, const std::string &reportFile)
 {
     std::ofstream csvFile = std::ofstream(reportFile, std::ios::out);
     always_assert(csvFile.is_open());
@@ -29,7 +29,7 @@ static void write_compression_report(const std::vector<BaseBenchmarkRecord> &res
     }
 }
 
-static void write_diff_report(const std::vector<DiffBenchmarkRecord> &results, const std::string &reportFile)
+void write_diff_report(const std::vector<DiffBenchmarkRecord> &results, const std::string &reportFile)
 {
     std::ofstream csvFile = std::ofstream(reportFile, std::ios::out | std::ios::app);
     always_assert(csvFile.is_open());
@@ -45,14 +45,14 @@ static void write_diff_report(const std::vector<DiffBenchmarkRecord> &results, c
     }
 }
 
-static void compression_thread_work(const ByteArray &data, CompressionMethod method, int compressionLevel, CompressionResult &result, const char *info)
+void compression_thread_work(const ByteArray &data, CompressionMethod method, int compressionLevel, CompressionResult &result, const char *info)
 {
     auto compResult = test_compression_method(data, method, compressionLevel);
     result = compResult;
     printf("Completed: %s\n", info);
 }
 
-static std::vector<BaseBenchmarkRecord> benchmark_continuos_compression_one_level(const ByteArray &data, const ByteArray &zOrderedData, int compressionLevel)
+std::vector<BaseBenchmarkRecord> benchmark_continuos_compression_one_level(const ByteArray &data, const ByteArray &zOrderedData, int compressionLevel)
 {
     // CompressionMethod_GZIP
     CompressionResult gzipResult = {};
@@ -246,9 +246,10 @@ void benchmark_compression(CziFile &cziFile, const std::string &reportFile, bool
     printf("\nFinished benchmark, results are written in: %s\n", reportFile.c_str());
 }
 
-static void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cfData,
-                                    const CompressionMethod cm, const int compLevel, CompressionResult &cr)
+void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cfData,
+                             const CompressionMethod cm, const int compLevel, CompressionResult &cr)
 {
+    ushort USHORT_MAX = std::numeric_limits<ushort>::max();
 
     always_assert(pfData.size() == cfData.size());
 
@@ -282,10 +283,12 @@ static void _diff_from_frame_gray16(const ByteArray &pfData, const ByteArray &cf
     cr = test_compression_method(ushortMappedDeltaBytes, cm, compLevel);
 }
 
-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)
+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)
 {
 
+    ushort USHORT_MAX = std::numeric_limits<ushort>::max();
+
     always_assert(pfData.size() == cfData.size());
 
     std::vector<int> delta;
@@ -527,4 +530,4 @@ 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/source_code/app/src/compression/compressors.cpp b/czi/source_code/app/src/compression/compressors.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e04a36dceaa190f8e717e19ba099139507fb0200
--- /dev/null
+++ b/czi/source_code/app/src/compression/compressors.cpp
@@ -0,0 +1,186 @@
+#include <compression/compressors.h>
+
+const char *compression_method_str(const CompressionMethod cm)
+{
+    switch (cm)
+    {
+    case CompressionMethod_GZIP:
+        return GZIP_NAME;
+    case CompressionMethod_LZMA:
+        return LZMA_NAME;
+    case CompressionMethod_BZIP2:
+        return BZIP2_NAME;
+    default:
+        INVALID_CASE;
+    }
+    return nullptr;
+}
+
+ByteArray gzip_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
+{
+    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "ZLIB's compress2 takes compression level from 1 to 9 included!");
+
+    size_t compressedSize = library_zlib::compressBound(data.size());
+    ByteArray compressedBuffer;
+    // Maybe try reserve or normal array.
+    compressedBuffer.resize(compressedSize);
+
+    Stopwatch s;
+    s.start();
+    int compressionResult = library_zlib::compress2(compressedBuffer.data(), &compressedSize, data.data(), data.size(), compressionLevel);
+    s.stop();
+    info.compressionTimeMS = s.elapsed_milliseconds();
+
+    switch (compressionResult)
+    {
+    case Z_OK:
+        break;
+    case Z_MEM_ERROR:
+        printf(RED "There wasn't enaugh memory!\n" RESET);
+        break;
+    case Z_BUF_ERROR:
+        printf(RED "Output buffer was too small!\n" RESET);
+        break;
+    default:
+        INVALID_CASE;
+    }
+    always_assert(compressionResult == Z_OK);
+
+    ByteArray actualCompressedData(compressedBuffer.begin(), compressedBuffer.begin() + compressedSize);
+
+    always_assert(actualCompressedData.size() == compressedSize);
+
+    return actualCompressedData;
+}
+
+ByteArray lzma_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
+{
+    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "LZMA's lzma_easy_buffer_encode takes compression level from 1 to 9 included!");
+
+    size_t maximumSize = library_lzma::lzma_stream_buffer_bound(data.size());
+    ByteArray buffer;
+    buffer.resize(maximumSize);
+    size_t finalSize = 0;
+
+    Stopwatch s;
+    s.start();
+
+    auto compressionResult = library_lzma::lzma_easy_buffer_encode(compressionLevel, library_lzma::LZMA_CHECK_NONE,
+                                                                   nullptr, data.data(), data.size(),
+                                                                   buffer.data(), &finalSize, maximumSize);
+    s.stop();
+    info.compressionTimeMS = s.elapsed_milliseconds();
+
+    switch (compressionResult)
+    {
+    case library_lzma::LZMA_MEM_ERROR:
+        printf(RED "Unable to allocate memory!\n" RESET);
+        break;
+    case library_lzma::LZMA_MEMLIMIT_ERROR:
+        printf(RED "Memory limit was reached!\n" RESET);
+        break;
+    case library_lzma::LZMA_BUF_ERROR:
+        printf(RED "Cannot consume input buffer!\n" RESET);
+        break;
+    case library_lzma::LZMA_PROG_ERROR:
+        printf(RED "Wrong arguments!\n" RESET);
+        break;
+        // To make GCC with -Wall happy.
+    case library_lzma::LZMA_OK:
+    case library_lzma::LZMA_STREAM_END:
+    case library_lzma::LZMA_NO_CHECK:
+    case library_lzma::LZMA_UNSUPPORTED_CHECK:
+    case library_lzma::LZMA_GET_CHECK:
+    case library_lzma::LZMA_FORMAT_ERROR:
+    case library_lzma::LZMA_OPTIONS_ERROR:
+    case library_lzma::LZMA_DATA_ERROR:
+        break;
+    }
+    always_assert(compressionResult == library_lzma::LZMA_OK);
+
+    ByteArray result(buffer.begin(), buffer.begin() + finalSize);
+    always_assert(result.size() == finalSize);
+
+    return result;
+}
+
+ByteArray bzip2_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
+{
+    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "BZ2's BZ2_bzBuffToBuffCompress takes compression level from 1 to 9 included!");
+
+    // Maximum compressed size calculation, taken from documentation:
+    //
+    // To guarantee that the compressed data will fit in its buffer,
+    // allocate an output buffer of size 1% larger than the uncompressed data,
+    // plus six hundred extra bytes.
+
+    size_t maximumSize = (size_t)((float_t)data.size() * 3.0f) + 600;
+    ByteArray buffer;
+    buffer.resize(maximumSize);
+    size_t compressedSize = maximumSize;
+
+    //TODO: Find way without this copy...
+    ByteArray input(data.begin(), data.end());
+    always_assert(data.size() == input.size());
+
+    // Default as stated in documentation.
+    const int workFactor = 30;
+    Stopwatch s;
+    s.start();
+    int compressionResult = library_bzip2::BZ2_bzBuffToBuffCompress((char *)buffer.data(), (uint *)(&compressedSize),
+                                                                    (char *)input.data(), (uint)data.size(),
+                                                                    compressionLevel, 0, workFactor);
+    s.stop();
+    info.compressionTimeMS = s.elapsed_milliseconds();
+
+    switch (compressionResult)
+    {
+    case BZ_CONFIG_ERROR:
+        printf(RED "Bzip2 has been mis-compiled!\n" RESET);
+        break;
+    case BZ_PARAM_ERROR:
+        printf(RED "Wrong parameters!\n" RESET);
+        break;
+    case BZ_MEM_ERROR:
+        printf(RED "Not enaugh memory avaible!\n" RESET);
+        break;
+    case BZ_OUTBUFF_FULL:
+        printf(RED "Output buffer wasn't big enaugh!\n" RESET);
+        break;
+    }
+    always_assert(compressionResult == BZ_OK);
+
+    ByteArray result(buffer.begin(), buffer.begin() + compressedSize);
+    always_assert(result.size() == compressedSize);
+
+    return result;
+}
+
+CompressionResult test_compression_method(const ByteArray &data, CompressionMethod method, int compressionLevel)
+{
+    CompressionResult result = {};
+    {
+        ByteArray compressedData;
+        switch (method)
+        {
+        case CompressionMethod_GZIP:
+            compressedData = gzip_encode(data, compressionLevel, result);
+            break;
+        case CompressionMethod_LZMA:
+            compressedData = lzma_encode(data, compressionLevel, result);
+            break;
+        case CompressionMethod_BZIP2:
+            compressedData = bzip2_encode(data, compressionLevel, result);
+            break;
+        default:
+            INVALID_CASE;
+        }
+        result.compressedSize = compressedData.size();
+    }
+
+    result.originalSize = data.size();
+    result.compressionRatio = compression_ratio((float)result.originalSize, (float)result.compressedSize);
+    result.ratioToOriginalSize = (float)result.compressedSize / (float)result.originalSize;
+
+    return result;
+}
\ No newline at end of file
diff --git a/czi/source_code/root/app/src/czi/czi_file.cpp b/czi/source_code/app/src/czi/czi_file.cpp
similarity index 100%
rename from czi/source_code/root/app/src/czi/czi_file.cpp
rename to czi/source_code/app/src/czi/czi_file.cpp
diff --git a/czi/source_code/root/app/src/czi/czi_parser.cpp b/czi/source_code/app/src/czi/czi_parser.cpp
similarity index 100%
rename from czi/source_code/root/app/src/czi/czi_parser.cpp
rename to czi/source_code/app/src/czi/czi_parser.cpp
diff --git a/czi/source_code/root/app/include/czi/czi_parts/compression_type.h b/czi/source_code/app/src/czi/czi_parts/compression_type.cpp
similarity index 64%
rename from czi/source_code/root/app/include/czi/czi_parts/compression_type.h
rename to czi/source_code/app/src/czi/czi_parts/compression_type.cpp
index d5c3a171e7009641f24cb6ec26b58061d913f8c3..c079374783e6012b0522be60610bee0b781a94e6 100644
--- a/czi/source_code/root/app/include/czi/czi_parts/compression_type.h
+++ b/czi/source_code/app/src/czi/czi_parts/compression_type.cpp
@@ -1,17 +1,4 @@
-#pragma once
-
-enum CompressionType
-{
-    // Uncompressed pixels.
-    CompressionType_Uncompressed = 0,
-    CompressionType_JpgFile = 1,
-    CompressionType_LZW = 2,
-    CompressionType_JpegXrFile = 4,
-    // Camera specific RAW data.
-    CompressionType_Camera,
-    // System specific RAW data.
-    CompressionType_System
-};
+#include <czi/czi_parts/compression_type.h>
 
 const char *compression_type_str(const CompressionType ct)
 {
diff --git a/czi/source_code/root/app/include/czi/czi_parts/dimension.h b/czi/source_code/app/src/czi/czi_parts/dimension.cpp
similarity index 55%
rename from czi/source_code/root/app/include/czi/czi_parts/dimension.h
rename to czi/source_code/app/src/czi/czi_parts/dimension.cpp
index eb31dbce374ae06c94153fd92bb51e0fa2508585..dfbdb4eac633ba6b245b55c86ba8dad66fa1388a 100644
--- a/czi/source_code/root/app/include/czi/czi_parts/dimension.h
+++ b/czi/source_code/app/src/czi/czi_parts/dimension.cpp
@@ -1,32 +1,5 @@
-#pragma once
-
-enum Dimension
-{
-    // Pixel index / offset in the X direction. Used for tiled images.
-    Dimension_X = 'X',
-    // Pixel index / offset in the Y direction. Used for tiled images.
-    Dimension_Y = 'Y',
-    // Channel in a Multi-Channel data set.
-    Dimension_C = 'C',
-    // Slice index (Z – direction).
-    Dimension_Z = 'Z',
-    // Time point in a sequentially acquired series of data.
-    Dimension_T = 'T',
-    // Rotation – used in acquisition modes where the data is recorded from various angles.
-    Dimension_R = 'R',
-    // Scene – for clustering items in X/Y direction (data belonging to contiguous regions of interests in a mosaic image).
-    Dimension_S = 'S',
-    // Illumination - illumination direction index (e.g. from left=0, from right=1).
-    Dimension_I = 'I',
-    // (Acquisition) Block index in segmented experiments. Note: This index has been dropped. Instead of the B index multiple single CZI images will be generated when saving segmented experiments.
-    Dimension_B = 'B',
-    // Mosaic tile index – this index uniquely identifies all tiles in a  specific plane.
-    Dimension_M = 'M',
-    // Phase index – for specific acquisition methods.
-    Dimension_H = 'H',
-    // View index (for multi – view images, e.g. SPIM)
-    Dimension_V = 'V'
-};
+#include <czi/czi_parts/dimension.h>
+#include <azgra/azgra.h>
 
 const char *dimension_type_str(const Dimension &d)
 {
diff --git a/czi/source_code/root/app/include/czi/czi_parts/pixel_type.h b/czi/source_code/app/src/czi/czi_parts/pixel_type.cpp
similarity index 70%
rename from czi/source_code/root/app/include/czi/czi_parts/pixel_type.h
rename to czi/source_code/app/src/czi/czi_parts/pixel_type.cpp
index d8ae235fb566aa7aa82cbdd374cd7e6c073ebf27..66336e6bb242970f87400b67b5b394c3513fd96c 100644
--- a/czi/source_code/root/app/include/czi/czi_parts/pixel_type.h
+++ b/czi/source_code/app/src/czi/czi_parts/pixel_type.cpp
@@ -1,33 +1,4 @@
-#pragma once
-#include <azgra/azgra.h>
-
-enum PixelType
-{
-    // 8 bit unsigned.
-    PixelType_Gray8 = 0,
-    // 16 bit unsigned
-    PixelType_Gray16 = 1,
-    // 32 bit IEEE float.
-    PixelType_Gray32Float = 2,
-    // 8 bit for each color channel (blue, green, red).
-    PixelType_Bgr24 = 3,
-    // 16 bit for each color channel (blue, green, red).
-    PixelType_Bgr48 = 4,
-    // 32 bit IEEE float for each color channel.
-    PixelType_Bgr96Float = 8,
-    // 8 bit for each color channel (blue, green, red) and alpha channel.
-    PixelType_Bgra32 = 9,
-    // 2 x 32 bit IEEE float for real and imaginary part of complex number.
-    PixelType_Gray64ComplexFloat = 10,
-    // 32 bit IEEE float for real and imaginary part of each color channel.
-    PixelType_Bgr192ComplexFloat = 11,
-    // [Planned] 32 bit integer.
-    PixelType_Gray32 = 12,
-    // [Planned] Double precision floating point.
-    PixelType_Gray64 = 13,
-    // For internal usage.
-    PixelType_None
-};
+#include <czi/czi_parts/pixel_type.h>
 
 // Get number of bytes needed to encode specific `PixelType`
 int get_bytes_per_pixel_type(const PixelType &pt)
diff --git a/czi/source_code/root/app/include/czi/czi_parts/pyramid_type.h b/czi/source_code/app/src/czi/czi_parts/pyramid_type.cpp
similarity index 75%
rename from czi/source_code/root/app/include/czi/czi_parts/pyramid_type.h
rename to czi/source_code/app/src/czi/czi_parts/pyramid_type.cpp
index cac3d514c9edf45374f740491f6faa45921eaf43..24cebce4c610c14e625997c8ac9bc7410aeca1ec 100644
--- a/czi/source_code/root/app/include/czi/czi_parts/pyramid_type.h
+++ b/czi/source_code/app/src/czi/czi_parts/pyramid_type.cpp
@@ -1,11 +1,5 @@
-#pragma once
-
-enum PyramidType
-{
-    PyramidType_None = 0,
-    PyramidType_SingleSubBlock = 1,
-    PyramidType_MultiSubBlock = 2
-};
+#include <czi/czi_parts/pyramid_type.h>
+#include <azgra/azgra.h>
 
 const char *pyramid_type_str(const PyramidType pt)
 {
diff --git a/czi/source_code/root/app/include/filesystem/file_system.h b/czi/source_code/app/src/filesystem/file_system.cpp
similarity index 92%
rename from czi/source_code/root/app/include/filesystem/file_system.h
rename to czi/source_code/app/src/filesystem/file_system.cpp
index d45bd917ad0d45bd575c4231ecd176b0afbd4a0e..0bd172d2f9a218d5da8395e0c56dcd4f5095f216 100644
--- a/czi/source_code/root/app/include/filesystem/file_system.h
+++ b/czi/source_code/app/src/filesystem/file_system.cpp
@@ -1,29 +1,16 @@
-#pragma once
+#include <filesystem/file_system.h>
+
 /*
 * Copyright Moravec Vojtech 2019.
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
 */
 
-#include "boost/filesystem.hpp"
-#include "boost/algorithm/string.hpp"
-
 namespace fs_wrapper
 {
 
 namespace fs = boost::filesystem;
 
-// CZI file extension.
-constexpr char CziExtUpperCase[] = ".CZI";
-
-struct SmallFileInfo
-{
-    // Name of the file.
-    std::string name;
-    // Whole path to file.
-    std::string path;
-};
-
 // Check if given path points to file.
 bool is_file(const std::string &pathToCheck)
 {
diff --git a/czi/source_code/app/src/image/cimg_wrapper.cpp b/czi/source_code/app/src/image/cimg_wrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ce572bbe1897291976cd7bf1fba99000d7b1dc0
--- /dev/null
+++ b/czi/source_code/app/src/image/cimg_wrapper.cpp
@@ -0,0 +1 @@
+#include <image/cimg_wrapper.h>
diff --git a/czi/source_code/root/app/src/image/image_matrix.cpp b/czi/source_code/app/src/image/image_matrix.cpp
similarity index 100%
rename from czi/source_code/root/app/src/image/image_matrix.cpp
rename to czi/source_code/app/src/image/image_matrix.cpp
diff --git a/czi/source_code/root/app/include/image/pixel_parse_functions.h b/czi/source_code/app/src/image/pixel_parse_functions.cpp
similarity index 95%
rename from czi/source_code/root/app/include/image/pixel_parse_functions.h
rename to czi/source_code/app/src/image/pixel_parse_functions.cpp
index 83d2594e53da08e1cd13217203deb87d53bbd6cc..920e3d692917a293d142f5b89b4293f9449bc06c 100644
--- a/czi/source_code/root/app/include/image/pixel_parse_functions.h
+++ b/czi/source_code/app/src/image/pixel_parse_functions.cpp
@@ -1,8 +1,4 @@
-#pragma once
-#include <azgra/stream/binary_converter.h>
-#include "pixel_structures.h"
-#include <custom_types.h>
-#include <czi/czi_parts/pixel_type.h>
+#include <image/pixel_parse_functions.h>
 
 std::shared_ptr<Gray8Pixel> bytes_to_Gray8Pixel(const ByteArray &bytes, ulong &index)
 {
diff --git a/czi/source_code/root/azgra_lib/CMakeLists.txt b/czi/source_code/azgra_lib/CMakeLists.txt
similarity index 93%
rename from czi/source_code/root/azgra_lib/CMakeLists.txt
rename to czi/source_code/azgra_lib/CMakeLists.txt
index f63a24fd4b6b6dd5e3ecfcd48bf310dcff6a7312..cec0079e319d6c6c5078af3699a6f416769159e8 100644
--- a/czi/source_code/root/azgra_lib/CMakeLists.txt
+++ b/czi/source_code/azgra_lib/CMakeLists.txt
@@ -9,6 +9,7 @@ add_library(${PROJECT_NAME} STATIC
     src/stream/buffered_binary_stream.cpp
     src/stream/memory_bit_stream.cpp
     src/utilities/Stopwatch.cpp
+    src/utilities/z_order.cpp
     )
 
 add_library(sub::azgra ALIAS ${PROJECT_NAME})
diff --git a/czi/source_code/root/azgra_lib/include/azgra/always_on_assert.h b/czi/source_code/azgra_lib/include/azgra/always_on_assert.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/always_on_assert.h
rename to czi/source_code/azgra_lib/include/azgra/always_on_assert.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/azgra.h b/czi/source_code/azgra_lib/include/azgra/azgra.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/azgra.h
rename to czi/source_code/azgra_lib/include/azgra/azgra.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/binary_converter.h b/czi/source_code/azgra_lib/include/azgra/stream/binary_converter.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/binary_converter.h
rename to czi/source_code/azgra_lib/include/azgra/stream/binary_converter.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/binary_file_stream.h b/czi/source_code/azgra_lib/include/azgra/stream/binary_file_stream.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/binary_file_stream.h
rename to czi/source_code/azgra_lib/include/azgra/stream/binary_file_stream.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/binary_stream_base.h b/czi/source_code/azgra_lib/include/azgra/stream/binary_stream_base.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/binary_stream_base.h
rename to czi/source_code/azgra_lib/include/azgra/stream/binary_stream_base.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/binary_writer.h b/czi/source_code/azgra_lib/include/azgra/stream/binary_writer.h
similarity index 77%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/binary_writer.h
rename to czi/source_code/azgra_lib/include/azgra/stream/binary_writer.h
index 966d42d9b084b9d01da9132983eb5c04071e1a6d..8cff2182e74f8877ffddc63ff61955e5bbf38897 100644
--- a/czi/source_code/root/azgra_lib/include/azgra/stream/binary_writer.h
+++ b/czi/source_code/azgra_lib/include/azgra/stream/binary_writer.h
@@ -2,7 +2,7 @@
 #include <azgra/azgra.h>
 #include <fstream>
 
-void write_bytes_to_file(const ByteArray &bytes, const char *fileName)
+inline void write_bytes_to_file(const ByteArray &bytes, const char *fileName)
 {
     std::ofstream binaryStream(fileName, std::ios::binary | std::ios::out);
     always_assert(binaryStream.is_open());
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/buffer_source_type.h b/czi/source_code/azgra_lib/include/azgra/stream/buffer_source_type.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/buffer_source_type.h
rename to czi/source_code/azgra_lib/include/azgra/stream/buffer_source_type.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/buffered_binary_stream.h b/czi/source_code/azgra_lib/include/azgra/stream/buffered_binary_stream.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/buffered_binary_stream.h
rename to czi/source_code/azgra_lib/include/azgra/stream/buffered_binary_stream.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/stream/memory_bit_stream.h b/czi/source_code/azgra_lib/include/azgra/stream/memory_bit_stream.h
similarity index 88%
rename from czi/source_code/root/azgra_lib/include/azgra/stream/memory_bit_stream.h
rename to czi/source_code/azgra_lib/include/azgra/stream/memory_bit_stream.h
index 381081c32dad9648c9199fa06283d05d10ddd1e0..d1eeeff3b9c3ec6195c80af27d3390514506059b 100644
--- a/czi/source_code/root/azgra_lib/include/azgra/stream/memory_bit_stream.h
+++ b/czi/source_code/azgra_lib/include/azgra/stream/memory_bit_stream.h
@@ -113,20 +113,4 @@ class InMemoryBitStream
 };
 
 // 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;
-}
\ No newline at end of file
+size_t bits_required(size_t maxValue);
\ No newline at end of file
diff --git a/czi/source_code/root/azgra_lib/include/azgra/utilities/Stopwatch.h b/czi/source_code/azgra_lib/include/azgra/utilities/Stopwatch.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/utilities/Stopwatch.h
rename to czi/source_code/azgra_lib/include/azgra/utilities/Stopwatch.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/utilities/type_mapper.h b/czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h
similarity index 100%
rename from czi/source_code/root/azgra_lib/include/azgra/utilities/type_mapper.h
rename to czi/source_code/azgra_lib/include/azgra/utilities/type_mapper.h
diff --git a/czi/source_code/root/azgra_lib/include/azgra/utilities/vector_utilities.h b/czi/source_code/azgra_lib/include/azgra/utilities/vector_utilities.h
similarity index 98%
rename from czi/source_code/root/azgra_lib/include/azgra/utilities/vector_utilities.h
rename to czi/source_code/azgra_lib/include/azgra/utilities/vector_utilities.h
index c2fc2474b1a91c3ef3e3e9eabd30a69e8bc5adb9..274761c2594b333f9fae4dadc05bf8329579faaa 100644
--- a/czi/source_code/root/azgra_lib/include/azgra/utilities/vector_utilities.h
+++ b/czi/source_code/azgra_lib/include/azgra/utilities/vector_utilities.h
@@ -1,4 +1,5 @@
 #pragma once
+#include <azgra/azgra.h>
 #include <vector>
 #include <algorithm>
 #include <limits>
@@ -139,4 +140,4 @@ std::map<T, size_t> create_histogram(const std::vector<T> &data)
     return histogram;
 }
 
-}; // namespace vecUtil
\ No newline at end of file
+}; // namespace vecUtil
diff --git a/czi/source_code/root/azgra_lib/include/azgra/utilities/z_order.h b/czi/source_code/azgra_lib/include/azgra/utilities/z_order.h
similarity index 57%
rename from czi/source_code/root/azgra_lib/include/azgra/utilities/z_order.h
rename to czi/source_code/azgra_lib/include/azgra/utilities/z_order.h
index 37f4d10259cd521b21f08612a9622fb205097038..27e511cc8aaf807baa1947a7b6042b0894032986 100644
--- a/czi/source_code/root/azgra_lib/include/azgra/utilities/z_order.h
+++ b/czi/source_code/azgra_lib/include/azgra/utilities/z_order.h
@@ -1,7 +1,7 @@
 #pragma once
 #include <azgra/azgra.h>
 #include <algorithm>
-
+#include <azgra/utilities/vector_utilities.h>
 /*
     Interleave implementation based on:
         https://lemire.me/blog/2018/01/08/how-fast-can-you-bit-interleave-32-bit-integers/
@@ -29,12 +29,12 @@ static inline uint deinterleave_lowuint32(ulong word)
     return (uint)word;
 }
 
-ulong interleave(uint x, uint y)
+inline ulong interleave(uint x, uint y)
 {
     return interleave_uint_with_zeros(x) | (interleave_uint_with_zeros(y) << 1);
 }
 
-std::pair<uint, uint> deinterleave(ulong input)
+inline std::pair<uint, uint> deinterleave(ulong input)
 {
     uint x = deinterleave_lowuint32(input);
     uint y = deinterleave_lowuint32(input >> 1);
@@ -67,64 +67,9 @@ struct PointWithIndex
     bool operator>=(const PointWithIndex &other) const { return (z >= other.z); }
 };
 
-std::vector<PointWithIndex> generate_ordered_z_order_indices(const uint colCount, const uint rowCount, const uint componentCount)
-{
-    std::vector<PointWithIndex> result;
-    result.resize((colCount * componentCount) * rowCount);
-
-    // This doesnt count with bytes per pixel
-    size_t index = 0;
-    for (uint row = 0; row < rowCount; row++)
-    {
-        for (uint col = 0; col < (colCount * componentCount); col++)
-        {
-            result[index] = PointWithIndex(col, row, index);
-            index++;
-        }
-    }
-
-    always_assert(((ulong)(colCount * componentCount) * (ulong)rowCount) == result.size());
-    std::sort(result.begin(), result.end());
-
-    return result;
-}
+std::vector<PointWithIndex> generate_ordered_z_order_indices(const uint colCount, const uint rowCount, const uint componentCount);
 
 ByteArray reorder_bytes_to_z_order(const ByteArray &bytes, const std::vector<PointWithIndex> &zIndices,
-                                   const uint componentSize)
-{
-    ByteArray zOrderedBytes;
-    zOrderedBytes.resize(bytes.size());
-    size_t it = 0;
-    size_t from, pos;
-    for (const PointWithIndex &index : zIndices)
-    {
-        from = (index.bufferPosition * componentSize);
-        //zOrderedBytes.insert(zOrderedBytes.end(), fromIt, toIt);
-        pos = it * componentSize;
-        vecUtil::vector_insert_at(zOrderedBytes, bytes, pos, from, componentSize);
-        it++;
-    }
-
-    always_assert(zOrderedBytes.size() == bytes.size());
-    return zOrderedBytes;
-}
-
+                                   const uint componentSize);
 ByteArray reorder_bytes_from_z_order(const ByteArray &zOrderedBytes, const std::vector<PointWithIndex> &zIndices,
-                                     const uint componentSize)
-{
-    ByteArray bytes;
-    bytes.resize(zOrderedBytes.size());
-
-    size_t it = 0;
-    size_t insertAt, copyFrom;
-    for (const PointWithIndex &index : zIndices)
-    {
-        insertAt = index.bufferPosition * componentSize;
-        copyFrom = it * componentSize;
-        vecUtil::vector_insert_at(bytes, zOrderedBytes, insertAt, copyFrom, componentSize);
-        ++it;
-    }
-    always_assert(bytes.size() == zOrderedBytes.size());
-
-    return bytes;
-}
\ No newline at end of file
+                                     const uint componentSize);
\ No newline at end of file
diff --git a/czi/source_code/root/azgra_lib/src/stream/binary_converter.cpp b/czi/source_code/azgra_lib/src/stream/binary_converter.cpp
similarity index 100%
rename from czi/source_code/root/azgra_lib/src/stream/binary_converter.cpp
rename to czi/source_code/azgra_lib/src/stream/binary_converter.cpp
diff --git a/czi/source_code/root/azgra_lib/src/stream/binary_file_stream.cpp b/czi/source_code/azgra_lib/src/stream/binary_file_stream.cpp
similarity index 100%
rename from czi/source_code/root/azgra_lib/src/stream/binary_file_stream.cpp
rename to czi/source_code/azgra_lib/src/stream/binary_file_stream.cpp
diff --git a/czi/source_code/root/azgra_lib/src/stream/binary_stream_base.cpp b/czi/source_code/azgra_lib/src/stream/binary_stream_base.cpp
similarity index 100%
rename from czi/source_code/root/azgra_lib/src/stream/binary_stream_base.cpp
rename to czi/source_code/azgra_lib/src/stream/binary_stream_base.cpp
diff --git a/czi/source_code/root/azgra_lib/src/stream/buffered_binary_stream.cpp b/czi/source_code/azgra_lib/src/stream/buffered_binary_stream.cpp
similarity index 100%
rename from czi/source_code/root/azgra_lib/src/stream/buffered_binary_stream.cpp
rename to czi/source_code/azgra_lib/src/stream/buffered_binary_stream.cpp
diff --git a/czi/source_code/root/azgra_lib/src/stream/memory_bit_stream.cpp b/czi/source_code/azgra_lib/src/stream/memory_bit_stream.cpp
similarity index 88%
rename from czi/source_code/root/azgra_lib/src/stream/memory_bit_stream.cpp
rename to czi/source_code/azgra_lib/src/stream/memory_bit_stream.cpp
index 3225447176e91e0f126c730e94000df96c7e1524..05a61c19da94ea74adb5efc8691680dfade5cf98 100644
--- a/czi/source_code/root/azgra_lib/src/stream/memory_bit_stream.cpp
+++ b/czi/source_code/azgra_lib/src/stream/memory_bit_stream.cpp
@@ -147,4 +147,22 @@ void InMemoryBitStream::operator>>(bool &bit)
 bool InMemoryBitStream::can_read() const
 {
     return ((bitBufferSize > 0) || (memoryBufferPosition < memoryBuffer->size()));
+}
+
+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;
 }
\ No newline at end of file
diff --git a/czi/source_code/root/azgra_lib/src/utilities/Stopwatch.cpp b/czi/source_code/azgra_lib/src/utilities/Stopwatch.cpp
similarity index 100%
rename from czi/source_code/root/azgra_lib/src/utilities/Stopwatch.cpp
rename to czi/source_code/azgra_lib/src/utilities/Stopwatch.cpp
diff --git a/czi/source_code/azgra_lib/src/utilities/z_order.cpp b/czi/source_code/azgra_lib/src/utilities/z_order.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4bb2c09ddcfac885cf8d10e1c3f3cf3c3a3a8ae
--- /dev/null
+++ b/czi/source_code/azgra_lib/src/utilities/z_order.cpp
@@ -0,0 +1,63 @@
+#include <azgra/utilities/z_order.h>
+
+std::vector<PointWithIndex> generate_ordered_z_order_indices(const uint colCount, const uint rowCount, const uint componentCount)
+{
+    std::vector<PointWithIndex> result;
+    result.resize((colCount * componentCount) * rowCount);
+
+    // This doesnt count with bytes per pixel
+    size_t index = 0;
+    for (uint row = 0; row < rowCount; row++)
+    {
+        for (uint col = 0; col < (colCount * componentCount); col++)
+        {
+            result[index] = PointWithIndex(col, row, index);
+            index++;
+        }
+    }
+
+    always_assert(((ulong)(colCount * componentCount) * (ulong)rowCount) == result.size());
+    std::sort(result.begin(), result.end());
+
+    return result;
+}
+
+ByteArray reorder_bytes_to_z_order(const ByteArray &bytes, const std::vector<PointWithIndex> &zIndices,
+                                   const uint componentSize)
+{
+    ByteArray zOrderedBytes;
+    zOrderedBytes.resize(bytes.size());
+    size_t it = 0;
+    size_t from, pos;
+    for (const PointWithIndex &index : zIndices)
+    {
+        from = (index.bufferPosition * componentSize);
+        //zOrderedBytes.insert(zOrderedBytes.end(), fromIt, toIt);
+        pos = it * componentSize;
+        vecUtil::vector_insert_at(zOrderedBytes, bytes, pos, from, componentSize);
+        it++;
+    }
+
+    always_assert(zOrderedBytes.size() == bytes.size());
+    return zOrderedBytes;
+}
+
+ByteArray reorder_bytes_from_z_order(const ByteArray &zOrderedBytes, const std::vector<PointWithIndex> &zIndices,
+                                     const uint componentSize)
+{
+    ByteArray bytes;
+    bytes.resize(zOrderedBytes.size());
+
+    size_t it = 0;
+    size_t insertAt, copyFrom;
+    for (const PointWithIndex &index : zIndices)
+    {
+        insertAt = index.bufferPosition * componentSize;
+        copyFrom = it * componentSize;
+        vecUtil::vector_insert_at(bytes, zOrderedBytes, insertAt, copyFrom, componentSize);
+        ++it;
+    }
+    always_assert(bytes.size() == zOrderedBytes.size());
+
+    return bytes;
+}
\ No newline at end of file
diff --git a/czi/source_code/root/CMakeLists.txt b/czi/source_code/root/CMakeLists.txt
deleted file mode 100644
index 0e69240453625fae2b331c3ce39e0c7f4462f021..0000000000000000000000000000000000000000
--- a/czi/source_code/root/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-cmake_minimum_required(VERSION 3.0.0)
-
-project(semestral-project)
-
-add_subdirectory(azgra_lib)
-add_subdirectory(app)
\ No newline at end of file
diff --git a/czi/source_code/root/app/include/bsdiff/api_bsdiff.h b/czi/source_code/root/app/include/bsdiff/api_bsdiff.h
deleted file mode 100644
index 16f78bf64e606a1271b485b8566feb47d566d143..0000000000000000000000000000000000000000
--- a/czi/source_code/root/app/include/bsdiff/api_bsdiff.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#pragma once
-#include "../custom_types.h"
-
-namespace _bsdiff
-{
-#define new _new
-#include "bsdiff.h"
-#include "bsdiff.c"
-#include "bspatch.h"
-#include "bspatch.c"
-#undef new
-
-struct bsdiff_read_info
-{
-    ByteArray readBuffer;
-    size_t readPos = 0;
-};
-
-static int bsdiff_write_impl(_bsdiff::bsdiff_stream *stream, const void *buffer, int size)
-{
-    ByteArray *vectorBuffer = (ByteArray *)stream->opaque;
-    byte *dataBuffer = (byte *)buffer;
-
-    vectorBuffer->insert(vectorBuffer->end(), dataBuffer, (dataBuffer + size));
-    return 0;
-}
-
-int bsdiff_read_impl(const struct _bsdiff::bspatch_stream *stream, void *buffer, int length)
-{
-    bsdiff_read_info *readInfo = (bsdiff_read_info *)stream->opaque;
-    byte *dataBuffer = (byte *)buffer;
-
-    for (int i = 0; i < length; i++)
-    {
-        dataBuffer[i] = readInfo->readBuffer[readInfo->readPos + i];
-    }
-    readInfo->readPos += length;
-
-    return 0;
-}
-}; // namespace _bsdiff
-/**
- * @brief 
- */
-constexpr int BSDIFF_API_SUCCESS = 0;
-constexpr int BSDIFF_API_FAILURE = -1;
-
-/**
- * @brief Create binary patch, which can be used to create current buffer from reference buffer. Patch is not compressed.
- * @param reference Reference data buffer.
- * @param current Current data buffer.
- * @param patchBuffer Patch buffer.
- * @return int BSDIFF_API_SUCCESS on success.
- */
-int bsdiff_create_patch(const ByteArray &reference, const ByteArray &current, ByteArray &patchBuffer)
-{
-    struct _bsdiff::bsdiff_stream patchStream;
-    patchStream.free = free;
-    patchStream.malloc = malloc;
-    patchStream.opaque = (void *)&patchBuffer;
-    patchStream.write = _bsdiff::bsdiff_write_impl;
-
-    int result = _bsdiff::bsdiff(reference.data(), reference.size(), current.data(), current.size(), &patchStream);
-    return result;
-}
-
-/**
- * @brief Apply binary patch to create current data buffer from reference buffer. 
- * 
- * @param reference Reference buffer.
- * @param patch Bsdiff patch buffer.
- * @param current Buffer to which data will be written.
- * @return int BSDIFF_API_SUCCESS on success.
- */
-int bsdiff_apply_patch(const ByteArray &reference, const ByteArray &patch, ByteArray &current)
-{
-    _bsdiff::bsdiff_read_info readInfo = {};
-    readInfo.readPos = 0;
-    readInfo.readBuffer = patch;
-
-    struct _bsdiff::bspatch_stream patchStream;
-    patchStream.opaque = (void *)&readInfo;
-    patchStream.read = _bsdiff::bsdiff_read_impl;
-
-    int result = _bsdiff::bspatch(reference.data(), reference.size(), current.data(), current.size(), &patchStream);
-    return result;
-}
diff --git a/czi/source_code/root/app/include/bsdiff/bsdiff.c b/czi/source_code/root/app/include/bsdiff/bsdiff.c
deleted file mode 100644
index ff5c0f216ae43923a740c35fb550990e54244e5a..0000000000000000000000000000000000000000
--- a/czi/source_code/root/app/include/bsdiff/bsdiff.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*-
- * 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 
- * 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.
- */
-
-#include "bsdiff.h"
-
-#include <limits.h>
-#include <string.h>
-
-#define MIN(x,y) (((x)<(y)) ? (x) : (y))
-
-static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t 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(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
-{
-	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 int64_t matchlen(const uint8_t *old,int64_t oldsize,const uint8_t *new,int64_t newsize)
-{
-	int64_t i;
-
-	for(i=0;(i<oldsize)&&(i<newsize);i++)
-		if(old[i]!=new[i]) break;
-
-	return i;
-}
-
-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)
-{
-	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(int64_t x,uint8_t *buf)
-{
-	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;
-}
-
-static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
-{
-	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;
-}
-
-struct bsdiff_request
-{
-	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=(int64_t *)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=(int64_t *)stream->malloc((oldsize+1)*sizeof(int64_t)))==NULL)
-		return -1;
-
-	if((req.buffer=(uint8_t *)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/source_code/root/app/include/compression/compressors.h b/czi/source_code/root/app/include/compression/compressors.h
deleted file mode 100644
index d8a9c86c280bff43e70ca798fe0b0d56d3b28104..0000000000000000000000000000000000000000
--- a/czi/source_code/root/app/include/compression/compressors.h
+++ /dev/null
@@ -1,480 +0,0 @@
-#pragma once
-#include <azgra/utilities/vector_utilities.h>
-#include <azgra/utilities/z_order.h>
-#include <azgra/utilities/Stopwatch.h>
-#include <custom_types.h>
-
-namespace library_zlib
-{
-#include <zlib.h>
-};
-
-namespace library_lzma
-{
-#include <lzma.h>
-};
-
-namespace library_bzip2
-{
-#include <bzlib.h>
-};
-
-enum CompressionMethod
-{
-    CompressionMethod_GZIP,
-    CompressionMethod_LZMA,
-    CompressionMethod_BZIP2,
-};
-
-const char *compression_method_str(const CompressionMethod cm)
-{
-    switch (cm)
-    {
-    case CompressionMethod_GZIP:
-        return GZIP_NAME;
-    case CompressionMethod_LZMA:
-        return LZMA_NAME;
-    case CompressionMethod_BZIP2:
-        return BZIP2_NAME;
-    default:
-        INVALID_CASE;
-    }
-    return nullptr;
-}
-
-struct CompressionResult
-{
-    size_t originalSize;
-    size_t compressedSize;
-    float compressionRatio;
-    float ratioToOriginalSize;
-    double compressionTimeMS;
-
-    CompressionResult()
-    {
-        originalSize = 0;
-        compressedSize = 0;
-        compressionRatio = 0.0f;
-        compressionTimeMS = 0;
-        ratioToOriginalSize = 0;
-    }
-
-    void divide(float x)
-    {
-        originalSize /= x;
-        compressedSize /= x;
-        compressionRatio /= x;
-        ratioToOriginalSize /= x;
-    }
-};
-
-constexpr size_t MAX_LITERAL_COUNT = 255;
-constexpr size_t MAX_RUN_COUNT = 255;
-constexpr size_t MAX_LOOKBACK_COUNT = 255;
-
-inline float compression_ratio(float uncompressedSize, float compressedSize)
-{
-    return (uncompressedSize / compressedSize);
-}
-
-ByteArray gzip_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
-{
-    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "ZLIB's compress2 takes compression level from 1 to 9 included!");
-
-    size_t compressedSize = library_zlib::compressBound(data.size());
-    ByteArray compressedBuffer;
-    // Maybe try reserve or normal array.
-    compressedBuffer.resize(compressedSize);
-
-    Stopwatch s;
-    s.start();
-    int compressionResult = library_zlib::compress2(compressedBuffer.data(), &compressedSize, data.data(), data.size(), compressionLevel);
-    s.stop();
-    info.compressionTimeMS = s.elapsed_milliseconds();
-
-    switch (compressionResult)
-    {
-    case Z_OK:
-        break;
-    case Z_MEM_ERROR:
-        printf(RED "There wasn't enaugh memory!\n" RESET);
-        break;
-    case Z_BUF_ERROR:
-        printf(RED "Output buffer was too small!\n" RESET);
-        break;
-    default:
-        INVALID_CASE;
-    }
-    always_assert(compressionResult == Z_OK);
-
-    ByteArray actualCompressedData(compressedBuffer.begin(), compressedBuffer.begin() + compressedSize);
-
-    always_assert(actualCompressedData.size() == compressedSize);
-
-    return actualCompressedData;
-}
-
-ByteArray lzma_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
-{
-    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "LZMA's lzma_easy_buffer_encode takes compression level from 1 to 9 included!");
-
-    size_t maximumSize = library_lzma::lzma_stream_buffer_bound(data.size());
-    ByteArray buffer;
-    buffer.resize(maximumSize);
-    size_t finalSize = 0;
-
-    Stopwatch s;
-    s.start();
-
-    auto compressionResult = library_lzma::lzma_easy_buffer_encode(compressionLevel, library_lzma::LZMA_CHECK_NONE,
-                                                                   nullptr, data.data(), data.size(),
-                                                                   buffer.data(), &finalSize, maximumSize);
-    s.stop();
-    info.compressionTimeMS = s.elapsed_milliseconds();
-
-    switch (compressionResult)
-    {
-    case library_lzma::LZMA_MEM_ERROR:
-        printf(RED "Unable to allocate memory!\n" RESET);
-        break;
-    case library_lzma::LZMA_MEMLIMIT_ERROR:
-        printf(RED "Memory limit was reached!\n" RESET);
-        break;
-    case library_lzma::LZMA_BUF_ERROR:
-        printf(RED "Cannot consume input buffer!\n" RESET);
-        break;
-    case library_lzma::LZMA_PROG_ERROR:
-        printf(RED "Wrong arguments!\n" RESET);
-        break;
-        // To make GCC with -Wall happy.
-    case library_lzma::LZMA_OK:
-    case library_lzma::LZMA_STREAM_END:
-    case library_lzma::LZMA_NO_CHECK:
-    case library_lzma::LZMA_UNSUPPORTED_CHECK:
-    case library_lzma::LZMA_GET_CHECK:
-    case library_lzma::LZMA_FORMAT_ERROR:
-    case library_lzma::LZMA_OPTIONS_ERROR:
-    case library_lzma::LZMA_DATA_ERROR:
-        break;
-    }
-    always_assert(compressionResult == library_lzma::LZMA_OK);
-
-    ByteArray result(buffer.begin(), buffer.begin() + finalSize);
-    always_assert(result.size() == finalSize);
-
-    return result;
-}
-
-ByteArray bzip2_encode(const ByteArray &data, int compressionLevel, CompressionResult &info)
-{
-    always_assert((compressionLevel >= 0 && compressionLevel <= 9) && "BZ2's BZ2_bzBuffToBuffCompress takes compression level from 1 to 9 included!");
-
-    // Maximum compressed size calculation, taken from documentation:
-    //
-    // To guarantee that the compressed data will fit in its buffer,
-    // allocate an output buffer of size 1% larger than the uncompressed data,
-    // plus six hundred extra bytes.
-
-    size_t maximumSize = (size_t)((float_t)data.size() * 3.0f) + 600;
-    ByteArray buffer;
-    buffer.resize(maximumSize);
-    size_t compressedSize = maximumSize;
-
-    //TODO: Find way without this copy...
-    ByteArray input(data.begin(), data.end());
-    always_assert(data.size() == input.size());
-
-    // Default as stated in documentation.
-    const int workFactor = 30;
-    Stopwatch s;
-    s.start();
-    int compressionResult = library_bzip2::BZ2_bzBuffToBuffCompress((char *)buffer.data(), (uint *)(&compressedSize),
-                                                                    (char *)input.data(), (uint)data.size(),
-                                                                    compressionLevel, 0, workFactor);
-    s.stop();
-    info.compressionTimeMS = s.elapsed_milliseconds();
-
-    switch (compressionResult)
-    {
-    case BZ_CONFIG_ERROR:
-        printf(RED "Bzip2 has been mis-compiled!\n" RESET);
-        break;
-    case BZ_PARAM_ERROR:
-        printf(RED "Wrong parameters!\n" RESET);
-        break;
-    case BZ_MEM_ERROR:
-        printf(RED "Not enaugh memory avaible!\n" RESET);
-        break;
-    case BZ_OUTBUFF_FULL:
-        printf(RED "Output buffer wasn't big enaugh!\n" RESET);
-        break;
-    }
-    always_assert(compressionResult == BZ_OK);
-
-    ByteArray result(buffer.begin(), buffer.begin() + compressedSize);
-    always_assert(result.size() == compressedSize);
-
-    return result;
-}
-
-#if 0
-// Run-Length encode bytes and return compressed bytes.
-ByteArray rle_encode(const ByteArray &bytes)
-{
-    ByteArray compressed;
-    byte literalBuffer[MAX_LITERAL_COUNT];
-    size_t literalCount = 0;
-    size_t runCount = 0;
-
-    size_t uncompresseddBufferSize = bytes.size();
-
-    for (size_t bufferIndex = 0; bufferIndex < uncompresseddBufferSize;)
-    {
-        byte symbol = bytes[bufferIndex];
-        runCount = 1;
-
-        // Encode run.
-        while ((runCount < MAX_RUN_COUNT) &&
-               (bytes[bufferIndex + runCount] == symbol) &&
-               (runCount < (uncompresseddBufferSize - bufferIndex)))
-        {
-            ++runCount;
-        }
-
-        // Maybe we want to encode runs of bigger size than 1.
-        if ((runCount > 1) ||
-            (literalCount == MAX_LITERAL_COUNT) ||
-            ((bufferIndex == (uncompresseddBufferSize - 1)) && literalCount > 0))
-        {
-            // Write literal buffer.
-            byte literalCountBYTE = (byte)literalCount;
-            always_assert(literalCountBYTE == literalCount);
-
-            compressed.push_back(literalCountBYTE);
-            for (size_t literalBufferIndex = 0; literalBufferIndex < literalCount; literalBufferIndex++)
-            {
-                compressed.push_back(literalBuffer[literalBufferIndex]);
-            }
-            literalCount = 0;
-
-            // Write run sequence.
-            byte runCountBYTE = (byte)runCount;
-            always_assert(runCountBYTE == runCount);
-            compressed.push_back(runCountBYTE);
-            compressed.push_back(symbol);
-
-            bufferIndex += runCount;
-        }
-        else
-        {
-            // Encode literal symbol.
-            literalBuffer[literalCount++] = symbol;
-            ++bufferIndex;
-        }
-    }
-
-    return compressed;
-}
-
-// Decode Run-Length encoded bytes.
-ByteArray rle_decode(const ByteArray &compressed)
-{
-    ByteArray uncompressed;
-    uncompressed.reserve(compressed.size());
-
-    size_t compressedBufferSize = compressed.size();
-    size_t bufferIndex = 0;
-
-    byte literalCount, runCount, runSymbol;
-    while (bufferIndex < compressedBufferSize)
-    {
-        literalCount = compressed[bufferIndex++];
-        while (literalCount--)
-        {
-            uncompressed.push_back(compressed[bufferIndex++]);
-        }
-
-        runCount = compressed[bufferIndex++];
-        runSymbol = compressed[bufferIndex++];
-        while (runCount--)
-        {
-            uncompressed.push_back(runSymbol);
-        }
-    }
-
-    return uncompressed;
-}
-
-ByteArray lz_encode(const ByteArray &bytes)
-{
-    ByteArray compressed;
-    byte literalBuffer[MAX_LITERAL_COUNT];
-    size_t literalCount = 0;
-
-    size_t uncompresseddBufferSize = bytes.size();
-
-    for (size_t bufferIndex = 0; bufferIndex <= uncompresseddBufferSize;)
-    {
-        size_t bestRun = 0;
-        size_t bestDistance = 0;
-
-        if (bufferIndex < uncompresseddBufferSize)
-        {
-            //TODO: In future we really need to upgrade MAX_LOOKBACK_COUNT to 16 or 32 bits.
-            size_t windowStartIndex = bufferIndex - (bufferIndex > MAX_LOOKBACK_COUNT ? MAX_LOOKBACK_COUNT : bufferIndex);
-            size_t windowEndIndex = windowStartIndex + ((bufferIndex - windowStartIndex) > MAX_RUN_COUNT) ? MAX_RUN_COUNT : bufferIndex - windowStartIndex;
-            for (size_t windowIndex = windowStartIndex; windowIndex < bufferIndex; windowIndex++)
-            {
-                size_t testIndex = bufferIndex;
-                size_t windowTestIndex = windowIndex;
-                size_t testRun = 0;
-
-                while ((windowTestIndex < windowEndIndex) && bytes[testIndex++] == bytes[windowTestIndex++])
-                {
-                    ++testRun;
-                }
-
-                if (bestRun < testRun)
-                {
-                    bestRun = testRun;
-                    bestDistance = bufferIndex - windowIndex;
-                }
-            }
-        }
-
-        // Maybe we want to encode runs of bigger size than 1.
-        bool writeRun = false;
-
-        if (literalCount > 0)
-        {
-            writeRun = bestRun > 4;
-        }
-        else
-        {
-            writeRun = bestRun > 2;
-        }
-
-        if ((writeRun) ||
-            (literalCount == MAX_LITERAL_COUNT) ||
-            ((bufferIndex == uncompresseddBufferSize) && literalCount > 0))
-        {
-            // Write literal buffer.
-            byte literalCountBYTE = (byte)literalCount;
-            always_assert(literalCountBYTE == literalCount);
-
-            if (literalCountBYTE > 0)
-            {
-                compressed.push_back(literalCountBYTE);
-                compressed.push_back(0);
-                for (size_t literalBufferIndex = 0; literalBufferIndex < literalCount; literalBufferIndex++)
-                {
-                    compressed.push_back(literalBuffer[literalBufferIndex]);
-                }
-                literalCount = 0;
-            }
-
-            if (writeRun)
-            {
-                // Write run sequence.
-                byte bestRunBYTE = (byte)bestRun;
-                always_assert(bestRunBYTE == bestRun);
-                byte bestDistanceBYTE = bestDistance;
-                always_assert(bestDistanceBYTE == bestDistance);
-
-                compressed.push_back(bestRunBYTE);
-                compressed.push_back(bestDistanceBYTE);
-
-                bufferIndex += bestRun;
-            }
-        }
-        else
-        {
-            // Encode literal symbol.
-            literalBuffer[literalCount++] = bytes[bufferIndex];
-            ++bufferIndex;
-        }
-    }
-
-    return compressed;
-}
-
-ByteArray lz_decode(ByteArray &compressed)
-{
-    ByteArray uncompressed;
-    uncompressed.reserve(compressed.size());
-
-    size_t compressedBufferSize = compressed.size();
-    size_t bufferIndex = 0;
-
-    //int count;
-    byte count, copyDistance;
-    while (bufferIndex < compressedBufferSize)
-    {
-        count = compressed[bufferIndex++];
-        copyDistance = compressed[bufferIndex++];
-        byte *copyPtr = vecUtil::last_element_pointer(&uncompressed) - ((int)copyDistance - 1);
-        if (copyDistance == 0)
-        {
-            copyPtr = compressed.data() + bufferIndex;
-            bufferIndex += count;
-        }
-
-        while (count--)
-        {
-            uncompressed.push_back(*copyPtr++);
-        }
-
-        // Version 2.
-        /*
-        if (copyDistance == 0)
-        {  
-            while (count--)
-            {
-                uncompressed.push_back(compressed[bufferIndex++]);
-            }
-        }
-        else
-        {
-            size_t source = (uncompressed.size() - 1) - copyDistance;
-            while (count--)
-            {
-                uncompressed.push_back(uncompressed[source++]);
-            }
-        }
-        */
-
-        //TODO: Maybe it would be better to use pairs to encode like in RLE.
-    }
-
-    return uncompressed;
-}
-#endif
-
-CompressionResult test_compression_method(const ByteArray &data, CompressionMethod method, int compressionLevel)
-{
-    CompressionResult result = {};
-    {
-        ByteArray compressedData;
-        switch (method)
-        {
-        case CompressionMethod_GZIP:
-            compressedData = gzip_encode(data, compressionLevel, result);
-            break;
-        case CompressionMethod_LZMA:
-            compressedData = lzma_encode(data, compressionLevel, result);
-            break;
-        case CompressionMethod_BZIP2:
-            compressedData = bzip2_encode(data, compressionLevel, result);
-            break;
-        default:
-            INVALID_CASE;
-        }
-        result.compressedSize = compressedData.size();
-    }
-
-    result.originalSize = data.size();
-    result.compressionRatio = compression_ratio((float)result.originalSize, (float)result.compressedSize);
-    result.ratioToOriginalSize = (float)result.compressedSize / (float)result.originalSize;
-
-    return result;
-}