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 ¤t, 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 ¤t); \ 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 ¤t, 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 ¤t) +{ + 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 ¤t, 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 ¤t) -{ - _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; -}