Transform: brought back axis constraint default after extruding. When
[blender-staging.git] / source / blender / imbuf / intern / openexr.cpp
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL 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. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * Copyright by Gernot Ziegler <gz@lysator.liu.se>.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  *
31  */
32
33 #ifdef WITH_OPENEXR
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string>
38
39 #include <iostream>
40
41 #include <half.h>
42 #include <ImfVersion.h>
43 #include <ImathBox.h>
44 #include <ImfArray.h>
45 #include <ImfIO.h>
46 #include <ImfChannelList.h>
47 #include <ImfPixelType.h>
48 #include <ImfInputFile.h>
49 #include <ImfOutputFile.h>
50
51 using namespace Imf;
52 using namespace Imath;
53
54 extern "C"
55 {
56 #ifdef WIN32
57 #include "BLI_winstuff.h"
58 #endif
59 #include "BLI_blenlib.h"
60
61 #include "imbuf.h"
62 #include "imbuf_patch.h"
63
64 #include "IMB_imbuf_types.h"
65 #include "IMB_imbuf.h"
66
67 #include "IMB_allocimbuf.h"
68 #include "IMB_cmap.h"
69 }
70
71
72 int imb_is_a_openexr(void *mem)
73 {
74         return Imf::isImfMagic ((const char *)mem);
75 }
76
77
78 class Mem_IStream: public IStream
79 {
80         public:
81
82                 Mem_IStream (unsigned char *exrbuf, int exrsize):
83                 IStream("dummy"), _exrpos (0), _exrsize(exrsize)  { _exrbuf = exrbuf; }
84
85                 virtual bool  read (char c[], int n);
86                 virtual Int64 tellg ();
87                 virtual void  seekg (Int64 pos);
88                 virtual void  clear ();
89 //virtual ~Mem_IStream() {}; // unused
90
91         private:
92
93                 Int64 _exrpos;
94                 Int64 _exrsize;
95                 unsigned char *_exrbuf;
96 };
97
98 bool Mem_IStream::read (char c[], int n)
99 {
100         if (n + _exrpos <= _exrsize)
101         {
102                 memcpy(c, (void *)(&_exrbuf[_exrpos]), n);
103                 _exrpos += n;
104                 return true;
105         }
106         else
107                 return false;
108 }
109
110
111 Int64 Mem_IStream::tellg ()
112 {
113         return _exrpos;
114 }
115
116
117 void Mem_IStream::seekg (Int64 pos)
118 {
119         _exrpos = pos;
120 }
121
122
123 void Mem_IStream::clear ()
124 {
125 }
126
127
128 struct _RGBAZ
129 {
130         half r;
131         half g;
132         half b;
133         half a;
134         half z;
135 };
136
137 typedef struct _RGBAZ RGBAZ;
138
139 extern "C"
140 {
141         short imb_save_openexr(struct ImBuf *ibuf, char *name, int flags)
142         {
143                 int width = ibuf->x;
144                 int height = ibuf->y;
145                 int i;
146
147                                                                                                   // summarize
148                 int write_zbuf = (flags & IB_zbuf) && ibuf->zbuf != 0;
149
150                 printf("OpenEXR-save: Saving %s image of %d x %d\n",
151                         write_zbuf ? "RGBAZ" : "RGBA", width, height);
152
153                 try
154                 {
155                         Header header (width, height);
156                         header.channels().insert ("R", Channel (HALF));
157                         header.channels().insert ("G", Channel (HALF));
158                         header.channels().insert ("B", Channel (HALF));
159                         header.channels().insert ("A", Channel (HALF));
160                         if (write_zbuf)
161                                 header.channels().insert ("Z", Channel (HALF));
162
163                         FrameBuffer frameBuffer;
164                         OutputFile *file;
165
166                         if (flags & IB_mem)
167                         {
168                                 printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n");
169                                 imb_addencodedbufferImBuf(ibuf);
170                                 ibuf->encodedsize = 0;
171                                 return(0);
172                         }
173                         else
174                         {
175                                 printf("OpenEXR-save: Creating output file %s\n", name);
176                                 file = new OutputFile(name, header);
177                         }
178
179                         RGBAZ *pixels = new RGBAZ[height * width];
180
181                         int bytesperpixel = (ibuf->depth + 7) >> 3;
182                         if ((bytesperpixel > 4) || (bytesperpixel == 2))
183                         {
184                                 printf("OpenEXR-save: unsupported bytes per pixel: %d\n", bytesperpixel);
185                                 return (0);
186                         }
187
188                         frameBuffer.insert ("R",
189                                 Slice (HALF,
190                                 (char *) &pixels[0].r,
191                                 sizeof (pixels[0]) * 1,
192                                 sizeof (pixels[0]) * width));
193
194                         frameBuffer.insert ("G",
195                                 Slice (HALF,
196                                 (char *) &pixels[0].g,
197                                 sizeof (pixels[0]) * 1,
198                                 sizeof (pixels[0]) * width));
199
200                         frameBuffer.insert ("B",
201                                 Slice (HALF,
202                                 (char *) &pixels[0].b,
203                                 sizeof (pixels[0]) * 1,
204                                 sizeof (pixels[0]) * width));
205
206                         frameBuffer.insert ("A",
207                                 Slice (HALF,
208                                 (char *) &pixels[0].a,
209                                 sizeof (pixels[0]) * 1,
210                                 sizeof (pixels[0]) * width));
211
212                         if (write_zbuf)
213                                 frameBuffer.insert ("Z",
214                                         Slice (HALF,
215                                         (char *) &pixels[0].z,
216                                         sizeof (pixels[0]) * 1,
217                                         sizeof (pixels[0]) * width));
218
219                         if (!ibuf->rect_float)
220                         {
221                                 printf("OpenEXR-save: Converting Blender 8/8/8/8 pixels to OpenEXR format\n");
222
223                                 RGBAZ *to = pixels;
224                                 unsigned char *from = (unsigned char *) ibuf->rect;
225
226                                 for (i = ibuf->x * ibuf->y; i > 0; i--)
227                                 {
228                                         to->r = (float)(from[0])/255.0;
229                                         to->g = (float)(from[1])/255.0;
230                                         to->b = (float)(from[2])/255.0;
231                                         to->a = (float)(from[3])/255.0;
232                                         to++; from += 4;
233                                 }
234                         }
235                         else
236                         {
237                                 printf("OpenEXR-save: Converting Blender FLOAT pixels to OpenEXR format\n");
238
239                                 RGBAZ *to = pixels;
240                                 float *from = ibuf->rect_float;
241
242                                 for (i = ibuf->x * ibuf->y; i > 0; i--)
243                                 {
244                                         to->r = from[0];
245                                         to->g = from[1];
246                                         to->b = from[2];
247                                         to->a = from[3];
248                                         to++; from += 4;
249                                 }
250                         }
251
252                         if (write_zbuf)
253                         {
254                                 RGBAZ *to = pixels;
255                                 int *fromz = ibuf->zbuf;
256
257                                 for (int i = ibuf->x * ibuf->y; i > 0; i--)
258                                 {
259                                         to->z =  (0.5+((float)(*fromz/65536)/65536.0));
260                                         to++; fromz ++;
261                                 }
262                         }
263
264                         printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height);
265
266                         file->setFrameBuffer (frameBuffer);
267                         file->writePixels (height);
268                         delete file;
269                 }
270                 catch (const std::exception &exc)
271                 {
272                         printf("OpenEXR-save: ERROR: %s\n", exc.what());
273                         if (ibuf) IMB_freeImBuf(ibuf);
274
275                         return (0);
276                 }
277
278                 return (1);
279                 printf("OpenEXR-save: Done.\n");
280         }
281
282         struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags)
283         {
284                 struct ImBuf *ibuf = 0;
285
286                 printf("OpenEXR-load: testing input, size is %d\n", size);
287                 if (imb_is_a_openexr(mem) == 0) return(0);
288
289                 InputFile *file = NULL;
290
291                 try
292                 {
293                         printf("OpenEXR-load: Creating InputFile from mem source\n");
294                         Mem_IStream membuf(mem, size);
295                         file = new InputFile(membuf);
296
297                         Box2i dw = file->header().dataWindow();
298                         int width  = dw.max.x - dw.min.x + 1;
299                         int height = dw.max.y - dw.min.y + 1;
300
301                         printf("OpenEXR-load: image data window %d %d %d %d\n",
302                                 dw.min.x, dw.min.y, dw.max.x, dw.max.y);
303
304                         const ChannelList &channels = file->header().channels();
305
306                         for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
307                         {
308                                 const Channel &channel = i.channel();
309                                 printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
310                                 if (channel.type != 1)
311                                 {
312                                         printf("OpenEXR-load: Can only process HALF input !!\n");
313                                         return(NULL);
314                                 }
315                         }
316
317                         RGBAZ *pixels = new RGBAZ[height * width];
318
319                         FrameBuffer frameBuffer;
320
321                         frameBuffer.insert ("R",
322                                 Slice (HALF,
323                                 (char *) &pixels[0].r,
324                                 sizeof (pixels[0]) * 1,
325                                 sizeof (pixels[0]) * width));
326
327                         frameBuffer.insert ("G",
328                                 Slice (HALF,
329                                 (char *) &pixels[0].g,
330                                 sizeof (pixels[0]) * 1,
331                                 sizeof (pixels[0]) * width));
332
333                         frameBuffer.insert ("B",
334                                 Slice (HALF,
335                                 (char *) &pixels[0].b,
336                                 sizeof (pixels[0]) * 1,
337                                 sizeof (pixels[0]) * width));
338
339                         frameBuffer.insert ("A",
340                                 Slice (HALF,
341                                 (char *) &pixels[0].a,
342                                 sizeof (pixels[0]) * 1,
343                                 sizeof (pixels[0]) * width));
344
345 // FIXME ? Would be able to read Z data or other channels here !
346
347                         printf("OpenEXR-load: Reading pixel data\n");
348                         file->setFrameBuffer (frameBuffer);
349                         file->readPixels (dw.min.y, dw.max.y);
350
351                         printf("OpenEXR-load: Converting to Blender ibuf\n");
352
353                         int bytesperpixel = 4;                            // since OpenEXR fills in unknown channels
354                         ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0);
355
356                         if (ibuf)
357                         {
358                                 ibuf->ftype = PNG;
359                                 imb_addrectImBuf(ibuf);
360
361                                 if (!(flags & IB_test))
362                                 {
363                                         unsigned char *to = (unsigned char *) ibuf->rect;
364                                         RGBAZ *from = pixels;
365                                         RGBAZ prescale;
366
367                                         for (int i = ibuf->x * ibuf->y; i > 0; i--)
368                                         {
369                                                 to[0] = (unsigned char)(((float)from->r > 1.0) ? 1.0 : (float)from->r)  * 255;
370                                                 to[1] = (unsigned char)(((float)from->g > 1.0) ? 1.0 : (float)from->g)  * 255;
371                                                 to[2] = (unsigned char)(((float)from->b > 1.0) ? 1.0 : (float)from->b)  * 255;
372                                                 to[3] = (unsigned char)(((float)from->a > 1.0) ? 1.0 : (float)from->a)  * 255;
373                                                 to += 4; from++;
374                                         }
375                                 }
376
377                         }
378                         else
379                                 printf("Couldn't allocate memory for PNG image\n");
380
381                         printf("OpenEXR-load: Done\n");
382
383                         return(ibuf);
384                 }
385                 catch (const std::exception &exc)
386                 {
387                         std::cerr << exc.what() << std::endl;
388                         if (ibuf) IMB_freeImBuf(ibuf);
389
390                         return (0);
391                 }
392
393         }
394
395 }                                                                                                 // export "C"
396
397 #endif  // #ifdef WITH_OPENEXR