From 459d0c94fb5e5d8d0cc0775294b55bece1e76aa9 Mon Sep 17 00:00:00 2001 From: Victor Forsiuk Date: Thu, 17 Oct 2024 12:39:31 +0300 Subject: [PATCH 1/4] Redesign load loops to make them OpenMP compatible --- src/imageio/imageio_pfm.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/imageio/imageio_pfm.c b/src/imageio/imageio_pfm.c index f8eddbea8434..b878428c32f6 100644 --- a/src/imageio/imageio_pfm.c +++ b/src/imageio/imageio_pfm.c @@ -80,28 +80,44 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img); if(!buf) goto error_cache_full; + const size_t npixels = (size_t)img->width * img->height; + + float *readbuf = dt_alloc_align_float(npixels * 4); + if(!readbuf) + goto error_cache_full; + + union { float f; guint32 i; } value; + if(cols == 3) { - ret = fread(buf, 3 * sizeof(float), (size_t)img->width * img->height, f); - for(size_t i = (size_t)img->width * img->height; i > 0; i--) - for(int c = 0; c < 3; c++) + ret = fread(readbuf, 3 * sizeof(float), npixels, f); + + for(size_t j = 0; j < img->height; j++) + for(size_t i = 0; i < img->width; i++) { - union { float f; guint32 i; } v; - v.f = buf[3 * (i - 1) + c]; - if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i); - buf[4 * (i - 1) + c] = v.f; + dt_aligned_pixel_t pix = {0.0f, 0.0f, 0.0f, 0.0f}; + for_three_channels(c) + { + value.f = readbuf[3 * (j * img->width + i) + c]; + if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i); + pix[c] = value.f; + } + copy_pixel_nontemporal(&buf[4 * (img->width * j + i)], pix); } } else + { + ret = fread(readbuf, sizeof(float), npixels, f); + for(size_t j = 0; j < img->height; j++) for(size_t i = 0; i < img->width; i++) { - union { float f; guint32 i; } v; - ret = fread(&v.f, sizeof(float), 1, f); - if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i); + value.f = readbuf[(j * img->width + i)]; + if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i); buf[4 * (img->width * j + i) + 2] = buf[4 * (img->width * j + i) + 1] - = buf[4 * (img->width * j + i) + 0] = v.f; + = buf[4 * (img->width * j + i) + 0] = value.f; } + } float *line = (float *)calloc(4 * img->width, sizeof(float)); if(line == NULL) goto error_cache_full; @@ -116,6 +132,7 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d free(line); fclose(f); + dt_free_align(readbuf); img->buf_dsc.cst = IOP_CS_RGB; img->buf_dsc.filters = 0u; From 1255ed78949a6cd39715b39820d7403f3ab5ee1f Mon Sep 17 00:00:00 2001 From: Victor Forsiuk Date: Fri, 18 Oct 2024 18:01:46 +0300 Subject: [PATCH 2/4] Add OpenMP parallelization to PFM data load loops --- src/imageio/imageio_pfm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/imageio/imageio_pfm.c b/src/imageio/imageio_pfm.c index b878428c32f6..ce05fd18973e 100644 --- a/src/imageio/imageio_pfm.c +++ b/src/imageio/imageio_pfm.c @@ -92,6 +92,7 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d { ret = fread(readbuf, 3 * sizeof(float), npixels, f); +DT_OMP_FOR(collapse(2)) for(size_t j = 0; j < img->height; j++) for(size_t i = 0; i < img->width; i++) { @@ -109,6 +110,7 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d { ret = fread(readbuf, sizeof(float), npixels, f); +DT_OMP_FOR(collapse(2)) for(size_t j = 0; j < img->height; j++) for(size_t i = 0; i < img->width; i++) { From 4e646757e88e024c2cf7996d67cd88c1db476e8a Mon Sep 17 00:00:00 2001 From: Victor Forsiuk Date: Fri, 18 Oct 2024 18:19:53 +0300 Subject: [PATCH 3/4] Get rid of the additional loop of reversing the order of rows ...we can do this by correcting the addressing in the resulting buffer filling loops so that the image rows end up in the right place from the beginning --- src/imageio/imageio_pfm.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/imageio/imageio_pfm.c b/src/imageio/imageio_pfm.c index ce05fd18973e..4e5c73e14556 100644 --- a/src/imageio/imageio_pfm.c +++ b/src/imageio/imageio_pfm.c @@ -99,7 +99,7 @@ DT_OMP_FOR(collapse(2)) dt_aligned_pixel_t pix = {0.0f, 0.0f, 0.0f, 0.0f}; for_three_channels(c) { - value.f = readbuf[3 * (j * img->width + i) + c]; + value.f = readbuf[3 * ((img->height - 1 - j) * img->width + i) + c]; if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i); pix[c] = value.f; } @@ -114,25 +114,13 @@ DT_OMP_FOR(collapse(2)) for(size_t j = 0; j < img->height; j++) for(size_t i = 0; i < img->width; i++) { - value.f = readbuf[(j * img->width + i)]; + value.f = readbuf[((img->height - 1 - j) * img->width + i)]; if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i); buf[4 * (img->width * j + i) + 2] = buf[4 * (img->width * j + i) + 1] = buf[4 * (img->width * j + i) + 0] = value.f; } } - float *line = (float *)calloc(4 * img->width, sizeof(float)); - if(line == NULL) goto error_cache_full; - - for(size_t j = 0; j < img->height / 2; j++) - { - memcpy(line, buf + img->width * j * 4, sizeof(float) * 4 * img->width); - memcpy(buf + img->width * j * 4, buf + img->width * (img->height - 1 - j) * 4, - sizeof(float) * 4 * img->width); - memcpy(buf + img->width * (img->height - 1 - j) * 4, line, sizeof(float) * 4 * img->width); - } - - free(line); fclose(f); dt_free_align(readbuf); From 31b102ffb1feba15b6ba6b8a1e04a351054901bc Mon Sep 17 00:00:00 2001 From: Victor Forsiuk Date: Fri, 18 Oct 2024 18:37:26 +0300 Subject: [PATCH 4/4] Minor code reformatting --- src/imageio/imageio_pfm.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/imageio/imageio_pfm.c b/src/imageio/imageio_pfm.c index 4e5c73e14556..a99e3e47f3bd 100644 --- a/src/imageio/imageio_pfm.c +++ b/src/imageio/imageio_pfm.c @@ -34,21 +34,32 @@ #include #include -dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf) +dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, + const char *filename, + dt_mipmap_buffer_t *mbuf) { const char *ext = filename + strlen(filename); - while(*ext != '.' && ext > filename) ext--; - if(strcasecmp(ext, ".pfm")) return DT_IMAGEIO_LOAD_FAILED; + + while(*ext != '.' && ext > filename) + ext--; + + if(strcasecmp(ext, ".pfm")) + return DT_IMAGEIO_LOAD_FAILED; FILE *f = g_fopen(filename, "rb"); - if(!f) return DT_IMAGEIO_FILE_NOT_FOUND; + if(!f) + return DT_IMAGEIO_FILE_NOT_FOUND; int ret = 0; int cols = 3; float scale_factor; char head[2] = { 'X', 'X' }; + ret = fscanf(f, "%c%c\n", head, head + 1); - if(ret != 2 || head[0] != 'P') goto error_corrupt; + + if(ret != 2 || head[0] != 'P') + goto error_corrupt; + if(head[1] == 'F') cols = 3; else if(head[1] == 'f') @@ -59,18 +70,25 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d char width_string[10] = { 0 }; char height_string[10] = { 0 }; char scale_factor_string[64] = { 0 }; + ret = fscanf(f, "%9s %9s %63s%*[^\n]", width_string, height_string, scale_factor_string); - if(ret != 3) goto error_corrupt; + + if(ret != 3) + goto error_corrupt; errno = 0; img->width = strtol(width_string, NULL, 0); img->height = strtol(height_string, NULL, 0); scale_factor = g_ascii_strtod(scale_factor_string, NULL); - if(errno != 0) goto error_corrupt; - if(img->width <= 0 || img->height <= 0 ) goto error_corrupt; + + if(errno != 0) + goto error_corrupt; + if(img->width <= 0 || img->height <= 0 ) + goto error_corrupt; ret = fread(&ret, sizeof(char), 1, f); - if(ret != 1) goto error_corrupt; + if(ret != 1) + goto error_corrupt; ret = 0; int swap_byte_order = (scale_factor >= 0.0) ^ (G_BYTE_ORDER == G_BIG_ENDIAN); @@ -78,7 +96,8 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d img->buf_dsc.channels = 4; img->buf_dsc.datatype = TYPE_FLOAT; float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img); - if(!buf) goto error_cache_full; + if(!buf) + goto error_cache_full; const size_t npixels = (size_t)img->width * img->height;