diff --git a/AppModel/include/app_api.h b/AppModel/include/app_api.h index 0e11b70..89cc639 100644 --- a/AppModel/include/app_api.h +++ b/AppModel/include/app_api.h @@ -7,87 +7,94 @@ extern "C" { #include #include -typedef void* Parameter; + typedef void* Parameter; -enum AppExtensionClassId -{ - AppExtensionClassId_Unknown, - AppExtensionClassId_Uint8, - AppExtensionClassId_Int8, - AppExtensionClassId_Uint16, - AppExtensionClassId_Int16, - AppExtensionClassId_Uint32, - AppExtensionClassId_Int32, - AppExtensionClassId_Uint64, - AppExtensionClassId_Int64, - AppExtensionClassId_Double, - AppExtensionClassId_Single, -}; + enum AppExtensionClassId + { + AppExtensionClassId_Unknown, + AppExtensionClassId_Uint8, + AppExtensionClassId_Int8, + AppExtensionClassId_Uint16, + AppExtensionClassId_Int16, + AppExtensionClassId_Uint32, + AppExtensionClassId_Int32, + AppExtensionClassId_Uint64, + AppExtensionClassId_Int64, + AppExtensionClassId_Double, + AppExtensionClassId_Single, + AppExtensionClassId_Logical, + }; -struct IAppExtensionFunctions -{ - bool (*pfn_IsNanOrInfDouble)(double d); + struct IAppExtensionFunctions + { + bool (*pfn_IsNanOrInfDouble)(double d); - bool (*pfn_IsNanOrInfSingle)(float f); + bool (*pfn_IsNanOrInfSingle)(float f); - void* (*pfn_GetData)(const Parameter* parameter); + double (*pfn_GetInfDouble)(void); - uint8_t* (*pfn_GetUint8s)(const Parameter* parameter); + double (*pfn_GetNaNDouble)(void); - int8_t* (*pfn_GetInt8s)(const Parameter* parameter); + void* (*pfn_GetData)(const Parameter* parameter); - uint16_t* (*pfn_GetUint16s)(const Parameter* parameter); + uint8_t* (*pfn_GetUint8s)(const Parameter* parameter); - int16_t* (*pfn_GetInt16s)(const Parameter* parameter); + int8_t* (*pfn_GetInt8s)(const Parameter* parameter); - uint32_t* (*pfn_GetUint32s)(const Parameter* parameter); + uint16_t* (*pfn_GetUint16s)(const Parameter* parameter); - int32_t* (*pfn_GetInt32s)(const Parameter* parameter); + int16_t* (*pfn_GetInt16s)(const Parameter* parameter); - uint64_t* (*pfn_GetUint64s)(const Parameter* parameter); + uint32_t* (*pfn_GetUint32s)(const Parameter* parameter); - int64_t* (*pfn_GetInt64s)(const Parameter* parameter); + int32_t* (*pfn_GetInt32s)(const Parameter* parameter); - double* (*pfn_GetDoubles)(const Parameter* parameter); + uint64_t* (*pfn_GetUint64s)(const Parameter* parameter); - float* (*pfn_GetSingles)(const Parameter* parameter); + int64_t* (*pfn_GetInt64s)(const Parameter* parameter); - bool (*pfn_IsNumeric)(const Parameter* parameter); + double* (*pfn_GetDoubles)(const Parameter* parameter); - bool (*pfn_IsChar)(const Parameter* parameter); + float* (*pfn_GetSingles)(const Parameter* parameter); - bool (*pfn_IsSparse)(const Parameter* parameter); + bool* (*pfn_GetLogicals)(const Parameter* parameter); - bool (*pfn_IsStruct)(const Parameter* parameter); + bool (*pfn_IsNumeric)(const Parameter* parameter); - Parameter* (*pfn_CreateString)(const char* string); + bool (*pfn_IsChar)(const Parameter* parameter); - void (*pfn_ReportErrorAndRaiseSignal)(const char* identifier, const char* message); + bool (*pfn_IsSparse)(const Parameter* parameter); - char* (*pfn_StrDupHostAllocated)(const char* string); + bool (*pfn_IsStruct)(const Parameter* parameter); - Parameter* (*pfn_CreateStructArray)(size_t ndim, const size_t* dims, int nfields, const char** field_names); + Parameter* (*pfn_CreateString)(const char* string); - void (*pfn_SetFieldByNumber)(Parameter* pa, size_t i, int fieldnum, Parameter* value); + void (*pfn_ReportErrorAndRaiseSignal)(const char* identifier, const char* message); - char* (*pfn_ConvertToUTF8String)(const Parameter* parameter); + char* (*pfn_StrDupHostAllocated)(const char* string); - void (*pfn_Free)(void* ptr); + Parameter* (*pfn_CreateStructArray)(size_t ndim, const size_t* dims, int nfields, const char** field_names); - Parameter* (*pfn_CreateNumericMatrixReal)(size_t m, size_t n, enum AppExtensionClassId class_id); + void (*pfn_SetFieldByNumber)(Parameter* pa, size_t i, int fieldnum, Parameter* value); - enum AppExtensionClassId (*pfn_GetClassId)(const Parameter* parameter); + char* (*pfn_ConvertToUTF8String)(const Parameter* parameter); - size_t (*pfn_GetNumberOfElements)(const Parameter* parameter); + void (*pfn_Free)(void* ptr); - size_t(*pfn_GetNumberOfDimensions)(const Parameter* parameter); + Parameter* (*pfn_CreateNumericMatrixReal)(size_t m, size_t n, enum AppExtensionClassId class_id); - void (*pfn_GetSizeOfDimensions)(const Parameter* parameter, size_t number_of_dimension, size_t* sizes); + enum AppExtensionClassId(*pfn_GetClassId)(const Parameter* parameter); - Parameter* (*pfn_GetField)(const Parameter* parameter, const char* field_name); + size_t(*pfn_GetNumberOfElements)(const Parameter* parameter); - Parameter* (*pfn_CreateNumericArrayReal)(size_t ndim, const size_t* dims, enum AppExtensionClassId class_id); -}; + size_t(*pfn_GetNumberOfDimensions)(const Parameter* parameter); + + void (*pfn_GetSizeOfDimensions)(const Parameter* parameter, size_t number_of_dimension, size_t* sizes); + + Parameter* (*pfn_GetField)(const Parameter* parameter, const char* field_name); + + Parameter* (*pfn_CreateNumericArrayReal)(size_t ndim, const size_t* dims, enum AppExtensionClassId class_id); + }; #ifdef __cplusplus } diff --git a/MatlabMex/app_api_implementation.c b/MatlabMex/app_api_implementation.c index 18ea5a5..0fe97c9 100644 --- a/MatlabMex/app_api_implementation.c +++ b/MatlabMex/app_api_implementation.c @@ -12,6 +12,16 @@ bool matlabMexIsNanOrInfSingle(float value) return mxIsNaN(value) || mxIsInf(value); } +double matlabMaxGetInfinityDouble(void) +{ + return mxGetInf(); +} + +double matlabMaxGetNaNDouble(void) +{ + return mxGetNaN(); +} + void* matlabMexGetData(const Parameter* parameter) { return mxGetData((const mxArray*)parameter); @@ -67,6 +77,11 @@ float* matlabMexGetSingles(const Parameter* parameter) return mxGetSingles((const mxArray*)parameter); } +bool* matlabMexGetLogicals(const Parameter* parameter) +{ + return mxGetLogicals((const mxArray*)parameter); +} + bool matlabMexIsNumeric(const Parameter* parameter) { return mxIsNumeric((const mxArray*)parameter); @@ -126,45 +141,76 @@ void matlabFree(void* ptr) mxFree(ptr); } -Parameter* matlabCreateNumericMatrixReal(size_t m, size_t n, enum AppExtensionClassId class_id) +mxClassID AppExtensionClassIdToMxClassId(enum AppExtensionClassId class_id) { - mxClassID mx_class_id; switch (class_id) { case AppExtensionClassId_Uint8: - mx_class_id = mxUINT8_CLASS; - break; + return mxUINT8_CLASS; case AppExtensionClassId_Int8: - mx_class_id = mxINT8_CLASS; - break; + return mxINT8_CLASS; case AppExtensionClassId_Uint16: - mx_class_id = mxUINT16_CLASS; - break; + return mxUINT16_CLASS; case AppExtensionClassId_Int16: - mx_class_id = mxINT16_CLASS; - break; + return mxINT16_CLASS; case AppExtensionClassId_Uint32: - mx_class_id = mxUINT32_CLASS; - break; + return mxUINT32_CLASS; case AppExtensionClassId_Int32: - mx_class_id = mxINT32_CLASS; - break; + return mxINT32_CLASS; case AppExtensionClassId_Uint64: - mx_class_id = mxUINT64_CLASS; - break; + return mxUINT64_CLASS; case AppExtensionClassId_Int64: - mx_class_id = mxINT64_CLASS; - break; + return mxINT64_CLASS; case AppExtensionClassId_Double: - mx_class_id = mxDOUBLE_CLASS; - break; + return mxDOUBLE_CLASS; case AppExtensionClassId_Single: - mx_class_id = mxSINGLE_CLASS; - break; + return mxSINGLE_CLASS; + case AppExtensionClassId_Logical: + return mxLOGICAL_CLASS; default: - mx_class_id = mxUNKNOWN_CLASS; - break; + return mxUNKNOWN_CLASS; } +} + +Parameter* matlabCreateNumericMatrixReal(size_t m, size_t n, enum AppExtensionClassId class_id) +{ + mxClassID mx_class_id = AppExtensionClassIdToMxClassId(class_id); + //switch (class_id) + //{ + //case AppExtensionClassId_Uint8: + // mx_class_id = mxUINT8_CLASS; + // break; + //case AppExtensionClassId_Int8: + // mx_class_id = mxINT8_CLASS; + // break; + //case AppExtensionClassId_Uint16: + // mx_class_id = mxUINT16_CLASS; + // break; + //case AppExtensionClassId_Int16: + // mx_class_id = mxINT16_CLASS; + // break; + //case AppExtensionClassId_Uint32: + // mx_class_id = mxUINT32_CLASS; + // break; + //case AppExtensionClassId_Int32: + // mx_class_id = mxINT32_CLASS; + // break; + //case AppExtensionClassId_Uint64: + // mx_class_id = mxUINT64_CLASS; + // break; + //case AppExtensionClassId_Int64: + // mx_class_id = mxINT64_CLASS; + // break; + //case AppExtensionClassId_Double: + // mx_class_id = mxDOUBLE_CLASS; + // break; + //case AppExtensionClassId_Single: + // mx_class_id = mxSINGLE_CLASS; + // break; + //default: + // mx_class_id = mxUNKNOWN_CLASS; + // break; + //} return (Parameter*)mxCreateNumericMatrix(m, n, mx_class_id, mxREAL); } @@ -194,6 +240,8 @@ enum AppExtensionClassId matlabGetClassId(const Parameter* parameter) return AppExtensionClassId_Double; case mxSINGLE_CLASS: return AppExtensionClassId_Single; + case mxLOGICAL_CLASS: + return AppExtensionClassId_Logical; default: return AppExtensionClassId_Unknown; } @@ -230,8 +278,8 @@ Parameter* matlabGetField(const Parameter* parameter, const char* field_name) Parameter* matlabCreateNumericArrayReal(size_t ndim, const size_t* dims, enum AppExtensionClassId class_id) { - mxClassID mx_class_id; - switch (class_id) + mxClassID mx_class_id = AppExtensionClassIdToMxClassId(class_id); + /*switch (class_id) { case AppExtensionClassId_Uint8: mx_class_id = mxUINT8_CLASS; @@ -266,7 +314,7 @@ Parameter* matlabCreateNumericArrayReal(size_t ndim, const size_t* dims, enum Ap default: mx_class_id = mxUNKNOWN_CLASS; break; - } + }*/ return (Parameter*)mxCreateNumericArray(ndim, dims, mx_class_id, mxREAL); } @@ -275,6 +323,8 @@ struct IAppExtensionFunctions g_appExtensionFunctions = { .pfn_IsNanOrInfDouble = matlabMexIsNanOrInfDouble, .pfn_IsNanOrInfSingle = matlabMexIsNanOrInfSingle, + .pfn_GetInfDouble = matlabMaxGetInfinityDouble, + .pfn_GetNaNDouble = matlabMaxGetNaNDouble, .pfn_GetData = matlabMexGetData, .pfn_GetUint8s = matlabMexGetUint8s, .pfn_GetInt8s = matlabMexGetInt8s, @@ -286,6 +336,7 @@ struct IAppExtensionFunctions g_appExtensionFunctions = .pfn_GetInt64s = matlabMexGetInt64s, .pfn_GetDoubles = matlabMexGetDoubles, .pfn_GetSingles = matlabMexGetSingles, + .pfn_GetLogicals = matlabMexGetLogicals, .pfn_IsNumeric = matlabMexIsNumeric, .pfn_IsChar = matlabMexIsChar, .pfn_IsSparse = matlabMexIsSparse, diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a2074d6..d5d9110 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -16,14 +16,21 @@ set (libSourceFiles "src/implementation/CziReader.cpp" "src/implementation/dbgprint.h" "src/implementation/dbgprint.cpp" - "src/implementation/CziReaderSbBlkStore.cpp" - "src/implementation/CziReaderSbBlkStore.h" - "src/implementation/CziUtilities.cpp" - "src/implementation/CziUtilities.h" - "src/implementation/include_rapidjson.h" - "src/implementation/argsutils.h" + "src/implementation/CziReaderSbBlkStore.cpp" + "src/implementation/CziReaderSbBlkStore.h" + "src/implementation/CziUtilities.cpp" + "src/implementation/CziUtilities.h" + "src/implementation/include_rapidjson.h" + "src/implementation/argsutils.h" "src/implementation/argsutils.cpp" - "src/implementation/CziWriter.cpp" "src/implementation/CziWriter.h") + "src/implementation/CziWriter.cpp" + "src/implementation/CziWriter.h" + "src/implementation/utils.cpp" + "src/implementation/utils.h" + "src/implementation/CziWriterManager.cpp" + "src/implementation/CziWriterManager.h" + "src/functions/func_open.cpp" + "src/functions/func_open.h" "src/functions/func_getsubblockbitmap.cpp" "src/functions/func_getsubblockbitmap.h") if(CMAKE_BUILD_TYPE MATCHES Debug) set(lib_ENABLE_LOGGING 1) diff --git a/lib/src/functions/func_getsubblockbitmap.cpp b/lib/src/functions/func_getsubblockbitmap.cpp new file mode 100644 index 0000000..ab2e9bb --- /dev/null +++ b/lib/src/functions/func_getsubblockbitmap.cpp @@ -0,0 +1,61 @@ +#include "func_getsubblockbitmap.h" +#include "../implementation/CziReaderManager.h" +#include +#include +#include "../implementation/argsutils.h" +#include "../implementation/utils.h" +#include "../implementation/dbgprint.h" + +using namespace std; + +void MexFunction_GetSubBlockBitmap_CheckArguments(MatlabArgs* args) +{ + // arguments: + // 2nd: handle [number] + // 3rd: subblock-number [number] + + if (args->nrhs < 3) + { + throw invalid_argument("not enough arguments"); + } + + if (!CArgsUtils::TryGetInt32(args->prhs[1], nullptr, args->app_functions)) + { + throw invalid_argument("2nd argument must be a number."); + } + + if (!CArgsUtils::TryGetInt32(args->prhs[2], nullptr, args->app_functions)) + { + throw invalid_argument("2nd argument must be a number."); + } +} + +void MexFunction_GetSubBlockBitmap_Execute(MatlabArgs* args) +{ + int id, blkNo; + bool b = CArgsUtils::TryGetInt32(args->prhs[1], &id, args->app_functions); + if (!b) + { + throw invalid_argument("2nd argument must be a number."); + } + + b = CArgsUtils::TryGetInt32(args->prhs[2], &blkNo, args->app_functions); + if (!b) + { + throw invalid_argument("3rd argument must be a number."); + } + + std::shared_ptr reader = Utils::GetReaderOrThrow(id); + + try + { + auto* out = reader->GetSubBlockImage(blkNo, args->app_functions); + args->plhs[0] = out; + } + catch (exception& exception) + { + (void)exception; // suppress "unreferenced local variable" warning + VDBGPRINT((CDbg::Level::Warn, "MexFunction_GetSubBlockBitmap_Execute: GetSubBlockImage failed -> %s.", exception.what())); + throw; + } +} \ No newline at end of file diff --git a/lib/src/functions/func_getsubblockbitmap.h b/lib/src/functions/func_getsubblockbitmap.h new file mode 100644 index 0000000..d753788 --- /dev/null +++ b/lib/src/functions/func_getsubblockbitmap.h @@ -0,0 +1,6 @@ +#pragma once + +#include "../mexFunctions.h" + +void MexFunction_GetSubBlockBitmap_CheckArguments(MatlabArgs* args); +void MexFunction_GetSubBlockBitmap_Execute(MatlabArgs* args); \ No newline at end of file diff --git a/lib/src/functions/func_open.cpp b/lib/src/functions/func_open.cpp new file mode 100644 index 0000000..3a9bc17 --- /dev/null +++ b/lib/src/functions/func_open.cpp @@ -0,0 +1,49 @@ +#include "func_open.h" +//#include "libraryInfo.h" +#include "../implementation/CziReaderManager.h" +#include +#include +#include "../implementation/dbgprint.h" +//#include "mexapi.h" +#include "../implementation/argsutils.h" +#include "../implementation/utils.h" + +using namespace std; + +void MexFunction_Open_CheckArguments(MatlabArgs* args) +{ + // 2nd argument : [string] filename + if (args->nrhs < 2) + { + throw invalid_argument("not enough arguments"); + } + + //if (!MexApi::GetInstance().MxIsChar(args->prhs[1])) + if (!args->app_functions->pfn_IsChar(args->prhs[1])) + { + throw invalid_argument("Expecting a string as 2nd argument"); + } +} + +void MexFunction_Open_Execute(MatlabArgs* args) +{ + //const auto filename = MexApi::GetInstance().UpMxArrayToMatlabAllocatedUtf8String(args->prhs[1]); + const auto filename = CArgsUtils::GetAsUtf8String(args->prhs[1], args->app_functions); + + int id = CziReaderManager::GetInstance().CreateNewInstance(); + auto reader = CziReaderManager::GetInstance().GetInstance(id); + try + { + VDBGPRINT((CDbg::Level::Trace, "MexFunction_Open_Execute: attempt to open file \"%s\".", filename)); + reader->Open(filename); + } + catch (exception& exception) + { + (void)exception; // suppress "unreferenced local variable" warning + VDBGPRINT((CDbg::Level::Warn, "MexFunction_Open_Execute: Open failed -> %s.", exception.what())); + CziReaderManager::GetInstance().RemoveInstance(id); + throw; + } + + args->plhs[0] = MexUtils::Int32To1x1Matrix(id, args->app_functions); +} diff --git a/lib/src/functions/func_open.h b/lib/src/functions/func_open.h new file mode 100644 index 0000000..7020850 --- /dev/null +++ b/lib/src/functions/func_open.h @@ -0,0 +1,6 @@ +#pragma once + +#include "../mexFunctions.h" + +void MexFunction_Open_CheckArguments(MatlabArgs* args); +void MexFunction_Open_Execute(MatlabArgs* args); \ No newline at end of file diff --git a/lib/src/implementation/CziReader.cpp b/lib/src/implementation/CziReader.cpp index 02d39ec..f4803c5 100644 --- a/lib/src/implementation/CziReader.cpp +++ b/lib/src/implementation/CziReader.cpp @@ -46,9 +46,9 @@ Parameter* CziReader::GetScalingAsMatlabStruct(IAppExtensionFunctions* app_funct //mexApi.MxSetFieldByNumber(s, 0, 1, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleYValid() ? scaling.scaleY : numeric_limits::quiet_NaN())); //mexApi.MxSetFieldByNumber(s, 0, 2, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleZValid() ? scaling.scaleZ : numeric_limits::quiet_NaN())); - app_functions->pfn_SetFieldByNumber(s, 0, 0, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleXValid() ? scaling.scaleX : numeric_limits::quiet_NaN())); - app_functions->pfn_SetFieldByNumber(s, 0, 1, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleYValid() ? scaling.scaleY : numeric_limits::quiet_NaN())); - app_functions->pfn_SetFieldByNumber(s, 0, 2, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleZValid() ? scaling.scaleZ : numeric_limits::quiet_NaN())); + app_functions->pfn_SetFieldByNumber(s, 0, 0, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleXValid() ? scaling.scaleX : numeric_limits::quiet_NaN(), app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 1, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleYValid() ? scaling.scaleY : numeric_limits::quiet_NaN(), app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 2, MexUtils::DoubleTo1x1Matrix(scaling.IsScaleZValid() ? scaling.scaleZ : numeric_limits::quiet_NaN(), app_functions)); return s; } @@ -85,16 +85,16 @@ Parameter* CziReader::GetInfo(IAppExtensionFunctions* app_functions) (sizeof(fieldNames) / sizeof(fieldNames[0])) - (statistics.IsMIndexValid() ? 0 : 2), fieldNames); - app_functions->pfn_SetFieldByNumber(s, 0, 0, MexUtils::Int32To1x1Matrix(statistics.subBlockCount)); - app_functions->pfn_SetFieldByNumber(s, 0, 1, CziReader::ConvertToMatlabStruct(statistics.boundingBox)); - app_functions->pfn_SetFieldByNumber(s, 0, 2, CziReader::ConvertToMatlabStruct(statistics.boundingBoxLayer0Only)); - app_functions->pfn_SetFieldByNumber(s, 0, 3, CziReader::ConvertToMatlabStruct(&statistics.dimBounds)); - app_functions->pfn_SetFieldByNumber(s, 0, 4, CziReader::ConvertToMatlabStruct(statistics.sceneBoundingBoxes)); + app_functions->pfn_SetFieldByNumber(s, 0, 0, MexUtils::Int32To1x1Matrix(statistics.subBlockCount, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 1, CziReader::ConvertToMatlabStruct(statistics.boundingBox, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 2, CziReader::ConvertToMatlabStruct(statistics.boundingBoxLayer0Only, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 3, CziReader::ConvertToMatlabStruct(&statistics.dimBounds, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 4, CziReader::ConvertToMatlabStruct(statistics.sceneBoundingBoxes, app_functions)); if (statistics.IsMIndexValid()) { - app_functions->pfn_SetFieldByNumber(s, 0, 5, MexUtils::Int32To1x1Matrix(statistics.minMindex)); - app_functions->pfn_SetFieldByNumber(s, 0, 6, MexUtils::Int32To1x1Matrix(statistics.maxMindex)); + app_functions->pfn_SetFieldByNumber(s, 0, 5, MexUtils::Int32To1x1Matrix(statistics.minMindex, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 6, MexUtils::Int32To1x1Matrix(statistics.maxMindex, app_functions)); } return s; @@ -425,7 +425,7 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() } } -/*static*/Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IDimBounds* bounds) +/*static*/Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IDimBounds* bounds, IAppExtensionFunctions* app_functions) { vector dimensions; for (auto i = (std::underlying_type::type)(libCZI::DimensionIndex::MinDim); i <= (std::underlying_type::type)(libCZI::DimensionIndex::MaxDim); ++i) @@ -446,47 +446,57 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() } size_t dims[2] = { 1, 1 }; - auto mexApi = MexApi::GetInstance(); - auto* s = mexApi.MxCreateStructArray(2, dims, (int)fieldNames.size(), &fieldNames[0]); + //auto mexApi = MexApi::GetInstance(); + //auto* s = mexApi.MxCreateStructArray(2, dims, (int)fieldNames.size(), &fieldNames[0]); + auto* s = app_functions->pfn_CreateStructArray(2, dims, (int)fieldNames.size(), &fieldNames[0]); for (int i = 0; i < dimensions.size(); ++i) { int startIndex, size; bounds->TryGetInterval(libCZI::Utils::CharToDimension(dimensions[i][0]), &startIndex, &size); - auto* no = mexApi.MxCreateNumericMatrix(1, 2, mxINT32_CLASS, mxREAL); - int* ptr = mexApi.MxGetInt32s(no); + //auto* no = mexApi.MxCreateNumericMatrix(1, 2, mxINT32_CLASS, mxREAL); + auto* no = app_functions->pfn_CreateNumericMatrixReal(1, 2, AppExtensionClassId_Int32); + //int* ptr = mexApi.MxGetInt32s(no); + int* ptr = app_functions->pfn_GetInt32s(no); *ptr = startIndex; *(ptr + 1) = size; - mexApi.MxSetFieldByNumber(s, 0, i, no); + //mexApi.MxSetFieldByNumber(s, 0, i, no); + app_functions->pfn_SetFieldByNumber(s, 0, i, no); } return s; } -/*static*/Parameter* CziReader::ConvertToMatlabStruct(const std::map& boundingBoxMap) +/*static*/Parameter* CziReader::ConvertToMatlabStruct(const std::map& boundingBoxMap, IAppExtensionFunctions* app_functions) { static const char* fieldNames[] = { "sceneIndex", "boundingBox", "boundingBoxLayer0" }; size_t dims[2] = { 1, boundingBoxMap.size() }; - auto mexApi = MexApi::GetInstance(); - auto* s = mexApi.MxCreateStructArray(2, dims, sizeof(fieldNames) / sizeof(fieldNames[0]), fieldNames); + //auto mexApi = MexApi::GetInstance(); + //auto* s = mexApi.MxCreateStructArray(2, dims, sizeof(fieldNames) / sizeof(fieldNames[0]), fieldNames); + auto* s = app_functions->pfn_CreateStructArray(2, dims, sizeof(fieldNames) / sizeof(fieldNames[0]), fieldNames); int i = 0; for (auto it = boundingBoxMap.cbegin(); it != boundingBoxMap.cend(); ++it) { - mexApi.MxSetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it->first)); + /*mexApi.MxSetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it->first)); mexApi.MxSetFieldByNumber(s, i, 1, CziReader::ConvertToMatlabStruct(it->second.boundingBox)); - mexApi.MxSetFieldByNumber(s, i, 2, CziReader::ConvertToMatlabStruct(it->second.boundingBoxLayer0)); + mexApi.MxSetFieldByNumber(s, i, 2, CziReader::ConvertToMatlabStruct(it->second.boundingBoxLayer0));*/ + app_functions->pfn_SetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it->first, app_functions)); + app_functions->pfn_SetFieldByNumber(s, i, 1, CziReader::ConvertToMatlabStruct(it->second.boundingBox, app_functions)); + app_functions->pfn_SetFieldByNumber(s, i, 2, CziReader::ConvertToMatlabStruct(it->second.boundingBoxLayer0, app_functions)); ++i; } return s; } -/*static*/ Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IntRect& rect) +/*static*/ Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IntRect& rect, IAppExtensionFunctions* app_functions) { - auto mexApi = MexApi::GetInstance(); - auto* m = mexApi.MxCreateNumericMatrix(1, 4, mxINT32_CLASS, mxREAL); - int* ptr = mexApi.MxGetInt32s(m); + //auto mexApi = MexApi::GetInstance(); + //auto* m = mexApi.MxCreateNumericMatrix(1, 4, mxINT32_CLASS, mxREAL); + auto* m = app_functions->pfn_CreateNumericMatrixReal(1, 4, AppExtensionClassId_Int32); + //int* ptr = mexApi.MxGetInt32s(m); + int* ptr = app_functions->pfn_GetInt32s(m); ptr[0] = rect.x; ptr[1] = rect.y; ptr[2] = rect.w; @@ -494,11 +504,13 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() return m; } -/*static*/ Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IntSize& size) +/*static*/ Parameter* CziReader::ConvertToMatlabStruct(const libCZI::IntSize& size, IAppExtensionFunctions* app_functions) { - auto mexApi = MexApi::GetInstance(); - auto* m = mexApi.MxCreateNumericMatrix(1, 2, mxINT32_CLASS, mxREAL); - int* ptr = mexApi.MxGetInt32s(m); + //auto mexApi = MexApi::GetInstance(); + //auto* m = mexApi.MxCreateNumericMatrix(1, 2, mxINT32_CLASS, mxREAL); + auto* m = app_functions->pfn_CreateNumericMatrixReal(1, 2, AppExtensionClassId_Int32); + //int* ptr = mexApi.MxGetInt32s(m); + int* ptr = app_functions->pfn_GetInt32s(m); ptr[0] = size.w; ptr[1] = size.h; return m; @@ -543,11 +555,11 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() { auto chDs = ds.GetChannelDisplaySettings(it); //mexApi.MxSetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it)); - app_functions->pfn_SetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it)); + app_functions->pfn_SetFieldByNumber(s, i, 0, MexUtils::Int32To1x1Matrix(it, app_functions)); //mexApi.MxSetFieldByNumber(s, i, 1, MexUtils::BooleanTo1x1Matrix(chDs->GetIsEnabled())); - app_functions->pfn_SetFieldByNumber(s, i, 1, MexUtils::BooleanTo1x1Matrix(chDs->GetIsEnabled())); + app_functions->pfn_SetFieldByNumber(s, i, 1, MexUtils::BooleanTo1x1Matrix(chDs->GetIsEnabled(), app_functions)); //mexApi.MxSetFieldByNumber(s, i, 2, MexUtils::DoubleTo1x1Matrix(chDs->GetWeight())); - app_functions->pfn_SetFieldByNumber(s, i, 2, MexUtils::DoubleTo1x1Matrix(chDs->GetWeight())); + app_functions->pfn_SetFieldByNumber(s, i, 2, MexUtils::DoubleTo1x1Matrix(chDs->GetWeight(), app_functions)); Rgb8Color tintingColor; if (chDs->TryGetTintingColorRgb8(&tintingColor)) @@ -574,7 +586,7 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() float blackPoint, whitePoint; chDs->GetBlackWhitePoint(&blackPoint, &whitePoint); //mexApi.MxSetFieldByNumber(s, i, 5, MexUtils::DoublesAsNx1Matrix(2, static_cast(blackPoint), static_cast(whitePoint))); - app_functions->pfn_SetFieldByNumber(s, i, 5, MexUtils::DoublesAsNx1Matrix(2, static_cast(blackPoint), static_cast(whitePoint))); + app_functions->pfn_SetFieldByNumber(s, i, 5, MexUtils::DoublesAsNx1Matrix(app_functions, 2, static_cast(blackPoint), static_cast(whitePoint))); switch (chDs->GetGradationCurveMode()) { @@ -588,7 +600,7 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() float gamma; chDs->TryGetGamma(&gamma); //mexApi.MxSetFieldByNumber(s, i, 7, MexUtils::DoubleTo1x1Matrix(gamma)); - app_functions->pfn_SetFieldByNumber(s, i, 7, MexUtils::DoubleTo1x1Matrix(gamma)); + app_functions->pfn_SetFieldByNumber(s, i, 7, MexUtils::DoubleTo1x1Matrix(gamma, app_functions)); break; case IDisplaySettings::GradationCurveMode::Spline: //mexApi.MxSetFieldByNumber(s, i, 6, mexApi.MxCreateString(gradationcurveSpline)); @@ -615,7 +627,7 @@ std::shared_ptr CziReader::GetDisplaySettingsFromCzi() return s; } -Parameter* CziReader::ReadSubBlock(int no) +Parameter* CziReader::ReadSubBlock(int no, IAppExtensionFunctions* app_functions) { auto sbBlk = this->reader->ReadSubBlock(no); if (!sbBlk) @@ -626,10 +638,10 @@ Parameter* CziReader::ReadSubBlock(int no) } int32_t h = this->sbBlkStore.AddSubBlock(sbBlk); - return MexUtils::Int32To1x1Matrix(h); + return MexUtils::Int32To1x1Matrix(h, app_functions); } -Parameter* CziReader::GetInfoFromSubBlock(int subBlkHandle) +Parameter* CziReader::GetInfoFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions) { auto sbBlk = this->sbBlkStore.GetForHandle(subBlkHandle); if (!sbBlk) @@ -640,10 +652,10 @@ Parameter* CziReader::GetInfoFromSubBlock(int subBlkHandle) } const auto& sbInfo = sbBlk->GetSubBlockInfo(); - return CziReader::ConvertToMatlabStruct(sbInfo); + return CziReader::ConvertToMatlabStruct(sbInfo, app_functions); } -Parameter* CziReader::GetMetadataFromSubBlock(int subBlkHandle) +Parameter* CziReader::GetMetadataFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions) { auto sbBlk = this->sbBlkStore.GetForHandle(subBlkHandle); if (!sbBlk) @@ -653,19 +665,21 @@ Parameter* CziReader::GetMetadataFromSubBlock(int subBlkHandle) throw invalid_argument(ss.str()); } - auto mexApi = MexApi::GetInstance(); + //auto mexApi = MexApi::GetInstance(); size_t sizeData; auto ptrData = sbBlk->GetRawData(ISubBlock::MemBlkType::Metadata, &sizeData); if (!ptrData) { - return mexApi.MxCreateString(""); + return app_functions->pfn_CreateString(""); + //return mexApi.MxCreateString(""); } string metadataXml(static_cast(ptrData.get()), sizeData); - return mexApi.MxCreateString(metadataXml.c_str()); + //return mexApi.MxCreateString(metadataXml.c_str()); + return app_functions->pfn_CreateString(metadataXml.c_str()); } -Parameter* CziReader::GetBitmapFromSubBlock(int subBlkHandle) +Parameter* CziReader::GetBitmapFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions) { auto sbBlk = this->sbBlkStore.GetForHandle(subBlkHandle); if (!sbBlk) @@ -676,7 +690,7 @@ Parameter* CziReader::GetBitmapFromSubBlock(int subBlkHandle) } auto bm = sbBlk->CreateBitmap(); - return ConvertToMxArray(bm.get()); + return ConvertToMxArray(bm.get(), app_functions); } bool CziReader::ReleaseSubBlock(int subBlkHandle) @@ -684,25 +698,35 @@ bool CziReader::ReleaseSubBlock(int subBlkHandle) return this->sbBlkStore.RemoveSubBlock(subBlkHandle); } -/*static*/Parameter* CziReader::ConvertToMatlabStruct(const libCZI::SubBlockInfo& sbBlkInfo) +/*static*/Parameter* CziReader::ConvertToMatlabStruct(const libCZI::SubBlockInfo& sbBlkInfo, IAppExtensionFunctions* app_functions) { - auto mexApi = MexApi::GetInstance(); + //auto mexApi = MexApi::GetInstance(); array fieldNames = { "Mode", "Pixeltype", "Coordinate", "LogicalRect", "PhysicalSize", "MIndex", "Zoom" }; - auto s = mexApi.MxCreateStructArray( + //auto s = mexApi.MxCreateStructArray( + auto s = app_functions->pfn_CreateStructArray( 2, MexUtils::Dims_1_by_1, static_cast(fieldNames.size()), fieldNames.data()); - mexApi.MxSetFieldByNumber(s, 0, 0, mexApi.MxCreateString(libCZI::Utils::CompressionModeToInformalString(sbBlkInfo.GetCompressionMode()))); + /*mexApi.MxSetFieldByNumber(s, 0, 0, mexApi.MxCreateString(libCZI::Utils::CompressionModeToInformalString(sbBlkInfo.GetCompressionMode()))); mexApi.MxSetFieldByNumber(s, 0, 1, mexApi.MxCreateString(libCZI::Utils::PixelTypeToInformalString(sbBlkInfo.pixelType))); mexApi.MxSetFieldByNumber(s, 0, 2, mexApi.MxCreateString(libCZI::Utils::DimCoordinateToString(&sbBlkInfo.coordinate).c_str())); mexApi.MxSetFieldByNumber(s, 0, 3, CziReader::ConvertToMatlabStruct(sbBlkInfo.logicalRect)); - mexApi.MxSetFieldByNumber(s, 0, 4, CziReader::ConvertToMatlabStruct(sbBlkInfo.physicalSize)); + mexApi.MxSetFieldByNumber(s, 0, 4, CziReader::ConvertToMatlabStruct(sbBlkInfo.physicalSize));*/ + + app_functions->pfn_SetFieldByNumber(s, 0, 0, app_functions->pfn_CreateString(libCZI::Utils::CompressionModeToInformalString(sbBlkInfo.GetCompressionMode()))); + app_functions->pfn_SetFieldByNumber(s, 0, 1, app_functions->pfn_CreateString(libCZI::Utils::PixelTypeToInformalString(sbBlkInfo.pixelType))); + app_functions->pfn_SetFieldByNumber(s, 0, 2, app_functions->pfn_CreateString(libCZI::Utils::DimCoordinateToString(&sbBlkInfo.coordinate).c_str())); + app_functions->pfn_SetFieldByNumber(s, 0, 3, CziReader::ConvertToMatlabStruct(sbBlkInfo.logicalRect, app_functions)); + app_functions->pfn_SetFieldByNumber(s, 0, 4, CziReader::ConvertToMatlabStruct(sbBlkInfo.physicalSize, app_functions)); + if (sbBlkInfo.mIndex != std::numeric_limits::max() && sbBlkInfo.mIndex != std::numeric_limits::min()) { - mexApi.MxSetFieldByNumber(s, 0, 5, MexUtils::Int32To1x1Matrix(sbBlkInfo.mIndex)); + //mexApi.MxSetFieldByNumber(s, 0, 5, MexUtils::Int32To1x1Matrix(sbBlkInfo.mIndex)); + app_functions->pfn_SetFieldByNumber(s, 0, 5, MexUtils::Int32To1x1Matrix(sbBlkInfo.mIndex, app_functions)); } - mexApi.MxSetFieldByNumber(s, 0, 6, MexUtils::DoubleTo1x1Matrix(sbBlkInfo.GetZoom())); + //mexApi.MxSetFieldByNumber(s, 0, 6, MexUtils::DoubleTo1x1Matrix(sbBlkInfo.GetZoom())); + app_functions->pfn_SetFieldByNumber(s, 0, 6, MexUtils::DoubleTo1x1Matrix(sbBlkInfo.GetZoom(), app_functions)); return s; } diff --git a/lib/src/implementation/CziReader.h b/lib/src/implementation/CziReader.h index bfb9fe4..bba6e7b 100644 --- a/lib/src/implementation/CziReader.h +++ b/lib/src/implementation/CziReader.h @@ -39,13 +39,13 @@ class CziReader std::array GetScaling(); Parameter* GetScalingAsMatlabStruct(IAppExtensionFunctions* app_functions); - Parameter* ReadSubBlock(int no); - Parameter* GetInfoFromSubBlock(int subBlkHandle); - Parameter* GetMetadataFromSubBlock(int subBlkHandle); - Parameter* GetBitmapFromSubBlock(int subBlkHandle); + Parameter* ReadSubBlock(int no, IAppExtensionFunctions* app_functions); + Parameter* GetInfoFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions); + Parameter* GetMetadataFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions); + Parameter* GetBitmapFromSubBlock(int subBlkHandle, IAppExtensionFunctions* app_functions); bool ReleaseSubBlock(int subBlkHandle); private: - static Parameter* ConvertToMatlabStruct(const libCZI::IDimBounds* bounds); + static Parameter* ConvertToMatlabStruct(const libCZI::IDimBounds* bounds, IAppExtensionFunctions* app_functions); /// Initializes the members "displaySettingsFromCzi" and "scalingInfoFromCzi". void InitializeInfoFromCzi(); @@ -56,11 +56,11 @@ class CziReader Parameter* GetMultiChannelScalingTileCompositeAllChannelsDisabled(const libCZI::IntRect& roi, float zoom, IAppExtensionFunctions* app_functions); static Parameter* ConvertToMxArray(libCZI::IBitmapData* bitmapData, IAppExtensionFunctions* app_functions); - static Parameter* ConvertToMatlabStruct(const std::map& boundingBoxMap); - static Parameter* ConvertToMatlabStruct(const libCZI::IntRect& rect); - static Parameter* ConvertToMatlabStruct(const libCZI::IntSize& size); + static Parameter* ConvertToMatlabStruct(const std::map& boundingBoxMap, IAppExtensionFunctions* app_functions); + static Parameter* ConvertToMatlabStruct(const libCZI::IntRect& rect, IAppExtensionFunctions* app_functions); + static Parameter* ConvertToMatlabStruct(const libCZI::IntSize& size, IAppExtensionFunctions* app_functions); static Parameter* ConvertToMatlabStruct(const libCZI::IDisplaySettings& ds, IAppExtensionFunctions* app_functions); - static Parameter* ConvertToMatlabStruct(const libCZI::SubBlockInfo& sbBlkInfo); + static Parameter* ConvertToMatlabStruct(const libCZI::SubBlockInfo& sbBlkInfo, IAppExtensionFunctions* app_functions); static void CopyTransposeGray8(libCZI::IBitmapData* bitmapData, void* pDst, size_t lineLength); static void CopyTransposeGray16(libCZI::IBitmapData* bitmapData, void* pDst, size_t lineLength); diff --git a/lib/src/implementation/CziWriterManager.cpp b/lib/src/implementation/CziWriterManager.cpp new file mode 100644 index 0000000..5220d22 --- /dev/null +++ b/lib/src/implementation/CziWriterManager.cpp @@ -0,0 +1,48 @@ +#include "CziWriterManager.h" +#include "dbgprint.h" + +using namespace std; + +/*static*/CziWriterManager CziWriterManager::instance; + +/*static*/CziWriterManager& CziWriterManager::GetInstance() +{ + return CziWriterManager::instance; +} + +void CziWriterManager::AddInstance(int id) +{ + VDBGPRINT((CDbg::Level::Trace, "CziWriterManager::AddInstance: add instance %i.\n", id)); + std::unique_lock lck(this->mutex); + this->map.insert(make_pair(id, make_shared< CziWriter>())); +} + +bool CziWriterManager::RemoveInstance(int id) +{ + std::unique_lock lck(this->mutex); + const auto noOfElementsRemoved = this->map.erase(id); + VDBGPRINT((CDbg::Level::Trace, "CziWriterManager::RemoveInstance: remove instance %i -> %s.", id, noOfElementsRemoved > 0 ? "success" : "failure")); + return noOfElementsRemoved > 0; +} + +std::shared_ptr CziWriterManager::GetInstance(int id) +{ + std::unique_lock lck(this->mutex); + return this->map.at(id); +} + +int CziWriterManager::CreateNewInstance() +{ + const int id = this->instanceCounter.fetch_add(1); + this->AddInstance(id); + return id; +} + +int CziWriterManager::RemoveAllInstances() +{ + std::unique_lock lck(this->mutex); + const int noOfExistingInstances = static_cast(this->map.size()); + VDBGPRINT((CDbg::Level::Trace, "CziWriterManager::RemoveAllInstances: # of existing instances is %i.\n", noOfExistingInstances)); + this->map.clear(); + return noOfExistingInstances; +} \ No newline at end of file diff --git a/lib/src/implementation/CziWriterManager.h b/lib/src/implementation/CziWriterManager.h new file mode 100644 index 0000000..407dc22 --- /dev/null +++ b/lib/src/implementation/CziWriterManager.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include "CziWriter.h" +#include + +/// This is the manager of "CZIWriter"-objects. They are created by the manager and are accessed +/// by a handle. +class CziWriterManager +{ +private: + std::atomic instanceCounter; + mutable std::mutex mutex; + std::unordered_map> map; + CziWriterManager() : instanceCounter{ 1 } {} + + static CziWriterManager instance; +public: + + /// Gets the (one and only) instance. + /// \returns The instance. + static CziWriterManager& GetInstance(); + + /// Removes the instance described by the specified id. + /// \param id The identifier. + /// \returns True if it succeeds, false if it fails. + bool RemoveInstance(int id); + + /// Creates a new instance and returns its id. + /// \returns The id of the new instance. + int CreateNewInstance(); + + /// Gets the instance associated with the specified id. + /// If the specified key is not present, then an out_of_range-exception is thrown. + /// \param id The identifier. + /// \returns The instance. + std::shared_ptr GetInstance(int id); + + /// Removes all instances, and return how many instances were destroyed. + /// \returns The number of instances that had to be destroyed. + int RemoveAllInstances(); +protected: + void AddInstance(int id); +}; \ No newline at end of file diff --git a/lib/src/implementation/argsutils.cpp b/lib/src/implementation/argsutils.cpp index 6f30be4..d0efbe1 100644 --- a/lib/src/implementation/argsutils.cpp +++ b/lib/src/implementation/argsutils.cpp @@ -6,6 +6,19 @@ using namespace std; using namespace libCZI; +/*static*/std::string CArgsUtils::GetAsUtf8String(const Parameter* pArr, IAppExtensionFunctions* app_functions) +{ + if (!app_functions->pfn_IsChar(pArr)) + { + return string(); + } + + char* utf8_char_array = app_functions->pfn_ConvertToUTF8String(pArr); + string argStr{ utf8_char_array }; + app_functions->pfn_Free(utf8_char_array); + return argStr; +} + /*static*/bool CArgsUtils::TryGetInt32(const Parameter* pArr, std::int32_t* ptr, IAppExtensionFunctions* app_functions) { //const mxClassID id = MexApi::GetInstance().MxGetClassID(pArr); @@ -211,7 +224,7 @@ using namespace libCZI; break; case AppExtensionClassId_Int64: { -// auto* pi64 = MexApi::GetInstance().MxGetInt64s(pArr); + // auto* pi64 = MexApi::GetInstance().MxGetInt64s(pArr); auto* pi64 = app_functions->pfn_GetInt64s(pArr); int64_t v = *(pi64 + index); if (v > static_cast(numeric_limits::max()) || v < static_cast(numeric_limits::min())) @@ -291,7 +304,7 @@ using namespace libCZI; break; case AppExtensionClassId_Uint8: { -// auto* const pui8 = MexApi::GetInstance().MxGetUint8s(pArr); + // auto* const pui8 = MexApi::GetInstance().MxGetUint8s(pArr); auto* const pui8 = app_functions->pfn_GetUint8s(pArr); rv = *(pui8 + index); } diff --git a/lib/src/implementation/argsutils.h b/lib/src/implementation/argsutils.h index bb53908..15a2209 100644 --- a/lib/src/implementation/argsutils.h +++ b/lib/src/implementation/argsutils.h @@ -19,6 +19,7 @@ class CArgsUtils void* data; }; + static std::string GetAsUtf8String(const Parameter* pArr, IAppExtensionFunctions* app_functions); static bool TryGetInt32(const Parameter* pArr, std::int32_t* ptr, IAppExtensionFunctions* app_functions); static bool TryGetInt32(const Parameter* pArr, size_t index, std::int32_t* ptr, IAppExtensionFunctions* app_functions); diff --git a/lib/src/implementation/utils.cpp b/lib/src/implementation/utils.cpp index fc42c65..b7139c9 100644 --- a/lib/src/implementation/utils.cpp +++ b/lib/src/implementation/utils.cpp @@ -5,7 +5,8 @@ #include #include "CziReaderManager.h" #include "CziWriterManager.h" -#include "mexapi.h" +//#include "mexapi.h" +#include #include "dbgprint.h" #if _WIN32 #include @@ -29,10 +30,13 @@ using namespace std; /*static*/bool Utils::icasecmp(const std::string& l, const std::string& r) { - return l.size() == r.size() - && equal(l.cbegin(), l.cend(), r.cbegin(), + return + l.size() == r.size() && + equal(l.cbegin(), l.cend(), r.cbegin(), [](std::string::value_type l1, std::string::value_type r1) - { return toupper(l1) == toupper(r1); }); + { + return toupper(l1) == toupper(r1); + }); } /*static*/std::uint8_t Utils::HexCharToInt(char c) @@ -221,16 +225,16 @@ class Converters static constexpr struct ConversionInfo { - mxClassID mx_class; + AppExtensionClassId mx_class; bool has_3rd_dimension; // whether the 3rd dimension is present and has size 3 libCZI::PixelType pixel_type; void(*conversion_function)(const CArgsUtils::ArrayInfo&, libCZI::IBitmapData*); } kConversionTable[] = { - { mxUINT8_CLASS, false, libCZI::PixelType::Gray8 , Converters::Convert_UINT8_to_Gray8}, - { mxUINT8_CLASS, true, libCZI::PixelType::Bgr24, Converters::Convert_UINT8_3d_to_Bgr24 }, - { mxUINT16_CLASS, false, libCZI::PixelType::Gray16, Converters::Convert_UINT16_to_Gray16 }, - { mxUINT16_CLASS, true, libCZI::PixelType::Bgr48, Converters::Convert_UINT16_3d_to_Bgr48 }, + { AppExtensionClassId_Uint8, false, libCZI::PixelType::Gray8 , Converters::Convert_UINT8_to_Gray8}, + { AppExtensionClassId_Uint8, true, libCZI::PixelType::Bgr24, Converters::Convert_UINT8_3d_to_Bgr24 }, + { AppExtensionClassId_Uint16, false, libCZI::PixelType::Gray16, Converters::Convert_UINT16_to_Gray16 }, + { AppExtensionClassId_Uint16, true, libCZI::PixelType::Bgr48, Converters::Convert_UINT16_3d_to_Bgr48 }, }; const bool has_3rd_dimension = array_info.number_of_dimensions == 3; @@ -249,33 +253,39 @@ class Converters // ---------------------------------------------------------------------------- -/*static*/mwSize MexUtils::Dims_1_by_1[2] = { 1, 1 }; +/*static*/size_t MexUtils::Dims_1_by_1[2] = { 1, 1 }; -/*static*/MexArray* MexUtils::FloatTo1x1Matrix(float v) +/*static*/Parameter* MexUtils::FloatTo1x1Matrix(float v, IAppExtensionFunctions* app_functions) { - auto m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); - float* ptr = MexApi::GetInstance().MxGetSingles(m); + //auto m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); + auto m = app_functions->pfn_CreateNumericMatrixReal(1, 1, AppExtensionClassId_Single); + //float* ptr = MexApi::GetInstance().MxGetSingles(m); + float* ptr = app_functions->pfn_GetSingles(m); *ptr = v; return m; } -/*static*/MexArray* MexUtils::DoubleTo1x1Matrix(double v) +/*static*/Parameter* MexUtils::DoubleTo1x1Matrix(double v, IAppExtensionFunctions* app_functions) { - auto m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); - double* ptr = MexApi::GetInstance().MxGetDoubles(m); - *ptr = MexUtils::CoerceValueDbl(v); + //auto m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxDOUBLE_CLASS, mxREAL); + auto m = app_functions->pfn_CreateNumericMatrixReal(1, 1, AppExtensionClassId_Double); + //double* ptr = MexApi::GetInstance().MxGetDoubles(m); + double* ptr = app_functions->pfn_GetDoubles(m); + *ptr = MexUtils::CoerceValueDbl(v, app_functions); return m; } -/*static*/MexArray* MexUtils::DoublesAsNx1Matrix(int count, ...) +/*static*/Parameter* MexUtils::DoublesAsNx1Matrix(IAppExtensionFunctions* app_functions, int count, ...) { - auto m = MexApi::GetInstance().MxCreateNumericMatrix(count, 1, mxDOUBLE_CLASS, mxREAL); - double* ptr = MexApi::GetInstance().MxGetDoubles(m); + //auto m = MexApi::GetInstance().MxCreateNumericMatrix(count, 1, mxDOUBLE_CLASS, mxREAL); + auto m = app_functions->pfn_CreateNumericMatrixReal(count, 1, AppExtensionClassId_Double); + //double* ptr = MexApi::GetInstance().MxGetDoubles(m); + double* ptr = app_functions->pfn_GetDoubles(m); va_list list; va_start(list, count); for (int arg = 0; arg < count; ++arg) { - *ptr++ = MexUtils::CoerceValueDbl(va_arg(list, double)); + *ptr++ = MexUtils::CoerceValueDbl(va_arg(list, double), app_functions); } // Cleanup the va_list when we're done. @@ -284,31 +294,37 @@ class Converters return m; } -/*static*/MexArray* MexUtils::Int32To1x1Matrix(int v) +/*static*/Parameter* MexUtils::Int32To1x1Matrix(int v, IAppExtensionFunctions* app_functions) { - auto* m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); - int* ptr = MexApi::GetInstance().MxGetInt32s(m); + //auto* m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxINT32_CLASS, mxREAL); + auto* m = app_functions->pfn_CreateNumericMatrixReal(1, 1, AppExtensionClassId_Int32); + //int* ptr = MexApi::GetInstance().MxGetInt32s(m); + int* ptr = app_functions->pfn_GetInt32s(m); *ptr = v; return m; } -/*static*/MexArray* MexUtils::BooleanTo1x1Matrix(bool b) +/*static*/Parameter* MexUtils::BooleanTo1x1Matrix(bool b, IAppExtensionFunctions* app_functions) { - auto* m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxLOGICAL_CLASS, mxREAL); - bool* ptr = MexApi::GetInstance().MxGetLogicals(m); + //auto* m = MexApi::GetInstance().MxCreateNumericMatrix(1, 1, mxLOGICAL_CLASS, mxREAL); + auto* m = app_functions->pfn_CreateNumericMatrixReal(1, 1, AppExtensionClassId_Logical); + //bool* ptr = MexApi::GetInstance().MxGetLogicals(m); + bool* ptr = app_functions->pfn_GetLogicals(m); *ptr = b; return m; } -/*static*/double MexUtils::CoerceValueDbl(double d) +/*static*/double MexUtils::CoerceValueDbl(double d, IAppExtensionFunctions* app_functions) { if (isnan(d)) { - return MexApi::GetInstance().GetDblNan(); + //return MexApi::GetInstance().GetDblNan(); + return app_functions->pfn_GetNaNDouble(); } else if (isinf(d)) { - return MexApi::GetInstance().GetDblInf(); + //return MexApi::GetInstance().GetDblInf(); + return app_functions->pfn_GetInfDouble(); } else { diff --git a/lib/src/implementation/utils.h b/lib/src/implementation/utils.h index 4016402..93fc8ae 100644 --- a/lib/src/implementation/utils.h +++ b/lib/src/implementation/utils.h @@ -27,13 +27,13 @@ class MexUtils { public: static size_t Dims_1_by_1[2]; - static Parameter* FloatTo1x1Matrix(float v); - static Parameter* DoubleTo1x1Matrix(double v); - static Parameter* Int32To1x1Matrix(int v); - static Parameter* BooleanTo1x1Matrix(bool b); - static Parameter* DoublesAsNx1Matrix(int count, ...); + static Parameter* FloatTo1x1Matrix(float v, IAppExtensionFunctions* app_functions); + static Parameter* DoubleTo1x1Matrix(double v, IAppExtensionFunctions* app_functions); + static Parameter* Int32To1x1Matrix(int v, IAppExtensionFunctions* app_functions); + static Parameter* BooleanTo1x1Matrix(bool b, IAppExtensionFunctions* app_functions); + static Parameter* DoublesAsNx1Matrix(IAppExtensionFunctions* app_functions, int count, ...); private: - static double CoerceValueDbl(double d); + static double CoerceValueDbl(double d, IAppExtensionFunctions* app_functions); }; class Bitmap : public libCZI::IBitmapData diff --git a/lib/src/mexFunctions.cpp b/lib/src/mexFunctions.cpp index ea47e04..d86562a 100644 --- a/lib/src/mexFunctions.cpp +++ b/lib/src/mexFunctions.cpp @@ -1,12 +1,11 @@ #include "mexFunctions.h" -#include #include #include "functions/func_getversion.h" +#include "functions/func_open.h" +#include "functions/func_getsubblockbitmap.h" /* #include "src/func_close.h" -#include "src/func_open.h" -#include "src/func_getsubblockbitmap.h" #include "src/func_getmultichannelscalingtilecomposite.h" #include "src/func_getinfo.h" #include "src/func_getmetadataxml.h" @@ -22,9 +21,9 @@ /*static*/const CMexFunctions::MexFuncItem CMexFunctions::funcItems[] = { {u8"GetVersion", {MexFunction_GetVersion_CheckArguments,MexFunction_GetVersion_Execute}}, - /* {u8"Open", {MexFunction_Open_CheckArguments,MexFunction_Open_Execute}}, {u8"GetSubBlockBitmap", {MexFunction_GetSubBlockBitmap_CheckArguments,MexFunction_GetSubBlockBitmap_Execute}}, + /* {u8"GetMultiChannelScalingTileComposite", {MexFunction_GetMultiChannelScalingTileComposite_CheckArguments,MexFunction_GetMultiChannelScalingTileComposite_Execute}}, {u8"GetInfo", {MexFunction_GetInfo_CheckArguments,MexFunction_GetInfo_Execute}}, {u8"GetScaling", {MexFunction_GetScaling_CheckArguments,MexFunction_GetScaling_Execute}},