Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ptahmose/libczi-zeiss
Browse files Browse the repository at this point in the history
  • Loading branch information
ptahmose committed Feb 13, 2024
2 parents 0deb3a6 + b0898cb commit 20a7efc
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 146 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15)
cmake_policy(SET CMP0091 NEW) # enable new "MSVC runtime library selection" (https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html)

project(libCZI
VERSION 0.58.0
VERSION 0.58.1
HOMEPAGE_URL "https://github.com/ZEISS/libczi"
DESCRIPTION "libCZI is an Open Source Cross-Platform C++ library to read and write CZI")

Expand Down
2 changes: 2 additions & 0 deletions Src/libCZI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set(LIBCZISRCFILES
CziMetadataSegment.cpp
CziParse.cpp
CZIReader.cpp
CziReaderCommon.cpp
CziReaderWriter.cpp
CziStructs.cpp
CziSubBlock.cpp
Expand Down Expand Up @@ -60,6 +61,7 @@ set(LIBCZISRCFILES
CziMetadataDocumentInfo2.h
CziMetadataSegment.h
CziParse.h
CziReaderCommon.h
CZIReader.h
CziReaderWriter.h
CziStructs.h
Expand Down
104 changes: 10 additions & 94 deletions Src/libCZI/CZIReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "CziUtils.h"
#include "utilities.h"
#include "CziAttachment.h"
#include "CziReaderCommon.h"

using namespace std;
using namespace libCZI;
Expand Down Expand Up @@ -101,15 +102,7 @@ CCZIReader::CCZIReader() : isOperational(false)
this->subBlkDir.EnumSubBlocks(
[&](int index, const CCziSubBlockDirectory::SubBlkEntry& entry)->bool
{
SubBlockInfo info;
info.compressionModeRaw = entry.Compression;
info.pixelType = CziUtils::PixelTypeFromInt(entry.PixelType);
info.coordinate = entry.coordinate;
info.logicalRect = IntRect{ entry.x,entry.y,entry.width,entry.height };
info.physicalSize = IntSize{ (std::uint32_t)entry.storedWidth, (std::uint32_t)entry.storedHeight };
info.mIndex = entry.mIndex;
info.pyramidType = CziUtils::PyramidTypeFromByte(entry.pyramid_type_from_spare);
return funcEnum(index, info);
return funcEnum(index, CziReaderCommon::ConvertToSubBlockInfo(entry));
});
}

Expand All @@ -135,30 +128,7 @@ CCZIReader::CCZIReader() : isOperational(false)
/*virtual*/void CCZIReader::EnumSubset(const IDimCoordinate* planeCoordinate, const IntRect* roi, bool onlyLayer0, const std::function<bool(int index, const SubBlockInfo& info)>& funcEnum)
{
this->ThrowIfNotOperational();

// TODO:
// Ok... for a first tentative, experimental and quick-n-dirty implementation, simply
// walk through all the subblocks. We surely want to have something more elaborated
// here.
this->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& info)->bool
{
// TODO: we only deal with layer 0 currently... or, more precisely, we do not take "zoom" into account at all
// -> well... added that boolean "onlyLayer0" - is this sufficient...?
if (onlyLayer0 == false || (info.physicalSize.w == info.logicalRect.w && info.physicalSize.h == info.logicalRect.h))
{
if (planeCoordinate == nullptr || CziUtils::CompareCoordinate(planeCoordinate, &info.coordinate) == true)
{
if (roi == nullptr || Utilities::DoIntersect(*roi, info.logicalRect))
{
bool b = funcEnum(index, info);
return b;
}
}
}

return true;
});
CziReaderCommon::EnumSubset(this, planeCoordinate, roi, onlyLayer0, funcEnum);
}

