Cycles: svn merge -r41266:41467 ^/trunk/blender
[blender-staging.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 #define open _open
41 #define read _read
42 #define close _close
43 #endif
44
45 #include "BLI_blenlib.h"
46 #include "BLI_utildefines.h"
47
48 #include "imbuf.h"
49 #include "IMB_imbuf_types.h"
50 #include "IMB_imbuf.h"
51 #include "IMB_filetype.h"
52
53 static ImBuf *imb_ibImageFromFile(const char *filepath, int flags)
54 {
55         ImBuf *ibuf;
56         ImFileType *type;
57
58         for(type=IMB_FILE_TYPES; type->is_a; type++) {
59                 if(type->load_filepath) {
60                         ibuf= type->load_filepath(filepath, flags);
61                         if(ibuf) {
62                                 if(flags & IB_premul) {
63                                         IMB_premultiply_alpha(ibuf);
64                                         ibuf->flags |= IB_premul;
65                                 }
66
67                                 return ibuf;
68                         }
69                 }
70         }
71         
72         return NULL;
73 }
74
75 ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, const char *descr)
76 {
77         ImBuf *ibuf;
78         ImFileType *type;
79
80         if(mem == NULL) {
81                 fprintf(stderr, "%s: NULL pointer\n", __func__);
82                 return NULL;
83         }
84
85         for(type=IMB_FILE_TYPES; type->is_a; type++) {
86                 if(type->load) {
87                         ibuf= type->load(mem, size, flags);
88                         if(ibuf) {
89                                 if(flags & IB_premul) {
90                                         IMB_premultiply_alpha(ibuf);
91                                         ibuf->flags |= IB_premul;
92                                 }
93
94                                 return ibuf;
95                         }
96                 }
97         }
98
99         fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr);
100
101         return NULL;
102 }
103
104 ImBuf *IMB_loadifffile(int file, int flags, const char *descr)
105 {
106         ImBuf *ibuf;
107         unsigned char *mem;
108         size_t size;
109
110         if(file == -1) return NULL;
111
112         size= BLI_file_descriptor_size(file);
113
114         mem= mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
115         if(mem==(unsigned char*)-1) {
116                 fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr);
117                 return NULL;
118         }
119
120         ibuf= IMB_ibImageFromMemory(mem, size, flags, descr);
121
122         if(munmap(mem, size))
123                 fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr);
124
125         return ibuf;
126 }
127
128 static void imb_cache_filename(char *filename, const char *name, int flags)
129 {
130         /* read .tx instead if it exists and is not older */
131         if(flags & IB_tilecache) {
132                 BLI_strncpy(filename, name, IB_FILENAME_SIZE);
133                 if(!BLI_replace_extension(filename, IB_FILENAME_SIZE, ".tx"))
134                         return;
135
136                 if(BLI_file_older(name, filename))
137                         return;
138         }
139
140         BLI_strncpy(filename, name, IB_FILENAME_SIZE);
141 }
142
143 ImBuf *IMB_loadiffname(const char *filepath, int flags)
144 {
145         ImBuf *ibuf;
146         int file, a;
147         char filepath_tx[IB_FILENAME_SIZE];
148
149         imb_cache_filename(filepath_tx, filepath, flags);
150
151         ibuf= imb_ibImageFromFile(filepath_tx, flags);
152
153         if(!ibuf) {
154                 file = open(filepath_tx, O_BINARY|O_RDONLY);
155                 if(file < 0) return NULL;
156
157                 ibuf= IMB_loadifffile(file, flags, filepath_tx);
158                 close(file);
159         }
160
161         if(ibuf) {
162                 BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
163                 BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename));
164                 for(a=1; a<ibuf->miptot; a++)
165                         BLI_strncpy(ibuf->mipmap[a-1]->cachename, filepath_tx, sizeof(ibuf->cachename));
166                 if(flags & IB_fields) IMB_de_interlace(ibuf);
167         }
168
169         return ibuf;
170 }
171
172 ImBuf *IMB_testiffname(const char *filepath, int flags)
173 {
174         ImBuf *ibuf;
175         int file;
176         char filepath_tx[IB_FILENAME_SIZE];
177
178         imb_cache_filename(filepath_tx, filepath, flags);
179
180         file = open(filepath_tx,O_BINARY|O_RDONLY);
181         if(file < 0) return NULL;
182
183         ibuf=IMB_loadifffile(file, flags|IB_test|IB_multilayer, filepath_tx);
184
185         if(ibuf) {
186                 BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
187                 BLI_strncpy(ibuf->cachename, filepath_tx, sizeof(ibuf->cachename));
188         }
189
190         close(file);
191
192         return ibuf;
193 }
194
195 static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int *rect)
196 {
197         ImFileType *type;
198         unsigned char *mem;
199         size_t size;
200
201         if(file == -1) return;
202
203         size= BLI_file_descriptor_size(file);
204
205         mem= mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
206         if(mem==(unsigned char*)-1) {
207                 fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename);
208                 return;
209         }
210
211         for(type=IMB_FILE_TYPES; type->is_a; type++)
212                 if(type->load_tile && type->ftype && type->ftype(type, ibuf))
213                         type->load_tile(ibuf, mem, size, tx, ty, rect);
214
215         if(munmap(mem, size))
216                 fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename);
217 }
218
219 void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
220 {
221         int file;
222
223         file = open(ibuf->cachename, O_BINARY|O_RDONLY);
224         if(file < 0) return;
225
226         imb_loadtilefile(ibuf, file, tx, ty, rect);
227
228         close(file);
229 }
230