svn merge -r 12937:13095 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., 59 Temple Place - Suite 330, Boston, MA        02111-1307, 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 #include <stdio.h>
34 #include <string.h> /*for memcpy*/
35
36 #include "logImageLib.h"
37 #include "cineonlib.h"
38 #include "dpxlib.h"
39
40 #include "IMB_imbuf_types.h"
41 #include "IMB_imbuf.h"
42
43 #include "MEM_guardedalloc.h"
44
45 static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
46 {
47         ImBuf *ibuf;
48         LogImageFile *image;
49         int x, y;
50         unsigned short *row, *upix;
51         int width, height, depth;
52         float *frow;
53         
54         image = logImageOpenFromMem(mem, size, use_cineon);
55         
56         if (!image) {
57                 printf("no image!\n");
58                 return NULL;
59         }
60         
61         logImageGetSize(image, &width, &height, &depth);
62         
63         if (depth != 3) { /*need to do greyscale loading eventually.*/
64                 logImageClose(image);
65                 return NULL;
66         }
67         
68         if (width == 0 && height == 0) {
69                 logImageClose(image);
70                 return NULL;
71         }
72         
73         ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags, 0);
74
75         row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c");
76         frow = ibuf->rect_float+width*height*4;
77         
78         for (y = 0; y < height; y++) {
79                 logImageGetRowBytes(image, row, y);
80                 upix = row;
81                 frow -= width*4;
82                 
83                 for (x=0; x<width; x++) {
84                         *(frow++) = ((float)*(upix++)) / 65535.0f;
85                         *(frow++) = ((float)*(upix++)) / 65535.0f;
86                         *(frow++) = ((float)*(upix++)) / 65535.0f;
87                         *(frow++) = 1.0f;
88                 }
89                 frow -= width*4;
90         }
91
92         MEM_freeN(row);
93         logImageClose(image);
94         
95         if (flags & IB_rect) {
96                 IMB_rect_from_float(ibuf);
97         }
98         return ibuf;
99 }
100
101 static int imb_save_dpx_cineon(ImBuf *buf, char *filename, int use_cineon, int flags)
102 {
103         LogImageByteConversionParameters conversion;
104         int width, height, depth;
105         LogImageFile* logImage;
106         unsigned short* line, *pixel;
107         int i, j;
108         int index;
109         float *fline;
110         
111         conversion.blackPoint = 95;
112         conversion.whitePoint = 685;
113         conversion.gamma = 1;
114         /*
115          * Get the drawable for the current image...
116          */
117
118         width = buf->x;
119         height = buf->y;
120         depth = 3;
121         
122         if (!buf->rect_float) return 0;
123         
124         logImageSetVerbose(0);
125         logImage = logImageCreate(filename, use_cineon, width, height, depth);
126
127         if (!logImage) return 0;
128         
129         logImageSetByteConversion(logImage, &conversion);
130
131         index = 0;
132         line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line");
133         
134         /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/
135         for (j = 0; j < height; ++j) {
136                 fline = &buf->rect_float[width*j*4];
137                 for (i=0; i<width; i++) {
138                         float *fpix, fpix2[3];
139                         /*we have to convert to cinepaint's 16-bit-per-channel here*/
140                         pixel = &line[i*depth];
141                         fpix = &fline[i*4];
142                         memcpy(fpix2, fpix, sizeof(float)*3);
143                         
144                         if (fpix2[0]>=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f;
145                         if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f;
146                         if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f;
147                         
148                         pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/
149                         pixel[1] = (unsigned short)(fpix2[1] * 65535.0f);
150                         pixel[2] = (unsigned short)(fpix2[2] * 65535.0f);
151                 }
152                 logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j);
153         }
154         logImageClose(logImage);
155
156         MEM_freeN(line);
157         return 1;
158 }
159
160 short imb_savecineon(struct ImBuf *buf, char *myfile, int flags)
161 {
162         return imb_save_dpx_cineon(buf, myfile, 1, flags);
163 }
164
165  
166 int imb_is_cineon(void *buf)
167 {
168         return cineonIsMemFileCineon(buf);
169 }
170
171 ImBuf *imb_loadcineon(unsigned char *mem, int size, int flags)
172 {
173         if(imb_is_cineon(mem))
174                 return imb_load_dpx_cineon(mem, 1, size, flags);
175         return NULL;
176 }
177
178 short imb_save_dpx(struct ImBuf *buf, char *myfile, int flags)
179 {
180         return imb_save_dpx_cineon(buf, myfile, 0, flags);
181 }
182
183 int imb_is_dpx(void *buf)
184 {
185         return dpxIsMemFileCineon(buf);
186 }
187
188 ImBuf *imb_loaddpx(unsigned char *mem, int size, int flags)
189 {
190         if(imb_is_dpx(mem))
191                 return imb_load_dpx_cineon(mem, 0, size, flags);
192         return NULL;
193 }