style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / imbuf / intern / cineon / dpxlib.c
1 /** \file blender/imbuf/intern/cineon/dpxlib.c
2  *  \ingroup imbcineon
3  */
4 /*
5  *       Dpx image file format library routines.
6  *
7  *       Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
8  *
9  *       This program is free software; you can redistribute it and/or modify it
10  *       under the terms of the GNU General Public License as published by the Free
11  *       Software Foundation; either version 2 of the License, or (at your option)
12  *       any later version.
13  *
14  *       This program is distributed in the hope that it will be useful, but
15  *       WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  *       or FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
17  *       for more details.
18  *
19  *       You should have received a copy of the GNU General Public License
20  *       along with this program; if not, write to the Free Software
21  *       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "dpxfile.h"
26 #include "dpxlib.h"
27
28 #include <stdio.h>
29 #include <math.h>
30 #include <stdlib.h>
31 #include <time.h>                                /* strftime() */
32 #include <sys/types.h>
33 #ifdef WIN32
34 #include <winsock.h>
35 #else
36 #include <netinet/in.h>  /* htonl() */
37 #endif
38 #include <string.h>                      /* memset */
39 #include "cin_debug_stuff.h"
40 #include "logmemfile.h"
41 #include "BLI_fileops.h"
42
43 static void
44 fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) {
45
46         (void)dpx; /* unused */
47         
48         chan->signage = 0;
49         chan->ref_low_data = htonl(0);
50         chan->ref_low_quantity = htonf(0.0);
51         chan->ref_high_data = htonl(1023);
52         chan->ref_high_quantity = htonf(2.046);
53         chan->designator1 = des;
54         chan->transfer_characteristics = 0;
55         chan->colourimetry = 0;
56         chan->bits_per_pixel = 10;
57         chan->packing = htons(1);
58         chan->encoding = 0;
59         chan->data_offset = 0;
60         chan->line_padding = htonl(0);
61         chan->channel_padding = htonl(0);
62         chan->description[0] = 0;
63 }
64
65 static void
66 dumpDpxChannelInfo(DpxChannelInformation* chan) {
67         d_printf("      Signage %ld", (intptr_t)ntohl(chan->signage));
68         d_printf("      Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
69         d_printf("      Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
70         d_printf("      Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
71         d_printf("      Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
72         d_printf("      Designator1: %d,", chan->designator1);
73         d_printf("      Bits per pixel %d\n", chan->bits_per_pixel);
74         d_printf("      Packing: %d,", ntohs(chan->packing));
75         d_printf("      Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset));
76 }
77
78 static void
79 fillDpxFileInfo(
80         DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) {
81
82         time_t fileClock;
83         struct tm* fileTime;
84
85         /* Note: always write files in network order */
86         /* By the spec, it shouldn't matter, but ... */
87
88         fileInfo->magic_num = htonl(DPX_FILE_MAGIC);
89         fileInfo->offset = htonl(dpx->imageOffset);
90         strcpy(fileInfo->vers, "v1.0");
91         fileInfo->file_size = htonl(dpx->imageOffset +
92                 pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4);
93         fileInfo->ditto_key = 0;
94         fileInfo->gen_hdr_size = htonl(
95                 sizeof(DpxFileInformation) +
96                 sizeof(DpxImageInformation) +
97                 sizeof(DpxOriginationInformation));
98         fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation));
99         fileInfo->user_data_size = 0;
100         strncpy(fileInfo->file_name, filename, 99);
101         fileInfo->file_name[99] = 0;
102
103         fileClock = time(0);
104         fileTime = localtime(&fileClock);
105         strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
106         /* Question: is %Z in strftime guaranteed to return 3 chars? */
107         fileInfo->create_date[23] = 0;
108
109         strcpy(fileInfo->creator, "David's DPX writer");
110         fileInfo->project[0] = 0;
111         fileInfo->copyright[0] = 0;
112         fileInfo->key = 0xFFFFFFFF; /* same in any byte order */
113 }
114
115 static void
116 dumpDpxFileInfo(DpxFileInformation* fileInfo) {
117         d_printf("\n--File Information--\n");
118         d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num));
119         d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset));
120         d_printf("Version \"%s\"\n", fileInfo->vers);
121         d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
122         d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key));
123         d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
124         d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
125         d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
126         d_printf("File name \"%s\"\n", fileInfo->file_name);
127         d_printf("Creation date \"%s\"\n", fileInfo->create_date);
128         d_printf("Creator \"%s\"\n", fileInfo->creator);
129         d_printf("Project \"%s\"\n", fileInfo->project);
130         d_printf("Copyright \"%s\"\n", fileInfo->copyright);
131         d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key));
132 }
133
134 static void
135 fillDpxImageInfo(
136         DpxFile* dpx, DpxImageInformation* imageInfo) {
137         imageInfo->orientation = 0;
138         imageInfo->channels_per_image = htons(1);
139         imageInfo->pixels_per_line = htonl(dpx->width);
140         imageInfo->lines_per_image = htonl(dpx->height);
141
142         if (dpx->depth == 1) {
143                 fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0);
144
145         }
146         else if (dpx->depth == 3) {
147                 fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50);
148         }
149 }
150
151 static void
152 dumpDpxImageInfo(DpxImageInformation* imageInfo) {
153
154         int n;
155         int i;
156         d_printf("\n--Image Information--\n");
157         d_printf("Image orientation %d,", ntohs(imageInfo->orientation));
158         n = ntohs(imageInfo->channels_per_image);
159         d_printf("Channels %d\n", n);
160         d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line));
161         d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image));
162         for (i = 0; i < n; ++i) {
163                 d_printf("      --Channel %d--\n", i);
164                 dumpDpxChannelInfo(&imageInfo->channel[i]);
165         }
166 }
167
168 static void
169 fillDpxOriginationInfo(
170         DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo)
171 {
172         /* unused */
173         (void)dpx;
174         (void)originInfo;
175         (void)fileInfo;
176 }
177
178 static void
179 dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) {
180         d_printf("\n--Origination Information--\n");
181         d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
182         d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
183         d_printf("X centre %f\n", ntohf(originInfo->x_centre));
184         d_printf("Y centre %f\n", ntohf(originInfo->y_centre));
185         d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size));
186         d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size));
187         d_printf("File name \"%s\"\n", originInfo->file_name);
188         d_printf("Creation time \"%s\"\n", originInfo->creation_time);
189         d_printf("Input device \"%s\"\n", originInfo->input_device);
190         d_printf("Serial number \"%s\"\n", originInfo->input_serial_number);
191 }
192
193 static void
194 initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) {
195         memset(header, 0, sizeof(DpxMainHeader));
196         fillDpxFileInfo(dpx, &header->fileInfo, shortFilename);
197         fillDpxImageInfo(dpx, &header->imageInfo);
198         fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo);
199 #if 0
200         fillDpxMPIInfo(dpx, &header->filmHeader);
201 #endif
202 }
203
204 static void
205 dumpDpxMainHeader(DpxMainHeader* header) {
206         dumpDpxFileInfo(&header->fileInfo);
207         dumpDpxImageInfo(&header->imageInfo);
208         dumpDpxOriginationInfo(&header->originInfo);
209 #if 0
210         dumpDpxMPIInformation(&header->filmHeader);
211 #endif
212 }
213
214 static int verbose = 0;
215 void
216 dpxSetVerbose(int verbosity) {
217         verbose = verbosity;
218 }
219
220 static void
221 verboseMe(DpxFile* dpx) {
222
223         d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth);
224         d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
225                 dpx->imageOffset, dpx->lineBufferLength * 4,
226                 dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4);
227 }
228
229 int
230 dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) {
231
232         /* Note: this code is bizarre because DPX files can wrap */
233         /* packed longwords across line boundaries!!!! */
234
235         size_t readLongs;
236         unsigned int longIndex;
237         int numPixels = dpx->width * dpx->depth;
238         int pixelIndex;
239
240         /* only seek if not reading consecutive lines */
241         /* this is not quite right yet, need to account for leftovers */
242         if (y != dpx->fileYPos) {
243                 int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
244                 if (verbose) d_printf("Seek in getRowBytes\n");
245                 if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
246                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
247                         return 1;
248                 }
249                 dpx->fileYPos = y;
250         }
251
252         /* read enough longwords */
253         readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed);
254         if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) {
255                 if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4);
256                 return 1;
257         }
258         ++dpx->fileYPos;
259
260         /* convert longwords to pixels */
261         pixelIndex = dpx->pixelBufferUsed;
262
263         /* this is just strange */
264         if (dpx->depth == 1) {
265                 for (longIndex = 0; longIndex < readLongs; ++longIndex) {
266                         unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
267                         dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
268                         t = t >> 10;
269                         dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
270                         t = t >> 10;
271                         dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
272                         pixelIndex += 3;
273                 }
274         }
275         else /* if (dpx->depth == 3) */ {
276                 for (longIndex = 0; longIndex < readLongs; ++longIndex) {
277                         unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
278                         t = t >> 2;
279                         dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
280                         t = t >> 10;
281                         dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
282                         t = t >> 10;
283                         dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
284                         pixelIndex += 3;
285                 }
286         }
287         dpx->pixelBufferUsed = pixelIndex;
288
289         /* extract required pixels */
290         for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
291                 if (dpx->params.doLogarithm)
292                         row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]];
293                 else
294                         row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
295         }
296
297         /* save remaining pixels */
298         while (pixelIndex < dpx->pixelBufferUsed) {
299                 dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex];
300                 ++pixelIndex;
301         }
302         dpx->pixelBufferUsed -= numPixels;
303
304         /* done! */
305         return 0;
306 }
307
308 int
309 dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) {
310
311         /* Note: this code is bizarre because DPX files can wrap */
312         /* packed longwords across line boundaries!!!! */
313
314         size_t writeLongs;
315         int longIndex;
316         int numPixels = dpx->width * dpx->depth;
317         int pixelIndex;
318         int pixelIndex2;
319
320         /* only seek if not reading consecutive lines */
321         /* this is not quite right yet */
322         if (y != dpx->fileYPos) {
323                 int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
324                 if (verbose) d_printf("Seek in getRowBytes\n");
325                 if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
326                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
327                         return 1;
328                 }
329                 dpx->fileYPos = y;
330         }
331
332         /* put new pixels into pixelBuffer */
333         for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
334                 if (dpx->params.doLogarithm)
335                         dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]];
336                 else
337                         dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
338         }
339         dpx->pixelBufferUsed += numPixels;
340
341         /* pack into longwords */
342         writeLongs = dpx->pixelBufferUsed / 3;
343         /* process whole line at image end */
344         if (dpx->fileYPos == (dpx->height - 1)) {
345                 writeLongs = pixelsToLongs(dpx->pixelBufferUsed);
346         }
347         pixelIndex = 0;
348         if (dpx->depth == 1) {
349                 for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
350                         unsigned int t = dpx->pixelBuffer[pixelIndex] |
351                                         (dpx->pixelBuffer[pixelIndex+1] << 10) |
352                                         (dpx->pixelBuffer[pixelIndex+2] << 20);
353                         dpx->lineBuffer[longIndex] = htonl(t);
354                         pixelIndex += 3;
355                 }
356         }
357         else {
358                 for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
359                         unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 |
360                                         (dpx->pixelBuffer[pixelIndex+1] << 12) |
361                                         (dpx->pixelBuffer[pixelIndex] << 22);
362                         dpx->lineBuffer[longIndex] = htonl(t);
363                         pixelIndex += 3;
364                 }
365         }
366
367         /* write them */
368         if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) {
369                 if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4);
370                 return 1;
371         }
372         ++dpx->fileYPos;
373
374         /* save remaining pixels */
375         pixelIndex2 = 0;
376         while (pixelIndex < dpx->pixelBufferUsed) {
377                 dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex];
378                 ++pixelIndex;
379                 ++pixelIndex2;
380         }
381         dpx->pixelBufferUsed = pixelIndex2;
382
383         return 0;
384 }
385
386 #define LFMEMFILE       0
387 #define LFREALFILE      1
388
389 static DpxFile* 
390 intern_dpxOpen(int mode, const char* bytestuff, int bufsize) {
391
392         DpxMainHeader header;
393         const char *filename = bytestuff;
394         DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
395         
396         if (dpx == 0) {
397                 if (verbose) d_printf("Failed to malloc dpx file structure.\n");
398                 return 0;
399         }
400
401         /* for close routine */
402         dpx->file = 0;
403         dpx->lineBuffer = 0;
404         dpx->pixelBuffer = 0;
405
406         if (mode == LFREALFILE) {
407                 filename = bytestuff;
408                 dpx->file = BLI_fopen(filename, "rb");
409                 if (dpx->file == 0) {   
410                         if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
411                         dpxClose(dpx);
412                         return 0;
413                 }
414                 dpx->membuffer = 0;
415                 dpx->memcursor = 0;
416                 dpx->membuffersize = 0;
417         }
418         else if (mode == LFMEMFILE) {
419                 dpx->membuffer = (unsigned char *)bytestuff;
420                 dpx->memcursor = (unsigned char *)bytestuff;
421                 dpx->membuffersize = bufsize;
422         }
423         
424         dpx->reading = 1;
425
426         if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
427                 if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
428                 dpxClose(dpx);
429                 return 0;
430         }
431
432         /* let's assume dpx files are always network order */
433         if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) {
434                 if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
435                         (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
436                 dpxClose(dpx);
437                 return 0;
438         }
439
440         if (ntohs(header.imageInfo.channel[0].packing) != 1) {
441                 if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing);
442                 dpxClose(dpx);
443                 return 0;
444         }
445
446
447         dpx->width = ntohl(header.imageInfo.pixels_per_line);
448         dpx->height = ntohl(header.imageInfo.lines_per_image);
449         dpx->depth = ntohs(header.imageInfo.channels_per_image);
450         /* Another DPX vs Cineon wierdness */
451         if (dpx->depth == 1) {
452                 switch (header.imageInfo.channel[0].designator1) {
453                 case 50: dpx->depth = 3; break;
454                 case 51: dpx->depth = 4; break;
455                 case 52: dpx->depth = 4; break;
456                 default: break;
457                 }
458         }
459         /* dpx->bitsPerPixel = 10; */
460         dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
461         if (dpx->bitsPerPixel != 10) {
462                 if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel);
463                 dpxClose(dpx);
464                 return 0;
465         }
466
467         dpx->imageOffset = ntohl(header.fileInfo.offset);
468         dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
469         dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
470         if (dpx->lineBuffer == 0) {
471                 if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
472                 dpxClose(dpx);
473                 return 0;
474         }
475
476         /* could have 2 pixels left over */
477         dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
478         if (dpx->pixelBuffer == 0) {
479                 if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
480                                 (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
481                 dpxClose(dpx);
482                 return 0;
483         }
484         dpx->pixelBufferUsed = 0;
485
486         if (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) {
487                 if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset);
488                 dpxClose(dpx);
489                 return 0;
490         }
491         dpx->fileYPos = 0;
492
493         logImageGetByteConversionDefaults(&dpx->params);
494         /* The SMPTE define this code:
495          *  0 - User-defined
496          *  1 - Printing density
497          *  2 - Linear
498          *  3 - Logarithmic
499          *  4 - Unspecified video
500          *  5 - SMPTE 240M
501          *  6 - CCIR 709-1
502          *  7 - CCIR 601-2 system B or G
503          *  8 - CCIR 601-2 system M
504          *  9 - NTSC composite video
505          *  10 - PAL composite video
506          *  11 - Z linear
507          *  12 - homogeneous
508          *
509          * Note that transfer_characteristics is U8, don't need
510          * check the byte order.
511          */
512         
513         switch (header.imageInfo.channel[0].transfer_characteristics) {
514                 case 1:
515                 case 2: /* linear */
516                         dpx->params.doLogarithm= 0;
517                         break;
518                 
519                 case 3:
520                         dpx->params.doLogarithm= 1;
521                         break;
522                 
523                 /* TODO - Unsupported, but for now just load them,
524                  * colors may look wrong, but can solve color conversion later
525                  */
526                 case 4: 
527                 case 5:
528                 case 6:
529                 case 7:
530                 case 8:
531                 case 9:
532                 case 10:
533                 case 11:
534                 case 12:
535                         if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics);
536                         dpx->params.doLogarithm= 0;
537                         break;
538                 default:
539                         if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics);
540                         dpxClose(dpx);
541                         return 0;
542                         break;
543         }
544         setupLut(dpx);
545
546         dpx->getRow = &dpxGetRowBytes;
547         dpx->setRow = 0;
548         dpx->close = &dpxClose;
549
550         if (verbose) {
551                 verboseMe(dpx);
552         }
553
554         return dpx;
555 }
556
557 DpxFile* 
558 dpxOpen(const char *filename) {
559         return intern_dpxOpen(LFREALFILE, filename, 0);
560 }
561
562 DpxFile* 
563 dpxOpenFromMem(unsigned char *buffer, unsigned int size) {
564         return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size);
565 }
566
567 int 
568 dpxIsMemFileCineon(void *buffer) {
569         int magicnum = 0;
570         magicnum = *((int*)buffer);
571         if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1;
572         else return 0;
573 }
574
575 DpxFile*
576 dpxCreate(const char* filename, int width, int height, int depth) {
577
578         /* Note: always write files in network order */
579         /* By the spec, it shouldn't matter, but ... */
580
581         DpxMainHeader header;
582         const char* shortFilename = 0;
583
584         DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
585         if (dpx == 0) {
586                 if (verbose) d_printf("Failed to malloc dpx file structure.\n");
587                 return 0;
588         }
589
590         memset(&header, 0, sizeof(header));
591
592         /* for close routine */
593         dpx->file = 0;
594         dpx->lineBuffer = 0;
595         dpx->pixelBuffer = 0;
596
597         dpx->file = BLI_fopen(filename, "wb");
598         if (dpx->file == 0) {
599                 if (verbose) d_printf("Couldn't open file %s\n", filename);
600                 dpxClose(dpx);
601                 return 0;
602         }
603         dpx->reading = 0;
604
605         dpx->width = width;
606         dpx->height = height;
607         dpx->depth = depth;
608         dpx->bitsPerPixel = 10;
609         dpx->imageOffset = sizeof(DpxMainHeader);
610
611         dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
612         dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
613         if (dpx->lineBuffer == 0) {
614                 if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
615                 dpxClose(dpx);
616                 return 0;
617         }
618
619         dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
620         if (dpx->pixelBuffer == 0) {
621                 if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
622                                 (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
623                 dpxClose(dpx);
624                 return 0;
625         }
626         dpx->pixelBufferUsed = 0;
627
628         /* find trailing part of filename */
629         shortFilename = strrchr(filename, '/');
630         if (shortFilename == 0) {
631                 shortFilename = filename;
632         }
633         else {
634                 ++shortFilename;
635         }
636         initDpxMainHeader(dpx, &header, shortFilename);
637         logImageGetByteConversionDefaults(&dpx->params);
638         /* Need set the file type before write the header!
639          *  2 - Linear
640          *  3 - Logarithmic
641          *
642          * Note that transfer characteristics is U8, don't need
643          * check the byte order.
644          */
645         if (dpx->params.doLogarithm == 0)
646                 header.imageInfo.channel[0].transfer_characteristics= 2;
647         else
648                 header.imageInfo.channel[0].transfer_characteristics= 3;
649
650         if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
651                 if (verbose) d_printf("Couldn't write image header\n");
652                 dpxClose(dpx);
653                 return 0;
654         }
655         dpx->fileYPos = 0;
656         setupLut(dpx);
657
658         dpx->getRow = 0;
659         dpx->setRow = &dpxSetRowBytes;
660         dpx->close = &dpxClose;
661
662         return dpx;
663 }
664
665 void
666 dpxClose(DpxFile* dpx) {
667
668         if (dpx == 0) {
669                 return;
670         }
671
672         if (dpx->file) {
673                 fclose(dpx->file);
674                 dpx->file = 0;
675         }
676
677         if (dpx->lineBuffer) {
678                 free(dpx->lineBuffer);
679                 dpx->lineBuffer = 0;
680         }
681
682         if (dpx->pixelBuffer) {
683                 free(dpx->pixelBuffer);
684                 dpx->pixelBuffer = 0;
685         }
686
687         free(dpx);
688 }
689
690 void
691 dpxDump(const char* filename) {
692
693         DpxMainHeader header;
694         FILE* file;
695
696         file = BLI_fopen(filename, "rb");
697         if (file == 0) {
698                 d_printf("Failed to open file \"%s\".\n", filename);
699                 return;
700         }
701
702         if (fread(&header, sizeof(header), 1, file) == 0) {
703                 d_printf("Not enough data for header in \"%s\".\n", filename);
704                 fclose(file);
705                 return;
706         }
707
708         fclose(file);
709         dumpDpxMainHeader(&header);
710 }