diff --git a/README.md b/README.md index 12312df8fe3ae32729bd40282fb95bfcc47fa6e9..0597290818f40345530195a300f9259d1f59569a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Data compression project ### TODO *deadline* 25.2.2019 -- [ ] Tweak Z-Order reordering +- [x] Tweak Z-Order reordering - Values, which are stored in more than one byte, must stay together. - Pixels, which contains more `channels`, can be separeted in final z order. (Try both separeted and not-separated) - Right now, when we `reorder` bytes we move *whole* pixel (*all channels*), but when pixel's channels will be separated we will move just one channel. diff --git a/czi-format/czi-parser/custom_types.h b/czi-format/czi-parser/custom_types.h index d29883dc64bc399aea582e99b1173dabc4714e52..20fb6b06489bcd68416b291165d2a539927ee31f 100644 --- a/czi-format/czi-parser/custom_types.h +++ b/czi-format/czi-parser/custom_types.h @@ -10,6 +10,7 @@ #include <memory> #include <vector> #include "always_on_assert.h" +#include <limits> constexpr bool NOT_IMPLEMENTED_YET = false; #define MUST_BE_IMPLEMENTED always_assert(false); @@ -20,6 +21,9 @@ typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; +constexpr uint UINT_MAX = std::numeric_limits<uint>::max(); +constexpr ulong ULONG_MAX = std::numeric_limits<ulong>::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 d031a6c0091170df2ee3a01e01cefc8a77856bd3..b28831e970dac2ace6e31d5324b4b9adbcfff9ef 100644 --- a/czi-format/czi-parser/czi_file.cpp +++ b/czi-format/czi-parser/czi_file.cpp @@ -345,10 +345,19 @@ std::vector<byte> CziFile::get_image_data(const uint subblockId, const bool ZCur if (ZCurveOrdered) { - auto zIndices = generate_ordered_z_order_indices(entry.width, entry.height); - always_assert(zIndices.size() == (ulong)(entry.width * entry.height)); + always_assert((uint)entry.width <= UINT_MAX && (uint)entry.height <= UINT_MAX); + uint componentCount = get_count_of_components_of_pixel(entry.pixelType); + uint componentSize = get_component_size_of_pixel(entry.pixelType); + + auto zIndices = generate_ordered_z_order_indices(entry.width, entry.height, componentCount); + always_assert(zIndices.size() == (ulong)(componentCount * entry.width * entry.height)); + + std::vector<byte> zOrderedBytes = reoder_bytes_to_z_order(imageBytes, zIndices, componentSize); + + auto back = reoder_bytes_from_z_order(zOrderedBytes, zIndices, componentSize); + bool eq = vecUtil::vector_eq(imageBytes, back); + always_assert(eq); - std::vector<byte> zOrderedBytes = reoder_bytes_to_z_order(imageBytes, zIndices, bytesPerPixel); return zOrderedBytes; } else diff --git a/czi-format/czi-parser/image/pixel_structures.h b/czi-format/czi-parser/image/pixel_structures.h index 453249ec05e9e1a0514622cf0c92aa66ac12b299..505a5bb07cc5d28bbf439f4c0f164b9b06df692d 100644 --- a/czi-format/czi-parser/image/pixel_structures.h +++ b/czi-format/czi-parser/image/pixel_structures.h @@ -636,4 +636,66 @@ int get_bytes_per_pixel_type(const PixelType &pt) 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/image/z_order.h b/czi-format/czi-parser/image/z_order.h index ecd4cb0d9583cb615a0612a41817bc9884dcf8e7..29546d1d7c694bbdefc1f3dcd1c1df7887c5ab17 100644 --- a/czi-format/czi-parser/image/z_order.h +++ b/czi-format/czi-parser/image/z_order.h @@ -67,54 +67,62 @@ struct PointWithIndex bool operator>=(const PointWithIndex &other) const { return (z >= other.z); } }; -std::vector<PointWithIndex> generate_ordered_z_order_indices(const uint width, const uint height) +std::vector<PointWithIndex> generate_ordered_z_order_indices(const uint colCount, const uint rowCount, const uint componentCount) { std::vector<PointWithIndex> result; - result.resize(width * height); + result.resize((colCount * componentCount) * rowCount); + // This doesnt count with bytes per pixel size_t index = 0; - for (uint y = 0; y < height; y++) + for (uint row = 0; row < rowCount; row++) { - for (uint x = 0; x < width; x++) + for (uint col = 0; col < (colCount * componentCount); col++) { - result[index] = PointWithIndex(x, y, index); + 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<byte> reoder_bytes_to_z_order(const std::vector<byte> &bytes, const std::vector<PointWithIndex> &zIndices, const uint chunkSize) +std::vector<byte> reoder_bytes_to_z_order(const std::vector<byte> &bytes, const std::vector<PointWithIndex> &zIndices, + const uint componentSize) { std::vector<byte> zOrderedBytes; - + zOrderedBytes.resize(bytes.size()); + size_t it = 0; + size_t from, pos; for (const PointWithIndex &index : zIndices) { - auto fromIt = bytes.begin() + index.bufferPosition; - auto toIt = fromIt + chunkSize; - zOrderedBytes.insert(zOrderedBytes.end(), fromIt, toIt); + 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()); + always_assert(zOrderedBytes.size() == bytes.size()); return zOrderedBytes; } -std::vector<byte> reoder_bytes_from_z_order(const std::vector<byte> &zOrderedBytes, const std::vector<PointWithIndex> &zIndices, const uint chunkSize) +std::vector<byte> reoder_bytes_from_z_order(const std::vector<byte> &zOrderedBytes, const std::vector<PointWithIndex> &zIndices, + const uint componentSize) { std::vector<byte> bytes; bytes.resize(zOrderedBytes.size()); - ulong iteration = 0; + size_t it = 0; size_t insertAt, copyFrom; for (const PointWithIndex &index : zIndices) { - insertAt = index.bufferPosition; - copyFrom = iteration * chunkSize; - vecUtil::vector_insert_at(bytes, zOrderedBytes, insertAt, copyFrom, chunkSize); - ++iteration; + insertAt = index.bufferPosition * componentSize; + copyFrom = it * componentSize; + vecUtil::vector_insert_at(bytes, zOrderedBytes, insertAt, copyFrom, componentSize); + ++it; } always_assert(bytes.size() == zOrderedBytes.size()); diff --git a/czi-format/czi-parser/main.cpp b/czi-format/czi-parser/main.cpp index 024746f2a9a9f813910600dcb8466ffe5c72022d..2f67f8e9865c0d8dc3ca8bce44a8ba196ebe39bb 100644 --- a/czi-format/czi-parser/main.cpp +++ b/czi-format/czi-parser/main.cpp @@ -8,7 +8,7 @@ int main(int argc, char **argv) args::Group cziFileGroup(argParser, "CZI file input - necessary.", args::Group::Validators::All); args::Group mainMethodGroup(argParser, "Methods:", args::Group::Validators::AtMostOne); args::Group optionsGroup(argParser, "Program options:", args::Group::Validators::DontCare); - args::Group compressionGroup(argParser, "Avaible compressions", args::Group::Validators::Xor); + args::Group compressionGroup(argParser, "Avaible compressions", args::Group::Validators::AtMostOne); // Main option, has to be set. Czi file. args::ValueFlag<std::string> cziFile(cziFileGroup, "czi file", "CZI file to load.", {'i', "input"}); @@ -64,6 +64,14 @@ int main(int argc, char **argv) parsedFile.test_compression(cm, verboseOption.Matched()); } + if (reportMethod) + { + if (verboseOption.Matched()) + parsedFile.report_verbose(); + else + parsedFile.report(); + } + /* std::string cziFile = (argc > 1) ? argv[1] : "/home/mor0146/gitlab/data_project/czi-format/data/CZT-Stack-Anno.czi"; //"/home/mor0146/gitlab/data_project/czi-format/data/m2/exampleSingleChannel.czi"; if (cziFile == "-v" || cziFile == "--version")