Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ set(ZSTD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/${ZSTD_VER}")
add_subdirectory(${ZSTD_DIR}/build/cmake)
set_property(TARGET libzstd_static PROPERTY POSITION_INDEPENDENT_CODE ON)

# Added by XS, add zlib for compilation to work
include_directories(${CMAKE_BINARY_DIR}/dependencies/zlib-1.2.8)
# Add libtiff
include_directories(${CMAKE_BINARY_DIR}/dependencies/${TIFF_VER}/libtiff)
include_directories(${ZSTD_DIR}/lib)
Expand Down
18 changes: 15 additions & 3 deletions mexSrc/compile_parallelReadTiff.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,22 @@
system('chmod 777 ../macArm/parallelReadTiff.mexmaca64');
end
elseif ispc
setenv('MW_MINGW64_LOC','C:/mingw64');
releaseFolder = '../windows';
%setenv('MW_MINGW64_LOC','C:/mingw64');
releaseFolder = '..\windows';
if ~exist(releaseFolder, 'dir')
mkdir(releaseFolder);
end
mex -outdir ../windows -output parallelReadTiff.mexw64 -v CXX="C:/mingw64/bin/g++" -v CXXOPTIMFLAGS="-DNDEBUG -O3" LDOPTIMFLAGS="-Wl',-rpath='''$ORIGIN'''' -O3 -DNDEBUG" CXXFLAGS='$CXXFLAGS -fopenmp -O3' LDFLAGS='$LDFLAGS -fopenmp -O3' -I'C:/Users/matt/Documents/GitHub/c-tiff/jenkinsBuild/install/include' -L'C:/Users/matt/Documents/GitHub/c-tiff/jenkinsBuild/install/lib' -lcppTiff.dll parallelreadtiffmex.cpp
mex -outdir ..\windows -output parallelReadTiff.mexw64 ...
-v CXX="C:\ProgramData\MATLAB\SupportPackages\R2022b\3P.instrset\mingw_w64.instrset\bin\g++" -v CXXOPTIMFLAGS="-DNDEBUG -O3" ...
LDOPTIMFLAGS="-Wl',-rpath='''$ORIGIN'''' -O3 -DNDEBUG" ...
CXXFLAGS='$CXXFLAGS -fopenmp -O3' LDFLAGS='$LDFLAGS -fopenmp -O3' ...
-I'..\dependencies\libdeflate-1.18' ...
-I'..\dependencies\tiff-4.7.0' ...
-I'..\dependencies\tiff-4.7.0\libtiff' ...
-I'..\build\dependencies\tiff-4.7.0\libtiff' ...
-I'..\dependencies\zlib-1.2.8' ...
-I'..\dependencies\zstd-1.5.6' ...
-I'..\build\dependencies\zlib-1.2.8' ...
-L'..\build' -lcppTiff.dll ...
parallelreadtiffmex.cpp
end
38 changes: 27 additions & 11 deletions mexSrc/parallelreadtiffmex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#include "../src/helperfunctions.h"
#include "../src/parallelreadtiff.h"


// Modified to read tiff from stack with a step size by accepting [start step end] as second argument.
// *Read with step is only enabled for the case of 3D, imageJ and 2D case are not touched.
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
Expand Down Expand Up @@ -44,7 +45,7 @@ void mexFunction(int nlhs, mxArray *plhs[],
TIFF* tif = TIFFOpen(fileName, "r");
if(!tif) mexErrMsgIdAndTxt("tiff:inputError","File \"%s\" cannot be opened",fileName);

uint64_t x = 1,y = 1,z = 1,bits = 1, startSlice = 0;
uint64_t x = 1,y = 1,z = 1,bits = 1, startSlice = 0, sliceStep = 1;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &x);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &y);

