diff --git a/src/imageio/imageio_pfm.c b/src/imageio/imageio_pfm.c index f8eddbea8434..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,44 +96,52 @@ 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; + + 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); + +DT_OMP_FOR(collapse(2)) + 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 * ((img->height - 1 - 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); + +DT_OMP_FOR(collapse(2)) 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[((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] = 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; - - 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); img->buf_dsc.cst = IOP_CS_RGB; img->buf_dsc.filters = 0u;