1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 * allocimbuf.c
19 */
20
21 /** \file
22 * \ingroup imbuf
23 */
24
25 #ifdef _WIN32
26 # include "mmap_win.h"
27 # include <io.h>
28 # include <stddef.h>
29 # include <sys/types.h>
30 #endif
31
32 #include "BLI_fileops.h"
33 #include "BLI_path_util.h"
34 #include "BLI_string.h"
35 #include "BLI_utildefines.h"
36 #include <stdlib.h>
37
38 #include "IMB_allocimbuf.h"
39 #include "IMB_filetype.h"
40 #include "IMB_imbuf.h"
41 #include "IMB_imbuf_types.h"
42 #include "imbuf.h"
43
44 #include "IMB_colormanagement.h"
45 #include "IMB_colormanagement_intern.h"
46
imb_handle_alpha(ImBuf * ibuf,int flags,char colorspace[IM_MAX_SPACE],char effective_colorspace[IM_MAX_SPACE])47 static void imb_handle_alpha(ImBuf *ibuf,
48 int flags,
49 char colorspace[IM_MAX_SPACE],
50 char effective_colorspace[IM_MAX_SPACE])
51 {
52 if (colorspace) {
53 if (ibuf->rect != NULL && ibuf->rect_float == NULL) {
54 /* byte buffer is never internally converted to some standard space,
55 * store pointer to its color space descriptor instead
56 */
57 ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace);
58 }
59
60 BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
61 }
62
63 bool is_data = (colorspace && IMB_colormanagement_space_name_is_data(colorspace));
64 int alpha_flags = (flags & IB_alphamode_detect) ? ibuf->flags : flags;
65
66 if (is_data || (flags & IB_alphamode_channel_packed)) {
67 /* Don't touch alpha. */
68 ibuf->flags |= IB_alphamode_channel_packed;
69 }
70 else if (flags & IB_alphamode_ignore) {
71 /* Make opaque. */
72 IMB_rectfill_alpha(ibuf, 1.0f);
73 ibuf->flags |= IB_alphamode_ignore;
74 }
75 else {
76 if (alpha_flags & IB_alphamode_premul) {
77 if (ibuf->rect) {
78 IMB_unpremultiply_alpha(ibuf);
79 }
80 else {
81 /* pass, floats are expected to be premul */
82 }
83 }
84 else {
85 if (ibuf->rect_float) {
86 IMB_premultiply_alpha(ibuf);
87 }
88 else {
89 /* pass, bytes are expected to be straight */
90 }
91 }
92 }
93
94 /* OCIO_TODO: in some cases it's faster to do threaded conversion,
95 * but how to distinguish such cases */
96 colormanage_imbuf_make_linear(ibuf, effective_colorspace);
97 }
98
IMB_ibImageFromMemory(const unsigned char * mem,size_t size,int flags,char colorspace[IM_MAX_SPACE],const char * descr)99 ImBuf *IMB_ibImageFromMemory(const unsigned char *mem,
100 size_t size,
101 int flags,
102 char colorspace[IM_MAX_SPACE],
103 const char *descr)
104 {
105 ImBuf *ibuf;
106 const ImFileType *type;
107 char effective_colorspace[IM_MAX_SPACE] = "";
108
109 if (mem == NULL) {
110 fprintf(stderr, "%s: NULL pointer\n", __func__);
111 return NULL;
112 }
113
114 if (colorspace) {
115 BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
116 }
117
118 for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
119 if (type->load) {
120 ibuf = type->load(mem, size, flags, effective_colorspace);
121 if (ibuf) {
122 imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace);
123 return ibuf;
124 }
125 }
126 }
127
128 if ((flags & IB_test) == 0) {
129 fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr);
130 }
131
132 return NULL;
133 }
134
IMB_ibImageFromFile(const char * filepath,int flags,char colorspace[IM_MAX_SPACE],const char * descr)135 static ImBuf *IMB_ibImageFromFile(const char *filepath,
136 int flags,
137 char colorspace[IM_MAX_SPACE],
138 const char *descr)
139 {
140 ImBuf *ibuf;
141 const ImFileType *type;
142 char effective_colorspace[IM_MAX_SPACE] = "";
143
144 if (colorspace) {
145 BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
146 }
147
148 for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
149 if (type->load_filepath) {
150 ibuf = type->load_filepath(filepath, flags, effective_colorspace);
151 if (ibuf) {
152 imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace);
153 return ibuf;
154 }
155 }
156 }
157
158 if ((flags & IB_test) == 0) {
159 fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr);
160 }
161
162 return NULL;
163 }
164
imb_is_filepath_format(const char * filepath)165 static bool imb_is_filepath_format(const char *filepath)
166 {
167 /* return true if this is one of the formats that can't be loaded from memory */
168 return BLI_path_extension_check_array(filepath, imb_ext_image_filepath_only);
169 }
170
IMB_loadifffile(int file,const char * filepath,int flags,char colorspace[IM_MAX_SPACE],const char * descr)171 ImBuf *IMB_loadifffile(
172 int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
173 {
174 ImBuf *ibuf;
175 unsigned char *mem;
176 size_t size;
177
178 if (file == -1) {
179 return NULL;
180 }
181
182 if (imb_is_filepath_format(filepath)) {
183 return IMB_ibImageFromFile(filepath, flags, colorspace, descr);
184 }
185
186 size = BLI_file_descriptor_size(file);
187
188 imb_mmap_lock();
189 mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
190 imb_mmap_unlock();
191
192 if (mem == (unsigned char *)-1) {
193 fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr);
194 return NULL;
195 }
196
197 ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr);
198
199 imb_mmap_lock();
200 if (munmap(mem, size)) {
201 fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr);
202 }
203 imb_mmap_unlock();
204
205 return ibuf;
206 }
207
imb_cache_filename(char * filename,const char * name,int flags)208 static void imb_cache_filename(char *filename, const char *name, int flags)
209 {
210 /* read .tx instead if it exists and is not older */
211 if (flags & IB_tilecache) {
212 BLI_strncpy(filename, name, IMB_FILENAME_SIZE);
213 if (!BLI_path_extension_replace(filename, IMB_FILENAME_SIZE, ".tx")) {
214 return;
215 }
216
217 if (BLI_file_older(name, filename)) {
218 return;
219 }
220 }
221
222 BLI_strncpy(filename, name, IMB_FILENAME_SIZE);
223 }
224
IMB_loadiffname(const char * filepath,int flags,char colorspace[IM_MAX_SPACE])225 ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
226 {
227 ImBuf *ibuf;
228 int file, a;
229 char filepath_tx[IMB_FILENAME_SIZE];
230
231 BLI_assert(!BLI_path_is_rel(filepath));
232
233 imb_cache_filename(filepath_tx, filepath, flags);
234
235 file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
236 if (file == -1) {
237 return NULL;
238 }
239
240 ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx);
241
242 if (ibuf) {
243 BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
244 BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename));
245 for (a = 1; a < ibuf->miptot; a++) {
246 BLI_strncpy(ibuf->mipmap[a - 1]->cachename, filepath_tx, sizeof(ibuf->cachename));
247 }
248 }
249
250 close(file);
251
252 return ibuf;
253 }
254
IMB_testiffname(const char * filepath,int flags)255 ImBuf *IMB_testiffname(const char *filepath, int flags)
256 {
257 ImBuf *ibuf;
258 int file;
259 char filepath_tx[IMB_FILENAME_SIZE];
260 char colorspace[IM_MAX_SPACE] = "\0";
261
262 BLI_assert(!BLI_path_is_rel(filepath));
263
264 imb_cache_filename(filepath_tx, filepath, flags);
265
266 file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
267 if (file == -1) {
268 return NULL;
269 }
270
271 ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath_tx);
272
273 if (ibuf) {
274 BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
275 BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename));
276 }
277
278 close(file);
279
280 return ibuf;
281 }
282
imb_loadtilefile(ImBuf * ibuf,int file,int tx,int ty,unsigned int * rect)283 static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int *rect)
284 {
285 const ImFileType *type;
286 unsigned char *mem;
287 size_t size;
288
289 if (file == -1) {
290 return;
291 }
292
293 size = BLI_file_descriptor_size(file);
294
295 imb_mmap_lock();
296 mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
297 imb_mmap_unlock();
298
299 if (mem == (unsigned char *)-1) {
300 fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename);
301 return;
302 }
303
304 for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) {
305 if (type->load_tile && type->ftype(type, ibuf)) {
306 type->load_tile(ibuf, mem, size, tx, ty, rect);
307 }
308 }
309
310 imb_mmap_lock();
311 if (munmap(mem, size)) {
312 fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename);
313 }
314 imb_mmap_unlock();
315 }
316
imb_loadtile(ImBuf * ibuf,int tx,int ty,unsigned int * rect)317 void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
318 {
319 int file;
320
321 file = BLI_open(ibuf->cachename, O_BINARY | O_RDONLY, 0);
322 if (file == -1) {
323 return;
324 }
325
326 imb_loadtilefile(ibuf, file, tx, ty, rect);
327
328 close(file);
329 }
330