48bda418d82860045f5bed130dd82a1dc47cedeb
[blender-staging.git] / source / blender / imbuf / intern / cineon / cineon_dpx.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): Julien Enche.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * cineon.c
27  * contributors: joeedh, Julien Enche
28  * I hearby donate this code and all rights to the Blender Foundation.
29  * $Id$
30  */
31
32 /** \file blender/imbuf/intern/cineon/cineon_dpx.c
33  *  \ingroup imbcineon
34  */
35
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40 #include "logImageCore.h"
41
42 #include "IMB_imbuf_types.h"
43 #include "IMB_imbuf.h"
44 #include "IMB_filetype.h"
45
46 #include "IMB_colormanagement.h"
47 #include "IMB_colormanagement_intern.h"
48
49 #include "BKE_global.h"
50
51 #include "MEM_guardedalloc.h"
52
53 static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags,
54                                          char colorspace[IM_MAX_SPACE])
55 {
56         ImBuf *ibuf;
57         LogImageFile *image;
58         int width, height, depth;
59
60         colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
61
62         logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0);
63
64         image = logImageOpenFromMemory(mem, size);
65
66         if (image == 0) {
67                 printf("DPX/Cineon: error opening image.\n");
68                 return 0;
69         }
70
71         logImageGetSize(image, &width, &height, &depth);
72
73         ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
74         if (ibuf == 0) {
75                 logImageClose(image);
76                 return 0;
77         }
78
79         if (!(flags & IB_test)) {
80                 if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
81                         logImageClose(image);
82                         IMB_freeImBuf(ibuf);
83                         return 0;
84                 }
85                 IMB_flipy(ibuf);
86         }
87
88         logImageClose(image);
89         ibuf->ftype = use_cineon ? CINEON : DPX;
90
91         if (flags & IB_alphamode_detect)
92                 ibuf->flags |= IB_alphamode_premul;
93
94         return ibuf;
95 }
96
97 static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
98 {
99         LogImageFile *logImage;
100         float *fbuf;
101         float *fbuf_ptr;
102         unsigned char *rect_ptr;
103         int x, y, depth, bitspersample, rvalue;
104
105         if (flags & IB_mem) {
106                 printf("DPX/Cineon: saving in memory is not supported.\n");
107                 return 0;
108         }
109         
110         logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0);
111
112         depth = (ibuf->planes + 7) >> 3;
113         if (depth > 4 || depth < 3) {
114                 printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename);
115                 return 0;
116         }
117
118         if (ibuf->ftype & CINEON_10BIT)
119                 bitspersample = 10;
120         else if (ibuf->ftype & CINEON_12BIT)
121                 bitspersample = 12;
122         else if (ibuf->ftype & CINEON_16BIT)
123                 bitspersample = 16;
124         else
125                 bitspersample = 8;
126
127         logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4),
128                                   (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender");
129
130         if (logImage == 0) {
131                 printf("DPX/Cineon: error creating file.\n");
132                 return 0;
133         }
134
135         if (ibuf->rect_float != 0 && bitspersample != 8) {
136                 /* don't use the float buffer to save 8 bpp picture to prevent color banding
137                  * (there's no dithering algorithm behing the logImageSetDataRGBA function) */
138
139                 fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
140
141                 for (y = 0; y < ibuf->y; y++) {
142                         float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x);
143                         float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x);
144
145                         memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float));
146                 }
147
148                 rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0);
149
150                 MEM_freeN(fbuf);
151         }
152         else {
153                 if (ibuf->rect == 0)
154                         IMB_rect_from_float(ibuf);
155
156                 fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
157                 if (fbuf == 0) {
158                         printf("DPX/Cineon: error allocating memory.\n");
159                         logImageClose(logImage);
160                         return 0;
161                 }
162                 for (y = 0; y < ibuf->y; y++) {
163                         for (x = 0; x < ibuf->x; x++) {
164                                 fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x);
165                                 rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x);
166                                 fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f;
167                                 fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f;
168                                 fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f;
169                                 fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f;
170                         }
171                 }
172                 rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0);
173                 MEM_freeN(fbuf);
174         }
175
176         logImageClose(logImage);
177         return rvalue;
178 }
179
180 int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags)
181 {
182         return imb_save_dpx_cineon(buf, myfile, 1, flags);
183 }
184
185 int imb_is_cineon(unsigned char *buf)
186 {
187         return logImageIsCineon(buf);
188 }
189
190 ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
191 {
192         if (imb_is_cineon(mem))
193                 return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
194         return 0;
195 }
196
197 int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
198 {
199         return imb_save_dpx_cineon(buf, myfile, 0, flags);
200 }
201
202 int imb_is_dpx(unsigned char *buf)
203 {
204         return logImageIsDpx(buf);
205 }
206
207 ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
208 {
209         if (imb_is_dpx(mem))
210                 return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
211         return 0;
212 }