Expand All @@ -58,10 +59,8 @@ void mexFunction(int nlhs, mxArray *plhs[],
}
}
else{
if(mxGetN(prhs[1]) != 2){
mexErrMsgIdAndTxt("tiff:inputError","Input range is not 2");
}
else{
// Modified for accepting both [start end] and [start step end] as second argument
if(mxGetN(prhs[1]) == 2){
startSlice = (uint64_t)*(mxGetPr(prhs[1]))-1;
z = (uint64_t)*((mxGetPr(prhs[1])+1))-startSlice;
uint64_t maxSize = 0;
Expand All @@ -74,6 +73,23 @@ void mexFunction(int nlhs, mxArray *plhs[],
mexErrMsgIdAndTxt("tiff:rangeOutOfBound","Range is out of bounds");
}
}
else if (mxGetN(prhs[1]) == 3){
if(isImageJIm(fileName)){
mexErrMsgIdAndTxt("tiff:inputError","Read with step is not supported for ImageJ.");
}
startSlice = (uint64_t)*(mxGetPr(prhs[1]))-1;
sliceStep = (uint64_t)*((mxGetPr(prhs[1])+1));
uint64_t endSlice = (uint64_t)*((mxGetPr(prhs[1])+2))-1;
z = (endSlice-startSlice)/sliceStep+1;

uint64_t maxSize = getImageSizeZ(fileName);
if (startSlice < 0 || endSlice+1 > maxSize){
mexErrMsgIdAndTxt("tiff:rangeOutOfBound","Range is out of bounds");
}
}
else{
mexErrMsgIdAndTxt("tiff:inputError","Input range is not 2 or 3");
}
}

TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits);
Expand Down Expand Up @@ -139,27 +155,27 @@ void mexFunction(int nlhs, mxArray *plhs[],
mexErrMsgIdAndTxt("tiff:dataTypeError","Data type not suppported");
}
}
// Case for 3D
// Case for 3D, modified to accept sliceStep as extra argument
else{
if(bits == 8){
plhs[0] = mxCreateNumericArray(3,(mwSize*)dim,mxUINT8_CLASS, mxREAL);
uint8_t* tiff = (uint8_t*)mxGetPr(plhs[0]);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
}
else if(bits == 16){
plhs[0] = mxCreateNumericArray(3,(mwSize*)dim,mxUINT16_CLASS, mxREAL);
uint16_t* tiff = (uint16_t*)mxGetPr(plhs[0]);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
}
else if(bits == 32){
plhs[0] = mxCreateNumericArray(3,(mwSize*)dim,mxSINGLE_CLASS, mxREAL);
float* tiff = (float*)mxGetPr(plhs[0]);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
}
else if(bits == 64){
plhs[0] = mxCreateNumericArray(3,(mwSize*)dim,mxDOUBLE_CLASS, mxREAL);
double* tiff = (double*)mxGetPr(plhs[0]);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
err = readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
}
else{
mexErrMsgIdAndTxt("tiff:dataTypeError","Data type not suppported");
Expand Down
21 changes: 17 additions & 4 deletions mexSrc/tests.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
addpath('../windows');
im = rand(100,100,100,'single');
im(:,:,2:2:100) = 1;
parallelWriteTiff('test.tif',im);

%%
%% parallelReadTiff in different modes
imT = parallelReadTiff('test.tif');

imT_1_6 = parallelReadTiff('test.tif',[1 6]); %[start end]
imT_1_2_11 = parallelReadTiff('test.tif',[1 2 11]);%[start step end]
imT_2_2_12 = parallelReadTiff('test.tif',[2 2 12]);%[start step end]
%% Visualize tiff read by different modes
figure;
montage(imT_1_6,'Size',[1 6]);
title('1 to 6');
figure;
montage(imT_1_2_11,'Size',[1 6]);
title('1 to 11 at step 2');
figure;
montage(imT_2_2_12,'Size',[1 6]);
title('2 to 12 at step 2');
%%
imSize = getImageSizeMex('test.tif');
imSize = getImageSizeMex('test.tif');
46 changes: 27 additions & 19 deletions src/parallelreadtiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ uint8_t readTiffParallelBak(uint64_t x, uint64_t y, uint64_t z, const char* file
return err;
}

uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize, uint8_t flipXY){
// Modified such that the function can read tiff from stack with step size as specified by sliceStep.
uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t sliceStep, uint64_t stripSize, uint8_t flipXY){
int32_t numWorkers = omp_get_max_threads();
int32_t batchSize = (z-1)/numWorkers+1;
uint64_t bytes = bits/8;
Expand Down Expand Up @@ -109,8 +110,10 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
}

void* buffer = malloc(x*stripSize*bytes);
for(int64_t dir = startSlice+(w*batchSize); dir < startSlice+((w+1)*batchSize); dir++){
if(dir>=z+startSlice || err) break;
// Modified to enable looping through tiff dir with user specified steps
for(int64_t dir = startSlice+(w*batchSize*sliceStep); dir < startSlice+((w+1)*batchSize*sliceStep); dir = dir+sliceStep){
// Modified, (z-1)*sliceStep+startSlice is the last slice to read
if(dir>=z*sliceStep+startSlice || err) break;

uint8_t counter = 0;
while(!TIFFSetDirectory(tif, (uint64_t)dir) && counter<3){
Expand Down Expand Up @@ -148,7 +151,7 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
for(int64_t k = 0; k < stripSize; k++){
if((k+(i*stripSize)) >= y) break;
for(int64_t j = 0; j < x; j++){
((uint8_t*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)*(x*y))] = ((uint8_t*)buffer)[j+(k*x)];
((uint8_t*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)/sliceStep*(x*y))] = ((uint8_t*)buffer)[j+(k*x)];
}
}
break;
Expand All @@ -157,7 +160,7 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
for(int64_t k = 0; k < stripSize; k++){
if((k+(i*stripSize)) >= y) break;
for(int64_t j = 0; j < x; j++){
((uint16_t*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)*(x*y))] = ((uint16_t*)buffer)[j+(k*x)];
((uint16_t*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)/sliceStep*(x*y))] = ((uint16_t*)buffer)[j+(k*x)];
}
}
break;
Expand All @@ -166,7 +169,7 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
for(int64_t k = 0; k < stripSize; k++){
if((k+(i*stripSize)) >= y) break;
for(int64_t j = 0; j < x; j++){
((float*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)*(x*y))] = ((float*)buffer)[j+(k*x)];
((float*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)/sliceStep*(x*y))] = ((float*)buffer)[j+(k*x)];
}
}
break;
Expand All @@ -175,7 +178,7 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
for(int64_t k = 0; k < stripSize; k++){
if((k+(i*stripSize)) >= y) break;
for(int64_t j = 0; j < x; j++){
((double*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)*(x*y))] = ((double*)buffer)[j+(k*x)];
((double*)tiff)[((j*y)+(k+(i*stripSize)))+((dir-startSlice)/sliceStep*(x*y))] = ((double*)buffer)[j+(k*x)];
}
}
break;
Expand All @@ -185,12 +188,12 @@ uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileNam
free(buffer);
TIFFClose(tif);
}
if(err){
if(errBak) return readTiffParallelBak(x, y, z, fileName, tiff, bits, startSlice, flipXY);
else {
printf(errString);
}
}
//if(err){
//if(errBak) return readTiffParallelBak(x, y, z, fileName, tiff, bits, startSlice, flipXY);
//else {
//printf(errString);
//}
//}
return err;
}

