~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/imbuf/intern/cineon/cineonlib.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * Contributor(s): Julien Enche.
 
21
 *
 
22
 */
 
23
 
1
24
/** \file blender/imbuf/intern/cineon/cineonlib.c
2
25
 *  \ingroup imbcineon
3
26
 */
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
 
 */
 
27
 
24
28
 
25
29
#include "cineonlib.h"
26
 
#include "cineonfile.h"
 
30
#include "logmemfile.h"
27
31
 
28
32
#include <stdio.h>
29
33
#include <math.h>
30
34
#include <stdlib.h>
31
 
#include <time.h>                                /* strftime() */
 
35
#include <time.h>
32
36
#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 */
 
37
#include <string.h>
39
38
 
 
39
#include "BLI_fileops.h"
 
40
#include "BLI_math_base.h"
40
41
#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
 
 
 
42
 
 
43
#include "logImageLib.h"
 
44
 
 
45
#include "MEM_guardedalloc.h"
 
46
 
 
47
/*
 
48
 * For debug purpose
 
49
 */
 
50
 
 
51
static int verbose = 0;
 
52
 
 
53
void cineonSetVerbose(int verbosity)
 
54
{
 
55
        verbose = verbosity;
 
56
}
 
57
 
 
58
static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header,
 
59
                                 const char *filename, const char *creator)
 
60
{
49
61
        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
 
 
 
62
        struct tm *fileTime;
 
63
        int i;
 
64
 
 
65
        memset(header, 0, sizeof(CineonMainHeader));
 
66
 
 
67
        /* --- File header --- */
 
68
        header->fileHeader.magic_num = swap_uint(CINEON_FILE_MAGIC, cineon->isMSB);
 
69
        header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
 
70
        header->fileHeader.gen_hdr_size = swap_uint(sizeof(CineonFileHeader) + sizeof(CineonImageHeader) +
 
71
                                                    sizeof(CineonOriginationHeader), cineon->isMSB);
 
72
        header->fileHeader.ind_hdr_size = 0;
 
73
        header->fileHeader.user_data_size = 0;
 
74
        header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset + cineon->height * getRowLength(cineon->width, cineon->element[0]), cineon->isMSB);
 
75
        strcpy(header->fileHeader.version, "v4.5");
 
76
        strncpy(header->fileHeader.file_name, filename, 99);
 
77
        header->fileHeader.file_name[99] = 0;
66
78
        fileClock = time(0);
67
79
        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;
 
80
        strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
 
81
        strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
 
82
        header->fileHeader.creation_time[11] = 0;
 
83
 
 
84
        /* --- Image header --- */
 
85
        header->imageHeader.orientation = 0;
 
86
        header->imageHeader.elements_per_image = cineon->depth;
 
87
 
 
88
        for (i = 0; i < 3; i++) {
 
89
                header->imageHeader.element[i].descriptor1 = 0;
 
90
                header->imageHeader.element[i].descriptor2 = i;
 
91
                header->imageHeader.element[i].bits_per_sample = cineon->element[0].bitsPerSample;
 
92
                header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB);
 
93
                header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB);
 
94
                header->imageHeader.element[i].ref_low_data = swap_uint(cineon->element[0].refLowData, cineon->isMSB);
 
95
                header->imageHeader.element[i].ref_low_quantity = swap_float(cineon->element[0].refLowQuantity, cineon->isMSB);
 
96
                header->imageHeader.element[i].ref_high_data = swap_uint(cineon->element[0].refHighData, cineon->isMSB);
 
97
                header->imageHeader.element[i].ref_high_quantity = swap_float(cineon->element[0].refHighQuantity, cineon->isMSB);
 
98
        }
 
99
 
 
100
        header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB);
 
101
        header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB);
 
102
        header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB);
 
103
        header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB);
 
104
        header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB);
 
105
        header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB);
 
106
        header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB);
 
107
        header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB);
 
108
        strncpy(header->imageHeader.label, creator, 199);
 
109
        header->imageHeader.label[199] = 0;
 
110
        header->imageHeader.interleave = 0;
 
111
        header->imageHeader.data_sign = 0;
 
112
        header->imageHeader.sense = 0;
 
113
        header->imageHeader.line_padding = swap_uint(0, cineon->isMSB);
 
114
        header->imageHeader.element_padding = swap_uint(0, cineon->isMSB);
 
115
 
 
116
        switch (cineon->element[0].packing) {
 
117
                case 0:
 
118
                        header->imageHeader.packing = 0;
 
119
                        break;
 
120
 
 
121
                case 1:
 
122
                        header->imageHeader.packing = 5;
 
123
                        break;
 
124
 
 
125
                case 2:
 
126
                        header->imageHeader.packing = 6;
 
127
                        break;
 
128
        }
 
129
 
 
130
        /* --- Origination header --- */
 
131
        /* we leave it blank */
 
132
 
 
133
        /* --- Film header --- */
 
134
        /* we leave it blank */
 
