support for reading/writing image resolution (dpi), for PNG and TIFF,
[blender-staging.git] / source / blender / imbuf / intern / allocimbuf.c
1 /*
2  * allocimbuf.c
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 /** \file blender/imbuf/intern/allocimbuf.c
33  *  \ingroup imbuf
34  */
35
36
37 /* It's become a bit messy... Basically, only the IMB_ prefixed files
38  * should remain. */
39
40 #include <stddef.h>
41
42 #include "IMB_imbuf.h"
43 #include "IMB_imbuf_types.h"
44
45 #include "IMB_allocimbuf.h"
46 #include "IMB_filetype.h"
47 #include "IMB_metadata.h"
48
49 #include "imbuf.h"
50
51 #include "MEM_CacheLimiterC-Api.h"
52 #include "MEM_guardedalloc.h"
53
54 void imb_freemipmapImBuf(ImBuf *ibuf)
55 {
56         int a;
57         
58         for(a=1; a<ibuf->miptot; a++) {
59                 if(ibuf->mipmap[a-1])
60                         IMB_freeImBuf(ibuf->mipmap[a-1]);
61                 ibuf->mipmap[a-1]= NULL;
62         }
63
64         ibuf->miptot= 0;
65 }
66
67 /* any free rect frees mipmaps to be sure, creation is in render on first request */
68 void imb_freerectfloatImBuf(ImBuf *ibuf)
69 {
70         if(ibuf==NULL) return;
71         
72         if(ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
73                 MEM_freeN(ibuf->rect_float);
74                 ibuf->rect_float=NULL;
75         }
76
77         imb_freemipmapImBuf(ibuf);
78         
79         ibuf->rect_float= NULL;
80         ibuf->mall &= ~IB_rectfloat;
81 }
82
83 /* any free rect frees mipmaps to be sure, creation is in render on first request */
84 void imb_freerectImBuf(ImBuf *ibuf)
85 {
86         if(ibuf==NULL) return;
87
88 #ifdef WITH_LCMS
89         if(ibuf->crect)
90                 MEM_freeN(ibuf->crect);
91         ibuf->crect= NULL;
92 #endif
93
94         if(ibuf->rect && (ibuf->mall & IB_rect))
95                 MEM_freeN(ibuf->rect);
96         ibuf->rect= NULL;
97         
98         imb_freemipmapImBuf(ibuf);
99
100         ibuf->mall &= ~IB_rect;
101 }
102
103 void imb_freetilesImBuf(ImBuf *ibuf)
104 {
105         int tx, ty;
106
107         if(ibuf==NULL) return;
108
109         if(ibuf->tiles && (ibuf->mall & IB_tiles)) {
110                 for(ty=0; ty<ibuf->ytiles; ty++) {
111                         for(tx=0; tx<ibuf->xtiles; tx++) {
112                                 if(ibuf->tiles[ibuf->xtiles*ty + tx]) {
113                                         imb_tile_cache_tile_free(ibuf, tx, ty);
114                                         MEM_freeN(ibuf->tiles[ibuf->xtiles*ty + tx]);
115                                 }
116                         }
117                 }
118
119                 MEM_freeN(ibuf->tiles);
120         }
121
122         ibuf->tiles= NULL;
123         ibuf->mall &= ~IB_tiles;
124 }
125
126 static void freeencodedbufferImBuf(ImBuf *ibuf)
127 {
128         if(ibuf==NULL) return;
129
130         if(ibuf->encodedbuffer && (ibuf->mall & IB_mem))
131                 MEM_freeN(ibuf->encodedbuffer);
132
133         ibuf->encodedbuffer = NULL;
134         ibuf->encodedbuffersize = 0;
135         ibuf->encodedsize = 0;
136         ibuf->mall &= ~IB_mem;
137 }
138
139 void IMB_freezbufImBuf(ImBuf *ibuf)
140 {
141         if(ibuf==NULL) return;
142
143         if(ibuf->zbuf && (ibuf->mall & IB_zbuf))
144                 MEM_freeN(ibuf->zbuf);
145
146         ibuf->zbuf= NULL;
147         ibuf->mall &= ~IB_zbuf;
148 }
149
150 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
151 {
152         if(ibuf==NULL) return;
153
154         if(ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat))
155                 MEM_freeN(ibuf->zbuf_float);
156
157         ibuf->zbuf_float= NULL;
158         ibuf->mall &= ~IB_zbuffloat;
159 }
160
161 void IMB_freeImBuf(ImBuf *ibuf)
162 {
163         if(ibuf) {
164                 if(ibuf->refcounter > 0) {
165                         ibuf->refcounter--;
166                 }
167                 else {
168                         imb_freerectImBuf(ibuf);
169                         imb_freerectfloatImBuf(ibuf);
170                         imb_freetilesImBuf(ibuf);
171                         IMB_freezbufImBuf(ibuf);
172                         IMB_freezbuffloatImBuf(ibuf);
173                         freeencodedbufferImBuf(ibuf);
174                         IMB_cache_limiter_unmanage(ibuf);
175                         IMB_metadata_free(ibuf);
176                         MEM_freeN(ibuf);
177                 }
178         }
179 }
180
181 void IMB_refImBuf(ImBuf *ibuf)
182 {
183         ibuf->refcounter++;
184 }
185
186 short addzbufImBuf(ImBuf *ibuf)
187 {
188         int size;
189         
190         if(ibuf==NULL) return FALSE;
191         
192         IMB_freezbufImBuf(ibuf);
193         
194         size = ibuf->x *ibuf->y *sizeof(unsigned int);
195         if((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
196                 ibuf->mall |= IB_zbuf;
197                 ibuf->flags |= IB_zbuf;
198                 return TRUE;
199         }
200         
201         return FALSE;
202 }
203
204 short addzbuffloatImBuf(ImBuf *ibuf)
205 {
206         int size;
207         
208         if(ibuf==NULL) return FALSE;
209         
210         IMB_freezbuffloatImBuf(ibuf);
211         
212         size = ibuf->x *ibuf->y *sizeof(float);
213         if((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
214                 ibuf->mall |= IB_zbuffloat;
215                 ibuf->flags |= IB_zbuffloat;
216                 return TRUE;
217         }
218         
219         return FALSE;
220 }
221
222
223 short imb_addencodedbufferImBuf(ImBuf *ibuf)
224 {
225         if(ibuf==NULL) return FALSE;
226
227         freeencodedbufferImBuf(ibuf);
228
229         if(ibuf->encodedbuffersize == 0) 
230                 ibuf->encodedbuffersize = 10000;
231
232         ibuf->encodedsize = 0;
233
234         if((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
235                 ibuf->mall |= IB_mem;
236                 ibuf->flags |= IB_mem;
237                 return TRUE;
238         }
239
240         return FALSE;
241 }
242
243
244 short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
245 {
246         unsigned int newsize, encodedsize;
247         void *newbuffer;
248
249         if(ibuf==NULL) return FALSE;
250
251         if(ibuf->encodedbuffersize < ibuf->encodedsize) {
252                 printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
253                 return FALSE;
254         }
255
256         newsize = 2 *ibuf->encodedbuffersize;
257         if(newsize < 10000) newsize = 10000;
258
259         newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
260         if(newbuffer == NULL) return FALSE;
261
262         if(ibuf->encodedbuffer) {
263                 memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
264         } else {
265                 ibuf->encodedsize = 0;
266         }
267
268         encodedsize = ibuf->encodedsize;
269
270         freeencodedbufferImBuf(ibuf);
271
272         ibuf->encodedbuffersize = newsize;
273         ibuf->encodedsize = encodedsize;
274         ibuf->encodedbuffer = newbuffer;
275         ibuf->mall |= IB_mem;
276         ibuf->flags |= IB_mem;
277
278         return TRUE;
279 }
280
281 short imb_addrectfloatImBuf(ImBuf *ibuf)
282 {
283         int size;
284         
285         if(ibuf==NULL) return FALSE;
286         
287         if(ibuf->rect_float)
288                 imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
289         
290         size = ibuf->x *ibuf->y;
291         size = size *4 *sizeof(float);
292         ibuf->channels= 4;
293         
294         if((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
295                 ibuf->mall |= IB_rectfloat;
296                 ibuf->flags |= IB_rectfloat;
297                 return TRUE;
298         }
299         
300         return FALSE;
301 }
302
303 /* question; why also add zbuf? */
304 short imb_addrectImBuf(ImBuf *ibuf)
305 {
306         int size;
307
308         if(ibuf==NULL) return FALSE;
309         
310         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
311         if(ibuf->rect && (ibuf->mall & IB_rect))
312                 MEM_freeN(ibuf->rect);
313         ibuf->rect= NULL;
314         
315         size = ibuf->x*ibuf->y;
316         size = size*sizeof(unsigned int);
317
318         if((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
319                 ibuf->mall |= IB_rect;
320                 ibuf->flags |= IB_rect;
321                 if(ibuf->depth > 32) return (addzbufImBuf(ibuf));
322                 else return TRUE;
323         }
324
325         return FALSE;
326 }
327
328 short imb_addtilesImBuf(ImBuf *ibuf)
329 {
330         if(ibuf==NULL) return FALSE;
331
332         if(!ibuf->tiles)
333                 if((ibuf->tiles = MEM_callocN(sizeof(unsigned int*)*ibuf->xtiles*ibuf->ytiles, "imb_tiles")))
334                         ibuf->mall |= IB_tiles;
335
336         return (ibuf->tiles != NULL);
337 }
338
339 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar d, unsigned int flags)
340 {
341         ImBuf *ibuf;
342
343         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
344
345         if(ibuf) {
346                 ibuf->x= x;
347                 ibuf->y= y;
348                 ibuf->depth= d;
349                 ibuf->ftype= TGA;
350                 ibuf->channels= 4;      /* float option, is set to other values when buffers get assigned */
351                 ibuf->ppm[0]= ibuf->ppm[1]= 150.0 / 0.0254; /* 150dpi -> pixels-per-meter */
352                 
353                 if(flags & IB_rect) {
354                         if(imb_addrectImBuf(ibuf)==FALSE) {
355                                 IMB_freeImBuf(ibuf);
356                                 return NULL;
357                         }
358                 }
359                 
360                 if(flags & IB_rectfloat) {
361                         if(imb_addrectfloatImBuf(ibuf)==FALSE) {
362                                 IMB_freeImBuf(ibuf);
363                                 return NULL;
364                         }
365                 }
366                 
367                 if(flags & IB_zbuf) {
368                         if(addzbufImBuf(ibuf)==FALSE) {
369                                 IMB_freeImBuf(ibuf);
370                                 return NULL;
371                         }
372                 }
373                 
374                 if(flags & IB_zbuffloat) {
375                         if(addzbuffloatImBuf(ibuf)==FALSE) {
376                                 IMB_freeImBuf(ibuf);
377                                 return NULL;
378                         }
379                 }
380         }
381         return (ibuf);
382 }
383
384 /* does no zbuffers? */
385 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
386 {
387         ImBuf *ibuf2, tbuf;
388         int flags = 0;
389         int a, x, y;
390         
391         if(ibuf1 == NULL) return NULL;
392
393         if(ibuf1->rect) flags |= IB_rect;
394         if(ibuf1->rect_float) flags |= IB_rectfloat;
395
396         x = ibuf1->x;
397         y = ibuf1->y;
398         if(ibuf1->flags & IB_fields) y *= 2;
399         
400         ibuf2 = IMB_allocImBuf(x, y, ibuf1->depth, flags);
401         if(ibuf2 == NULL) return NULL;
402
403         if(flags & IB_rect)
404                 memcpy(ibuf2->rect, ibuf1->rect, x *y *sizeof(int));
405         
406         if(flags & IB_rectfloat)
407                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels *x *y *sizeof(float));
408
409         if(ibuf1->encodedbuffer) {
410                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
411                 if(imb_addencodedbufferImBuf(ibuf2) == FALSE) {
412                         IMB_freeImBuf(ibuf2);
413                         return NULL;
414                 }
415
416                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
417         }
418
419         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
420         tbuf = *ibuf1;
421         
422         // fix pointers 
423         tbuf.rect               = ibuf2->rect;
424         tbuf.rect_float = ibuf2->rect_float;
425         tbuf.encodedbuffer = ibuf2->encodedbuffer;
426         tbuf.zbuf= NULL;
427         tbuf.zbuf_float= NULL;
428         for(a=0; a<IB_MIPMAP_LEVELS; a++)
429                 tbuf.mipmap[a]= NULL;
430         
431         // set malloc flag
432         tbuf.mall               = ibuf2->mall;
433         tbuf.c_handle           = NULL;
434         tbuf.refcounter         = 0;
435
436         // for now don't duplicate metadata
437         tbuf.metadata = NULL;
438
439         *ibuf2 = tbuf;
440         
441         return(ibuf2);
442 }
443
444 /* support for cache limiting */
445
446 static void imbuf_cache_destructor(void *data)
447 {
448         ImBuf *ibuf = (ImBuf*) data;
449
450         imb_freerectImBuf(ibuf);
451         imb_freerectfloatImBuf(ibuf);
452         IMB_freezbufImBuf(ibuf);
453         IMB_freezbuffloatImBuf(ibuf);
454         freeencodedbufferImBuf(ibuf);
455
456         ibuf->c_handle = NULL;
457 }
458
459 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
460 {
461         static MEM_CacheLimiterC *c = NULL;
462
463         if(!c)
464                 c = new_MEM_CacheLimiter(imbuf_cache_destructor);
465
466         return &c;
467 }
468
469 void IMB_free_cache_limiter(void)
470 {
471         delete_MEM_CacheLimiter(*get_imbuf_cache_limiter());
472         *get_imbuf_cache_limiter() = NULL;
473 }
474
475 void IMB_cache_limiter_insert(ImBuf *i)
476 {
477         if(!i->c_handle) {
478                 i->c_handle = MEM_CacheLimiter_insert(
479                         *get_imbuf_cache_limiter(), i);
480                 MEM_CacheLimiter_ref(i->c_handle);
481                 MEM_CacheLimiter_enforce_limits(
482                         *get_imbuf_cache_limiter());
483                 MEM_CacheLimiter_unref(i->c_handle);
484         }
485 }
486
487 void IMB_cache_limiter_unmanage(ImBuf *i)
488 {
489         if(i->c_handle) {
490                 MEM_CacheLimiter_unmanage(i->c_handle);
491                 i->c_handle = NULL;
492         }
493 }
494
495 void IMB_cache_limiter_touch(ImBuf *i)
496 {
497         if(i->c_handle)
498                 MEM_CacheLimiter_touch(i->c_handle);
499 }
500
501 void IMB_cache_limiter_ref(ImBuf *i)
502 {
503         if(i->c_handle)
504                 MEM_CacheLimiter_ref(i->c_handle);
505 }
506
507 void IMB_cache_limiter_unref(ImBuf *i)
508 {
509         if(i->c_handle)
510                 MEM_CacheLimiter_unref(i->c_handle);
511 }
512
513 int IMB_cache_limiter_get_refcount(ImBuf *i)
514 {
515         if(i->c_handle)
516                 return MEM_CacheLimiter_get_refcount(i->c_handle);
517
518         return 0;
519 }
520