From f0e32d77ec6f9d294b62153c52ea9e9c84cd9ca3 Mon Sep 17 00:00:00 2001 From: theazgra <theazgra@gmail.com> Date: Fri, 8 Mar 2019 11:48:59 +0100 Subject: [PATCH] Small refactoring and start of image difference. --- czi-format/czi-parser/binary_converter.cpp | 71 +++++-- czi-format/czi-parser/binary_converter.h | 7 +- .../czi-parser/compression/compressors.h | 31 +-- czi-format/czi-parser/custom_types.h | 1 + czi-format/czi-parser/czi_file.cpp | 192 ++++++------------ czi-format/czi-parser/czi_file.h | 9 +- .../czi-parser/czi_parts/compression_type.h | 28 ++- czi-format/czi-parser/czi_parts/dimension.h | 81 +++++++- czi-format/czi-parser/czi_parts/pixel_type.h | 98 +++++++++ .../czi-parser/czi_parts/pyramid_type.h | 22 +- czi-format/czi-parser/image/image_matrix.cpp | 2 +- czi-format/czi-parser/image/image_matrix.h | 2 +- .../czi-parser/image/pixel_structures.h | 100 +-------- czi-format/czi-parser/main.cpp | 15 +- .../czi-parser/utilities/vector_utilities.h | 17 +- 15 files changed, 404 insertions(+), 272 deletions(-) diff --git a/czi-format/czi-parser/binary_converter.cpp b/czi-format/czi-parser/binary_converter.cpp index b723cb7..81200fd 100644 --- a/czi-format/czi-parser/binary_converter.cpp +++ b/czi-format/czi-parser/binary_converter.cpp @@ -6,13 +6,13 @@ #include "binary_converter.h" short bytes_to_short(const ByteArray &bytes, const ulong fromIndex) { - always_assert(bytes.size() >= 2); - always_assert(fromIndex <= bytes.size() - 2); + always_assert(bytes.size() >= sizeof(short)); + always_assert(fromIndex <= bytes.size() - sizeof(short)); // Little endian auto bit = &bytes[fromIndex]; - if (fromIndex % 2 == 0) + if (fromIndex % 2 == sizeof(short)) { return (*((short *)bit)); } @@ -24,13 +24,13 @@ short bytes_to_short(const ByteArray &bytes, const ulong fromIndex) int bytes_to_int(const ByteArray &bytes, const ulong fromIndex) { - always_assert(bytes.size() >= 4); - always_assert(fromIndex <= bytes.size() - 4); + always_assert(bytes.size() >= sizeof(int)); + always_assert(fromIndex <= bytes.size() - sizeof(int)); // Little endian auto bit = &bytes[fromIndex]; - if (fromIndex % 4 == 0) + if (fromIndex % sizeof(int) == 0) { return (*((int *)bit)); } @@ -42,12 +42,12 @@ int bytes_to_int(const ByteArray &bytes, const ulong fromIndex) int bytes_to_long(const ByteArray &bytes, const ulong fromIndex) { - always_assert(bytes.size() >= 8); - always_assert(fromIndex <= bytes.size() - 8); + always_assert(bytes.size() >= sizeof(long)); + always_assert(fromIndex <= bytes.size() - sizeof(long)); // Little endian auto bit = &bytes[fromIndex]; - if (fromIndex % 8 == 0) + if (fromIndex % sizeof(long) == 0) { return (*((long *)bit)); } @@ -61,21 +61,21 @@ int bytes_to_long(const ByteArray &bytes, const ulong fromIndex) float bytes_to_float(const ByteArray &bytes, const ulong fromIndex) { - always_assert(bytes.size() >= 4); - always_assert(fromIndex <= bytes.size() - 4); + always_assert(bytes.size() >= sizeof(float)); + always_assert(fromIndex <= bytes.size() - sizeof(float)); float result; - memcpy(&result, (bytes.data() + fromIndex), 4); + memcpy(&result, (bytes.data() + fromIndex), sizeof(float)); return result; } double bytes_to_double(const ByteArray &bytes, const ulong fromIndex) { - always_assert(bytes.size() >= 8); - always_assert(fromIndex <= bytes.size() - 8); + always_assert(bytes.size() >= sizeof(double)); + always_assert(fromIndex <= bytes.size() - sizeof(double)); double result; - memcpy(&result, (bytes.data() + fromIndex), 8); + memcpy(&result, (bytes.data() + fromIndex), sizeof(double)); return result; } @@ -107,4 +107,45 @@ std::string utf8bytes_to_string(const ByteArray &bytes, const ulong fromIndex, c ByteArray stringBytes(fromIt, fromIt + byteCount); std::string result = boost::locale::conv::from_utf<char>((char *)stringBytes.data(), "UTF-8"); return result; +} + +ByteArray int_to_bytes(const int &i) +{ + ByteArray intBytes; + intBytes.resize(sizeof(int)); + + std::memcpy(intBytes.data(), &i, sizeof(int)); + return intBytes; +} + +void int_to_bytes(const int &i, ByteArray &buffer, size_t bufferPosition) +{ + always_assert(buffer.size() - bufferPosition >= sizeof(int)); + std::memcpy((buffer.data() + bufferPosition), &i, sizeof(int)); +} + +std::vector<ushort> bytes_to_ushort_array(const ByteArray &data) +{ + std::vector<ushort> result; + result.resize(data.size() / sizeof(ushort)); + + size_t index = 0; + for (size_t i = 0; i < data.size(); i += 2) + { + result[index++] = bytes_to_ushort(data, i); + } + + return result; +} + +ByteArray int_array_to_bytes(const std::vector<int> &data) +{ + ByteArray result; + result.resize(data.size() * sizeof(int)); + + for (size_t i = 0; i < data.size(); i++) + { + int_to_bytes(data[i], result, i * sizeof(int)); + } + return result; } \ No newline at end of file diff --git a/czi-format/czi-parser/binary_converter.h b/czi-format/czi-parser/binary_converter.h index 91bbb97..8945f88 100644 --- a/czi-format/czi-parser/binary_converter.h +++ b/czi-format/czi-parser/binary_converter.h @@ -35,7 +35,12 @@ ulong bytes_to_ulong(const ByteArray &bytes, const ulong fromIndex = 0); std::string utf8bytes_to_string(const ByteArray &bytes); // Convert number of UTF-8 bytes, from specified index, to string. std::string utf8bytes_to_string(const ByteArray &bytes, const ulong fromIndex, const uint byteCount); +// Convert int into 4 bytes. +ByteArray int_to_bytes(const int &i); +// Convert int into 4 bytes, which will be added into buffer. +void int_to_bytes(const int &i, ByteArray &buffer, size_t bufferPosition); -//char get_hex_value(int x); +std::vector<ushort> bytes_to_ushort_array(const ByteArray &data); +ByteArray int_array_to_bytes(const std::vector<int> &data); #include "binary_converter.cpp" \ No newline at end of file diff --git a/czi-format/czi-parser/compression/compressors.h b/czi-format/czi-parser/compression/compressors.h index ff91671..2a75b3c 100644 --- a/czi-format/czi-parser/compression/compressors.h +++ b/czi-format/czi-parser/compression/compressors.h @@ -436,26 +436,27 @@ ByteArray lz_decode(ByteArray &compressed) CompressionResult test_compression_method(const ByteArray &data, CompressionMethod method, int compressionLevel) { - ByteArray compressedData; CompressionResult result = {}; - - 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; + 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.compressedSize = compressedData.size(); result.compressionRatio = compression_ratio((float)result.originalSize, (float)result.compressedSize); result.percentageOfOriginalSize = ((float)result.compressedSize / (float)result.originalSize) * 100.0f; diff --git a/czi-format/czi-parser/custom_types.h b/czi-format/czi-parser/custom_types.h index 28d8ae7..22a8910 100644 --- a/czi-format/czi-parser/custom_types.h +++ b/czi-format/czi-parser/custom_types.h @@ -24,6 +24,7 @@ typedef unsigned long ulong; constexpr uint UINT_MAX = std::numeric_limits<uint>::max(); constexpr ulong ULONG_MAX = std::numeric_limits<ulong>::max(); constexpr short SHORT_MAX = std::numeric_limits<short>::max(); +constexpr short USHORT_MAX = std::numeric_limits<ushort>::max(); #define TagType std::string, std::string typedef std::pair<TagType> Tag; diff --git a/czi-format/czi-parser/czi_file.cpp b/czi-format/czi-parser/czi_file.cpp index 0e4d065..0e274fb 100644 --- a/czi-format/czi-parser/czi_file.cpp +++ b/czi-format/czi-parser/czi_file.cpp @@ -49,131 +49,6 @@ const char *CziFile::pixel_type_str(const PixelType px) const return nullptr; } -const char *CziFile::pyramid_type_str(const PyramidType pt) const -{ - switch (pt) - { - case PyramidType_None: - return "None"; - case PyramidType_SingleSubBlock: - return "SingleSubBlock"; - case PyramidType_MultiSubBlock: - return "MultiSubBlock"; - break; - default: - { - always_assert("Bad pyramid type." && false); - break; - } - } - return nullptr; -} - -const char *CziFile::compression_type_str(const CompressionType ct) const -{ - switch (ct) - { - case CompressionType_Uncompressed: - return "Uncompressed"; - case CompressionType_LZW: - return "LZW"; - case CompressionType_JpgFile: - return "JpgFile"; - case CompressionType_JpegXrFile: - return "JpegXrFile"; - case CompressionType_Camera: - return "Camera"; - case CompressionType_System: - return "System"; - break; - default: - { - always_assert("Bad compression type." && false); - break; - } - } - return nullptr; -} - -const char *CziFile::dimension_type_str(const Dimension &d) const -{ - switch (d) - { - case Dimension_X: - return "X (width)"; - case Dimension_Y: - return "Y (height)"; - case Dimension_C: - return "C (channels)"; - case Dimension_Z: - return "Z (Z-slices)"; - case Dimension_T: - return "T (timestamps)"; - case Dimension_R: - return "R (rotation)"; - case Dimension_S: - return "S (scene)"; - case Dimension_I: - return "I (illumination)"; - case Dimension_B: - return "B (block index)"; - case Dimension_M: - return "M (mosaic)"; - case Dimension_H: - return "H (phase)"; - case Dimension_V: - return "V (views)"; - - break; - default: - { - always_assert("Bad dimension type." && false); - break; - } - } - return nullptr; -} - -const char *CziFile::dimension_char(const Dimension &d) const -{ - std::string result; - switch (d) - { - case Dimension_X: - return "X"; - break; - case Dimension_Y: - return "Y"; - break; - case Dimension_C: - return "C"; - case Dimension_Z: - return "Z"; - case Dimension_T: - return "T"; - case Dimension_R: - return "R"; - case Dimension_S: - return "S"; - case Dimension_I: - return "I"; - case Dimension_B: - return "B"; - case Dimension_M: - return "M"; - case Dimension_H: - return "H"; - case Dimension_V: - return "V"; - default: - { - always_assert("Bad dimension type." && false); - break; - } - } - return nullptr; -} - std::string CziFile::dimension_stack_str(const std::vector<DimensionEntryDV1> &dims, bool includeSize) const { @@ -495,7 +370,7 @@ void CziFile::dump_continuous_data(const std::string &dir) const } } -void CziFile::differences_between_next(const std::string baseName) const +void CziFile::absolutu_difference_between_frames(const std::string baseName) const { if (subBlockDirectory.entries.size() <= 1) { @@ -510,7 +385,7 @@ void CziFile::differences_between_next(const std::string baseName) const fName = baseName + "diff_" + std::to_string(i - 1) + "_" + std::to_string(i) + ".ppm"; ImageMatrix next = get_image(i); - ImageMatrix diff_ref_next = ref.create_difference_matrix(next); + ImageMatrix diff_ref_next = ref.create_absolute_difference_matrix(next); diff_ref_next.save_as_ppm(fName.c_str()); @@ -616,4 +491,67 @@ void CziFile::test_compression(CompressionMethod method, bool verbose, int compr printf("Original size: %8lu B Compressed size: %8lu B Compressed Z-Order size: %8lu B\n", overallN.originalSize, overallN.compressedSize, overallZ.compressedSize); printf("Original size (%%): 100%% Compressed: %5.5f%% Compressed Z-Order: %5.5f%%\n", overallN.percentageOfOriginalSize, overallZ.percentageOfOriginalSize); printf("Average compression time: %f ms\n", overallN.compressionTimeMS); +} + +std::vector<std::pair<uint, std::vector<uint>>> CziFile::get_subblocks_grouped_by_channels() const +{ + std::vector<std::pair<uint, std::vector<uint>>> result; + result.reserve(subBlockDirectory.channelCount); + + for (uint channel = 0; channel < subBlockDirectory.channelCount; channel++) + { + std::vector<uint> subblocksInChannel; + for (uint subblock = 0; subblock < subBlockDirectory.entryCount; subblock++) + { + int subblockChannel = subBlockDirectory.entries[subblock].channel; + always_assert(subblockChannel >= 0); + if ((uint)subblockChannel == channel) + { + subblocksInChannel.push_back(subblock); + } + } + result.push_back(std::make_pair(channel, subblocksInChannel)); + } + + return result; +} + +void CziFile::frames_difference() const +{ + // TODO: This will now handle only Gray16 pixels! + + auto framesByChannels = get_subblocks_grouped_by_channels(); + + for (const std::pair<uint, std::vector<uint>> &channelGroup : framesByChannels) + { + printf("Starting channel %u\n", channelGroup.first); + for (size_t i = 1; i < channelGroup.second.size(); i++) + { + // This assertion will fail if pixel type isn't Gray16 + always_assert(subBlockDirectory.entries[channelGroup.second[i - 1]].pixelType == PixelType_Gray16); + always_assert(subBlockDirectory.entries[channelGroup.second[i]].pixelType == PixelType_Gray16); + + auto prevFrameData = get_image_data(channelGroup.second[i - 1], false); + auto currentFrameData = get_image_data(channelGroup.second[i], false); + always_assert(prevFrameData.size() == currentFrameData.size()); + + std::vector<ushort> prevFrameValues = bytes_to_ushort_array(prevFrameData); + std::vector<ushort> currentFrameValues = bytes_to_ushort_array(currentFrameData); + always_assert(prevFrameValues.size() == currentFrameValues.size()); + + std::vector<int> differenceArray = vecUtil::diff_vectors<ushort, int>(prevFrameValues, currentFrameValues); + + ByteArray intBytes = int_array_to_bytes(differenceArray); + + auto frameCompResult = test_compression_method(currentFrameData, CompressionMethod_BZIP2, 6); + auto diffCompResult = test_compression_method(intBytes, CompressionMethod_BZIP2, 6); + + float diffSizeDif = ((float)diffCompResult.compressedSize / (float)frameCompResult.compressedSize) * 100.0f; + + printf("Frame [%u | %u]: Size %7lu Compression ratio: %7f\n", + channelGroup.second[i - 1], channelGroup.second[i], frameCompResult.compressedSize, frameCompResult.compressionRatio); + + printf(" Diff: Size %7lu Compression ratio: %7f\n Size: %f\n\n", diffCompResult.compressedSize, diffCompResult.compressionRatio, diffSizeDif); + } + } } \ No newline at end of file diff --git a/czi-format/czi-parser/czi_file.h b/czi-format/czi-parser/czi_file.h index a1d0ca5..c5ae40e 100644 --- a/czi-format/czi-parser/czi_file.h +++ b/czi-format/czi-parser/czi_file.h @@ -14,10 +14,6 @@ class CziFile { private: void print_segment_header(const SegmentHeader &segmentHeader) const; - const char *pyramid_type_str(const PyramidType pt) const; - const char *compression_type_str(const CompressionType ct) const; - const char *dimension_type_str(const Dimension &d) const; - const char *dimension_char(const Dimension &d) const; std::string dimension_stack_str(const std::vector<DimensionEntryDV1> &dims, bool includeSize) const; public: @@ -52,9 +48,12 @@ public: // Dump all images to graphics files. void dump_images(const std::string &baseName) const; // Save differences between next images, so 0x1;1x2;... - void differences_between_next(const std::string baseName) const; + void absolutu_difference_between_frames(const std::string baseName) const; // Report compression ratios of images in normal and Z order. void test_compression(CompressionMethod method, bool verbose, int compressionLevel) const; + // Get pairs of subblocks in different channels. + std::vector<std::pair<uint, std::vector<uint>>> get_subblocks_grouped_by_channels() const; + void frames_difference() const; }; #include "czi_file.cpp" \ No newline at end of file diff --git a/czi-format/czi-parser/czi_parts/compression_type.h b/czi-format/czi-parser/czi_parts/compression_type.h index d7770cb..d5c3a17 100644 --- a/czi-format/czi-parser/czi_parts/compression_type.h +++ b/czi-format/czi-parser/czi_parts/compression_type.h @@ -11,4 +11,30 @@ enum CompressionType CompressionType_Camera, // System specific RAW data. CompressionType_System -}; \ No newline at end of file +}; + +const char *compression_type_str(const CompressionType ct) +{ + switch (ct) + { + case CompressionType_Uncompressed: + return "Uncompressed"; + case CompressionType_LZW: + return "LZW"; + case CompressionType_JpgFile: + return "JpgFile"; + case CompressionType_JpegXrFile: + return "JpegXrFile"; + case CompressionType_Camera: + return "Camera"; + case CompressionType_System: + return "System"; + break; + default: + { + always_assert("Bad compression type." && false); + break; + } + } + return nullptr; +} \ No newline at end of file diff --git a/czi-format/czi-parser/czi_parts/dimension.h b/czi-format/czi-parser/czi_parts/dimension.h index 4ab01c8..a85a36d 100644 --- a/czi-format/czi-parser/czi_parts/dimension.h +++ b/czi-format/czi-parser/czi_parts/dimension.h @@ -25,4 +25,83 @@ enum Dimension Dimension_H = 'H', // View index (for multi – view images, e.g. SPIM) Dimension_V = 'V' -}; \ No newline at end of file +}; + +const char *dimension_type_str(const Dimension &d) +{ + switch (d) + { + case Dimension_X: + return "X (width)"; + case Dimension_Y: + return "Y (height)"; + case Dimension_C: + return "C (channels)"; + case Dimension_Z: + return "Z (Z-slices)"; + case Dimension_T: + return "T (timestamps)"; + case Dimension_R: + return "R (rotation)"; + case Dimension_S: + return "S (scene)"; + case Dimension_I: + return "I (illumination)"; + case Dimension_B: + return "B (block index)"; + case Dimension_M: + return "M (mosaic)"; + case Dimension_H: + return "H (phase)"; + case Dimension_V: + return "V (views)"; + + break; + default: + { + always_assert("Bad dimension type." && false); + break; + } + } + return nullptr; +} + +const char *dimension_char(const Dimension &d) +{ + std::string result; + switch (d) + { + case Dimension_X: + return "X"; + break; + case Dimension_Y: + return "Y"; + break; + case Dimension_C: + return "C"; + case Dimension_Z: + return "Z"; + case Dimension_T: + return "T"; + case Dimension_R: + return "R"; + case Dimension_S: + return "S"; + case Dimension_I: + return "I"; + case Dimension_B: + return "B"; + case Dimension_M: + return "M"; + case Dimension_H: + return "H"; + case Dimension_V: + return "V"; + default: + { + always_assert("Bad dimension type." && false); + break; + } + } + return nullptr; +} \ No newline at end of file diff --git a/czi-format/czi-parser/czi_parts/pixel_type.h b/czi-format/czi-parser/czi_parts/pixel_type.h index 8b61fe4..d8a4d15 100644 --- a/czi-format/czi-parser/czi_parts/pixel_type.h +++ b/czi-format/czi-parser/czi_parts/pixel_type.h @@ -1,4 +1,5 @@ #pragma once +#include "../custom_types.h" enum PixelType { // 8 bit unsigned. @@ -26,3 +27,100 @@ enum PixelType // For internal usage. PixelType_None }; + +// Get number of bytes needed to encode specific `PixelType` +int get_bytes_per_pixel_type(const PixelType &pt) +{ + switch (pt) + { + case PixelType_Gray8: + return 1; + case PixelType_Gray16: + return 2; + case PixelType_Gray32Float: + return 4; + case PixelType_Bgr24: + return 3; + case PixelType_Bgr48: + return 6; + case PixelType_Bgr96Float: + return 12; + case PixelType_Bgra32: + return 4; + case PixelType_Gray64ComplexFloat: + return 8; + case PixelType_Bgr192ComplexFloat: + return 24; + case PixelType_Gray32: + return 4; + case PixelType_Gray64: + return 8; + + default: + always_assert("Bad pixel type." && false); + break; + } + return -1; +} + +// Get number of bytes, by which ByteArray can be reordered in Z-Order. +uint get_component_size_of_pixel(const PixelType &pt) +{ + switch (pt) + { + case PixelType_Gray8: + return 1; + case PixelType_Gray16: + return 2; + case PixelType_Gray32Float: + return 4; + case PixelType_Bgr24: + return 1; // Channels will be separated. + case PixelType_Bgr48: + return 2; // Channels will be separated. + case PixelType_Bgr96Float: + return 4; // Channels will be separated. + case PixelType_Bgra32: + return 1; // Channels will be separated. + case PixelType_Gray64ComplexFloat: + return 4; // Channels will be separated. + case PixelType_Bgr192ComplexFloat: + return 4; // Channels will be separated. + case PixelType_Gray32: + return 4; + case PixelType_Gray64: + return 8; + default: + INVALID_CASE; + break; + } + return -1; +} + +// Get number of separable components in specific `PixelType`. +uint get_count_of_components_of_pixel(const PixelType &pt) +{ + switch (pt) + { + case PixelType_Gray8: + case PixelType_Gray16: + case PixelType_Gray32Float: + case PixelType_Gray32: + case PixelType_Gray64: + return 1; + case PixelType_Gray64ComplexFloat: + return 2; + case PixelType_Bgr24: + case PixelType_Bgr48: + case PixelType_Bgr96Float: + return 3; + case PixelType_Bgra32: + return 4; + case PixelType_Bgr192ComplexFloat: + return 6; + default: + INVALID_CASE; + break; + } + return -1; +} \ No newline at end of file diff --git a/czi-format/czi-parser/czi_parts/pyramid_type.h b/czi-format/czi-parser/czi_parts/pyramid_type.h index 339dfa5..cac3d51 100644 --- a/czi-format/czi-parser/czi_parts/pyramid_type.h +++ b/czi-format/czi-parser/czi_parts/pyramid_type.h @@ -5,4 +5,24 @@ enum PyramidType PyramidType_None = 0, PyramidType_SingleSubBlock = 1, PyramidType_MultiSubBlock = 2 -}; \ No newline at end of file +}; + +const char *pyramid_type_str(const PyramidType pt) +{ + switch (pt) + { + case PyramidType_None: + return "None"; + case PyramidType_SingleSubBlock: + return "SingleSubBlock"; + case PyramidType_MultiSubBlock: + return "MultiSubBlock"; + break; + default: + { + always_assert("Bad pyramid type." && false); + break; + } + } + return nullptr; +} \ No newline at end of file diff --git a/czi-format/czi-parser/image/image_matrix.cpp b/czi-format/czi-parser/image/image_matrix.cpp index 267824a..eff1ef6 100644 --- a/czi-format/czi-parser/image/image_matrix.cpp +++ b/czi-format/czi-parser/image/image_matrix.cpp @@ -207,7 +207,7 @@ void ImageMatrix::fill(std::shared_ptr<BasePixel> px) data[i] = px; } -ImageMatrix ImageMatrix::create_difference_matrix(const ImageMatrix &other) +ImageMatrix ImageMatrix::create_absolute_difference_matrix(const ImageMatrix &other) { ImageMatrix diff(colCount, rowCount, PixelType_Gray8); diff --git a/czi-format/czi-parser/image/image_matrix.h b/czi-format/czi-parser/image/image_matrix.h index b6308bd..b6280f3 100644 --- a/czi-format/czi-parser/image/image_matrix.h +++ b/czi-format/czi-parser/image/image_matrix.h @@ -53,7 +53,7 @@ public: void save_as_ppm(const char *fName) const; // Set all pixels to one value of `px`. void fill(std::shared_ptr<BasePixel> px); - ImageMatrix create_difference_matrix(const ImageMatrix &other); + ImageMatrix create_absolute_difference_matrix(const ImageMatrix &other); }; #include "image_matrix.cpp" \ No newline at end of file diff --git a/czi-format/czi-parser/image/pixel_structures.h b/czi-format/czi-parser/image/pixel_structures.h index 4c771bd..7c442c2 100644 --- a/czi-format/czi-parser/image/pixel_structures.h +++ b/czi-format/czi-parser/image/pixel_structures.h @@ -1,5 +1,4 @@ #pragma once -#include "../czi_parts/pixel_type.h" #include "../custom_types.h" template <typename Number> @@ -603,101 +602,4 @@ struct Bgr192ComplexFloatPixel : BasePixel return *this; } -}; - -// Get number of bytes needed to encode specific `PixelType` -int get_bytes_per_pixel_type(const PixelType &pt) -{ - switch (pt) - { - case PixelType_Gray8: - return 1; - case PixelType_Gray16: - return 2; - case PixelType_Gray32Float: - return 4; - case PixelType_Bgr24: - return 3; - case PixelType_Bgr48: - return 6; - case PixelType_Bgr96Float: - return 12; - case PixelType_Bgra32: - return 4; - case PixelType_Gray64ComplexFloat: - return 8; - case PixelType_Bgr192ComplexFloat: - return 24; - case PixelType_Gray32: - return 4; - case PixelType_Gray64: - return 8; - - default: - always_assert("Bad pixel type." && false); - break; - } - return -1; -} - -// Get number of bytes, by which ByteArray can be reordered in Z-Order. -uint get_component_size_of_pixel(const PixelType &pt) -{ - switch (pt) - { - case PixelType_Gray8: - return 1; - case PixelType_Gray16: - return 2; - case PixelType_Gray32Float: - return 4; - case PixelType_Bgr24: - return 1; // Channels will be separated. - case PixelType_Bgr48: - return 2; // Channels will be separated. - case PixelType_Bgr96Float: - return 4; // Channels will be separated. - case PixelType_Bgra32: - return 1; // Channels will be separated. - case PixelType_Gray64ComplexFloat: - return 4; // Channels will be separated. - case PixelType_Bgr192ComplexFloat: - return 4; // Channels will be separated. - case PixelType_Gray32: - return 4; - case PixelType_Gray64: - return 8; - default: - INVALID_CASE; - break; - } - return -1; -} - -// Get number of separable components in specific `PixelType`. -uint get_count_of_components_of_pixel(const PixelType &pt) -{ - switch (pt) - { - case PixelType_Gray8: - case PixelType_Gray16: - case PixelType_Gray32Float: - case PixelType_Gray32: - case PixelType_Gray64: - return 1; - case PixelType_Gray64ComplexFloat: - return 2; - case PixelType_Bgr24: - case PixelType_Bgr48: - case PixelType_Bgr96Float: - return 3; - case PixelType_Bgra32: - return 4; - case PixelType_Bgr192ComplexFloat: - return 6; - default: - INVALID_CASE; - break; - } - return -1; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/czi-format/czi-parser/main.cpp b/czi-format/czi-parser/main.cpp index 5372f05..55655b2 100644 --- a/czi-format/czi-parser/main.cpp +++ b/czi-format/czi-parser/main.cpp @@ -20,8 +20,9 @@ int main(int argc, char **argv) args::Flag compressionTestMethod(mainMethodGroup, "compression-test", "Compress subblocks and output compression ratios <compression method>", {"compression-test"}); args::Flag versionMethod(mainMethodGroup, "Version test", "Check version", {"version", 'V'}); args::Flag benchmarkMethod(mainMethodGroup, "Compression benchmark", "Start compression benchmark for selected CZI file. <report-file> [continuos] [verbose].", {"benchmark"}); - args::Flag exportDataMethod(mainMethodGroup, "Export binary dat", "Export raw image data <folder> [continuos]", {"dump-data"}); + args::Flag exportDataMethod(mainMethodGroup, "Export binary data", "Export raw image data <folder> [continuos]", {"dump-data"}); args::Flag exportImagesMethod(mainMethodGroup, "Export images", "Export images to ppm files <folder>", {"dump-images"}); + args::Flag frameDiffMethod(mainMethodGroup, "Frame difference", "TODO", {"frame-diff"}); // Options args::Flag dontParseMetadataOption(optionsGroup, "no metadata", "Dont read metadata byte", {"no-metadata"}); @@ -29,9 +30,9 @@ int main(int argc, char **argv) args::ValueFlag<int> compressionLevelOption(optionsGroup, "Compression level", "Compression level", {'l', "level"}); args::ValueFlag<std::string> folderOption(optionsGroup, "Folder", "Folder to which save exported items.", {'f', "folder"}); args::ValueFlag<std::string> reportFileOption(optionsGroup, "Report file", "File where to write report.", {'r', "report"}); - args::Flag gzipCompressionOption(compressionGroup, "GZIP", "GZIP (zlib) compression", {"gzip"}); - args::Flag lzmaCompressionOption(compressionGroup, "LZMA", "LZMA (2?) compression", {"lzma"}); - args::Flag bzip2CompressionOption(compressionGroup, "BZIP2", "BZip2 compression", {"bzip2"}); + args::Flag gzipCompressionOption(compressionGroup, "GZIP", "gzip (zlib) compression", {"gzip"}); + args::Flag lzmaCompressionOption(compressionGroup, "LZMA", "lzma compression", {"lzma"}); + args::Flag bzip2CompressionOption(compressionGroup, "BZIP2", "bzip2 compression", {"bzip2"}); args::Flag continuousCompressionOption(compressionGroup, "Continuos compression", "Compress continuos array of image data into one buffer.", {'c'}); try @@ -91,6 +92,12 @@ int main(int argc, char **argv) return 0; } + if (frameDiffMethod) + { + parsedFile.frames_difference(); + return 0; + } + // Test compression method. if (compressionTestMethod) { diff --git a/czi-format/czi-parser/utilities/vector_utilities.h b/czi-format/czi-parser/utilities/vector_utilities.h index a8529b5..76482d5 100644 --- a/czi-format/czi-parser/utilities/vector_utilities.h +++ b/czi-format/czi-parser/utilities/vector_utilities.h @@ -44,4 +44,19 @@ inline bool contains(const std::vector<T> &vec, const T &elem) return (std::find(vec.begin(), vec.end(), elem) != vec.end()); } -}; // namespace vecUtil \ No newline at end of file +template <typename T, typename DiffType> +std::vector<DiffType> diff_vectors(const std::vector<T> &a, const std::vector<T> &b) +{ + always_assert(a.size() == b.size()); + + std::vector<DiffType> result; + result.resize(a.size()); + for (size_t i = 0; i < a.size(); i++) + { + result[i] = (DiffType)(b[i] - a[i]); + } + + return result; +} + +}; // namespace vecUtil -- GitLab