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