135
}
 
136
 
 
137
LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
 
138
{
 
139
        CineonMainHeader header;
 
140
        LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
 
141
        char *filename = (char *)byteStuff;
 
142
        int i;
 
143
        unsigned int dataOffset;
 
144
 
 
145
        if (cineon == 0) {
 
146
                if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
 
147
                return 0;
 
148
        }
 
149
 
 
150
        /* zero the header */
 
151
        memset(&header, 0, sizeof(CineonMainHeader));
 
152
 
 
153
        /* for close routine */
 
154
        cineon->file = 0;
 
155
 
 
156
        if (fromMemory == 0) {
 
157
                /* byteStuff is then the filename */
 
158
                cineon->file = BLI_fopen(filename, "rb");
 
159
                if (cineon->file == 0) {
 
160
                        if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename);
 
161
                        logImageClose(cineon);
 
162
                        return 0;
 
163
                }
 
164
                /* not used in this case */
 
165
                cineon->memBuffer = 0;
 
166
                cineon->memCursor = 0;
 
167
                cineon->memBufferSize = 0;
 
168
        }
 
169
        else {
 
170
                cineon->memBuffer = (unsigned char *)byteStuff;
 
171
                cineon->memCursor = (unsigned char *)byteStuff;
 
172
                cineon->memBufferSize = bufferSize;
 
173
        }
 
174
 
 
175
        if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
 
176
                if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
 
177
                logImageClose(cineon);
 
178
                return 0;
 
179
        }
 
180
 
 
181
        /* endianness determination */
 
182
        if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
 
183
                cineon->isMSB = 1;
 
184
                if (verbose) printf("Cineon: File is MSB.\n");
 
185
        }
 
186
        else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
 
187
                cineon->isMSB = 0;
 
188
                if (verbose) printf("Cineon: File is LSB.\n");
 
189
        }
 
190
        else {
 
191
                if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n",
 
192
                                        (unsigned long)header.fileHeader.magic_num, byteStuff);
 
193
                logImageClose(cineon);
 
194
                return 0;
 
195
        }
 
196
 
 
197
        cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
 
198
        cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
 
199
        cineon->depth = header.imageHeader.elements_per_image;
 
200
        cineon->srcFormat = format_Cineon;
 
201
 
 
202
        if (header.imageHeader.interleave == 0)
 
203
                cineon->numElements = 1;
 
204
        else if (header.imageHeader.interleave == 2)
 
205
                cineon->numElements = header.imageHeader.elements_per_image;
 
206
        else {
 
207
                if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
 
208
                return 0;
 
209
        }
135
210
 
136
211
        if (cineon->depth == 1) {
137
 
                fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
138
 
 
 
212
                /* Grayscale image */
 
213
                cineon->element[0].descriptor = descriptor_Luminance;
 
214
                cineon->element[0].transfer = transfer_Linear;
 
215
                cineon->element[0].depth = 1;
139
216
        }
140
217
        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;
 
218
                /* RGB image */
 
219
                if (cineon->numElements == 1) {
 
220
                        cineon->element[0].descriptor = descriptor_RGB;
 
221
                        cineon->element[0].transfer = transfer_PrintingDensity;
 
222
                        cineon->element[0].depth = 3;
 
223
                }
 
224
                else if (cineon->numElements == 3) {
 
225
                        cineon->element[0].descriptor = descriptor_Red;
 
226
                        cineon->element[0].transfer = transfer_PrintingDensity;
 
227
                        cineon->element[0].depth = 1;
 
228
                        cineon->element[1].descriptor = descriptor_Green;
 
229
                        cineon->element[1].transfer = transfer_PrintingDensity;
 
230
                        cineon->element[1].depth = 1;
 
231
                        cineon->element[2].descriptor = descriptor_Blue;
 
232
                        cineon->element[2].transfer = transfer_PrintingDensity;
 
233
                        cineon->element[2].depth = 1;
 
234
                }
 
235
        }
 
236
        else {
 
237
                if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
 
238
                return 0;
 
239
        }
 
240
 
 
241
        dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
 
242
 
 
243
        for (i = 0; i < cineon->numElements; i++) {
 
244
                cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
 
245
                cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
 
246
                cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB);
 
247
                cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB);
 
248
                cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB);
 
249
                cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);
 
250
 
 
251
                switch (header.imageHeader.packing) {
 
252
                        case 0:
 
253
                                cineon->element[i].packing = 0;
 
254
                                break;
 
255
 
 
256
                        case 5:
 
257
                                cineon->element[i].packing = 1;
 
258
                                break;
 
259
 
 
260
                        case 6:
 
261
                                cineon->element[i].packing = 2;
 
262
                                break;
 
263
 
 
264
                        default:
 
265
                                /* Not supported */
 
266
                                if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
 
267
                                return 0;
 
268
                }
 
269
 
 
270
                if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData))
 
271
                        cineon->element[i].refLowData = 0;
 
