From 61bb44b544358b76d0c84a866acafed190ce7ef2 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:38:09 -0500 Subject: [PATCH 1/9] update source code --- parallelReadTiff/cSrc/main.c | 54 +- parallelReadTiff/cSrc/parallelReadTiff.c | 924 +++++++++++++++++------ parallelReadTiff/cSrc/parallelReadTiff.h | 36 +- 3 files changed, 773 insertions(+), 241 deletions(-) diff --git a/parallelReadTiff/cSrc/main.c b/parallelReadTiff/cSrc/main.c index 237583c..adef1ae 100644 --- a/parallelReadTiff/cSrc/main.c +++ b/parallelReadTiff/cSrc/main.c @@ -1,13 +1,57 @@ #include "parallelReadTiff.h" #include +#include +#include +#include +#include + +int +parse_console_args(int argc, char *argv[], char **file_name) +{ + int c, parse_code = -1; + + while ((c = getopt(argc, argv, "f:")) != -1) { + switch (c) { + case 'f': + *file_name = optarg; + parse_code = 0; + break; + default: + fprintf(stderr, "Usage: %s [-f filename]\n", argv[0]); + parse_code = -1; + exit(EXIT_FAILURE); + } + } + return parse_code; +} + +int main(int argc, char *argv[]){ + + char *file_name = NULL; + void *tiff = NULL; + int i = 0; + // parse console argument + int parse_code = parse_console_args(argc, argv, &file_name); + if (parse_code) { + return parse_code; + } + + // print file name for validating purpose + printf("Filename: %s\n", file_name ? file_name : "(none)"); -int main(){ clock_t begin = clock(); - void* test = readTiffParallelWrapper("C:\\Users\\Matt\\Desktop\\testTiff\\test.tif"); - if(!test) return 1; + // calling tiff loading process. + parallel_TIFF_load(file_name, &tiff, 1, NULL); + + if(!tiff) return 1; clock_t end = clock(); double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; - printf("%f\n",time_spent); - free(test); + printf("Read Tiff File Done! Time spent: %.4f seconds\n",time_spent); + + printf("first few bytes "); + for (i = 0; i < 10; i++) { + printf("%d ", ((uint8_t*)tiff)[i]); + } + free(tiff); return 0; } diff --git a/parallelReadTiff/cSrc/parallelReadTiff.c b/parallelReadTiff/cSrc/parallelReadTiff.c index f48cbc8..d9a2d54 100644 --- a/parallelReadTiff/cSrc/parallelReadTiff.c +++ b/parallelReadTiff/cSrc/parallelReadTiff.c @@ -1,87 +1,91 @@ -#include -#include #include "parallelReadTiff.h" -//mex -v COPTIMFLAGS="-O3 -fwrapv -DNDEBUG" CFLAGS='$CFLAGS -O3 -fopenmp' LDFLAGS='$LDFLAGS -O3 -fopenmp' '-I/global/home/groups/software/sl-7.x86_64/modules/libtiff/4.1.0/libtiff/' '-L/global/home/groups/software/sl-7.x86_64/modules/libtiff/4.1.0/libtiff/' -ltiff /clusterfs/fiona/matthewmueller/parallelTiffTesting/main.c +#include "tiffio.h" +// #define ENABLE_OPENMP -void DummyHandler(const char* module, const char* fmt, va_list ap) +#ifdef ENABLE_OPENMP +#include "omp.h" +#endif + +#define CREATE_ARRAY(result_var, type, ndim, dim) do { \ + size_t i = 0, dim_prod = 1; \ + for (i = 0; i < (ndim); i++) { \ + dim_prod *= (dim)[i]; \ + } \ + result_var = (void *)malloc(dim_prod * sizeof(type)); \ +} while (0) + +void +DummyHandler(const char *module, const char *fmt, va_list ap) { // ignore errors and warnings } -void readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize){ - int32_t numWorkers = omp_get_max_threads(); - int32_t batchSize = (z-1)/numWorkers+1; - - uint64_t bytes = bits/8; +// Backup method in case there are errors reading strips +void +readTiffParallelBak(uint64_t x, uint64_t y, uint64_t z, const char *fileName, void *tiff, uint64_t bits, + uint64_t startSlice, uint8_t flipXY) +{ + int32_t numWorkers = omp_get_max_threads(); + int32_t batchSize = (z - 1) / numWorkers + 1; + uint64_t bytes = bits / 8; int32_t w; - uint8_t err = 0; - char errString[10000]; - #pragma omp parallel for - for(w = 0; w < numWorkers; w++){ - - TIFF* tif = TIFFOpen(fileName, "r"); - if(!tif){ - #pragma omp critical - { - err = 1; - sprintf(errString,"Thread %d: File \"%s\" cannot be opened\n",w,fileName); - } - } - 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; - - uint8_t counter = 0; - while(!TIFFSetDirectory(tif, (uint64_t)dir) && counter<3){ - printf("Thread %d: File \"%s\" Directory \"%d\" failed to open. Try %d\n",w,fileName,dir,counter+1); +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (w = 0; w < numWorkers; w++) { + + TIFF *tif = TIFFOpen(fileName, "r"); + if (!tif) + printf("tiff:threadError", "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + + void *buffer = malloc(x * bytes); + for (int64_t dir = startSlice + (w * batchSize); dir < startSlice + ((w + 1) * batchSize); dir++) { + if (dir >= z + startSlice) + break; + + int counter = 0; + while (!TIFFSetDirectory(tif, (uint64_t)dir) && counter < 3) { + printf("Thread %d: File \"%s\" Directory \"%d\" failed to open. Try %d\n", w, fileName, dir, + counter + 1); counter++; } - for (int64_t i = 0; i*stripSize < y; i++) - { - - //loading the data into a buffer - switch(bits){ + for (int64_t i = 0; i < y; i++) { + TIFFReadScanline(tif, buffer, i, 0); + if (!flipXY) { + memcpy(tiff + ((i * x) * bytes), buffer, x * bytes); + continue; + } + // loading the data into a buffer + switch (bits) { case 8: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(uint8_t*)buffer, stripSize*x*(bits/8)); - 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)]; - } + for (int64_t j = 0; j < x; j++) { + ((uint8_t *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((uint8_t *)buffer)[j]; } break; case 16: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(uint16_t*)buffer, stripSize*x*(bits/8)); - 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)]; - } + for (int64_t j = 0; j < x; j++) { + ((uint16_t *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((uint16_t *)buffer)[j]; } break; case 32: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(float*)buffer, stripSize*x*(bits/8)); - 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)]; - } + for (int64_t j = 0; j < x; j++) { + ((float *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((float *)buffer)[j]; } break; case 64: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(double*)buffer, stripSize*x*(bits/8)); - 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)]; - } + for (int64_t j = 0; j < x; j++) { + ((double *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((double *)buffer)[j]; } break; } @@ -90,237 +94,703 @@ void readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, free(buffer); TIFFClose(tif); } - if(err) printf("%s\n", errString); } -void readTiffParallel2D(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize){ - int32_t numWorkers = omp_get_max_threads(); - uint64_t stripsPerDir = (uint64_t)ceil((double)y/(double)stripSize); - int32_t batchSize = (stripsPerDir-1)/numWorkers+1; +void +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) +{ + int32_t numWorkers = omp_get_max_threads(); + int32_t batchSize = (z - 1) / numWorkers + 1; + uint64_t bytes = bits / 8; - uint64_t bytes = bits/8; + uint16_t compressed = 1; + TIFF * tif = TIFFOpen(fileName, "r"); + TIFFGetField(tif, TIFFTAG_COMPRESSION, &compressed); int32_t w; - uint8_t err = 0; - char errString[10000]; + uint8_t errBak = 0; + uint8_t err = 0; + char errString[10000]; + if (compressed > 1 || z < 32768) { + TIFFClose(tif); +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (w = 0; w < numWorkers; w++) { + + uint8_t outCounter = 0; + TIFF * tif = TIFFOpen(fileName, "r"); + while (!tif) { + tif = TIFFOpen(fileName, "r"); + if (outCounter == 3) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + err = 1; + sprintf(errString, "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + } + continue; + } + outCounter++; + } + + 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; + + uint8_t counter = 0; + while (!TIFFSetDirectory(tif, (uint64_t)dir) && counter < 3) { + counter++; + if (counter == 3) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + err = 1; + sprintf(errString, "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + } + } + } + if (err) + break; + for (int64_t i = 0; i * stripSize < y; i++) { + + // loading the data into a buffer + int64_t cBytes = TIFFReadEncodedStrip(tif, i, buffer, stripSize * x * bytes); + if (cBytes < 0) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + errBak = 1; + err = 1; + sprintf(errString, "Thread %d: Strip %ld cannot be read\n", w, i); + } + break; + } + if (!flipXY) { + memcpy(tiff + ((i * stripSize * x) * bytes), buffer, cBytes); + continue; + } + switch (bits) { + case 8: + // Map Values to flip x and y for MATLAB + 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)]; + } + } + break; + case 16: + // Map Values to flip x and y for MATLAB + 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)]; + } + } + break; + case 32: + // Map Values to flip x and y for MATLAB + 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)]; + } + } + break; + case 64: + // Map Values to flip x and y for MATLAB + 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)]; + } + } + break; + } + } + } + free(buffer); + TIFFClose(tif); + } + } + else { + uint64_t stripsPerDir = (uint64_t)ceil((double)y / (double)stripSize); +#ifdef _WIN32 + int fd = open(fileName, O_RDONLY | O_BINARY); +#else + int fd = open(fileName, O_RDONLY); +#endif + if (fd == -1) + printf("disk:threadError", "File \"%s\" cannot be opened from Disk\n", fileName); + + if (!tif) + printf("tiff:threadError", "File \"%s\" cannot be opened\n", fileName); + uint64_t offset = 0; + uint64_t *offsets = NULL; + TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &offsets); + uint64_t *byteCounts = NULL; + TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &byteCounts); + if (!offsets || !byteCounts) + printf("tiff:threadError", "Could not get offsets or byte counts from the tiff file\n"); + offset = offsets[0]; + uint64_t fOffset = offsets[stripsPerDir - 1] + byteCounts[stripsPerDir - 1]; + uint64_t zSize = fOffset - offset; + TIFFSetDirectory(tif, 1); + TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &offsets); + uint64_t gap = offsets[0] - fOffset; + + lseek(fd, offset, SEEK_SET); + + TIFFClose(tif); + uint64_t curr = 0; + uint64_t bytesRead = 0; + // TESTING + // Not sure if we will need to read in chunks like for ImageJ + for (uint64_t i = 0; i < z; i++) { + bytesRead = read(fd, tiff + curr, zSize); + curr += bytesRead; + lseek(fd, gap, SEEK_CUR); + } + close(fd); + uint64_t size = x * y * z * (bits / 8); + void * tiffC = malloc(size); + memcpy(tiffC, tiff, size); +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (uint64_t k = 0; k < z; k++) { + for (uint64_t j = 0; j < x; j++) { + for (uint64_t i = 0; i < y; i++) { + switch (bits) { + case 8: + ((uint8_t *)tiff)[i + (j * y) + (k * x * y)] = + ((uint8_t *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 16: + ((uint16_t *)tiff)[i + (j * y) + (k * x * y)] = + ((uint16_t *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 32: + ((float *)tiff)[i + (j * y) + (k * x * y)] = + ((float *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 64: + ((double *)tiff)[i + (j * y) + (k * x * y)] = + ((double *)tiffC)[j + (i * x) + (k * x * y)]; + break; + } + } + } + } + free(tiffC); + } + if (err) { + if (errBak) + readTiffParallelBak(x, y, z, fileName, tiff, bits, startSlice, flipXY); + else + printf("tiff:threadError", errString); + } +} +// Backup method in case there are errors reading strips +void +readTiffParallel2DBak(uint64_t x, uint64_t y, uint64_t z, const char *fileName, void *tiff, uint64_t bits, + uint64_t startSlice, uint8_t flipXY) +{ + int32_t numWorkers = omp_get_max_threads(); + int32_t batchSize = (y - 1) / numWorkers + 1; + uint64_t bytes = bits / 8; - #pragma omp parallel for - for(w = 0; w < numWorkers; w++){ + int32_t w; +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (w = 0; w < numWorkers; w++) { + + TIFF *tif = TIFFOpen(fileName, "r"); + if (!tif) + printf("tiff:threadError", "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + + void *buffer = malloc(x * bytes); + for (int64_t dir = startSlice + (w * batchSize); dir < startSlice + ((w + 1) * batchSize); dir++) { + if (dir >= z + startSlice) + break; + + int counter = 0; + while (!TIFFSetDirectory(tif, (uint64_t)0) && counter < 3) { + printf("Thread %d: File \"%s\" Directory \"%d\" failed to open. Try %d\n", w, fileName, dir, + counter + 1); + counter++; + } - TIFF* tif = TIFFOpen(fileName, "r"); - if(!tif){ - #pragma omp critical - { - err = 1; - sprintf(errString,"Thread %d: File \"%s\" cannot be opened\n",w,fileName); + for (int64_t i = (w * batchSize); i < ((w + 1) * batchSize); i++) { + if (i >= y) + break; + TIFFReadScanline(tif, buffer, i, 0); + if (!flipXY) { + memcpy(tiff + ((i * x) * bytes), buffer, x * bytes); + continue; + } + // loading the data into a buffer + switch (bits) { + case 8: + // Map Values to flip x and y for MATLAB + for (int64_t j = 0; j < x; j++) { + ((uint8_t *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((uint8_t *)buffer)[j]; + } + break; + case 16: + // Map Values to flip x and y for MATLAB + for (int64_t j = 0; j < x; j++) { + ((uint16_t *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((uint16_t *)buffer)[j]; + } + break; + case 32: + // Map Values to flip x and y for MATLAB + for (int64_t j = 0; j < x; j++) { + ((float *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((float *)buffer)[j]; + } + break; + case 64: + // Map Values to flip x and y for MATLAB + for (int64_t j = 0; j < x; j++) { + ((double *)tiff)[((j * y) + i) + ((dir - startSlice) * (x * y))] = + ((double *)buffer)[j]; + } + break; + } } } + free(buffer); + TIFFClose(tif); + } +} - void* buffer = malloc(x*stripSize*bytes); +void +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) +{ + int32_t numWorkers = omp_get_max_threads(); + uint64_t stripsPerDir = (uint64_t)ceil((double)y / (double)stripSize); + int32_t batchSize = (stripsPerDir - 1) / numWorkers + 1; + uint64_t bytes = bits / 8; + int32_t w; + uint8_t err = 0; + uint8_t errBak = 0; + char errString[10000]; + +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (w = 0; w < numWorkers; w++) { + + uint8_t outCounter = 0; + TIFF * tif = TIFFOpen(fileName, "r"); + while (!tif) { + tif = TIFFOpen(fileName, "r"); + if (outCounter == 3) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + err = 1; + sprintf(errString, "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + } + continue; + } + outCounter++; + } + + void *buffer = malloc(x * stripSize * bytes); uint8_t counter = 0; - while(!TIFFSetDirectory(tif, 0) && counter<3){ - printf("Thread %d: File \"%s\" Directory \"%d\" failed to open. Try %d\n",w,fileName,0,counter+1); + while (!TIFFSetDirectory(tif, 0) && counter < 3) { + printf("Thread %d: File \"%s\" Directory \"%d\" failed to open. Try %d\n", w, fileName, 0, + counter + 1); counter++; + if (counter == 3) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + err = 1; + sprintf(errString, "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + } + } } - for (int64_t i = (w*batchSize); i < (w+1)*batchSize; i++) - { - if(i*stripSize >= y || err) break; - //loading the data into a buffer - switch(bits){ + for (int64_t i = (w * batchSize); i < (w + 1) * batchSize; i++) { + if (i * stripSize >= y || err) + break; + // loading the data into a buffer + int64_t cBytes = TIFFReadEncodedStrip(tif, i, buffer, stripSize * x * bytes); + if (cBytes < 0) { +#ifdef ENABLE_OPENMP +#pragma omp critical +#endif + { + errBak = 1; + err = 1; + sprintf(errString, "Thread %d: Strip %ld cannot be read\n", w, i); + } + break; + } + if (!flipXY) { + memcpy(tiff + ((i * stripSize * x) * bytes), buffer, cBytes); + continue; + } + switch (bits) { case 8: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(uint8_t*)buffer, stripSize*x*(bits/8)); - 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)))] = ((uint8_t*)buffer)[j+(k*x)]; + 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)))] = + ((uint8_t *)buffer)[j + (k * x)]; } } - break; + break; case 16: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(uint16_t*)buffer, stripSize*x*(bits/8)); - 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)))] = ((uint16_t*)buffer)[j+(k*x)]; + 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)))] = + ((uint16_t *)buffer)[j + (k * x)]; } } - break; + break; case 32: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(float*)buffer, stripSize*x*(bits/8)); - 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)))] = ((float*)buffer)[j+(k*x)]; + 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)))] = + ((float *)buffer)[j + (k * x)]; } } - break; + break; case 64: // Map Values to flip x and y for MATLAB - TIFFReadEncodedStrip(tif, i,(double*)buffer, stripSize*x*(bits/8)); - 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)))] = ((double*)buffer)[j+(k*x)]; + 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)))] = + ((double *)buffer)[j + (k * x)]; } } - break; + break; } } free(buffer); TIFFClose(tif); } - if(err) printf("%s\n", errString); + + if (err) { + if (errBak) + readTiffParallel2DBak(x, y, z, fileName, tiff, bits, startSlice, flipXY); + else + printf("tiff:threadError", errString); + } } -void* readTiffParallelWrapper(const char* fileName) +// Reading images saved by ImageJ +void +readTiffParallelImageJ(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) { - TIFFSetWarningHandler(DummyHandler); - TIFF* tif = TIFFOpen(fileName, "r"); - if(!tif) return NULL; - - uint64_t x = 1,y = 1,z = 1,bits = 1, startSlice = 0; - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &x); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &y); - - uint64_t s = 0, m = 0, t = 1; - while(TIFFSetDirectory(tif,t)){ - s = t; - t *= 8; - if(s > t){ - t = 65535; - printf("Number of slices > 32768"); - break; +#ifdef _WIN32 + int fd = open(fileName, O_RDONLY | O_BINARY); +#else + int fd = open(fileName, O_RDONLY); +#endif + TIFF *tif = TIFFOpen(fileName, "r"); + if (!tif) + printf("tiff:threadError", "File \"%s\" cannot be opened\n", fileName); + uint64_t offset = 0; + uint64_t *offsets = NULL; + TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &offsets); + if (offsets) + offset = offsets[0]; + + TIFFClose(tif); + lseek(fd, offset, SEEK_SET); + uint64_t bytes = bits / 8; + //#pragma omp parallel for + /* + for(uint64_t i = 0; i < z; i++){ + uint64_t cOffset = x*y*bytes*i; + //pread(fd,tiff+cOffset,x*y*bytes,offset+cOffset); + read(fd,tiff+cOffset,x*y*bytes); + }*/ + uint64_t chunk = 0; + uint64_t tBytes = x * y * z * bytes; + uint64_t bytesRead; + uint64_t rBytes = tBytes; + if (tBytes < INT_MAX) + bytesRead = read(fd, tiff, tBytes); + else { + while (chunk < tBytes) { + rBytes = tBytes - chunk; + if (rBytes > INT_MAX) + bytesRead = read(fd, tiff + chunk, INT_MAX); + else + bytesRead = read(fd, tiff + chunk, rBytes); + chunk += bytesRead; } } - while(s != t){ - m = (s+t+1)/2; - if(TIFFSetDirectory(tif,m)){ - s = m; - } - else{ - if(m > 0) t = m-1; - else t = m; + close(fd); + // Swap endianess for types greater than 8 bits + // TODO: May need to change later because we may not always need to swap + if (bits > 8) { +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (uint64_t i = 0; i < x * y * z; i++) { + switch (bits) { + case 16: + //((uint16_t*)tiff)[i] = ((((uint16_t*)tiff)[i] & 0xff) >> 8) | (((uint16_t*)tiff)[i] << + // 8); + //((uint16_t*)tiff)[i] = bswap_16(((uint16_t*)tiff)[i]); + ((uint16_t *)tiff)[i] = + ((((uint16_t *)tiff)[i] << 8) & 0xff00) | ((((uint16_t *)tiff)[i] >> 8) & 0x00ff); + break; + case 32: + //((num & 0xff000000) >> 24) | ((num & 0x00ff0000) >> 8) | ((num & 0x0000ff00) << 8) | + //(num << 24) + //((float*)tiff)[i] = bswap_32(((float*)tiff)[i]); + ((uint32_t *)tiff)[i] = ((((uint32_t *)tiff)[i] << 24) & 0xff000000) | + ((((uint32_t *)tiff)[i] << 8) & 0x00ff0000) | + ((((uint32_t *)tiff)[i] >> 8) & 0x0000ff00) | + ((((uint32_t *)tiff)[i] >> 24) & 0x000000ff); + break; + case 64: + //((double*)tiff)[i] = bswap_64(((double*)tiff)[i]); + ((uint64_t *)tiff)[i] = ((((uint64_t *)tiff)[i] << 56) & 0xff00000000000000UL) | + ((((uint64_t *)tiff)[i] << 40) & 0x00ff000000000000UL) | + ((((uint64_t *)tiff)[i] << 24) & 0x0000ff0000000000UL) | + ((((uint64_t *)tiff)[i] << 8) & 0x000000ff00000000UL) | + ((((uint64_t *)tiff)[i] >> 8) & 0x00000000ff000000UL) | + ((((uint64_t *)tiff)[i] >> 24) & 0x0000000000ff0000UL) | + ((((uint64_t *)tiff)[i] >> 40) & 0x000000000000ff00UL) | + ((((uint64_t *)tiff)[i] >> 56) & 0x00000000000000ffUL); + break; + } } } - z = s+1; - - TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits); - uint64_t stripSize = 1; - TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &stripSize); - TIFFClose(tif); - - if(z <= 1){ - if(bits == 8){ - uint8_t* tiff = (uint8_t*)malloc(x*y*z*sizeof(uint8_t)); - readTiffParallel2D(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 16){ - uint16_t* tiff = (uint16_t*)malloc(x*y*z*sizeof(uint16_t)); - readTiffParallel2D(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 32){ - float* tiff = (float*)malloc(x*y*z*sizeof(float)); - readTiffParallel2D(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 64){ - double* tiff = (double*)malloc(x*y*z*sizeof(double)); - readTiffParallel2D(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else{ - return NULL; + // Find a way to do this in-place without making a copy + if (flipXY) { + uint64_t size = x * y * z * (bits / 8); + void * tiffC = malloc(size); + memcpy(tiffC, tiff, size); +#ifdef ENABLE_OPENMP +#pragma omp parallel for +#endif + for (uint64_t k = 0; k < z; k++) { + for (uint64_t j = 0; j < x; j++) { + for (uint64_t i = 0; i < y; i++) { + switch (bits) { + case 8: + ((uint8_t *)tiff)[i + (j * y) + (k * x * y)] = + ((uint8_t *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 16: + ((uint16_t *)tiff)[i + (j * y) + (k * x * y)] = + ((uint16_t *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 32: + ((float *)tiff)[i + (j * y) + (k * x * y)] = + ((float *)tiffC)[j + (i * x) + (k * x * y)]; + break; + case 64: + ((double *)tiff)[i + (j * y) + (k * x * y)] = + ((double *)tiffC)[j + (i * x) + (k * x * y)]; + break; + } + } + } } - + free(tiffC); } - else{ - if(bits == 8){ - uint8_t* tiff = (uint8_t*)malloc(x*y*z*sizeof(uint8_t)); - readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 16){ - uint16_t* tiff = (uint16_t*)malloc(x*y*z*sizeof(uint16_t)); - readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 32){ - float* tiff = (float*)malloc(x*y*z*sizeof(float)); - readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else if(bits == 64){ - double* tiff = (double*)malloc(x*y*z*sizeof(double)); - readTiffParallel(x,y,z,fileName, (void*)tiff, bits, startSlice, stripSize); - return (void*)tiff; - } - else{ - return NULL; +} + +uint8_t +isImageJIm(TIFF *tif) +{ + if (!tif) + return 0; + char *tiffDesc = NULL; + if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &tiffDesc)) { + if (strstr(tiffDesc, "ImageJ")) { + return 1; } } - - // Should never get here but return NULL if we do - return NULL; + return 0; } -uint64_t* getImageSize(const char* fileName){ +uint64_t +imageJImGetZ(TIFF *tif) +{ + if (!tif) + return 0; + char *tiffDesc = NULL; + if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &tiffDesc)) { + if (strstr(tiffDesc, "ImageJ")) { + char *nZ = strstr(tiffDesc, "images="); + if (nZ) { + nZ += 7; + char *temp; + return strtol(nZ, &temp, 10); + } + } + } + return 0; +} +void +get_tiff_info(char *fileName, parallel_tiff_range_t *strip_range, uint64_t *x, uint64_t *y, uint64_t *z, + uint64_t *bits, uint64_t *startSlice, uint64_t *stripSize, uint64_t *is_imageJ, + uint64_t *imageJ_Z) +{ TIFFSetWarningHandler(DummyHandler); - TIFF* tif = TIFFOpen(fileName, "r"); - if(!tif) printf("File \"%s\" cannot be opened",fileName); - - uint64_t x = 1,y = 1,z = 1; - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &x); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &y); - uint16_t s = 0, m = 0, t = 1; - while(TIFFSetDirectory(tif,t)){ - s = t; - t *= 8; - if(s > t){ - t = 65535; - printf("Number of slices > 32768\n"); - break; + TIFF *tif = TIFFOpen(fileName, "r"); + if (!tif) + printf("tiff:inputError", "File \"%s\" cannot be opened", fileName); + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, x); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, y); + + if (strip_range == NULL) { + uint16_t s = 0, m = 0, t = 1; + while (TIFFSetDirectory(tif, t)) { + s = t; + t *= 8; + if (s > t) { + t = 65535; + printf("Number of slices > 32768\n"); + break; + } + } + while (s != t) { + m = (s + t + 1) / 2; + if (TIFFSetDirectory(tif, m)) { + s = m; + } + else { + if (m > 0) + t = m - 1; + else + t = m; + } } + *z = s + 1; } - while(s != t){ - m = (s+t+1)/2; - if(TIFFSetDirectory(tif,m)){ - s = m; + else { + if (strip_range->length != 2) { + printf("tiff:inputError", "Input range is not 2"); } - else{ - if(m > 0) t = m-1; - else t = m; + else { + *startSlice = (uint64_t)(*(strip_range->range)) - 1; + *z = (uint64_t)(*(strip_range->range + 1)) - startSlice[0]; + if (!TIFFSetDirectory(tif, startSlice[0] + z[0] - 1) || !TIFFSetDirectory(tif, startSlice[0])) { + printf("tiff:rangeOutOfBound", "Range is out of bounds"); + } } } - z = s+1; + *is_imageJ = isImageJIm(tif); + *imageJ_Z = imageJImGetZ(tif); + if (*is_imageJ) { + *is_imageJ = 1; + *imageJ_Z = imageJImGetZ(tif); + if (*imageJ_Z) + *z = *imageJ_Z; + } + + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, bits); + TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, stripSize); TIFFClose(tif); - uint64_t* dims = (uint64_t*)malloc(3*sizeof(uint64_t)); - dims[0] = y; - dims[1] = x; - dims[2] = z; - return dims; } -// Returns number of bits the tiff file is. -uint64_t getDataType(const char* fileName){ - TIFFSetWarningHandler(DummyHandler); - TIFF* tif = TIFFOpen(fileName, "r"); - if(!tif) printf("File \"%s\" cannot be opened",fileName); +void * +_get_tiff_array(int bits, int ndim, size_t *dims) +{ + void *tiff = NULL; + if (bits == 8) { + CREATE_ARRAY(tiff, uint8_t, ndim, dims); + } + else if (bits == 16) { + CREATE_ARRAY(tiff, uint16_t, ndim, dims); + } + else if (bits == 32) { + CREATE_ARRAY(tiff, float, ndim, dims); + } + else if (bits == 64) { + CREATE_ARRAY(tiff, double, ndim, dims); + } + return tiff; +} - uint64_t bits = 1; - TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits); - TIFFClose(tif); +void +_TIFF_load(char *fileName, uint8_t isImageJIm, uint64_t x, uint64_t y, uint64_t z, uint64_t bits, + uint64_t startSlice, uint64_t stripSize, uint8_t flipXY, int ndim, size_t *dims, void **tiff_ptr) +{ + if (tiff_ptr == NULL) { + printf("tiff:dataTypeError, Data type not suppported\n"); + } + *tiff_ptr = _get_tiff_array(bits, ndim, dims); + // Case for ImageJ + if (isImageJIm) { + readTiffParallelImageJ(x, y, z, fileName, *tiff_ptr, bits, startSlice, stripSize, flipXY); + } + // Case for 2D + else if (z <= 1) { + readTiffParallel2D(x, y, z, fileName, *tiff_ptr, bits, startSlice, stripSize, flipXY); + } + // Case for 3D + else { + readTiffParallel(x, y, z, fileName, *tiff_ptr, bits, startSlice, stripSize, flipXY); + } +} - return bits; +void +parallel_TIFF_load(char *fileName, void **tiff_ptr, uint8_t flipXY, parallel_tiff_range_t *strip_range) +{ + uint64_t x = 1, y = 1, z = 1, bits = 1, startSlice = 0, stripeSize = 0, is_imageJ = 0, imageJ_Z = 0; + get_tiff_info(fileName, strip_range, &x, &y, &z, &bits, &startSlice, &stripeSize, &is_imageJ, &imageJ_Z); -} + int ndim = 3; + uint64_t dims[ndim]; + dims[0] = flipXY ? y : x; + dims[1] = flipXY ? x : y; + dims[2] = z; + + _TIFF_load(fileName, is_imageJ, x, y, z, bits, startSlice, stripeSize, flipXY, ndim, dims, tiff_ptr); +} \ No newline at end of file diff --git a/parallelReadTiff/cSrc/parallelReadTiff.h b/parallelReadTiff/cSrc/parallelReadTiff.h index 0ef31f0..3b50f43 100644 --- a/parallelReadTiff/cSrc/parallelReadTiff.h +++ b/parallelReadTiff/cSrc/parallelReadTiff.h @@ -1,16 +1,34 @@ #ifndef PARALLELREADTIFF_H #define PARALLELREADTIFF_H -#include "tiffio.h" + #include +#include #include -#include "omp.h" - -void readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char* fileName, void* tiff, uint64_t bits, uint64_t startSlice, uint64_t stripSize); - -void* readTiffParallelWrapper(const char* fileName); +#include +#include +#include +#include +#include -uint64_t* getImageSize(const char* fileName); +typedef struct { + uint64_t *range; + size_t length; +} parallel_tiff_range_t; -uint64_t getDataType(const char* fileName); +/** + * This function loads a TIFF image file in parallel into memory, and returns a pointer to the loaded data. + * The image data is stored in the memory pointed to by tiff_ptr, and the dimensions of the image are stored + * in strip_range. If flipXY is set to a non-zero value, the image dimensions will be swapped. The function + * also takes in a file name parameter to specify the location of the TIFF image file to load. + * + * @param fileName: A pointer to a string that specifies the location of the TIFF image file to load. + * @param tiff_ptr: A pointer to a pointer that will be used to return the memory location of the loaded image data. + * @param flipXY: An unsigned 8-bit integer that specifies whether to swap the X and Y dimensions of the image. + * @param strip_range: A pointer to a parallel_tiff_range_t struct that will be used to return the dimensions of the image. + * + * @return This function does not return a value, but the loaded image data and image dimensions are returned via the + * tiff_ptr and strip_range parameters, respectively. + */ +void parallel_TIFF_load(char *fileName, void **tiff_ptr, uint8_t flipXY, parallel_tiff_range_t *strip_range); -#endif // PARALLELREADTIFF_H +#endif // PARALLELREADTIFF_H \ No newline at end of file From d317bc160d0518f15a6a3897558e7b3e0d399039 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:41:06 -0500 Subject: [PATCH 2/9] clang format --- parallelReadTiff/cSrc/main.c | 21 ++++++++++++--------- parallelReadTiff/cSrc/parallelReadTiff.c | 15 ++++++++------- parallelReadTiff/cSrc/parallelReadTiff.h | 4 ++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/parallelReadTiff/cSrc/main.c b/parallelReadTiff/cSrc/main.c index adef1ae..03fd8de 100644 --- a/parallelReadTiff/cSrc/main.c +++ b/parallelReadTiff/cSrc/main.c @@ -9,7 +9,7 @@ int parse_console_args(int argc, char *argv[], char **file_name) { int c, parse_code = -1; - + while ((c = getopt(argc, argv, "f:")) != -1) { switch (c) { case 'f': @@ -25,11 +25,13 @@ parse_console_args(int argc, char *argv[], char **file_name) return parse_code; } -int main(int argc, char *argv[]){ - +int +main(int argc, char *argv[]) +{ + char *file_name = NULL; void *tiff = NULL; - int i = 0; + int i = 0; // parse console argument int parse_code = parse_console_args(argc, argv, &file_name); if (parse_code) { @@ -43,14 +45,15 @@ int main(int argc, char *argv[]){ // calling tiff loading process. parallel_TIFF_load(file_name, &tiff, 1, NULL); - if(!tiff) return 1; - clock_t end = clock(); - double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; - printf("Read Tiff File Done! Time spent: %.4f seconds\n",time_spent); + if (!tiff) + return 1; + clock_t end = clock(); + double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; + printf("Read Tiff File Done! Time spent: %.4f seconds\n", time_spent); printf("first few bytes "); for (i = 0; i < 10; i++) { - printf("%d ", ((uint8_t*)tiff)[i]); + printf("%d ", ((uint8_t *)tiff)[i]); } free(tiff); return 0; diff --git a/parallelReadTiff/cSrc/parallelReadTiff.c b/parallelReadTiff/cSrc/parallelReadTiff.c index d9a2d54..8ad47b5 100644 --- a/parallelReadTiff/cSrc/parallelReadTiff.c +++ b/parallelReadTiff/cSrc/parallelReadTiff.c @@ -7,13 +7,14 @@ #include "omp.h" #endif -#define CREATE_ARRAY(result_var, type, ndim, dim) do { \ - size_t i = 0, dim_prod = 1; \ - for (i = 0; i < (ndim); i++) { \ - dim_prod *= (dim)[i]; \ - } \ - result_var = (void *)malloc(dim_prod * sizeof(type)); \ -} while (0) +#define CREATE_ARRAY(result_var, type, ndim, dim) \ + do { \ + size_t i = 0, dim_prod = 1; \ + for (i = 0; i < (ndim); i++) { \ + dim_prod *= (dim)[i]; \ + } \ + result_var = (void *)malloc(dim_prod * sizeof(type)); \ + } while (0) void DummyHandler(const char *module, const char *fmt, va_list ap) diff --git a/parallelReadTiff/cSrc/parallelReadTiff.h b/parallelReadTiff/cSrc/parallelReadTiff.h index 3b50f43..9e54766 100644 --- a/parallelReadTiff/cSrc/parallelReadTiff.h +++ b/parallelReadTiff/cSrc/parallelReadTiff.h @@ -11,8 +11,8 @@ #include typedef struct { - uint64_t *range; - size_t length; + uint64_t *range; + size_t length; } parallel_tiff_range_t; /** From f04a8aa5d68bcad3f8be4612c0c271acf2f7c24e Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:41:39 -0500 Subject: [PATCH 3/9] clang format --- parallelReadTiff/cSrc/CMakeLists.txt | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 parallelReadTiff/cSrc/CMakeLists.txt diff --git a/parallelReadTiff/cSrc/CMakeLists.txt b/parallelReadTiff/cSrc/CMakeLists.txt new file mode 100644 index 0000000..3285fb9 --- /dev/null +++ b/parallelReadTiff/cSrc/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required (VERSION 2.8.12) + +# Setup cmake policies. +foreach(p + CMP0012 + CMP0013 + CMP0014 + CMP0022 # CMake 2.8.12 + CMP0025 # CMake 3.0 + CMP0053 # CMake 3.1 + CMP0054 # CMake 3.1 + CMP0074 # CMake 3.12 + CMP0075 # CMake 3.12 + CMP0083 # CMake 3.14 + CMP0093 # CMake 3.15 + ) + if(POLICY ${p}) + cmake_policy(SET ${p} NEW) + endif() +endforeach() + +project(OMP_TIFF C) + +# Find LibTIFF +option(USE_LIB_TIFF "Enable LibTiff." ON) +if(USE_LIB_TIFF) + find_package(TIFF REQUIRED) + if(TIFF_FOUND) + # Add the LibTIFF include directory to the include path + include_directories(${TIFF_INCLUDE_DIRS}) + add_library(omp_tiff parallelReadTiff.c) + target_compile_options(omp_tiff PRIVATE ${OpenMP_C_FLAGS}) + target_link_libraries(omp_tiff PUBLIC ${OpenMP_C_LIBRARIES}) + target_link_libraries(omp_tiff PUBLIC ${TIFF_LIBRARIES}) + target_include_directories(omp_tiff PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + + add_executable(main main.c) + target_link_libraries(main ${TIFF_LIBRARIES}) + target_link_libraries(main omp_tiff) + else() + message(WARNING "LibTiff not found, ignore building the executables which requires LibTiff support.") + endif() +endif() \ No newline at end of file From 4349f63790bfa7230f51360dea0a958fd9d8b5c1 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:44:42 -0500 Subject: [PATCH 4/9] find OpenMP --- parallelReadTiff/cSrc/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/parallelReadTiff/cSrc/CMakeLists.txt b/parallelReadTiff/cSrc/CMakeLists.txt index 3285fb9..2549a3c 100644 --- a/parallelReadTiff/cSrc/CMakeLists.txt +++ b/parallelReadTiff/cSrc/CMakeLists.txt @@ -21,6 +21,19 @@ endforeach() project(OMP_TIFF C) +# Find OpenMP +option(USE_SYSTEM_OPENMP "Use system-installed OpenMP." ON) +if(USE_SYSTEM_OPENMP) + find_package(OpenMP REQUIRED) + if(OPENMP_FOUND) + add_definitions(-DENABLE_OPENMP=1) + set(ENABLE_OPENMP 1) + set(OPENMP_LIBRARIES "${OpenMP_C_LIBRARIES}") + else() + message(FATAL_ERROR "OpenMP not found") + endif() +endif() + # Find LibTIFF option(USE_LIB_TIFF "Enable LibTiff." ON) if(USE_LIB_TIFF) From 7297a5f36d2adbc0c0e12e839066c49948763e9b Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:53:10 -0500 Subject: [PATCH 5/9] improve timing --- parallelReadTiff/cSrc/main.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/parallelReadTiff/cSrc/main.c b/parallelReadTiff/cSrc/main.c index 03fd8de..212ef27 100644 --- a/parallelReadTiff/cSrc/main.c +++ b/parallelReadTiff/cSrc/main.c @@ -32,6 +32,9 @@ main(int argc, char *argv[]) char *file_name = NULL; void *tiff = NULL; int i = 0; + struct timespec start, end; + double duration; + // parse console argument int parse_code = parse_console_args(argc, argv, &file_name); if (parse_code) { @@ -41,15 +44,19 @@ main(int argc, char *argv[]) // print file name for validating purpose printf("Filename: %s\n", file_name ? file_name : "(none)"); - clock_t begin = clock(); + clock_gettime(CLOCK_MONOTONIC, &start); // start timing the operation + // calling tiff loading process. parallel_TIFF_load(file_name, &tiff, 1, NULL); + clock_gettime(CLOCK_MONOTONIC, &end); // end timing the operation + + duration = (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec); // calculate duration in nanoseconds + + printf("Read Tiff File Done! Time taken: %.4f nanoseconds\n", duration/1000000); + if (!tiff) return 1; - clock_t end = clock(); - double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; - printf("Read Tiff File Done! Time spent: %.4f seconds\n", time_spent); printf("first few bytes "); for (i = 0; i < 10; i++) { From 80890a0c9ac02b149af83c287c49bbd1461805fa Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:54:14 -0500 Subject: [PATCH 6/9] improve timing --- parallelReadTiff/cSrc/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parallelReadTiff/cSrc/main.c b/parallelReadTiff/cSrc/main.c index 212ef27..3a9423e 100644 --- a/parallelReadTiff/cSrc/main.c +++ b/parallelReadTiff/cSrc/main.c @@ -53,7 +53,7 @@ main(int argc, char *argv[]) duration = (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec); // calculate duration in nanoseconds - printf("Read Tiff File Done! Time taken: %.4f nanoseconds\n", duration/1000000); + printf("Read Tiff File Done! Time taken: %.4f seconds\n", duration/1e9); if (!tiff) return 1; From 3471947857698b90e52bdc44b45f3e9eaecb8cef Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:54:44 -0500 Subject: [PATCH 7/9] improve timing --- parallelReadTiff/cSrc/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/parallelReadTiff/cSrc/main.c b/parallelReadTiff/cSrc/main.c index 3a9423e..8d31349 100644 --- a/parallelReadTiff/cSrc/main.c +++ b/parallelReadTiff/cSrc/main.c @@ -62,6 +62,7 @@ main(int argc, char *argv[]) for (i = 0; i < 10; i++) { printf("%d ", ((uint8_t *)tiff)[i]); } + printf("\n"); free(tiff); return 0; } From 3656f80cf4e06cdd4276f4709cffc34078456fcb Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 00:58:49 -0500 Subject: [PATCH 8/9] clang format --- parallelReadTiff/cSrc/.clang-format | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 parallelReadTiff/cSrc/.clang-format diff --git a/parallelReadTiff/cSrc/.clang-format b/parallelReadTiff/cSrc/.clang-format new file mode 100644 index 0000000..8a3cfe1 --- /dev/null +++ b/parallelReadTiff/cSrc/.clang-format @@ -0,0 +1,64 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AlignConsecutiveAssignments: true +#llvm11: AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: true +AlignConsecutiveMacros: true +#llvm10-11: AlignOperands: true - Align +#llvm11: AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: None +AlwaysBreakAfterReturnType: AllDefinitions +BraceWrapping: + AfterFunction: true + #llvm10-11: AfterControlStatement: false - Never + BeforeCatch: true + BeforeElse: true + #llvm11: BeforeLambdaBody: false + #llvm11: BeforeWhile: false +BreakBeforeBraces: Stroustrup +BreakAfterJavaFieldAnnotations: true +BreakStringLiterals: true +ColumnLimit: 110 # Update $max_trace_macro_line_len in bin/trace also +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 3 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 4 + SortPriority: 0 + - Regex: '.*' + Priority: 0 + SortPriority: 0 + - Regex: '^PDC*.*' + Priority: 1 + SortPriority: 0 + - Regex: 'private.*' + Priority: 2 + SortPriority: 0 +IncludeIsMainRegex: '(public)?$' +IndentCaseLabels: true +#llvm11: IndentCaseBlocks: false +IndentGotoLabels: false +#llvm11: IndentExternBlock: AfterExternBlock +IndentWidth: 4 +#llvm11: InsertTrailingCommas: None +# MacroBlockBegin: "^BEGIN_FUNC" +# MacroBlockEnd: "^END_FUNC" +ObjCBlockIndentWidth: 4 +#llvm11: ObjCBreakBeforeNestedBlockParam: true +ReflowComments: true +SortIncludes: false +StatementMacros: + - FUNC_ENTER + - FUNC_LEAVE + - PGOTO_DONE + - PGOTO_ERROR +#llvm10: TypenameMacros: +#llvm10: - STACK_OF +#llvm10: - LIST +#llvm11: WhitespaceSensitiveMacros: +#llvm11: - STRINGIZE +#llvm11: - PP_STRINGIZE +... + From c5f40acc0545ef8c52f1e1221701b3fda5c3ae94 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 20 Apr 2023 23:55:35 -0500 Subject: [PATCH 9/9] fix printf --- parallelReadTiff/cSrc/parallelReadTiff.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/parallelReadTiff/cSrc/parallelReadTiff.c b/parallelReadTiff/cSrc/parallelReadTiff.c index 8ad47b5..4d6873c 100644 --- a/parallelReadTiff/cSrc/parallelReadTiff.c +++ b/parallelReadTiff/cSrc/parallelReadTiff.c @@ -39,7 +39,7 @@ readTiffParallelBak(uint64_t x, uint64_t y, uint64_t z, const char *fileName, vo TIFF *tif = TIFFOpen(fileName, "r"); if (!tif) - printf("tiff:threadError", "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + printf("tiff:threadError | Thread %d: File \"%s\" cannot be opened\n", w, fileName); void *buffer = malloc(x * bytes); for (int64_t dir = startSlice + (w * batchSize); dir < startSlice + ((w + 1) * batchSize); dir++) { @@ -241,17 +241,17 @@ readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char *fileName, void int fd = open(fileName, O_RDONLY); #endif if (fd == -1) - printf("disk:threadError", "File \"%s\" cannot be opened from Disk\n", fileName); + printf("disk:threadError | File \"%s\" cannot be opened from Disk\n", fileName); if (!tif) - printf("tiff:threadError", "File \"%s\" cannot be opened\n", fileName); + printf("tiff:threadError | File \"%s\" cannot be opened\n", fileName); uint64_t offset = 0; uint64_t *offsets = NULL; TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &offsets); uint64_t *byteCounts = NULL; TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &byteCounts); if (!offsets || !byteCounts) - printf("tiff:threadError", "Could not get offsets or byte counts from the tiff file\n"); + printf("tiff:threadError | Could not get offsets or byte counts from the tiff file\n"); offset = offsets[0]; uint64_t fOffset = offsets[stripsPerDir - 1] + byteCounts[stripsPerDir - 1]; uint64_t zSize = fOffset - offset; @@ -308,7 +308,7 @@ readTiffParallel(uint64_t x, uint64_t y, uint64_t z, const char *fileName, void if (errBak) readTiffParallelBak(x, y, z, fileName, tiff, bits, startSlice, flipXY); else - printf("tiff:threadError", errString); + printf("tiff:threadError %s\n", errString); } } @@ -329,7 +329,7 @@ readTiffParallel2DBak(uint64_t x, uint64_t y, uint64_t z, const char *fileName, TIFF *tif = TIFFOpen(fileName, "r"); if (!tif) - printf("tiff:threadError", "Thread %d: File \"%s\" cannot be opened\n", w, fileName); + printf("tiff:threadError | Thread %d: File \"%s\" cannot be opened\n", w, fileName); void *buffer = malloc(x * bytes); for (int64_t dir = startSlice + (w * batchSize); dir < startSlice + ((w + 1) * batchSize); dir++) { @@ -517,7 +517,7 @@ readTiffParallel2D(uint64_t x, uint64_t y, uint64_t z, const char *fileName, voi if (errBak) readTiffParallel2DBak(x, y, z, fileName, tiff, bits, startSlice, flipXY); else - printf("tiff:threadError", errString); + printf("tiff:threadError %s\n", errString); } } @@ -533,7 +533,7 @@ readTiffParallelImageJ(uint64_t x, uint64_t y, uint64_t z, const char *fileName, #endif TIFF *tif = TIFFOpen(fileName, "r"); if (!tif) - printf("tiff:threadError", "File \"%s\" cannot be opened\n", fileName); + printf("tiff:threadError | File \"%s\" cannot be opened\n", fileName); uint64_t offset = 0; uint64_t *offsets = NULL; TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &offsets); @@ -682,7 +682,7 @@ get_tiff_info(char *fileName, parallel_tiff_range_t *strip_range, uint64_t *x, u TIFFSetWarningHandler(DummyHandler); TIFF *tif = TIFFOpen(fileName, "r"); if (!tif) - printf("tiff:inputError", "File \"%s\" cannot be opened", fileName); + printf("tiff:inputError | File \"%s\" cannot be opened", fileName); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, x); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, y); @@ -714,13 +714,13 @@ get_tiff_info(char *fileName, parallel_tiff_range_t *strip_range, uint64_t *x, u } else { if (strip_range->length != 2) { - printf("tiff:inputError", "Input range is not 2"); + printf("tiff:inputError | Input range is not 2"); } else { *startSlice = (uint64_t)(*(strip_range->range)) - 1; *z = (uint64_t)(*(strip_range->range + 1)) - startSlice[0]; if (!TIFFSetDirectory(tif, startSlice[0] + z[0] - 1) || !TIFFSetDirectory(tif, startSlice[0])) { - printf("tiff:rangeOutOfBound", "Range is out of bounds"); + printf("tiff:rangeOutOfBound | Range is out of bounds"); } } }