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