272
 
 
273
                if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refHighData))
 
274
                        cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue;
 
275
 
 
276
                if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity))
 
277
                        cineon->element[i].refLowQuantity = 0.0f;
 
278
 
 
279
                if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) {
 
280
                        if (cineon->element[i].transfer == transfer_PrintingDensity)
 
281
                                cineon->element[i].refHighQuantity = 2.048f;
 
282
                        else
 
283
                                cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
 
284
                }
 
285
 
 
286
                cineon->element[i].dataOffset = dataOffset;
 
287
                dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
 
288
        }
 
289
 
 
290
        cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
 
291
        cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
 
292
        cineon->gamma = 1.7f;
596
293
 
597
294
        if (verbose) {
598
 
                verboseMe(cineon);
 
295
                printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
 
296
                for (i = 0; i < cineon->numElements; i++) {
 
297
                        printf(" Element %d:\n", i);
 
298
                        printf("  Bits per sample: %d\n", cineon->element[i].bitsPerSample);
 
299
                        printf("  Depth: %d\n", cineon->element[i].depth);
 
300
                        printf("  Transfer characteristics: %d\n", cineon->element[i].transfer);
 
301
                        printf("  Packing: %d\n", cineon->element[i].packing);
 
302
                        printf("  Descriptor: %d\n", cineon->element[i].descriptor);
 
303
                        printf("  Data offset: %u\n", cineon->element[i].dataOffset);
 
304
                        printf("  Reference low data: %u\n", cineon->element[i].refLowData);
 
305
                        printf("  Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
 
306
                        printf("  Reference high data: %u\n", cineon->element[i].refHighData);
 
307
                        printf("  Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
 
308
                        printf("\n");
 
309
                }
 
310
 
 
311
                printf("Gamma: %f\n", cineon->gamma);
 
312
                printf("Reference black: %f\n", cineon->referenceBlack);
 
313
                printf("Reference white: %f\n", cineon->referenceWhite);
 
314
                printf("----------------------------\n");
599
315
        }
600
 
 
601
316
        return cineon;
602
317
}
603
318
 
604
 
int cineonIsMemFileCineon(unsigned char *mem)
 
319
LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
605
320
{
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;
 
321
        CineonMainHeader header;
 
322
        const char *shortFilename = 0;
 
323
        /* unsigned char pad[6044]; */
 
324
 
 
325
        LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
 
326
        if (cineon == 0) {
 
327
                if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
 
328
                return 0;
 
329
        }
 
330
 
 
331
        /* Only 10 bits Cineon are supported */
 
332
        if (bitsPerSample != 10) {
 
333
                if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n");
 
334
                logImageClose(cineon);
 
335
                return 0;
 
336
        }
743
337
 
744
338
        cineon->width = width;
745
339
        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 */
 
340
        cineon->element[0].bitsPerSample = 10;
 
341
        cineon->element[0].dataOffset = sizeof(CineonMainHeader);
 
342
        cineon->element[0].maxValue = 1023;
 
343
        cineon->isMSB = 1;
 
344
        cineon->numElements = 1;
 
345
        cineon->element[0].packing = 1;
 
346
        cineon->depth = 3;
 
347
        cineon->element[0].depth = 3;
 
348
        cineon->element[0].descriptor = descriptor_RGB;
 
349
        cineon->element[0].transfer = transfer_PrintingDensity;
 
350
        cineon->element[0].refHighQuantity = 2.048f;
 
351
        cineon->element[0].refLowQuantity = 0;
 
352
        cineon->element[0].refLowData = 0;
 
353
        cineon->element[0].refHighData = cineon->element[0].maxValue;
 
354
        cineon->referenceWhite = 685.0f;
 
355
        cineon->referenceBlack = 95.0f;
 
356
        cineon->gamma = 1.7f;
 
357
 
768
358
        shortFilename = strrchr(filename, '/');
769
 
        if (shortFilename == 0) {
 
359
        if (shortFilename == 0)
770
360
                shortFilename = filename;
771
 
        }
772
 
        else {
773
 
                ++shortFilename;
774
 
        }
 
361
        else
 
362
                shortFilename++;
775
363
 
776
 
        if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
777
 
                cineonClose(cineon);
 
364
        cineon->file = BLI_fopen(filename, "wb");
 
365
        if (cineon->file == 0) {
 
366
                if (verbose) printf("cineon: Couldn't open file %s\n", filename);
 
367
                logImageClose(cineon);
778
368
                return 0;
779
369
        }
780
370
 
 
371
        fillCineonMainHeader(cineon, &header, shortFilename, creator);
 
372
 
781
373
        if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
782
 
                if (verbose) d_printf("Couldn't write image header\n");
783
 
                cineonClose(cineon);
 
374
                if (verbose) printf("cineon: Couldn't write image header\n");
 
375
                logImageClose(cineon);
784
376
                return 0;
785
377
        }
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
378
 
795
379
        return cineon;
796
380
}
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
 
}