Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.git] / source / blender / imbuf / intern / cineon / cineonlib.c
1 /*
2  *       Cineon image file format library routines.
3  *
4  *       Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
5  *
6  *       This program is free software; you can redistribute it and/or modify it
7  *       under the terms of the GNU General Public License as published by the Free
8  *       Software Foundation; either version 2 of the License, or (at your option)
9  *       any later version.
10  *
11  *       This program is distributed in the hope that it will be useful, but
12  *       WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  *       or FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
14  *       for more details.
15  *
16  *       You should have received a copy of the GNU General Public License
17  *       along with this program; if not, write to the Free Software
18  *       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  */
21
22 /** \file blender/imbuf/intern/cineon/cineonlib.c
23  *  \ingroup imbcineon
24  */
25
26 #include "cineonlib.h"
27 #include "cineonfile.h"
28
29 #include <stdio.h>
30 #include <math.h>
31 #include <stdlib.h>
32 #include <time.h>                                /* strftime() */
33 #include <sys/types.h>
34 #ifdef WIN32
35 #include <winsock.h>
36 #else
37 #include <netinet/in.h>  /* htonl() */
38 #endif
39 #include <string.h>                      /* memset */
40
41 #include "BLI_utildefines.h"
42 #include "BLI_fileops.h"
43
44 #include "cin_debug_stuff.h"
45 #include "logmemfile.h"
46
47 static void
48 fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) {
49
50         time_t fileClock;
51         struct tm* fileTime;
52
53         fileInfo->magic_num = htonl(CINEON_FILE_MAGIC);
54         fileInfo->image_offset = htonl(cineon->imageOffset);
55         fileInfo->gen_hdr_size = htonl(
56                 sizeof(CineonFileInformation) +
57                 sizeof(CineonImageInformation) +
58                 sizeof(CineonFormatInformation) +
59                 sizeof(CineonOriginationInformation));
60         fileInfo->ind_hdr_size = 0;
61         fileInfo->user_data_size = 0;
62         fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength);
63         strcpy(fileInfo->vers, "V4.5");
64         strncpy(fileInfo->file_name, filename, 99);
65         fileInfo->file_name[99] = 0;
66
67         fileClock = time(0);
68         fileTime = localtime(&fileClock);
69         strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime);
70         /* Question: is %Z in strftime guaranteed to return 3 chars? */
71         strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime);
72         fileInfo->create_time[11] = 0;
73 }
74
75 static void
76 dumpCineonFileInfo(CineonFileInformation* fileInfo) {
77         d_printf("\n--File Information--\n");
78         d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num));
79         d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset));
80         d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
81         d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
82         d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
83         d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
84         d_printf("Version \"%s\"\n", fileInfo->vers);
85         d_printf("File name \"%s\"\n", fileInfo->file_name);
86         d_printf("Creation date \"%s\"\n", fileInfo->create_date);
87         d_printf("Creation time \"%s\"\n", fileInfo->create_time);
88 }
89
90 static void
91 fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) {
92
93         chan->designator1 = 0;
94         chan->designator2 = des;
95         chan->bits_per_pixel = 10;
96         chan->pixels_per_line = htonl(cineon->width);
97         chan->lines_per_image = htonl(cineon->height);
98         chan->ref_low_data = htonl(0);
99         chan->ref_low_quantity = htonf(0.0);
100         chan->ref_high_data = htonl(1023);
101         chan->ref_high_quantity = htonf(2.046);
102 }
103
104 static void
105 dumpCineonChannelInfo(CineonChannelInformation* chan) {
106         d_printf("      Metric selector: %d", chan->designator1);
107         switch (chan->designator1) {
108                 case 0: d_printf(" (Universal)\n"); break;
109                 default: d_printf(" (Vendor specific)\n"); break;
110         }
111         d_printf("      Metric: %d,", chan->designator2);
112         switch (chan->designator2) {
113                 case 0: d_printf(" B&W (printing density?)\n"); break;
114                 case 1: d_printf(" Red printing density\n"); break;
115                 case 2: d_printf(" Green printing density\n"); break;
116                 case 3: d_printf(" Blue printing density\n"); break;
117                 case 4: d_printf(" Red CCIR XA/11\n"); break;
118                 case 5: d_printf(" Green CCIR XA/11\n"); break;
119                 case 6: d_printf(" Blue CCIR XA/11\n"); break;
120                 default: d_printf(" (unknown)\n"); break;
121         }
122         d_printf("      Bits per pixel %d\n", chan->bits_per_pixel);
123         d_printf("      Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line));
124         d_printf("      Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image));
125         d_printf("      Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
126         d_printf("      Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
127         d_printf("      Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
128         d_printf("      Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
129 }
130
131 static void
132 fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) {
133
134         imageInfo->orientation = 0;
135         imageInfo->channels_per_image = cineon->depth;
136
137         if (cineon->depth == 1) {
138                 fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
139
140         }
141         else if (cineon->depth == 3) {
142                 fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1);
143                 fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2);
144                 fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3);
145         }
146
147         imageInfo->white_point_x = htonf(undefined());
148         imageInfo->white_point_y = htonf(undefined());
149         imageInfo->red_primary_x = htonf(undefined());
150         imageInfo->red_primary_y = htonf(undefined());
151         imageInfo->green_primary_x = htonf(undefined());
152         imageInfo->green_primary_y = htonf(undefined());
153         imageInfo->blue_primary_x = htonf(undefined());
154         imageInfo->blue_primary_y = htonf(undefined());
155
156         strcpy(imageInfo->label, "David's Cineon writer.");
157
158 }
159
160 static void
161 dumpCineonImageInfo(CineonImageInformation* imageInfo) {
162
163         int i;
164         d_printf("\n--Image Information--\n");
165         d_printf("Image orientation %d,", imageInfo->orientation);
166         switch (imageInfo->orientation) {
167                 case 0: d_printf(" LRTB\n"); break;
168                 case 1: d_printf(" LRBT\n"); break;
169                 case 2: d_printf(" RLTB\n"); break;
170                 case 3: d_printf(" RLBT\n"); break;
171                 case 4: d_printf(" TBLR\n"); break;
172                 case 5: d_printf(" TBRL\n"); break;
173                 case 6: d_printf(" BTLR\n"); break;
174                 case 7: d_printf(" BTRL\n"); break;
175                 default: d_printf(" (unknown)\n"); break;
176         }
177         d_printf("Channels %d\n", imageInfo->channels_per_image);
178         for (i = 0; i < imageInfo->channels_per_image; ++i) {
179                 d_printf("      --Channel %d--\n", i);
180                 dumpCineonChannelInfo(&imageInfo->channel[i]);
181         }
182
183         d_printf("White point x %f\n", ntohf(imageInfo->white_point_x));
184         d_printf("White point y %f\n", ntohf(imageInfo->white_point_y));
185         d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x));
186         d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y));
187         d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x));
188         d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y));
189         d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x));
190         d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y));
191         d_printf("Label \"%s\"\n", imageInfo->label);
192 }
193
194 static void
195 fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) {
196
197         (void)cineon; /* unused */
198         
199         formatInfo->interleave = 0;
200         formatInfo->packing = 5;
201         formatInfo->signage = 0;
202         formatInfo->sense = 0;
203         formatInfo->line_padding = htonl(0);
204         formatInfo->channel_padding = htonl(0);
205 }
206
207 static void
208 dumpCineonFormatInfo(CineonFormatInformation* formatInfo) {
209         d_printf("\n--Format Information--\n");
210         d_printf("Interleave %d,", formatInfo->interleave);
211         switch (formatInfo->interleave) {
212                 case 0: d_printf(" pixel interleave\n"); break;
213                 case 1: d_printf(" line interleave\n"); break;
214                 case 2: d_printf(" channel interleave\n"); break;
215                 default: d_printf(" (unknown)\n"); break;
216         }
217         d_printf("Packing %d,", formatInfo->packing);
218         if (formatInfo->packing & 0x80) { 
219                 d_printf(" multi pixel,");
220         }
221         else {
222                 d_printf(" single pixel,");
223         }
224         switch (formatInfo->packing & 0x7F) {
225                 case 0: d_printf(" tight\n"); break;
226                 case 1: d_printf(" byte packed left\n"); break;
227                 case 2: d_printf(" byte packed right\n"); break;
228                 case 3: d_printf(" word packed left\n"); break;
229                 case 4: d_printf(" word packed right\n"); break;
230                 case 5: d_printf(" long packed left\n"); break;
231                 case 6: d_printf(" long packed right\n"); break;
232                 default: d_printf(" (unknown)\n"); break;
233         }
234         d_printf("Sign %d,", formatInfo->signage);
235         if (formatInfo->signage) { 
236                 d_printf(" signed\n");
237         }
238         else {
239                 d_printf(" unsigned\n");
240         }
241         d_printf("Sense %d,", formatInfo->signage);
242         if (formatInfo->signage) { 
243                 d_printf(" negative\n");
244         }
245         else {
246                 d_printf(" positive\n");
247         }
248         d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding));
249         d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding));
250 }
251
252 static void
253 fillCineonOriginationInfo(CineonFile* cineon,
254         CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) {
255         
256         (void)cineon; /* unused */
257
258         originInfo->x_offset = htonl(0);
259         originInfo->y_offset = htonl(0);
260         strcpy(originInfo->file_name, fileInfo->file_name);
261         strcpy(originInfo->create_date, fileInfo->create_date);
262         strcpy(originInfo->create_time, fileInfo->create_time);
263         strncpy(originInfo->input_device, "David's Cineon writer", 64);
264         strncpy(originInfo->model_number, "Software", 32);
265         strncpy(originInfo->serial_number, "001", 32);
266         originInfo->x_input_samples_per_mm = htonf(undefined());
267         originInfo->y_input_samples_per_mm =    htonf(undefined());
268         /* this should probably be undefined, too */
269         originInfo->input_device_gamma = htonf(1.0);
270 }
271
272 static void
273 dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) {
274         d_printf("\n--Origination Information--\n");
275         d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
276         d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
277         d_printf("File name \"%s\"\n", originInfo->file_name);
278         d_printf("Creation date \"%s\"\n", originInfo->create_date);
279         d_printf("Creation time \"%s\"\n", originInfo->create_time);
280         d_printf("Input device \"%s\"\n", originInfo->input_device);
281         d_printf("Model number \"%s\"\n", originInfo->model_number);
282         d_printf("Serial number \"%s\"\n", originInfo->serial_number);
283         d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm));
284         d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm));
285         d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma));
286 }
287
288 static int
289 initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) {
290
291         fillCineonFileInfo(cineon, &header->fileInfo, imagename);
292         fillCineonImageInfo(cineon, &header->imageInfo);
293         fillCineonFormatInfo(cineon, &header->formatInfo);
294         fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo);
295
296         return 0;
297 }
298
299 static void
300 UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) {
301         dumpCineonFileInfo(&header->fileInfo);
302         dumpCineonImageInfo(&header->imageInfo);
303         dumpCineonFormatInfo(&header->formatInfo);
304         dumpCineonOriginationInfo(&header->originInfo);
305 }
306
307 static int verbose = 0;
308 void
309 cineonSetVerbose(int verbosity) {
310         verbose = verbosity;
311 }
312
313 static void
314 verboseMe(CineonFile* cineon) {
315
316         d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth);
317         d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
318                 cineon->imageOffset, cineon->lineBufferLength * 4,
319                 cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height);
320 }
321
322 int
323 cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
324
325         int longsRead;
326         int pixelIndex;
327         int longIndex;
328         int numPixels = cineon->width * cineon->depth;
329
330
331         /* only seek if not reading consecutive lines */
332         if (y != cineon->fileYPos) {
333                 int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
334                 if (verbose) d_printf("Seek in getRowBytes\n");
335                 if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
336                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
337                         return 1;
338                 }
339                 cineon->fileYPos = y;
340         }
341
342         longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
343         if (longsRead != cineon->lineBufferLength) {
344                 if (verbose) {
345                         d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
346                         perror("cineonGetRowBytes");
347                 }
348
349                 return 1;
350         }
351
352         /* remember where we left the car, honey */
353         ++cineon->fileYPos;
354
355         /* convert longwords to pixels */
356         pixelIndex = 0;
357         for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
358                 unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
359                 t = t >> 2;
360                 cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff;
361                 t = t >> 10;
362                 cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff;
363                 t = t >> 10;
364                 cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff;
365                 pixelIndex += 3;
366         }
367
368         /* extract required pixels */
369         for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
370                 if (cineon->params.doLogarithm)
371                         row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]];
372                 else
373                         row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
374         }
375
376         return 0;
377 }
378
379 int
380 cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
381
382         int pixelIndex;
383         int numPixels = cineon->width * cineon->depth;
384         int longIndex;
385         int longsWritten;
386
387         /* put new pixels into pixelBuffer */
388         for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
389                 if (cineon->params.doLogarithm)
390                         cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]];
391                 else
392                         cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
393         }
394
395         /* pack into longwords */
396         pixelIndex = 0;
397         for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
398                 unsigned int t =
399                                 (cineon->pixelBuffer[pixelIndex] << 22) |
400                                 (cineon->pixelBuffer[pixelIndex+1] << 12) |
401                                 (cineon->pixelBuffer[pixelIndex+2] << 2);
402                 cineon->lineBuffer[longIndex] = htonl(t);
403                 pixelIndex += 3;
404         }
405
406         /* only seek if not reading consecutive lines */
407         if (y != cineon->fileYPos) {
408                 int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
409                 if (verbose) d_printf("Seek in setRowBytes\n");
410                 if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
411                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
412                         return 1;
413                 }
414                 cineon->fileYPos = y;
415         }
416
417         longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
418         if (longsWritten != cineon->lineBufferLength) {
419                 if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
420                 return 1;
421         }
422
423         ++cineon->fileYPos;
424
425         return 0;
426 }
427
428 int
429 cineonGetRow(CineonFile* cineon, unsigned short* row, int y) {
430
431         int longsRead;
432         int pixelIndex;
433         int longIndex;
434 /*      int numPixels = cineon->width * cineon->depth;
435 */
436         /* only seek if not reading consecutive lines */
437         if (y != cineon->fileYPos) {
438                 int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
439                 if (verbose) d_printf("Seek in getRow\n");
440                 if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
441                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
442                         return 1;
443                 }
444                 cineon->fileYPos = y;
445         }
446
447         longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
448         if (longsRead != cineon->lineBufferLength) {
449                 if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
450                 return 1;
451         }
452
453         /* remember where we left the car, honey */
454         ++cineon->fileYPos;
455
456         /* convert longwords to pixels */
457         pixelIndex = 0;
458         for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
459                 unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
460                 t = t >> 2;
461                 row[pixelIndex+2] = (unsigned short) t & 0x3ff;
462                 t = t >> 10;
463                 row[pixelIndex+1] = (unsigned short) t & 0x3ff;
464                 t = t >> 10;
465                 row[pixelIndex] = (unsigned short) t & 0x3ff;
466                 pixelIndex += 3;
467         }
468
469         return 0;
470 }
471
472 int
473 cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) {
474
475         int pixelIndex;
476 /*      int numPixels = cineon->width * cineon->depth;
477 */      int longIndex;
478         int longsWritten;
479
480         /* pack into longwords */
481         pixelIndex = 0;
482         for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
483                 unsigned int t =
484                                 (row[pixelIndex] << 22) |
485                                 (row[pixelIndex+1] << 12) |
486                                 (row[pixelIndex+2] << 2);
487                 cineon->lineBuffer[longIndex] = htonl(t);
488                 pixelIndex += 3;
489         }
490
491         /* only seek if not reading consecutive lines */
492         if (y != cineon->fileYPos) {
493                 int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
494                 if (verbose) d_printf("Seek in setRowBytes\n");
495                 if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
496                         if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
497                         return 1;
498                 }
499                 cineon->fileYPos = y;
500         }
501
502         longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
503         if (longsWritten != cineon->lineBufferLength) {
504                 if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
505                 return 1;
506         }
507
508         ++cineon->fileYPos;
509
510         return 0;
511 }
512
513 CineonFile* 
514 cineonOpen(const char* filename) {
515
516         CineonGenericHeader header;
517
518         CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
519         if (cineon == 0) {
520                 if (verbose) d_printf("Failed to malloc cineon file structure.\n");
521                 return 0;
522         }
523
524         /* for close routine */
525         cineon->file = 0;
526         cineon->lineBuffer = 0;
527         cineon->pixelBuffer = 0;
528         cineon->membuffer = 0;
529         cineon->memcursor = 0;
530         cineon->membuffersize = 0;
531         
532         cineon->file = BLI_fopen(filename, "rb");
533         if (cineon->file == 0) {
534                 if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
535                 cineonClose(cineon);
536                 return 0;
537         }
538         cineon->reading = 1;
539
540         if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) {
541                 if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
542                 cineonClose(cineon);
543                 return 0;
544         }
545
546         /* let's assume cineon files are always network order */
547         if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
548                 if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
549                         (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
550                 cineonClose(cineon);
551                 return 0;
552         }
553
554         if (header.formatInfo.packing != 5) {
555                 if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
556                 cineonClose(cineon);
557                 return 0;
558         }
559
560         cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
561         cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
562         cineon->depth = header.imageInfo.channels_per_image;
563         /* cineon->bitsPerPixel = 10; */
564         cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
565         cineon->imageOffset = ntohl(header.fileInfo.image_offset);
566
567         cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
568         cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
569         if (cineon->lineBuffer == 0) {
570                 if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
571                 cineonClose(cineon);
572                 return 0;
573         }
574
575         cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
576         if (cineon->pixelBuffer == 0) {
577                 if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
578                                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
579                 cineonClose(cineon);
580                 return 0;
581         }
582         cineon->pixelBufferUsed = 0;
583
584         if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
585                 if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
586                 cineonClose(cineon);
587                 return 0;
588         }
589         cineon->fileYPos = 0;
590
591         logImageGetByteConversionDefaults(&cineon->params);
592         setupLut(cineon);
593
594         cineon->getRow = &cineonGetRowBytes;
595         cineon->setRow = 0;
596         cineon->close = &cineonClose;
597
598         if (verbose) {
599                 verboseMe(cineon);
600         }
601
602         return cineon;
603 }
604
605 int cineonIsMemFileCineon(unsigned char *mem)
606 {
607         unsigned int num;
608         memcpy(&num, mem, sizeof(unsigned int));
609         
610         if (num != ntohl(CINEON_FILE_MAGIC)) {
611                 return 0;
612         }
613         else return 1;
614 }
615
616 CineonFile* 
617 cineonOpenFromMem(unsigned char *mem, unsigned int size) {
618
619         CineonGenericHeader header;
620         
621         CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
622         if (cineon == 0) {
623                 if (verbose) d_printf("Failed to malloc cineon file structure.\n");
624                 return 0;
625         }
626
627         /* for close routine */
628         cineon->file = 0;
629         cineon->lineBuffer = 0;
630         cineon->pixelBuffer = 0;
631         cineon->membuffer = mem;
632         cineon->membuffersize = size;
633         cineon->memcursor = mem;
634         
635         cineon->file = 0;
636         cineon->reading = 1;
637         verbose = 0;
638         if (size < sizeof(CineonGenericHeader)) {
639                 if (verbose) d_printf("Not enough data for header!\n");
640                 cineonClose(cineon);
641                 return 0;
642         }
643
644         logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon);
645
646         /* let's assume cineon files are always network order */
647         if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
648                 if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num));
649
650                 cineonClose(cineon);
651                 return 0;
652         }
653
654         if (header.formatInfo.packing != 5) {
655                 if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
656                 cineonClose(cineon);
657                 return 0;
658         }
659
660         cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
661         cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
662         cineon->depth = header.imageInfo.channels_per_image;
663         /* cineon->bitsPerPixel = 10; */
664         cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
665         cineon->imageOffset = ntohl(header.fileInfo.image_offset);
666
667         cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
668         cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
669         if (cineon->lineBuffer == 0) {
670                 if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
671                 cineonClose(cineon);
672                 return 0;
673         }
674
675         cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
676         if (cineon->pixelBuffer == 0) {
677                 if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
678                                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
679                 cineonClose(cineon);
680                 return 0;
681         }
682         cineon->pixelBufferUsed = 0;
683         
684         if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
685                 if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
686                 cineonClose(cineon);
687                 return 0;
688         }
689         
690         cineon->fileYPos = 0;
691
692         logImageGetByteConversionDefaults(&cineon->params);
693         setupLut(cineon);
694
695         cineon->getRow = &cineonGetRowBytes;
696         cineon->setRow = 0;
697         cineon->close = &cineonClose;
698
699         if (verbose) {
700                 verboseMe(cineon);
701         }
702
703         return cineon;
704 }
705
706
707 int
708 cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) {
709         *width = cineon->width;
710         *height = cineon->height;
711         *depth = cineon->depth;
712         return 0;
713 }
714
715 CineonFile*
716 cineonCreate(const char* filename, int width, int height, int depth) {
717
718         /* Note: always write files in network order */
719         /* By the spec, it shouldn't matter, but ... */
720
721         CineonGenericHeader header;
722         const char* shortFilename = 0;
723
724         CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile));
725         if (cineon == 0) {
726                 if (verbose) d_printf("Failed to malloc cineon file structure.\n");
727                 return 0;
728         }
729
730         memset(&header, 0, sizeof(header));
731
732         /* for close routine */
733         cineon->file = 0;
734         cineon->lineBuffer = 0;
735         cineon->pixelBuffer = 0;
736
737         cineon->file = BLI_fopen(filename, "wb");
738         if (cineon->file == 0) {
739                 if (verbose) d_printf("Couldn't open file %s\n", filename);
740                 cineonClose(cineon);
741                 return 0;
742         }
743         cineon->reading = 0;
744
745         cineon->width = width;
746         cineon->height = height;
747         cineon->depth = depth;
748         cineon->bitsPerPixel = 10;
749         cineon->imageOffset = sizeof(CineonGenericHeader);
750
751         cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
752         cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
753         if (cineon->lineBuffer == 0) {
754                 if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
755                 cineonClose(cineon);
756                 return 0;
757         }
758
759         cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
760         if (cineon->pixelBuffer == 0) {
761                 if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
762                                 (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
763                 cineonClose(cineon);
764                 return 0;
765         }
766         cineon->pixelBufferUsed = 0;
767
768         /* find trailing part of filename */
769         shortFilename = strrchr(filename, '/');
770         if (shortFilename == 0) {
771                 shortFilename = filename;
772         }
773         else {
774                 ++shortFilename;
775         }
776
777         if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
778                 cineonClose(cineon);
779                 return 0;
780         }
781
782         if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
783                 if (verbose) d_printf("Couldn't write image header\n");
784                 cineonClose(cineon);
785                 return 0;
786         }
787         cineon->fileYPos = 0;
788
789         logImageGetByteConversionDefaults(&cineon->params);
790         setupLut(cineon);
791
792         cineon->getRow = 0;
793         cineon->setRow = &cineonSetRowBytes;
794         cineon->close = &cineonClose;
795
796         return cineon;
797 }
798
799 void
800 cineonClose(CineonFile* cineon) {
801
802         if (cineon == 0) {
803                 return;
804         }
805
806         if (cineon->file) {
807                 fclose(cineon->file);
808                 cineon->file = 0;
809         }
810
811         if (cineon->lineBuffer) {
812                 free(cineon->lineBuffer);
813                 cineon->lineBuffer = 0;
814         }
815
816         if (cineon->pixelBuffer) {
817                 free(cineon->pixelBuffer);
818                 cineon->pixelBuffer = 0;
819         }
820
821         free(cineon);
822 }