/*virtual*/std::shared_ptr<ISubBlock> CCZIReader::ReadSubBlock(int index)
Expand All @@ -176,41 +146,7 @@ CCZIReader::CCZIReader() : isOperational(false)
/*virtual*/bool CCZIReader::TryGetSubBlockInfoOfArbitrarySubBlockInChannel(int channelIndex, SubBlockInfo& info)
{
this->ThrowIfNotOperational();

// TODO: we should be able to gather this information when constructing the subblock-list
// for the time being... just walk through the whole list
//
bool foundASubBlock = false;
SubBlockStatistics s = this->subBlkDir.GetStatistics();
if (!s.dimBounds.IsValid(DimensionIndex::C))
{
// in this case -> just take the first subblock...
this->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& sbinfo)->bool
{
info = sbinfo;
foundASubBlock = true;
return false;
});
}
else
{
this->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& sbinfo)->bool
{
int c;
if (sbinfo.coordinate.TryGetPosition(DimensionIndex::C, &c) == true && c == channelIndex)
{
info = sbinfo;
foundASubBlock = true;
return false;
}

return true;
});
}

return foundASubBlock;
return CziReaderCommon::TryGetSubBlockInfoOfArbitrarySubBlockInChannel(this, channelIndex, info);
}

/*virtual*/bool CCZIReader::TryGetSubBlockInfo(int index, SubBlockInfo* info) const
Expand All @@ -223,13 +159,7 @@ CCZIReader::CCZIReader() : isOperational(false)

if (info != nullptr)
{
info->compressionModeRaw = entry.Compression;
info->pixelType = CziUtils::PixelTypeFromInt(entry.PixelType);
info->coordinate = entry.coordinate;
info->logicalRect = IntRect{ entry.x,entry.y,entry.width,entry.height };
info->physicalSize = IntSize{ static_cast<std::uint32_t>(entry.storedWidth), static_cast<std::uint32_t>(entry.storedHeight) };
info->mIndex = entry.mIndex;
info->pyramidType = CziUtils::PyramidTypeFromByte(entry.pyramid_type_from_spare);
*info = CziReaderCommon::ConvertToSubBlockInfo(entry);
}

return true;
Expand Down Expand Up @@ -273,25 +203,11 @@ CCZIReader::CCZIReader() : isOperational(false)
/*virtual*/void CCZIReader::EnumerateSubset(const char* contentFileType, const char* name, const std::function<bool(int index, const libCZI::AttachmentInfo& info)>& funcEnum)
{
this->ThrowIfNotOperational();
libCZI::AttachmentInfo ai;
ai.contentFileType[sizeof(ai.contentFileType) - 1] = '\0';
this->attachmentDir.EnumAttachments(
[&](int index, const CCziAttachmentsDirectory::AttachmentEntry& ae)
{
if (contentFileType == nullptr || strcmp(contentFileType, ae.ContentFileType) == 0)
{
if (name == nullptr || strcmp(name, ae.Name) == 0)
{
ai.contentGuid = ae.ContentGuid;
memcpy(ai.contentFileType, ae.ContentFileType, sizeof(ae.ContentFileType));
ai.name = ae.Name;
bool b = funcEnum(index, ai);
return b;
}
}

return true;
});
CziReaderCommon::EnumerateSubset(
std::bind(&CCziAttachmentsDirectory::EnumAttachments, &this->attachmentDir, std::placeholders::_1),
contentFileType,
name,
funcEnum);
}

/*virtual*/std::shared_ptr<libCZI::IAttachment> CCZIReader::ReadAttachment(int index)
Expand Down
118 changes: 118 additions & 0 deletions Src/libCZI/CziReaderCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-FileCopyrightText: 2024 Carl Zeiss Microscopy GmbH
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "CziReaderCommon.h"

#include "CziUtils.h"
#include "utilities.h"

using namespace std;
using namespace libCZI;

/*static*/void CziReaderCommon::EnumSubset(
libCZI::ISubBlockRepository* repository,
const libCZI::IDimCoordinate* planeCoordinate,
const libCZI::IntRect* roi,
bool onlyLayer0,
const std::function<bool(int index, const libCZI::SubBlockInfo& info)>& funcEnum)
{
// Ok... for a first tentative, experimental and quick-n-dirty implementation, simply
// walk through all the subblocks. We surely want to have something more elaborated
// here.
repository->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& info)->bool
{
if (onlyLayer0 == false || (info.physicalSize.w == info.logicalRect.w && info.physicalSize.h == info.logicalRect.h))
{
if (planeCoordinate == nullptr || CziUtils::CompareCoordinate(planeCoordinate, &info.coordinate) == true)
{
if (roi == nullptr || Utilities::DoIntersect(*roi, info.logicalRect))
{
const bool b = funcEnum(index, info);
return b;
}
}
}

return true;
});
}

