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 ByteArray &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
{
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;
}
ByteArray 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);
{
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));
ByteArray zOrderedBytes = reorder_bytes_to_z_order(imageBytes, zIndices, componentSize);
return zOrderedBytes;
}
else
{
return imageBytes;
}
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
ByteArray CziFile::get_continuous_image_data(const bool ZCurveOrdered) const
{
// Find required size.
size_t totalSize = 0;
for (auto &&entry : subBlockDirectory.entries)
totalSize += entry.subBlock.dataSize;
// Allocate size.
ByteArray data;
data.resize(totalSize);
size_t bufferEnd = 0;
if (ZCurveOrdered)
{
for (size_t subblockId = 0; subblockId < subBlockDirectory.entries.size(); subblockId++)
{
auto zOrderSubblockData = get_image_data(subblockId, true);
vecUtil::vector_insert_at(data, zOrderSubblockData, bufferEnd, 0, zOrderSubblockData.size());
bufferEnd += zOrderSubblockData.size();
}
}
else
{
BinaryFileStream stream(fileName);
for (size_t subblockId = 0; subblockId < subBlockDirectory.entries.size(); subblockId++)
{
auto entry = subBlockDirectory.entries[subblockId];
stream.move_to(entry.subBlock.dataLocation);
stream.consume_into(data, bufferEnd, entry.subBlock.dataSize);
bufferEnd += entry.subBlock.dataSize;
}
}
return data;
}
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::dump_images(const std::string &baseName) const
//#pragma omp parallel for
for (size_t i = 0; i < subBlockDirectory.entries.size(); i++)
{
auto subblock = get_image(i);
std::string fName = baseName + "subblock_" + std::to_string(i) + ".ppm";
subblock.save_as_ppm(fName.c_str());
}
}
void CziFile::dump_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, int compressionLevel) 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;
printf("\tCompression level: %i\n", compressionLevel);
CompressionResult overallN;
CompressionResult overallZ;
Stopwatch stopwatch;
size_t done = 0;
// #pragma omp parallel for
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, compressionLevel);
CompressionResult zResult = test_compression_method(dataZ, method, compressionLevel);
// #pragma omp critical
// {
done += 1;
float perc = (float)done / (float)subBlockDirectory.entries.size();
printf("Done: %f %%\n", perc * 100.0f);
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;
overallN.compressionTimeMS += nResult.compressionTimeMS;
overallZ.compressionTimeMS += zResult.compressionTimeMS;
printf("Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f; Size(N): %5.3f%%; Size(Z): %5.3f%%; Time: %8f ms\n",
(int)i, nResult.compressionRatio, zResult.compressionRatio, nResult.percentageOfOriginalSize,
zResult.percentageOfOriginalSize, nResult.compressionTimeMS);
}
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: %f ms\n", overallN.compressionTimeMS);