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 "system/macros.h"
30#include "system/mem_alloc.h"
31#include "imageio/imageio_pfm.h"
32#include "develop/imageop.h" // for IOP_CS_RGB
33
34#include <assert.h>
35#include <glib/gstdio.h>
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <strings.h>
40#include <time.h>
41
43{
44 const char *ext = filename + strlen(filename);
45 while(*ext != '.' && ext > filename) ext--;
46 if(strcasecmp(ext, ".pfm")) return DT_IMAGEIO_FILE_CORRUPTED;
47 FILE *f = g_fopen(filename, "rb");
49 int ret = 0;
50 int cols = 3;
51 float scale_factor;
52 char head[2] = { 'X', 'X' };
53 ret = fscanf(f, "%c%c\n", head, head + 1);
54 if(ret != 2 || head[0] != 'P') goto error_corrupt;
55 if(head[1] == 'F')
56 cols = 3;
57 else if(head[1] == 'f')
58 cols = 1;
59 else
60 goto error_corrupt;
61 char width_string[10] = { 0 };
62 char height_string[10] = { 0 };
63 char scale_factor_string[64] = { 0 };
64 ret = fscanf(f, "%9s %9s %63s%*[^\n]", width_string, height_string, scale_factor_string);
65 if(ret != 3) goto error_corrupt;
66 errno = 0;
67 img->width = strtol(width_string, NULL, 0);
68 img->height = strtol(height_string, NULL, 0);
69 scale_factor = g_ascii_strtod(scale_factor_string, NULL);
70 if(errno != 0) goto error_corrupt;
71 if(img->width <= 0 || img->height <= 0 ) goto error_corrupt;
72 ret = fread(&ret, sizeof(char), 1, f);
73 if(ret != 1) goto error_corrupt;
74 ret = 0;
75
76 int swap_byte_order = (scale_factor >= 0.0) ^ (G_BYTE_ORDER == G_BIG_ENDIAN);
77
78 img->dsc.channels = 4;
79 img->dsc.datatype = TYPE_FLOAT;
80 img->dsc.bpp = 4 * sizeof(float);
81 img->dsc.cst = IOP_CS_RGB;
82 img->dsc.filters = 0u;
83 img->flags &= ~DT_IMAGE_LDR;
84 img->flags &= ~DT_IMAGE_RAW;
85 img->flags &= ~DT_IMAGE_S_RAW;
86 img->flags |= DT_IMAGE_HDR;
87 img->loader = LOADER_PFM;
88
89 if(IS_NULL_PTR(mbuf))
90 {
91 fclose(f);
92 return DT_IMAGEIO_OK;
93 }
94
95 float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img);
96 if(IS_NULL_PTR(buf)) goto error_cache_full;
97
98 if(cols == 3)
99 {
100 ret = fread(buf, 3 * sizeof(float), (size_t)img->width * img->height, f);
101 for(size_t i = (size_t)img->width * img->height; i > 0; i--)
102 for(int c = 0; c < 3; c++)
103 {
104 union { float f; guint32 i; } v;
105 v.f = buf[3 * (i - 1) + c];
106 if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
107 buf[4 * (i - 1) + c] = v.f;
108 }
109 }
110 else
111 for(size_t j = 0; j < img->height; j++)
112 for(size_t i = 0; i < img->width; i++)
113 {
114 union { float f; guint32 i; } v;
115 ret = fread(&v.f, sizeof(float), 1, f);
116 if(swap_byte_order) v.i = GUINT32_SWAP_LE_BE(v.i);
117 buf[4 * (img->width * j + i) + 2] = buf[4 * (img->width * j + i) + 1]
118 = buf[4 * (img->width * j + i) + 0] = v.f;
119 }
120 float *line = (float *)calloc(4 * img->width, sizeof(float));
121 if(IS_NULL_PTR(line)) goto error_cache_full;
122 for(size_t j = 0; j < img->height / 2; j++)
123 {
124 memcpy(line, buf + img->width * j * 4, sizeof(float) * 4 * img->width);
125 memcpy(buf + img->width * j * 4, buf + img->width * (img->height - 1 - j) * 4,
126 sizeof(float) * 4 * img->width);
127 memcpy(buf + img->width * (img->height - 1 - j) * 4, line, sizeof(float) * 4 * img->width);
128 }
129 dt_free(line);
130 fclose(f);
131 return DT_IMAGEIO_OK;
132
133error_corrupt:
134 fclose(f);
136error_cache_full:
137 fclose(f);
139}
140
141// clang-format off
142// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
143// vim: shiftwidth=2 expandtab tabstop=2 cindent
144// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
145// clang-format on
@ IOP_CS_RGB
const float f
const float v
@ TYPE_FLOAT
Definition format.h:56
dt_imageio_retval_t
Definition image.h:91
@ DT_IMAGEIO_OK
Definition image.h:92
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:95
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:94
@ DT_IMAGE_HDR
Definition image.h:126
@ LOADER_PFM
Definition image.h:290
dt_imageio_retval_t dt_imageio_open_pfm(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
Definition imageio_pfm.c:42
#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 macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
int32_t height
Definition image.h:397
dt_image_loader_t loader
Definition image.h:417
int32_t flags
Definition image.h:401
int32_t width
Definition image.h:397
dt_iop_buffer_dsc_t dsc
Definition image.h:419
uint32_t filters
Definition format.h:89
unsigned int channels
Definition format.h:83
dt_iop_buffer_type_t datatype
Definition format.h:85