Expand Down Expand Up @@ -565,15 +568,15 @@ uint8_t readTiffParallelImageJ(uint64_t x, uint64_t y, uint64_t z, const char* f
return err;
}


// Modified for accepting zRange in the format of both [start end] and [start step end]
// tiff pointer guaranteed to be NULL or the correct size array for the tiff file
void* readTiffParallelWrapperHelper(const char* fileName, void* tiff, uint8_t flipXY, const std::vector<uint64_t> &zRange = {})
{
TIFFSetWarningHandler(DummyHandler);
TIFF* tif = TIFFOpen(fileName, "r");
if(!tif) return NULL;

uint64_t x = 1,y = 1,z = 1,bits = 1, startSlice = 0;
uint64_t x = 1,y = 1,z = 1,bits = 1, startSlice = 0, sliceStep = 1;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &x);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &y);
z = getImageSizeZ(fileName);
Expand All @@ -597,6 +600,11 @@ void* readTiffParallelWrapperHelper(const char* fileName, void* tiff, uint8_t fl
startSlice = zRange[0];
z = zRange[1];
}
else if(zRange.size() == 3){
startSlice = zRange[0];
sliceStep = zRange[1];
z = (zRange[2]-zRange[0])/sliceStep+1;
}
else{
startSlice = zRange[0];
z = zRange[0]+1;
Expand Down Expand Up @@ -657,22 +665,22 @@ void* readTiffParallelWrapperHelper(const char* fileName, void* tiff, uint8_t fl
else{
if(bits == 8){
if(!tiff) tiff = (uint8_t*)malloc(x*y*z*sizeof(uint8_t));
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
return (void*)tiff;
}
else if(bits == 16){
if(!tiff) tiff = (uint16_t*)malloc(x*y*z*sizeof(uint16_t));
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
return (void*)tiff;
}
else if(bits == 32){
if(!tiff) tiff = (float*)malloc(x*y*z*sizeof(float));
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
return (void*)tiff;
}
else if(bits == 64){
if(!tiff) tiff = (double*)malloc(x*y*z*sizeof(double));
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize, flipXY);
readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, sliceStep, stripSize, flipXY);
return (void*)tiff;
}
else{
Expand Down
2 changes: 1 addition & 1 deletion src/parallelreadtiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <cstdint>
#include <vector>

uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize, uint8_t flipXY);
uint8_t readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t sliceStep, uint64_t stripSize, uint8_t flipXY);

uint8_t readTiffParallel2D(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize, uint8_t flipXY);

Expand Down