Skip to content

Commit 9334965

Browse files
authored
Merge pull request #17689 from victoryforce/accelerate-PFM-loading
[imageio] Radically speed up PFM loading
2 parents 0a68891 + 31b102f commit 9334965

File tree

1 file changed

+58
-32
lines changed

1 file changed

+58
-32
lines changed

src/imageio/imageio_pfm.c

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,32 @@
3434
#include <time.h>
3535
#include <unistd.h>
3636

37-
dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
37+
dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img,
38+
const char *filename,
39+
dt_mipmap_buffer_t *mbuf)
3840
{
3941
const char *ext = filename + strlen(filename);
40-
while(*ext != '.' && ext > filename) ext--;
41-
if(strcasecmp(ext, ".pfm")) return DT_IMAGEIO_LOAD_FAILED;
42+
43+
while(*ext != '.' && ext > filename)
44+
ext--;
45+
46+
if(strcasecmp(ext, ".pfm"))
47+
return DT_IMAGEIO_LOAD_FAILED;
4248

4349
FILE *f = g_fopen(filename, "rb");
44-
if(!f) return DT_IMAGEIO_FILE_NOT_FOUND;
50+
if(!f)
51+
return DT_IMAGEIO_FILE_NOT_FOUND;
4552

4653
int ret = 0;
4754
int cols = 3;
4855
float scale_factor;
4956
char head[2] = { 'X', 'X' };
57+
5058
ret = fscanf(f, "%c%c\n", head, head + 1);
51-
if(ret != 2 || head[0] != 'P') goto error_corrupt;
59+
60+
if(ret != 2 || head[0] != 'P')
61+
goto error_corrupt;
62+
5263
if(head[1] == 'F')
5364
cols = 3;
5465
else if(head[1] == 'f')
@@ -59,63 +70,78 @@ dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, d
5970
char width_string[10] = { 0 };
6071
char height_string[10] = { 0 };
6172
char scale_factor_string[64] = { 0 };
73+
6274
ret = fscanf(f, "%9s %9s %63s%*[^\n]", width_string, height_string, scale_factor_string);
63-
if(ret != 3) goto error_corrupt;
75+
76+
if(ret != 3)
77+
goto error_corrupt;
6478

6579
errno = 0;
6680
img->width = strtol(width_string, NULL, 0);
6781
img->height = strtol(height_string, NULL, 0);
6882
scale_factor = g_ascii_strtod(scale_factor_string, NULL);
69-
if(errno != 0) goto error_corrupt;
70-
if(img->width <= 0 || img->height <= 0 ) goto error_corrupt;
83+
84+
if(errno != 0)
85+
goto error_corrupt;
86+
if(img->width <= 0 || img->height <= 0 )
87+
goto error_corrupt;
7188

7289
ret = fread(&ret, sizeof(char), 1, f);
73-
if(ret != 1) goto error_corrupt;
90+
if(ret != 1)
91+
goto error_corrupt;
7492
ret = 0;
7593

7694
int swap_byte_order = (scale_factor >= 0.0) ^ (G_BYTE_ORDER == G_BIG_ENDIAN);
7795

7896
img->buf_dsc.channels = 4;
7997
img->buf_dsc.datatype = TYPE_FLOAT;
8098
float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img);
81-
if(!buf) goto error_cache_full;
99+
if(!buf)
100+
goto error_cache_full;
101+
102+
const size_t npixels = (size_t)img->width * img->height;
103+
104+
float *readbuf = dt_alloc_align_float(npixels * 4);
105+
if(!readbuf)
106+
goto error_cache_full;
107+
108+
union { float f; guint32 i; } value;
82109

83110
if(cols == 3)
84111
{
85-
ret = fread(buf, 3 * sizeof(float), (size_t)img->width * img->height, f);
86-
for(size_t i = (size_t)img->width * img->height; i > 0; i--)
87-
for(int c = 0; c < 3; c++)
112+
ret = fread(readbuf, 3 * sizeof(float), npixels, f);
113+
114+
DT_OMP_FOR(collapse(2))
115+
for(size_t j = 0; j < img->height; j++)
116+
for(size_t i = 0; i < img->width; i++)
88117
{
89-
union { float f; guint32 i; } v;
90-
v.f = buf[3 * (i - 1) + c];
91-
if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
92-
buf[4 * (i - 1) + c] = v.f;
118+
dt_aligned_pixel_t pix = {0.0f, 0.0f, 0.0f, 0.0f};
119+
for_three_channels(c)
120+
{
121+
value.f = readbuf[3 * ((img->height - 1 - j) * img->width + i) + c];
122+
if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i);
123+
pix[c] = value.f;
124+
}
125+
copy_pixel_nontemporal(&buf[4 * (img->width * j + i)], pix);
93126
}
94127
}
95128
else
129+
{
130+
ret = fread(readbuf, sizeof(float), npixels, f);
131+
132+
DT_OMP_FOR(collapse(2))
96133
for(size_t j = 0; j < img->height; j++)
97134
for(size_t i = 0; i < img->width; i++)
98135
{
99-
union { float f; guint32 i; } v;
100-
ret = fread(&v.f, sizeof(float), 1, f);
101-
if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
136+
value.f = readbuf[((img->height - 1 - j) * img->width + i)];
137+
if(swap_byte_order) value.i = GUINT32_SWAP_LE_BE(value.i);
102138
buf[4 * (img->width * j + i) + 2] = buf[4 * (img->width * j + i) + 1]
103-
= buf[4 * (img->width * j + i) + 0] = v.f;
139+
= buf[4 * (img->width * j + i) + 0] = value.f;
104140
}
105-
106-
float *line = (float *)calloc(4 * img->width, sizeof(float));
107-
if(line == NULL) goto error_cache_full;
108-
109-
for(size_t j = 0; j < img->height / 2; j++)
110-
{
111-
memcpy(line, buf + img->width * j * 4, sizeof(float) * 4 * img->width);
112-
memcpy(buf + img->width * j * 4, buf + img->width * (img->height - 1 - j) * 4,
113-
sizeof(float) * 4 * img->width);
114-
memcpy(buf + img->width * (img->height - 1 - j) * 4, line, sizeof(float) * 4 * img->width);
115141
}
116142

117-
free(line);
118143
fclose(f);
144+
dt_free_align(readbuf);
119145

120146
img->buf_dsc.cst = IOP_CS_RGB;
121147
img->buf_dsc.filters = 0u;

0 commit comments

Comments
 (0)