svn merge -r36583:36603 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / imbuf / intern / cineon / cineon_dpx.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * cineon.c
28  * contributors: joeedh
29  * I hearby donate this code and all rights to the Blender Foundation.
30  * $Id$
31  */
32
33 /** \file blender/imbuf/intern/cineon/cineon_dpx.c
34  *  \ingroup imbcineon
35  */
36
37  
38 #include <stdio.h>
39 #include <string.h> /*for memcpy*/
40
41 #include "logImageLib.h"
42 #include "cineonlib.h"
43 #include "dpxlib.h"
44
45 #include "IMB_imbuf_types.h"
46 #include "IMB_imbuf.h"
47 #include "IMB_filetype.h"
48
49 #include "BKE_global.h"
50
51 #include "MEM_guardedalloc.h"
52
53 #if 0
54 static void cineon_conversion_parameters(LogImageByteConversionParameters *params)
55 {
56 //      params->blackPoint = scene?scene->r.cineonblack:95;
57 //      params->whitePoint = scene?scene->r.cineonwhite:685;
58 //      params->gamma = scene?scene->r.cineongamma:1.7f;
59 //      params->doLogarithm = scene?scene->r.subimtype & R_CINEON_LOG:0;
60         
61         params->blackPoint = 95;
62         params->whitePoint = 685;
63         params->gamma = 1.0f;
64         params->doLogarithm = 0;
65 }
66 #endif
67
68 static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
69 {
70         ImBuf *ibuf;
71         LogImageFile *image;
72         int x, y;
73         unsigned short *row, *upix;
74         int width, height, depth;
75         float *frow;
76
77         logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
78         
79         image = logImageOpenFromMem(mem, size, use_cineon);
80         
81         if (!image) {
82                 printf("no image!\n");
83                 return NULL;
84         }
85         
86         logImageGetSize(image, &width, &height, &depth);
87         
88         if (depth != 3) { /*need to do greyscale loading eventually.*/
89                 logImageClose(image);
90                 return NULL;
91         }
92         
93         if (width == 0 && height == 0) {
94                 logImageClose(image);
95                 return NULL;
96         }
97         
98         ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
99
100         row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c");
101         frow = ibuf->rect_float+width*height*4;
102         
103         for (y = 0; y < height; y++) {
104                 logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */
105                 upix = row;
106                 frow -= width*4;
107                 
108                 for (x=0; x<width; x++) {
109                         *(frow++) = ((float)*(upix++)) / 65535.0f;
110                         *(frow++) = ((float)*(upix++)) / 65535.0f;
111                         *(frow++) = ((float)*(upix++)) / 65535.0f;
112                         *(frow++) = 1.0f;
113                 }
114                 frow -= width*4;
115         }
116
117         MEM_freeN(row);
118         logImageClose(image);
119         
120         if (flags & IB_rect) {
121                 IMB_rect_from_float(ibuf);
122         }
123         return ibuf;
124 }
125
126 static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
127 {
128         LogImageByteConversionParameters conversion;
129         const int width= ibuf->x;
130         const int height= ibuf->y;
131         const int depth= 3;
132         LogImageFile* logImage;
133         unsigned short* line, *pixel;
134         int i, j;
135         float *fline;
136         float *fbuf;
137         int is_alloc= 0;
138         
139         (void)flags; /* unused */
140
141         // cineon_conversion_parameters(&conversion);
142         logImageGetByteConversionDefaults(&conversion);
143
144         /*
145          * Get the drawable for the current image...
146          */
147
148         fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc);
149
150         if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */
151                 return 0;
152         }
153         
154         logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
155         logImage = logImageCreate(filename, use_cineon, width, height, depth);
156
157         if (!logImage) return 0;
158         
159         if(logImageSetByteConversion(logImage, &conversion)==0) {
160                 printf("error setting args\n");
161         }
162
163         line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line");
164         
165         /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/
166         for (j = 0; j < height; ++j) {
167                 fline = &fbuf[width*j*4];
168                 for (i=0; i<width; i++) {
169                         float *fpix, fpix2[3];
170                         /*we have to convert to cinepaint's 16-bit-per-channel here*/
171                         pixel = &line[i*depth];
172                         fpix = &fline[i*4];
173                         memcpy(fpix2, fpix, sizeof(float)*3);
174                         
175                         if (fpix2[0]>=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f;
176                         if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f;
177                         if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f;
178                         
179                         pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/
180                         pixel[1] = (unsigned short)(fpix2[1] * 65535.0f);
181                         pixel[2] = (unsigned short)(fpix2[2] * 65535.0f);
182                 }
183                 logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j);
184         }
185         logImageClose(logImage);
186
187         MEM_freeN(line);
188         
189         if(is_alloc) {
190                 MEM_freeN(fbuf);
191         }
192         
193         return 1;
194 }
195
196 int imb_savecineon(struct ImBuf *buf, const char *myfile, int flags)
197 {
198         return imb_save_dpx_cineon(buf, myfile, 1, flags);
199 }
200
201  
202 int imb_is_cineon(unsigned char *buf)
203 {
204         return cineonIsMemFileCineon(buf);
205 }
206
207 ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags)
208 {
209         if(imb_is_cineon(mem))
210                 return imb_load_dpx_cineon(mem, 1, size, flags);
211         return NULL;
212 }
213
214 int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
215 {
216         return imb_save_dpx_cineon(buf, myfile, 0, flags);
217 }
218
219 int imb_is_dpx(unsigned char *buf)
220 {
221         return dpxIsMemFileCineon(buf);
222 }
223
224 ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags)
225 {
226         if(imb_is_dpx(mem))
227                 return imb_load_dpx_cineon(mem, 0, size, flags);
228         return NULL;
229 }