Skip to content
Merged
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
90 changes: 58 additions & 32 deletions src/imageio/imageio_pfm.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,32 @@
#include <time.h>
#include <unistd.h>

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')
Expand All @@ -59,63 +70,78 @@ 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);

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;
Expand Down
Loading