Newer
Older
return ((header.filePart == 0) && (header.fileGuid == header.masterFileGuid));
void CziFile::print_segment_header(const SegmentHeader &segmentHeader) const
{
printf("---------SegmentHeader---------\n");
printf("%-25s %15s\n", "SID", segmentHeader.sId.c_str());
printf("%-25s %15li\n", "AllocatedSize", segmentHeader.allocatedSize);
printf("%-25s %15li\n", "UsedSize", segmentHeader.usedSize);
printf("-------------------------------\n");
}
const char *CziFile::pixel_type_str(const PixelType px) const
always_assert("Bad pixel type." && false);
return nullptr;
const char *CziFile::pyramid_type_str(const PyramidType pt) const
return "MultiSubBlock";
break;
default:
{
always_assert("Bad pyramid type." && false);
return nullptr;
const char *CziFile::compression_type_str(const CompressionType ct) const
return "System";
break;
default:
{
always_assert("Bad compression type." && false);
return nullptr;
const char *CziFile::dimension_type_str(const Dimension &d) const
return "X (width)";
return "Y (height)";
return "C (channels)";
return "Z (Z-slices)";
return "T (timestamps)";
return "R (rotation)";
return "S (scene)";
return "I (illumination)";
return "B (block index)";
return "M (mosaic)";
return "H (phase)";
return "V (views)";
break;
default:
{
always_assert("Bad dimension type." && false);
return nullptr;
const char *CziFile::dimension_char(const Dimension &d) const
default:
{
always_assert("Bad dimension type." && false);
break;
}
}
std::string CziFile::dimension_stack_str(const std::vector<DimensionEntryDV1> &dims, bool includeSize) const
{
std::string result;
for (const DimensionEntryDV1 &entry : dims)
{
result.append(dimension_char(entry.dimension));
// + std::string(includeSize ? () : ""));
if (includeSize)
result.append("(" + std::to_string(entry.size) + ")-");
}
if (includeSize)
{
result = result.substr(0, result.length() - 1);
printf("==========SubBlock directory==========\n");
print_segment_header(subBlockDirectory.header);
printf("%-25s %15i\n", "EntryCount", subBlockDirectory.entryCount);
for (size_t entry = 0; entry < subBlockDirectory.entryCount; entry++)
{
printf("SubBlockId: %i\tPixelType: %s\tCompression: %s\tDimensionStack: %s\tPyramidType: %s\n",
(int)entry,
pixel_type_str(subBlockDirectory.entries[entry].pixelType),
compression_type_str(subBlockDirectory.entries[entry].compression),
dimension_stack_str(subBlockDirectory.entries[entry].dimensions, true).c_str(),
pyramid_type_str(subBlockDirectory.entries[entry].pyramidType));
}
printf("======================================\n");
std::string byte_array_str(const std::vector<byte> &bytes)
{
std::string result = "";
for (size_t i = 0; i < bytes.size(); i++)
{
result.append(std::to_string(bytes[i]));
if (i % 4 == 0 && i != bytes.size() - 1)
result.append("-");
}
return result;
}
{
printf("Loaded CZI FILE: %s\n", fileName.c_str());
printf("==========Summary report==========\n");
print_segment_header(header.header);
printf("%-25s %13i.%i\n", "FileVersion", header.fileVersion.major, header.fileVersion.minor);
printf("%-25s %15i\n", "FilePart", header.filePart);
printf("%-25s %30s\n", "MasterGUID", byte_array_str(header.masterFileGuid).c_str());
printf("%-25s %30s\n", "FileGUID", byte_array_str(header.masterFileGuid).c_str());
//TODO: Replace with GUID print.
printf("%-25s %15i\n", "GUIDs are matching", vecUtil::vector_eq(header.masterFileGuid, header.fileGuid));
printf("%-25s %15i\n", "UpdatePending", header.updatePending);
printf("%-25s %15li\n", "SubblockDirPosition", header.subBlockDirectoryPosition);
printf("%-25s %15li\n", "MetadataPosition", header.metadataPosition);
printf("%-25s %15li\n", "AttachmentDirPosition", header.attachmentDirectoryPosition);
printf("%-25s %15i\n", "SubBlockCount", subBlockDirectory.entryCount);
printf("%-25s %15i\n", "AttachmentCount", attachmentDirectory.entryCount);
{
std::map<PixelType, int> pixelTypeMap;
std::map<CompressionType, int> compressionMap;
std::map<std::string, int> dimensionMap;
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
for (size_t sbId = 0; sbId < subBlockDirectory.entryCount; sbId++)
{
const DirectoryEntryDV entry = subBlockDirectory.entries[sbId];
if (pixelTypeMap.count(entry.pixelType))
pixelTypeMap[entry.pixelType]++;
else
pixelTypeMap.emplace(std::make_pair(entry.pixelType, 1));
if (compressionMap.count(entry.compression))
compressionMap[entry.compression]++;
else
compressionMap.emplace(std::make_pair(entry.compression, 1));
std::string dimStackStr = dimension_stack_str(entry.dimensions, false);
if (dimensionMap.count(dimStackStr))
dimensionMap[dimStackStr]++;
else
dimensionMap.emplace(std::make_pair(dimStackStr, 1));
}
printf("Pixel type distribution:\n");
for (auto &&ptPair : pixelTypeMap)
{
printf("\t%s %ix\n", pixel_type_str(ptPair.first), ptPair.second);
}
printf("Compression type distribution:\n");
for (auto &&ctPair : compressionMap)
{
printf("\t%s %ix\n", compression_type_str(ctPair.first), ctPair.second);
}
printf("Dimension stack distribution:\n");
for (auto &&dimPair : dimensionMap)
{
printf("\t%s %ix\n", dimPair.first.c_str(), dimPair.second);
}
}
//printf("%-25s %15i\n", "DimensionCount", subBlockDirectory.entries[0].dimensionCount);
//printf("%-25s %15s\n", "PixelType", pixel_type_str(subBlockDirectory.entries[0].pixelType));
}
printf("==================================\n");
ImageMatrix CziFile::get_image(const uint subblockId) const
{
// // subblockId is in bounds.
// always_assert((uint)subblockId < subBlockDirectory.entries.size());
// // Image is not empty.
// always_assert(entry.width > 0 && entry.height > 0);
// // Read image bytes.
// std::vector<byte> imageBytes;
// {
// BinaryFileStream cziStream(fileName);
// imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize);
// }
auto imageBytes = get_image_data(subblockId, false);
auto entry = subBlockDirectory.entries[subblockId];
ImageMatrix image = ImageMatrix((uint)entry.width, (uint)entry.height, entry.pixelType, imageBytes);
return image;
}
std::vector<byte> CziFile::get_image_data(const uint subblockId, const bool ZCurveOrdered) const
always_assert((uint)subblockId < subBlockDirectory.entries.size());
auto entry = subBlockDirectory.entries[subblockId];
always_assert(entry.width > 0 && entry.height > 0);
// Read image bytes.
std::vector<byte> imageBytes;
{
BinaryFileStream cziStream(fileName);
imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize);
}
// Check if read data are correct and not corrupted.
int bytesPerPixel = get_bytes_per_pixel_type(entry.pixelType);
ulong expectedSize = entry.width * entry.height * bytesPerPixel;
always_assert(expectedSize == imageBytes.size());
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);
return zOrderedBytes;
}
else
{
return imageBytes;
}
void CziFile::differences_between_next(const std::string baseName) const
{
if (subBlockDirectory.entries.size() <= 1)
{
printf("There aren't 2 different images in this CZI file.\n");
return;
}
std::string fName;
ImageMatrix ref = get_image(0);
for (size_t i = 1; i < subBlockDirectory.entries.size(); i++)
{
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);
diff_ref_next.save_as_ppm(fName.c_str());
void CziFile::extract_images(const std::string &baseName) const
{
std::string fName;
for (size_t i = 0; i < subBlockDirectory.entries.size(); i++)
{
auto subblock = get_image(i);
fName = baseName + "subblock_" + std::to_string(i) + ".ppm";
subblock.save_as_ppm(fName.c_str());
}
}
void CziFile::dump_image_data(const std::string &baseName) const
{
BinaryFileStream cziStream(fileName);
int imageIndex = 0;
for (const DirectoryEntryDV &entry : subBlockDirectory.entries)
{
always_assert(entry.width > 0 && entry.height > 0);
std::string binaryFileName = baseName + std::to_string(imageIndex++) + ".bin";
auto imageBytes = cziStream.move_and_consume_bytes(entry.subBlock.dataLocation, entry.subBlock.dataSize);
write_bytes_to_file(imageBytes, binaryFileName.c_str());
printf("Wrote %s\n", binaryFileName.c_str());
}
}
void CziFile::test_compression(CompressionMethod method, bool verbose) const
case CompressionMethod_GZIP:
printf("Selected compression: GZIP (zlib)\n");
break;
case CompressionMethod_LZMA:
printf("Selected compression: LZMA (2?)\n");
break;
case CompressionMethod_BZIP2:
printf("Selected compression: BZIP2 \n");
break;
CompressionResult overallN;
CompressionResult overallZ;
Stopwatch stopwatch;
for (size_t i = 0; i < subBlockDirectory.entries.size(); i++)
{
auto data = get_image_data(i, false);
auto dataZ = get_image_data(i, true);
CompressionResult nResult = test_compression_method(data, method, settings, stopwatch);
CompressionResult zResult = test_compression_method(dataZ, method, settings, stopwatch);
overallN.compressionRatio += nResult.compressionRatio;
overallZ.compressionRatio += zResult.compressionRatio;
overallN.originalSize += data.size();
overallN.compressedSize += nResult.compressedSize;
overallZ.compressedSize += zResult.compressedSize;
overallN.percentageOfOriginalSize += nResult.percentageOfOriginalSize;
overallZ.percentageOfOriginalSize += zResult.percentageOfOriginalSize;
printf("Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f; Size(N): %5.3f%%; Size(Z): %5.3f%%; Time: %8.1f ms\n",
(int)i, nResult.compressionRatio, zResult.compressionRatio, nResult.percentageOfOriginalSize,
zResult.percentageOfOriginalSize, stopwatch.last_lap_milliseconds());
}
float dataCount = (float)subBlockDirectory.entries.size();
overallN.divide(dataCount);
overallZ.divide(dataCount);
printf("Overall compression ratios: Normal %8f Z-Ordered: %8f\n", overallN.compressionRatio, overallZ.compressionRatio);
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: %.1f ms\n", stopwatch.average_lap_time_in_milliseconds());