Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_pfm.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2011, 2013-2014, 2016 johannes hanika.
4 Copyright (C) 2012 Richard Wonka.
5 Copyright (C) 2012, 2014-2017 Tobias Ellinghaus.
6 Copyright (C) 2014, 2016 Roman Lebedev.
7 Copyright (C) 2014 Ulrich Pegelow.
8 Copyright (C) 2020-2021 Hubert Kowalski.
9 Copyright (C) 2020-2021 Pascal Obry.
10 Copyright (C) 2022 Martin Baƙinka.
11 Copyright (C) 2023 Alynx Zhou.
12
13 darktable is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 darktable is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with darktable. If not, see <http://www.gnu.org/licenses/>.
25*/
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29#include "common/darktable.h"
30#include "common/imageio_pfm.h"
31#include "develop/imageop.h" // for IOP_CS_RGB
32
33#include <assert.h>
34#include <errno.h>
35#include <math.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <strings.h>
39#include <sys/stat.h>
40#include <sys/types.h>
41#include <time.h>
42#include <unistd.h>
43
45{
46 const char *ext = filename + strlen(filename);
47 while(*ext != '.' && ext > filename) ext--;
48 if(strcasecmp(ext, ".pfm")) return DT_IMAGEIO_FILE_CORRUPTED;
49 FILE *f = g_fopen(filename, "rb");
51 int ret = 0;
52 int cols = 3;
53 float scale_factor;
54 char head[2] = { 'X', 'X' };
55 ret = fscanf(f, "%c%c\n", head, head + 1);
56 if(ret != 2 || head[0] != 'P') goto error_corrupt;
57 if(head[1] == 'F')
58 cols = 3;
59 else if(head[1] == 'f')
60 cols = 1;
61 else
62 goto error_corrupt;
63 char width_string[10] = { 0 };
64 char height_string[10] = { 0 };
65 char scale_factor_string[64] = { 0 };
66 ret = fscanf(f, "%9s %9s %63s%*[^\n]", width_string, height_string, scale_factor_string);
67 if(ret != 3) goto error_corrupt;
68 errno = 0;
69 img->width = strtol(width_string, NULL, 0);
70 img->height = strtol(height_string, NULL, 0);
71 scale_factor = g_ascii_strtod(scale_factor_string, NULL);
72 if(errno != 0) goto error_corrupt;
73 if(img->width <= 0 || img->height <= 0 ) goto error_corrupt;
74 ret = fread(&ret, sizeof(char), 1, f);
75 if(ret != 1) goto error_corrupt;
76 ret = 0;
77
78 int swap_byte_order = (scale_factor >= 0.0) ^ (G_BYTE_ORDER == G_BIG_ENDIAN);
79
80 img->dsc.channels = 4;
81 img->dsc.datatype = TYPE_FLOAT;
82 img->dsc.bpp = 4 * sizeof(float);
83 img->dsc.cst = IOP_CS_RGB;
84 img->dsc.filters = 0u;
85 img->flags &= ~DT_IMAGE_LDR;
86 img->flags &= ~DT_IMAGE_RAW;
87 img->flags &= ~DT_IMAGE_S_RAW;
88 img->flags |= DT_IMAGE_HDR;
89 img->loader = LOADER_PFM;
90
91 if(IS_NULL_PTR(mbuf))
92 {
93 fclose(f);
94 return DT_IMAGEIO_OK;
95 }
96
97 float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img);
98 if(IS_NULL_PTR(buf)) goto error_cache_full;
99
100 if(cols == 3)
101 {
102 ret = fread(buf, 3 * sizeof(float), (size_t)img->width * img->height, f);
103 for(size_t i = (size_t)img->width * img->height; i > 0; i--)
104 for(int c = 0; c < 3; c++)
105 {
106 union { float f; guint32 i; } v;
107 v.f = buf[3 * (i - 1) + c];
108 if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
109 buf[4 * (i - 1) + c] = v.f;
110 }
111 }
112 else
113 for(size_t j = 0; j < img->height; j++)
114 for(size_t i = 0; i < img->width; i++)
115 {
116 union { float f; guint32 i; } v;
117 ret = fread(&v.f, sizeof(float), 1, f);
118 if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
119 buf[4 * (img->width * j + i) + 2] = buf[4 * (img->width * j + i) + 1]
120 = buf[4 * (img->width * j + i) + 0] = v.f;
121 }
122 float *line = (float *)calloc(4 * img->width, sizeof(float));
123 if(IS_NULL_PTR(line)) goto error_cache_full;
124 for(size_t j = 0; j < img->height / 2; j++)
125 {
126 memcpy(line, buf + img->width * j * 4, sizeof(float) * 4 * img->width);
127 memcpy(buf + img->width * j * 4, buf + img->width * (img->height - 1 - j) * 4,
128 sizeof(float) * 4 * img->width);
129 memcpy(buf + img->width * (img->height - 1 - j) * 4, line, sizeof(float) * 4 * img->width);
130 }
131 dt_free(line);
132 fclose(f);
133 return DT_IMAGEIO_OK;
134
135error_corrupt:
136 fclose(f);
138error_cache_full:
139 fclose(f);
141}
142
143// clang-format off
144// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
145// vim: shiftwidth=2 expandtab tabstop=2 cindent
146// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
147// clang-format on
@ IOP_CS_RGB
const dt_aligned_pixel_t f
#define dt_free(ptr)
Definition darktable.h:456
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
@ TYPE_FLOAT
Definition format.h:46
dt_imageio_retval_t
Definition image.h:78
@ DT_IMAGEIO_OK
Definition image.h:79
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:82
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:81
@ DT_IMAGE_HDR
Definition image.h:113
@ LOADER_PFM
Definition image.h:229
dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
Definition imageio_pfm.c:44
const float v
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
int32_t height
Definition image.h:315
dt_image_loader_t loader
Definition image.h:335
int32_t flags
Definition image.h:319
int32_t width
Definition image.h:315
dt_iop_buffer_dsc_t dsc
Definition image.h:337
uint32_t filters
Definition format.h:60
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56