2
* Cineon image file format library routines.
4
* Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
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)
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
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.
20
* Contributor(s): Julien Enche.
1
24
/** \file blender/imbuf/intern/cineon/cineonlib.c
2
25
* \ingroup imbcineon
5
* Cineon image file format library routines.
7
* Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
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)
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
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.
25
29
#include "cineonlib.h"
26
#include "cineonfile.h"
30
#include "logmemfile.h"
30
34
#include <stdlib.h>
31
#include <time.h> /* strftime() */
32
36
#include <sys/types.h>
36
#include <netinet/in.h> /* htonl() */
38
#include <string.h> /* memset */
39
#include "BLI_fileops.h"
40
#include "BLI_math_base.h"
40
41
#include "BLI_utildefines.h"
41
#include "BLI_fileops.h"
43
#include "cin_debug_stuff.h"
44
#include "logmemfile.h"
47
fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) {
43
#include "logImageLib.h"
45
#include "MEM_guardedalloc.h"
51
static int verbose = 0;
53
void cineonSetVerbose(int verbosity)
58
static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header,
59
const char *filename, const char *creator)
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
memset(header, 0, sizeof(CineonMainHeader));
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;
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);
90
fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) {
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);
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;
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;
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));
131
fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) {
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;
84
/* --- Image header --- */
85
header->imageHeader.orientation = 0;
86
header->imageHeader.elements_per_image = cineon->depth;
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);
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);
116
switch (cineon->element[0].packing) {
118
header->imageHeader.packing = 0;
122
header->imageHeader.packing = 5;
126
header->imageHeader.packing = 6;
130
/* --- Origination header --- */
131
/* we leave it blank */
133
/* --- Film header --- */
134
/* we leave it blank */
137
LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
139
CineonMainHeader header;
140
LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
141
char *filename = (char *)byteStuff;
143
unsigned int dataOffset;
146
if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
150
/* zero the header */
151
memset(&header, 0, sizeof(CineonMainHeader));
153
/* for close routine */
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);
164
/* not used in this case */
165
cineon->memBuffer = 0;
166
cineon->memCursor = 0;
167
cineon->memBufferSize = 0;
170
cineon->memBuffer = (unsigned char *)byteStuff;
171
cineon->memCursor = (unsigned char *)byteStuff;
172
cineon->memBufferSize = bufferSize;
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);
181
/* endianness determination */
182
if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
184
if (verbose) printf("Cineon: File is MSB.\n");
186
else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
188
if (verbose) printf("Cineon: File is LSB.\n");
191
if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n",
192
(unsigned long)header.fileHeader.magic_num, byteStuff);
193
logImageClose(cineon);
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;
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;
207
if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
136
211
if (cineon->depth == 1) {
137
fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
212
/* Grayscale image */
213
cineon->element[0].descriptor = descriptor_Luminance;
214
cineon->element[0].transfer = transfer_Linear;
215
cineon->element[0].depth = 1;
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);
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());
155
strcpy(imageInfo->label, "David's Cineon writer.");
160
dumpCineonImageInfo(CineonImageInformation* imageInfo) {
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;
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]);
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);
194
fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) {
196
(void)cineon; /* unused */
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);
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;
216
d_printf("Packing %d,", formatInfo->packing);
217
if (formatInfo->packing & 0x80) {
218
d_printf(" multi pixel,");
221
d_printf(" single pixel,");
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;
233
d_printf("Sign %d,", formatInfo->signage);
234
if (formatInfo->signage) {
235
d_printf(" signed\n");
238
d_printf(" unsigned\n");
240
d_printf("Sense %d,", formatInfo->signage);
241
if (formatInfo->signage) {
242
d_printf(" negative\n");
245
d_printf(" positive\n");
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));
252
fillCineonOriginationInfo(CineonFile* cineon,
253
CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) {
255
(void)cineon; /* unused */
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);
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));
288
initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) {
290
fillCineonFileInfo(cineon, &header->fileInfo, imagename);
291
fillCineonImageInfo(cineon, &header->imageInfo);
292
fillCineonFormatInfo(cineon, &header->formatInfo);
293
fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo);
299
UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) {
300
dumpCineonFileInfo(&header->fileInfo);
301
dumpCineonImageInfo(&header->imageInfo);
302
dumpCineonFormatInfo(&header->formatInfo);
303
dumpCineonOriginationInfo(&header->originInfo);
306
static int verbose = 0;
308
cineonSetVerbose(int verbosity) {
313
verboseMe(CineonFile* cineon) {
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);
322
cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
327
int numPixels = cineon->width * cineon->depth;
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);
338
cineon->fileYPos = y;
341
longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
342
if (longsRead != cineon->lineBufferLength) {
344
d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
345
perror("cineonGetRowBytes");
351
/* remember where we left the car, honey */
354
/* convert longwords to pixels */
356
for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
357
unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
359
cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff;
361
cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff;
363
cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff;
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]];
372
row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
379
cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
382
int numPixels = cineon->width * cineon->depth;
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]];
391
cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
394
/* pack into longwords */
396
for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
398
(cineon->pixelBuffer[pixelIndex] << 22) |
399
(cineon->pixelBuffer[pixelIndex+1] << 12) |
400
(cineon->pixelBuffer[pixelIndex+2] << 2);
401
cineon->lineBuffer[longIndex] = htonl(t);
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);
413
cineon->fileYPos = y;
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);
428
cineonGetRow(CineonFile* cineon, unsigned short* row, int y) {
433
/* int numPixels = cineon->width * cineon->depth;
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);
443
cineon->fileYPos = y;
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);
452
/* remember where we left the car, honey */
455
/* convert longwords to pixels */
457
for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
458
unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
460
row[pixelIndex+2] = (unsigned short) t & 0x3ff;
462
row[pixelIndex+1] = (unsigned short) t & 0x3ff;
464
row[pixelIndex] = (unsigned short) t & 0x3ff;
472
cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) {
475
/* int numPixels = cineon->width * cineon->depth;
479
/* pack into longwords */
481
for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
483
(row[pixelIndex] << 22) |
484
(row[pixelIndex+1] << 12) |
485
(row[pixelIndex+2] << 2);
486
cineon->lineBuffer[longIndex] = htonl(t);
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);
498
cineon->fileYPos = y;
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);
513
cineonOpen(const char* filename) {
515
CineonGenericHeader header;
517
CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
519
if (verbose) d_printf("Failed to malloc cineon file structure.\n");
523
/* for close routine */
525
cineon->lineBuffer = 0;
526
cineon->pixelBuffer = 0;
527
cineon->membuffer = 0;
528
cineon->memcursor = 0;
529
cineon->membuffersize = 0;
531
cineon->file = BLI_fopen(filename, "rb");
532
if (cineon->file == 0) {
533
if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
539
if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) {
540
if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
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);
553
if (header.formatInfo.packing != 5) {
554
if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
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);
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);
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));
581
cineon->pixelBufferUsed = 0;
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);
588
cineon->fileYPos = 0;
590
logImageGetByteConversionDefaults(&cineon->params);
593
cineon->getRow = &cineonGetRowBytes;
595
cineon->close = &cineonClose;
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;
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;
237
if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
241
dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
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);
251
switch (header.imageHeader.packing) {
253
cineon->element[i].packing = 0;
257
cineon->element[i].packing = 1;
261
cineon->element[i].packing = 2;
266
if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
270
if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData))
271
cineon->element[i].refLowData = 0;
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;
276
if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity))
277
cineon->element[i].refLowQuantity = 0.0f;
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;
283
cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
286
cineon->element[i].dataOffset = dataOffset;
287
dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
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;
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);
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");
604
int cineonIsMemFileCineon(unsigned char *mem)
319
LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
607
memcpy(&num, mem, sizeof(unsigned int));
609
if (num != ntohl(CINEON_FILE_MAGIC)) {
616
cineonOpenFromMem(unsigned char *mem, unsigned int size) {
618
CineonGenericHeader header;
620
CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
622
if (verbose) d_printf("Failed to malloc cineon file structure.\n");
626
/* for close routine */
628
cineon->lineBuffer = 0;
629
cineon->pixelBuffer = 0;
630
cineon->membuffer = mem;
631
cineon->membuffersize = size;
632
cineon->memcursor = mem;
637
if (size < sizeof(CineonGenericHeader)) {
638
if (verbose) d_printf("Not enough data for header!\n");
643
logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon);
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));
653
if (header.formatInfo.packing != 5) {
654
if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
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);
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);
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));
681
cineon->pixelBufferUsed = 0;
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);
689
cineon->fileYPos = 0;
691
logImageGetByteConversionDefaults(&cineon->params);
694
cineon->getRow = &cineonGetRowBytes;
696
cineon->close = &cineonClose;
707
cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) {
708
*width = cineon->width;
709
*height = cineon->height;
710
*depth = cineon->depth;
715
cineonCreate(const char* filename, int width, int height, int depth) {
717
/* Note: always write files in network order */
718
/* By the spec, it shouldn't matter, but ... */
720
CineonGenericHeader header;
721
const char* shortFilename = 0;
723
CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile));
725
if (verbose) d_printf("Failed to malloc cineon file structure.\n");
729
memset(&header, 0, sizeof(header));
731
/* for close routine */
733
cineon->lineBuffer = 0;
734
cineon->pixelBuffer = 0;
736
cineon->file = BLI_fopen(filename, "wb");
737
if (cineon->file == 0) {
738
if (verbose) d_printf("Couldn't open file %s\n", filename);
321
CineonMainHeader header;
322
const char *shortFilename = 0;
323
/* unsigned char pad[6044]; */
325
LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
327
if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
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);
744
338
cineon->width = width;
745
339
cineon->height = height;
746
cineon->depth = depth;
747
cineon->bitsPerPixel = 10;
748
cineon->imageOffset = sizeof(CineonGenericHeader);
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);
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));
765
cineon->pixelBufferUsed = 0;
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;
344
cineon->numElements = 1;
345
cineon->element[0].packing = 1;
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;
768
358
shortFilename = strrchr(filename, '/');
769
if (shortFilename == 0) {
359
if (shortFilename == 0)
770
360
shortFilename = filename;
776
if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
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);
371
fillCineonMainHeader(cineon, &header, shortFilename, creator);
781
373
if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
782
if (verbose) d_printf("Couldn't write image header\n");
374
if (verbose) printf("cineon: Couldn't write image header\n");
375
logImageClose(cineon);
786
cineon->fileYPos = 0;
788
logImageGetByteConversionDefaults(&cineon->params);
792
cineon->setRow = &cineonSetRowBytes;
793
cineon->close = &cineonClose;
799
cineonClose(CineonFile* cineon) {
806
fclose(cineon->file);
810
if (cineon->lineBuffer) {
811
free(cineon->lineBuffer);
812
cineon->lineBuffer = 0;
815
if (cineon->pixelBuffer) {
816
free(cineon->pixelBuffer);
817
cineon->pixelBuffer = 0;