/*static*/bool CziReaderCommon::TryGetSubBlockInfoOfArbitrarySubBlockInChannel(
libCZI::ISubBlockRepository* repository,
int channelIndex,
libCZI::SubBlockInfo& info)
{
bool foundASubBlock = false;
SubBlockStatistics s = repository->GetStatistics();
if (!s.dimBounds.IsValid(DimensionIndex::C))
{
// in this case -> just take the first subblock...
repository->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& sbinfo)->bool
{
info = sbinfo;
foundASubBlock = true;
return false;
});
}
else
{
repository->EnumerateSubBlocks(
[&](int index, const SubBlockInfo& sbinfo)->bool
{
int c;
if (sbinfo.coordinate.TryGetPosition(DimensionIndex::C, &c) == true && c == channelIndex)
{
info = sbinfo;
foundASubBlock = true;
return false;
}

return true;
});
}

return foundASubBlock;
}

/*static*/void CziReaderCommon::EnumerateSubset(
const std::function<void(const std::function<bool(int index, const CCziAttachmentsDirectory::AttachmentEntry&)>&)>& func,
const char* contentFileType,
const char* name,
const std::function<bool(int index, const libCZI::AttachmentInfo& info)>& funcEnum)
{
libCZI::AttachmentInfo ai;
ai.contentFileType[sizeof(ai.contentFileType) - 1] = '\0';
func(
[&](int index, const CCziAttachmentsDirectoryBase::AttachmentEntry& ae)
{
if (contentFileType == nullptr || strcmp(contentFileType, ae.ContentFileType) == 0)
{
if (name == nullptr || strcmp(name, ae.Name) == 0)
{
ai.contentGuid = ae.ContentGuid;
memcpy(ai.contentFileType, ae.ContentFileType, sizeof(ae.ContentFileType));
ai.name = ae.Name;
bool b = funcEnum(index, ai);
return b;
}
}

return true;
});
}

/*static*/libCZI::SubBlockInfo CziReaderCommon::ConvertToSubBlockInfo(const CCziSubBlockDirectory::SubBlkEntry& entry)
{
SubBlockInfo info;
info.compressionModeRaw = entry.Compression;
info.pixelType = CziUtils::PixelTypeFromInt(entry.PixelType);
info.coordinate = entry.coordinate;
info.logicalRect = IntRect{ entry.x,entry.y,entry.width,entry.height };
info.physicalSize = IntSize{ (std::uint32_t)entry.storedWidth, (std::uint32_t)entry.storedHeight };
info.mIndex = entry.mIndex;
info.pyramidType = CziUtils::PyramidTypeFromByte(entry.pyramid_type_from_spare);
return info;
}
34 changes: 34 additions & 0 deletions Src/libCZI/CziReaderCommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2024 Carl Zeiss Microscopy GmbH
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#pragma once

#include "libCZI.h"
#include "CziAttachment.h"
#include <functional>

/// Here we gather some common functionality that is used by both the CziReader and the CziReaderWriter classes.
class CziReaderCommon
{
public:
static void EnumSubset(
libCZI::ISubBlockRepository* repository,
const libCZI::IDimCoordinate* planeCoordinate,
const libCZI::IntRect* roi,
bool onlyLayer0,
const std::function<bool(int index, const libCZI::SubBlockInfo& info)>& funcEnum);

static bool TryGetSubBlockInfoOfArbitrarySubBlockInChannel(
libCZI::ISubBlockRepository* repository,
int channelIndex,
libCZI::SubBlockInfo& info);

static void EnumerateSubset(
const std::function<void(const std::function<bool(int index, const CCziAttachmentsDirectory::AttachmentEntry&)>&)>& func,
const char* contentFileType,
const char* name,
const std::function<bool(int index, const libCZI::AttachmentInfo& info)>& funcEnum);

static libCZI::SubBlockInfo ConvertToSubBlockInfo(const CCziSubBlockDirectory::SubBlkEntry& entry);
};
Loading

0 comments on commit 20a7efc

Please sign in to comment.