From d35054efd1dadbfa13a6bc2c2a275663ebfa91d6 Mon Sep 17 00:00:00 2001 From: theazgra <theazgra@gmail.com> Date: Wed, 30 Jan 2019 13:19:43 +0100 Subject: [PATCH] Switched to custom assert, which is firing even in Release mode. --- czi-format/Links to Download.txt | 14 +-- czi-format/czi-parser/CMakeLists.txt | 4 +- czi-format/czi-parser/always_on_assert.h | 71 ++++++++++++ czi-format/czi-parser/binary_converter.cpp | 20 ++-- czi-format/czi-parser/binary_converter.h | 1 - czi-format/czi-parser/binary_stream.cpp | 42 ++++---- czi-format/czi-parser/binary_stream.h | 4 +- czi-format/czi-parser/custom_types.h | 2 +- czi-format/czi-parser/czi_file.cpp | 24 +++-- czi-format/czi-parser/czi_parser.cpp | 41 +++---- .../czi_parts/attachment_directory_segment.h | 2 +- .../czi-parser/czi_parts/directory_entry_dv.h | 2 +- .../czi_parts/subblock_directory_segment.h | 2 +- czi-format/czi-parser/file_system.h | 102 ++++++++++++++++++ czi-format/czi-parser/image_writer.h | 3 +- czi-format/czi-parser/main.cpp | 7 ++ 16 files changed, 266 insertions(+), 75 deletions(-) create mode 100644 czi-format/czi-parser/always_on_assert.h create mode 100644 czi-format/czi-parser/file_system.h diff --git a/czi-format/Links to Download.txt b/czi-format/Links to Download.txt index 6d11afe..bc4196e 100644 --- a/czi-format/Links to Download.txt +++ b/czi-format/Links to Download.txt @@ -1,10 +1,10 @@ Basic testing ------------- -http://czisamples.blob.core.windows.net/czi-samples/TESTIMAGES.zip +X http://czisamples.blob.core.windows.net/czi-samples/TESTIMAGES.zip Advanced testing ---------------- -http://czisamples.blob.core.windows.net/czi-samples/Legend.txt +X http://czisamples.blob.core.windows.net/czi-samples/Legend.txt http://czisamples.blob.core.windows.net/czi-samples/ApoTome/40x075_Artemia-Flash-AT-1Ch-Z-sect.czi http://czisamples.blob.core.windows.net/czi-samples/ApoTome/40x14_GMMe_AT-4ch-Z_Dapi-Vimentin488_Phalloidine568-Lamin647(WF).czi @@ -20,17 +20,17 @@ http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_Apo http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_ApoTome_2ch_raw_Tiles.czi http://czisamples.blob.core.windows.net/czi-samples/ApoTome/Kidney-FS44_FS45_ApoTome_2ch_sect_Tiles-stitched.czi http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/20x_HE.czi -http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Intestine_3color_RAC.czi +X http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Intestine_3color_RAC.czi http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Kidney_40x_z_stack.czi http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Kidney_RAC_3color.czi http://czisamples.blob.core.windows.net/czi-samples/Axio Scan.Z1/Young_mouse.czi -http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/EB3-microtubules-GFP_H2BmCherry_2chT(SD).czi +X http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/EB3-microtubules-GFP_H2BmCherry_2chT(SD).czi http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/LLC-PK1_2chTZ-triggered-20msec(SD).czi http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/LLC-PK1_TubX-emerald_H2B-mCherry-2chZ(SD).czi http://czisamples.blob.core.windows.net/czi-samples/CellObserver SD/Micrasterias fimbriata#1_2chTZ(SD).czi http://czisamples.blob.core.windows.net/czi-samples/Multiscene/Mouse-kidney-3-scene_VivaTome_1chZS.czi http://czisamples.blob.core.windows.net/czi-samples/Tiles/Mouse_stomach_20x_ROI_3chZTiles(WF).czi http://czisamples.blob.core.windows.net/czi-samples/VivaTome/Mouse_kidney_VivaTome-1chTZ.czi -http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-Cells_63x_oversampled-3chZ(WF).czi -http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells-bin2x2_3chTZ(WF).czi -http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells_mitosis_3chZ(WF).czi +X http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-Cells_63x_oversampled-3chZ(WF).czi +X http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells-bin2x2_3chTZ(WF).czi +X http://czisamples.blob.core.windows.net/czi-samples/Widefield/BPAE-cells_mitosis_3chZ(WF).czi diff --git a/czi-format/czi-parser/CMakeLists.txt b/czi-format/czi-parser/CMakeLists.txt index 146bed2..f9ee73e 100644 --- a/czi-format/czi-parser/CMakeLists.txt +++ b/czi-format/czi-parser/CMakeLists.txt @@ -6,10 +6,12 @@ enable_testing() add_executable(czi-parser main.cpp) +set(CMAKE_CXX_FLAGS "-Wall") + # set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) -find_package(Boost REQUIRED COMPONENTS locale) +find_package(Boost REQUIRED COMPONENTS filesystem locale) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) target_link_libraries(czi-parser ${Boost_LIBRARIES}) diff --git a/czi-format/czi-parser/always_on_assert.h b/czi-format/czi-parser/always_on_assert.h new file mode 100644 index 0000000..df1bfbc --- /dev/null +++ b/czi-format/czi-parser/always_on_assert.h @@ -0,0 +1,71 @@ +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* + * ISO C99 Standard: 7.2 Diagnostics <assert.h> + */ + +/* + Moravec: + Always enabled assert. +*/ + +#define _ASSERT_H 1 +#include <features.h> + +#ifndef _ASSERT_H_DECLS +#define _ASSERT_H_DECLS +__BEGIN_DECLS + +/* This prints an "assertion failed" message and aborts. */ +extern void __assert_fail(const char *__assertion, const char *__file, + unsigned int __line, const char *__function) + __THROW __attribute__((__noreturn__)); + +/* Likewise, but prints the error text for ERRNUM. */ +extern void __assert_perror_fail(int __errnum, const char *__file, + unsigned int __line, const char *__function) + __THROW __attribute__((__noreturn__)); + +/* The following is not at all used here but needed for standard + compliance. */ +extern void __assert(const char *__assertion, const char *__file, int __line) + __THROW __attribute__((__noreturn__)); + +__END_DECLS +#endif /* Not _assert_H_DECLS */ + +#if defined __cplusplus ? __GNUC_PREREQ(2, 6) : __GNUC_PREREQ(2, 4) +#define __assert_FUNCTION __extension__ __PRETTY_FUNCTION__ +#else +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#define __assert_FUNCTION __func__ +#else +#define __assert_FUNCTION ((const char *)0) +#endif +#endif + +#if defined __cplusplus +#define always_assert(expr) \ + (static_cast<bool>(expr) \ + ? void(0) \ + : __assert_fail(#expr, __FILE__, __LINE__, __assert_FUNCTION)) +#endif +#if defined __USE_ISOC11 && !defined __cplusplus +#undef static_assert +#define static_assert _Static_assert +#endif \ No newline at end of file diff --git a/czi-format/czi-parser/binary_converter.cpp b/czi-format/czi-parser/binary_converter.cpp index 5ab47db..e553999 100644 --- a/czi-format/czi-parser/binary_converter.cpp +++ b/czi-format/czi-parser/binary_converter.cpp @@ -6,8 +6,8 @@ #include "binary_converter.h" short bytes_to_short(const std::vector<byte> &bytes, const uint fromIndex) { - assert(bytes.size() >= 2); - assert(fromIndex <= bytes.size() - 2); + always_assert(bytes.size() >= 2); + always_assert(fromIndex <= bytes.size() - 2); // Little endian auto bit = &bytes[fromIndex]; @@ -24,8 +24,8 @@ short bytes_to_short(const std::vector<byte> &bytes, const uint fromIndex) int bytes_to_int(const std::vector<byte> &bytes, const uint fromIndex) { - assert(bytes.size() >= 4); - assert(fromIndex <= bytes.size() - 4); + always_assert(bytes.size() >= 4); + always_assert(fromIndex <= bytes.size() - 4); // Little endian auto bit = &bytes[fromIndex]; @@ -42,8 +42,8 @@ int bytes_to_int(const std::vector<byte> &bytes, const uint fromIndex) int bytes_to_long(const std::vector<byte> &bytes, const uint fromIndex) { - assert(bytes.size() >= 8); - assert(fromIndex <= bytes.size() - 8); + always_assert(bytes.size() >= 8); + always_assert(fromIndex <= bytes.size() - 8); // Little endian auto bit = &bytes[fromIndex]; @@ -61,8 +61,8 @@ int bytes_to_long(const std::vector<byte> &bytes, const uint fromIndex) float bytes_to_float(const std::vector<byte> &bytes, const uint fromIndex) { - assert(bytes.size() >= 4); - assert(fromIndex <= bytes.size() - 4); + always_assert(bytes.size() >= 4); + always_assert(fromIndex <= bytes.size() - 4); float result; memcpy(&result, (bytes.data() + fromIndex), 4); @@ -71,8 +71,8 @@ float bytes_to_float(const std::vector<byte> &bytes, const uint fromIndex) double bytes_to_double(const std::vector<byte> &bytes, const uint fromIndex) { - assert(bytes.size() >= 8); - assert(fromIndex <= bytes.size() - 8); + always_assert(bytes.size() >= 8); + always_assert(fromIndex <= bytes.size() - 8); double result; memcpy(&result, (bytes.data() + fromIndex), 8); diff --git a/czi-format/czi-parser/binary_converter.h b/czi-format/czi-parser/binary_converter.h index 8ab95aa..d99112e 100644 --- a/czi-format/czi-parser/binary_converter.h +++ b/czi-format/czi-parser/binary_converter.h @@ -10,7 +10,6 @@ * EVERY CONVERSION DONE HERE WORKS ONLY WITH LITTLE ENDIAN AT THIS MOMENT! */ -#include <assert.h> #include "custom_types.h" #include <string> diff --git a/czi-format/czi-parser/binary_stream.cpp b/czi-format/czi-parser/binary_stream.cpp index 1bc86e5..a0a9d40 100644 --- a/czi-format/czi-parser/binary_stream.cpp +++ b/czi-format/czi-parser/binary_stream.cpp @@ -14,10 +14,10 @@ BinaryStream::BinaryStream(const std::string &file) void BinaryStream::open_stream(const std::string &file) { - assert(!this->isOpen); + always_assert(!this->isOpen); this->fileStream = std::ifstream(file, std::ios::binary | std::ios::in | std::ios::ate); - assert(this->fileStream.is_open()); + always_assert(this->fileStream.is_open()); this->isOpen = true; @@ -42,37 +42,37 @@ BinaryStream::~BinaryStream() long BinaryStream::get_size() const { - assert(this->isOpen); + always_assert(this->isOpen); return this->fileSize; } long BinaryStream::get_position() { - assert(this->isOpen); + always_assert(this->isOpen); return (long)(this->fileStream.tellg()); } void BinaryStream::move_to(const long position) { - assert(this->isOpen); + always_assert(this->isOpen); this->fileStream.seekg(position); } void BinaryStream::move_to_beginning() { - assert(this->isOpen); + always_assert(this->isOpen); this->fileStream.seekg(std::ios::beg); } void BinaryStream::move_to_end() { - assert(this->isOpen); + always_assert(this->isOpen); this->fileStream.seekg(std::ios::end); } void BinaryStream::move_by(const long distance) { - assert(this->isOpen); + always_assert(this->isOpen); auto currentPosition = this->fileStream.tellg(); auto requiredPosition = currentPosition + distance; this->fileStream.seekg(requiredPosition); @@ -80,16 +80,16 @@ void BinaryStream::move_by(const long distance) byte BinaryStream::consume_byte() { - assert(this->isOpen); + always_assert(this->isOpen); char readedChar; this->fileStream.read(&readedChar, 1); byte result = (byte)readedChar; return result; } -bool BinaryStream::consume_bool(const short byteCount) +bool BinaryStream::consume_bool(const ushort byteCount) { - assert(this->isOpen); + always_assert(this->isOpen); auto bytes = consume_bytes(byteCount); int sum = 0; @@ -101,37 +101,37 @@ bool BinaryStream::consume_bool(const short byteCount) short BinaryStream::consume_short() { - assert(this->isOpen); + always_assert(this->isOpen); return bytes_to_short(consume_bytes(2)); } int BinaryStream::consume_int() { - assert(this->isOpen); + always_assert(this->isOpen); return bytes_to_int(consume_bytes(4)); } long BinaryStream::consume_long() { - assert(this->isOpen); + always_assert(this->isOpen); return bytes_to_long(consume_bytes(8)); } float BinaryStream::consume_float() { - assert(this->isOpen); + always_assert(this->isOpen); return bytes_to_float(consume_bytes(4)); } double BinaryStream::consume_double() { - assert(this->isOpen); + always_assert(this->isOpen); return bytes_to_double(consume_bytes(8)); } std::vector<byte> BinaryStream::consume_whole_file() { - assert(this->isOpen); + always_assert(this->isOpen); std::vector<byte> result; this->fileStream.seekg(std::ios::beg); result.insert(result.begin(), std::istream_iterator<byte>(this->fileStream), std::istream_iterator<byte>()); @@ -140,15 +140,15 @@ std::vector<byte> BinaryStream::consume_whole_file() std::vector<byte> BinaryStream::consume_rest_of_file() { - assert(this->isOpen); + always_assert(this->isOpen); std::vector<byte> result; result.insert(result.begin(), std::istream_iterator<byte>(this->fileStream), std::istream_iterator<byte>()); return result; } -std::vector<byte> BinaryStream::consume_bytes(const long byteCount) +std::vector<byte> BinaryStream::consume_bytes(const ulong byteCount) { - assert(this->isOpen); + always_assert(this->isOpen); //TODO: Can this be made faster? std::vector<byte> result; @@ -170,7 +170,7 @@ std::vector<byte> BinaryStream::consume_bytes(const long byteCount) std::vector<byte> BinaryStream::move_and_consume_bytes(const long position, const long byteCount) { - assert(this->isOpen); + always_assert(this->isOpen); move_to(position); return consume_bytes(byteCount); } \ No newline at end of file diff --git a/czi-format/czi-parser/binary_stream.h b/czi-format/czi-parser/binary_stream.h index 5bf281f..9a92d51 100644 --- a/czi-format/czi-parser/binary_stream.h +++ b/czi-format/czi-parser/binary_stream.h @@ -38,7 +38,7 @@ public: // Read one byte. byte consume_byte(); // Read specified number of bytes are converts them into bool. - bool consume_bool(const short byteCount); + bool consume_bool(const ushort byteCount); // Read two bytes and converts them into short. short consume_short(); // Read four bytes and converts them into int. @@ -55,7 +55,7 @@ public: // Read rest of the file, from current position to end, into memory. std::vector<byte> consume_rest_of_file(); // Read specified number of bytes. - std::vector<byte> consume_bytes(const long byteCount); + std::vector<byte> consume_bytes(const ulong byteCount); // Move file stream to requested position and read specified number of bytes. std::vector<byte> move_and_consume_bytes(const long position, const long byteCount); }; diff --git a/czi-format/czi-parser/custom_types.h b/czi-format/czi-parser/custom_types.h index ee6df34..e064b54 100644 --- a/czi-format/czi-parser/custom_types.h +++ b/czi-format/czi-parser/custom_types.h @@ -4,7 +4,7 @@ #define VERBOSE_PARSER 0 #include <vector> -#include <assert.h> +#include "always_on_assert.h" constexpr bool NOT_IMPLEMENTED_YET = false; diff --git a/czi-format/czi-parser/czi_file.cpp b/czi-format/czi-parser/czi_file.cpp index 7bcb35d..d183a10 100644 --- a/czi-format/czi-parser/czi_file.cpp +++ b/czi-format/czi-parser/czi_file.cpp @@ -42,9 +42,11 @@ const char *pixel_type_str(const PixelType px) case PixelType::Gray64: return "Gray64"; default: - assert("Bad pixel type." && false); + always_assert("Bad pixel type." && false); break; } + + return nullptr; } const char *pyramid_type_str(const PyramidType pt) @@ -60,10 +62,11 @@ const char *pyramid_type_str(const PyramidType pt) break; default: { - assert("Bad pyramid type." && false); + always_assert("Bad pyramid type." && false); break; } } + return nullptr; } const char *compression_type_str(const CompressionType ct) @@ -85,10 +88,11 @@ const char *compression_type_str(const CompressionType ct) break; default: { - assert("Bad compression type." && false); + always_assert("Bad compression type." && false); break; } } + return nullptr; } const char *dimension_type_str(const Dimension d) @@ -123,10 +127,11 @@ const char *dimension_type_str(const Dimension d) break; default: { - assert("Bad dimension type." && false); + always_assert("Bad dimension type." && false); break; } } + return nullptr; } void CziFile::report_verbose() const @@ -198,7 +203,10 @@ void CziFile::report() const printf("%-25s %15i\n", "SubBlockCount", subBlockDirectory.entryCount); if (subBlockDirectory.entryCount > 0) + { printf("%-25s %15i\n", "DimensionCount", subBlockDirectory.entries[0].dimensionCount); + printf("%-25s %15s\n", "PixelType", pixel_type_str(subBlockDirectory.entries[0].pixelType)); + } printf("%-25s %15i\n", "AttachmentCount", attachmentDirectory.entryCount); @@ -211,10 +219,10 @@ void CziFile::extract_images(const std::string &baseName) const int imageIndex = 0; for (const DirectoryEntryDV &entry : subBlockDirectory.entries) { - assert(entry.width > 0 && entry.height > 0); + always_assert(entry.width > 0 && entry.height > 0); auto imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize); - std::string imageFileName = baseName + std::to_string(imageIndex++) + ".bpm"; + std::string imageFileName = baseName + std::to_string(imageIndex++) + ".pnm"; create_image_file(imageFileName.c_str(), imageBytes, entry.pixelType, entry.width, entry.height); } } @@ -225,12 +233,12 @@ void CziFile::dump_image_data(const std::string &baseName) const int imageIndex = 0; for (const DirectoryEntryDV &entry : subBlockDirectory.entries) { - assert(entry.width > 0 && entry.height > 0); + always_assert(entry.width > 0 && entry.height > 0); auto imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize); std::string binaryFileName = baseName + std::to_string(imageIndex++) + ".bin"; std::ofstream binaryStream(binaryFileName, std::ios::binary | std::ios::out); - assert(binaryStream.is_open()); + always_assert(binaryStream.is_open()); binaryStream.write(reinterpret_cast<const char *>(imageBytes.data()), imageBytes.size()); printf("Wrote %s\n", binaryFileName.c_str()); } diff --git a/czi-format/czi-parser/czi_parser.cpp b/czi-format/czi-parser/czi_parser.cpp index 3286dd7..6d34c83 100644 --- a/czi-format/czi-parser/czi_parser.cpp +++ b/czi-format/czi-parser/czi_parser.cpp @@ -21,8 +21,9 @@ CziFile CziParser::parse_czi_file(const std::string &file) for (size_t subBlockId = 0; subBlockId < parsedFile.subBlockDirectory.entryCount; subBlockId++) { + int filePart = parsedFile.subBlockDirectory.entries[subBlockId].filePart; - assert(filePart == 0 && "We are currently supporting only single-file scenario."); + always_assert(filePart == 0 && "We are currently supporting only single-file scenario."); long subBlockPosition = parsedFile.subBlockDirectory.entries[subBlockId].filePosition; int entrySize = parsedFile.subBlockDirectory.entries[subBlockId].entrySize; @@ -62,7 +63,7 @@ FileHeaderSegment CziParser::parse_file_header(BinaryStream &cziStream) { FileHeaderSegment result; result.header = parse_segment_header(cziStream); - assert(result.header.sId == FileHeaderSegmentSID); + always_assert(result.header.sId == FileHeaderSegmentSID); result.fileVersion = {}; result.fileVersion.major = cziStream.consume_int(); @@ -88,12 +89,12 @@ FileHeaderSegment CziParser::parse_file_header(BinaryStream &cziStream) MetadataSegment CziParser::parse_metadata(BinaryStream &cziStream, const long position) { - assert(position > 0); + always_assert(position > 0); cziStream.move_to(position); MetadataSegment result = {}; result.header = parse_segment_header(cziStream); - assert(result.header.sId == MetadataSegmentSID); + always_assert(result.header.sId == MetadataSegmentSID); result.xmlSize = cziStream.consume_int(); result.attachmentSize = cziStream.consume_int(); @@ -114,12 +115,12 @@ MetadataSegment CziParser::parse_metadata(BinaryStream &cziStream, const long po SubBlockDirectorySegment CziParser::parse_subblock_directory(BinaryStream &cziStream, const long position) { - assert(position > 0); + always_assert(position > 0); cziStream.move_to(position); SubBlockDirectorySegment result = {}; result.header = parse_segment_header(cziStream); - assert(result.header.sId == SubBlockDirectorySegmentSID); + always_assert(result.header.sId == SubBlockDirectorySegmentSID); result.entryCount = cziStream.consume_int(); // 124 B are reserved, skipping. @@ -143,7 +144,7 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre result.schemaType = cziStream.consume_bytes(2); - assert(result.schemaType.size() == 2 && result.schemaType[0] == 'D' && result.schemaType[1] == 'V'); + always_assert(result.schemaType.size() == 2 && result.schemaType[0] == 'D' && result.schemaType[1] == 'V'); result.pixelType = to_pixel_type(cziStream.consume_int()); result.filePosition = cziStream.consume_long(); @@ -155,7 +156,7 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre cziStream.move_by(5); result.dimensionCount = cziStream.consume_int(); - assert(result.dimensionCount > 0); + always_assert(result.dimensionCount > 0); result.dimensions.reserve(result.dimensionCount); for (size_t dim = 0; dim < result.dimensionCount; dim++) @@ -179,12 +180,12 @@ DirectoryEntryDV CziParser::parse_subblock_directory_entry(BinaryStream &cziStre AttachmentDirectorySegment CziParser::parse_attachment_directory(BinaryStream &cziStream, const long position) { - assert(position > 0); + always_assert(position > 0); cziStream.move_to(position); AttachmentDirectorySegment result = {}; result.header = parse_segment_header(cziStream); - assert(result.header.sId == AttachmentDirectorySegmentSID); + always_assert(result.header.sId == AttachmentDirectorySegmentSID); result.entryCount = cziStream.consume_int(); @@ -208,7 +209,7 @@ AttachmentEntryA1 CziParser::parse_attachment_entry(BinaryStream &cziStream) { AttachmentEntryA1 result = {}; result.schemaType = cziStream.consume_bytes(2); - assert(result.schemaType.size() == 2 && result.schemaType[0] == 'A' && result.schemaType[1] == '1'); + always_assert(result.schemaType.size() == 2 && result.schemaType[0] == 'A' && result.schemaType[1] == '1'); // Next 10 bytes are reserved. cziStream.move_by(10); @@ -248,12 +249,12 @@ DimensionEntryDV1 CziParser::parse_dimension_entry(BinaryStream &cziStream) SubBlockSegment CziParser::parse_subblock(BinaryStream &cziStream, const long position, const int entryIndex, const int entrySize) { - assert(position > 0); + always_assert(position > 0); cziStream.move_to(position); SubBlockSegment result = {}; result.header = parse_segment_header(cziStream); - assert(result.header.sId == SubBlockSegmentSID); + always_assert(result.header.sId == SubBlockSegmentSID); result.metadataSize = cziStream.consume_int(); result.attachmentSize = cziStream.consume_int(); @@ -288,13 +289,13 @@ SubBlockSegment CziParser::parse_subblock(BinaryStream &cziStream, const long po AttachmentSegment CziParser::parse_attachment_segment(BinaryStream &cziStream, const long position, const int entryIndex) { - assert(position > 0); + always_assert(position > 0); cziStream.move_to(position); AttachmentSegment result = {}; result.directoryEntryIndex = entryIndex; result.header = parse_segment_header(cziStream); - assert(result.header.sId == AttachmentSegmentSID); + always_assert(result.header.sId == AttachmentSegmentSID); result.dataSize = cziStream.consume_int(); // 12 B reserved next 128 B are for AttachmentEntry which is saved under 'entryIndex' in @@ -331,7 +332,7 @@ PixelType CziParser::to_pixel_type(const int value) break; } default: - assert("Bad pixel type." && false); + always_assert("Bad pixel type." && false); break; } return result; @@ -348,7 +349,7 @@ PyramidType CziParser::to_pyramid_type(const byte value) break; default: { - assert("Bad pyramid type." && false); + always_assert("Bad pyramid type." && false); break; } } @@ -369,7 +370,7 @@ CompressionType CziParser::to_compression_type(const int value) break; default: { - assert("Bad compression type." && false); + always_assert("Bad compression type." && false); break; } } @@ -378,7 +379,7 @@ CompressionType CziParser::to_compression_type(const int value) Dimension CziParser::to_dimension_type(const std::vector<byte> &bytes) { - assert(bytes.size() == 4); + always_assert(bytes.size() == 4); Dimension result = static_cast<Dimension>((char)bytes[0]); switch (result) { @@ -397,7 +398,7 @@ Dimension CziParser::to_dimension_type(const std::vector<byte> &bytes) break; default: { - assert("Bad dimension type." && false); + always_assert("Bad dimension type." && false); break; } } diff --git a/czi-format/czi-parser/czi_parts/attachment_directory_segment.h b/czi-format/czi-parser/czi_parts/attachment_directory_segment.h index 2b80d34..5b9bd9c 100644 --- a/czi-format/czi-parser/czi_parts/attachment_directory_segment.h +++ b/czi-format/czi-parser/czi_parts/attachment_directory_segment.h @@ -9,7 +9,7 @@ struct AttachmentDirectorySegment // Segment header of attachment directory. SegmentHeader header; // Number of entries in directory. - int entryCount; + uint entryCount; // Attachment directory entries. std::vector<AttachmentEntryA1> entries; }; diff --git a/czi-format/czi-parser/czi_parts/directory_entry_dv.h b/czi-format/czi-parser/czi_parts/directory_entry_dv.h index 15ae296..ad1c25a 100644 --- a/czi-format/czi-parser/czi_parts/directory_entry_dv.h +++ b/czi-format/czi-parser/czi_parts/directory_entry_dv.h @@ -20,7 +20,7 @@ struct DirectoryEntryDV // Type of image pyramid. PyramidType pyramidType; // Number of dimension entries. Minimally one. - int dimensionCount; + uint dimensionCount; // Dimensions. std::vector<DimensionEntryDV1> dimensions; // Referenced SubBlock. diff --git a/czi-format/czi-parser/czi_parts/subblock_directory_segment.h b/czi-format/czi-parser/czi_parts/subblock_directory_segment.h index 98209d5..224fcf6 100644 --- a/czi-format/czi-parser/czi_parts/subblock_directory_segment.h +++ b/czi-format/czi-parser/czi_parts/subblock_directory_segment.h @@ -9,7 +9,7 @@ struct SubBlockDirectorySegment // SubBlock directory segment header. SegmentHeader header; // Number of entries in directory. - int entryCount; + uint entryCount; // Collection of DirectoryEntryDV, they are the exact same copy as in SubBlock segment. std::vector<DirectoryEntryDV> entries; }; \ No newline at end of file diff --git a/czi-format/czi-parser/file_system.h b/czi-format/czi-parser/file_system.h new file mode 100644 index 0000000..d833dcd --- /dev/null +++ b/czi-format/czi-parser/file_system.h @@ -0,0 +1,102 @@ +#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 "boost/filesystem.hpp" +#include "boost/algorithm/string.hpp" + +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) +{ + auto file = fs::path(pathToCheck); + return (fs::exists(file) && fs::is_regular_file(file)); +} + +// Check if given path points to directory. +bool is_directory(const std::string &pathToCheck) +{ + return fs::is_directory(fs::path(pathToCheck)); +} + +// Create all missing directories in path. +bool create_directory_path(const std::string &desiredPath) +{ + return fs::create_directories(fs::path(desiredPath)); +} + +// Get name of the file, specified by its path. +std::string get_filename(const std::string &selectedPath) +{ + return fs::path(selectedPath).filename().string(); +} + +// Get name, without extension, of the file, specified by its path. +std::string get_filename_without_extension(const std::string &selectedPath) +{ + fs::path file(selectedPath); + auto name = file.filename().string(); + auto ext = file.extension().string(); + return name.substr(0, name.length() - ext.length()); +} + +// Get files, whose names begin with prefix. +std::vector<SmallFileInfo> get_files_with_same_prefix(const std::vector<SmallFileInfo> &files, const std::string &prefix) +{ + std::vector<SmallFileInfo> result; + + for (const SmallFileInfo &file : files) + { + if (boost::algorithm::starts_with(file.name, prefix)) + { + result.push_back(file); + } + } + + return result; +} + +// 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) +{ + fs::path refFile(filePath); + always_assert(fs::is_regular_file(refFile)); + always_assert(refFile.has_parent_path()); + + fs::path dir = refFile.parent_path(); + + std::vector<SmallFileInfo> files; + + fs::path entryPath; + for (fs::directory_entry &entry : fs::directory_iterator(dir)) + { + entryPath = entry.path(); + if (fs::is_regular_file(entryPath)) + { + if (!onlyCziFiles || (boost::to_upper_copy(fs::extension(entryPath)) == CziExtUpperCase)) + { + SmallFileInfo fi = {}; + fi.name = entryPath.filename().string(); + fi.path = entryPath.string(); + files.push_back(fi); + } + } + } + + return files; +} \ No newline at end of file diff --git a/czi-format/czi-parser/image_writer.h b/czi-format/czi-parser/image_writer.h index 6d23ed6..5bcad62 100644 --- a/czi-format/czi-parser/image_writer.h +++ b/czi-format/czi-parser/image_writer.h @@ -26,5 +26,6 @@ void create_image_file(const char *fileName, const std::vector<byte> &bytes, con } //set_pixel() - img.save_bmp(fileName); + img.save_pnm(fileName); + } \ No newline at end of file diff --git a/czi-format/czi-parser/main.cpp b/czi-format/czi-parser/main.cpp index 1b93255..402f849 100644 --- a/czi-format/czi-parser/main.cpp +++ b/czi-format/czi-parser/main.cpp @@ -1,10 +1,13 @@ #include "czi_parser.h" +#include "file_system.h" int main(int argc, char **argv) { std::string cziFile; cziFile = (argc > 1) ? argv[1] : "/home/mor0146/Downloads/cziFiles/TESTIMAGES/CZT-Stack-Anno.czi"; + always_assert(is_file(cziFile)); + std::string method = argc > 2 ? argv[2] : ""; std::string dumpName = argc > 3 ? argv[3] : ""; @@ -13,6 +16,10 @@ int main(int argc, char **argv) bool dumpRawImageData = method == "--dump-raw-image-data"; bool dumpImageData = method == "--dump-image-data"; + auto name = get_filename_without_extension(cziFile); + auto x = get_files_in_parent_directory(cziFile, true); + auto y = get_files_with_same_prefix(x, name); + CziParser parser; auto parseResult = parser.parse_czi_file(cziFile); -- GitLab