Blender V4.3
cineonlib.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 1999-2001 David Hodson <hodsond@acm.org>.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "cineonlib.h"
12#include "logmemfile.h"
13
14#include <cmath>
15#include <cstdio>
16#include <cstdlib>
17#include <cstring>
18#include <ctime>
19#include <sys/types.h>
20
21#include "BLI_fileops.h"
22#include "BLI_string.h"
23#include "BLI_utildefines.h"
24
25#include "MEM_guardedalloc.h"
26
27/*
28 * For debug purpose
29 */
30
31static int verbose = 0;
32
33void cineonSetVerbose(int verbosity)
34{
35 verbose = verbosity;
36}
37
39 CineonMainHeader *header,
40 const char *filepath,
41 const char *creator)
42{
43 time_t fileClock;
44 const tm *fileTime;
45 int i;
46
47 memset(header, 0, sizeof(CineonMainHeader));
48
49 /* --- File header --- */
51 header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
54 cineon->isMSB);
55 header->fileHeader.ind_hdr_size = 0;
56 header->fileHeader.user_data_size = 0;
58 cineon->element[0].dataOffset +
59 cineon->height * getRowLength(cineon->width, &cineon->element[0]),
60 cineon->isMSB);
61 STRNCPY(header->fileHeader.version, "v4.5");
62 STRNCPY(header->fileHeader.file_name, filepath);
63 fileClock = time(nullptr);
64 fileTime = localtime(&fileClock);
65 strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
66 strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
67 header->fileHeader.creation_time[11] = 0;
68
69 /* --- Image header --- */
70 header->imageHeader.orientation = 0;
71 header->imageHeader.elements_per_image = cineon->depth;
72
73 for (i = 0; i < 3; i++) {
74 header->imageHeader.element[i].descriptor1 = 0;
75 header->imageHeader.element[i].descriptor2 = i;
77 header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB);
78 header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB);
80 cineon->isMSB);
82 cineon->isMSB);
84 cineon->isMSB);
86 cineon->element[0].refHighQuantity, cineon->isMSB);
87 }
88
89 header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB);
90 header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB);
91 header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB);
92 header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB);
93 header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB);
94 header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB);
95 header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB);
96 header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB);
97 STRNCPY(header->imageHeader.label, creator);
98 header->imageHeader.interleave = 0;
99 header->imageHeader.data_sign = 0;
100 header->imageHeader.sense = 0;
101 header->imageHeader.line_padding = swap_uint(0, cineon->isMSB);
102 header->imageHeader.element_padding = swap_uint(0, cineon->isMSB);
103
104 switch (cineon->element[0].packing) {
105 case 0:
106 header->imageHeader.packing = 0;
107 break;
108
109 case 1:
110 header->imageHeader.packing = 5;
111 break;
112
113 case 2:
114 header->imageHeader.packing = 6;
115 break;
116 }
117
118 /* --- Origination header --- */
119 /* we leave it blank */
120
121 /* --- Film header --- */
122 /* we leave it blank */
123}
124
125LogImageFile *cineonOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
126{
127 CineonMainHeader header;
128 LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
129 const char *filepath = (const char *)byteStuff;
130 int i;
131 uint dataOffset;
132
133 if (cineon == nullptr) {
134 if (verbose) {
135 printf("Cineon: Failed to malloc cineon file structure.\n");
136 }
137 return nullptr;
138 }
139
140 /* zero the header */
141 memset(&header, 0, sizeof(CineonMainHeader));
142
143 /* for close routine */
144 cineon->file = nullptr;
145
146 if (fromMemory == 0) {
147 /* byteStuff is then the filepath */
148 cineon->file = BLI_fopen(filepath, "rb");
149 if (cineon->file == nullptr) {
150 if (verbose) {
151 printf("Cineon: Failed to open file \"%s\".\n", filepath);
152 }
153 logImageClose(cineon);
154 return nullptr;
155 }
156 /* not used in this case */
157 cineon->memBuffer = nullptr;
158 cineon->memCursor = nullptr;
159 cineon->memBufferSize = 0;
160 }
161 else {
162 cineon->memBuffer = (uchar *)byteStuff;
163 cineon->memCursor = (uchar *)byteStuff;
164 cineon->memBufferSize = bufferSize;
165 }
166
167 if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
168 if (verbose) {
169 printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
170 }
171 logImageClose(cineon);
172 return nullptr;
173 }
174
175 /* endianness determination */
177 cineon->isMSB = 1;
178 if (verbose) {
179 printf("Cineon: File is MSB.\n");
180 }
181 }
182 else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
183 cineon->isMSB = 0;
184 if (verbose) {
185 printf("Cineon: File is LSB.\n");
186 }
187 }
188 else {
189 if (verbose) {
190 printf("Cineon: Bad magic number %lu in \"%s\".\n",
191 ulong(header.fileHeader.magic_num),
192 byteStuff);
193 }
194 logImageClose(cineon);
195 return nullptr;
196 }
197
198 cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
199 cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
200
201 if (cineon->width == 0 || cineon->height == 0) {
202 if (verbose) {
203 printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height);
204 }
205 logImageClose(cineon);
206 return nullptr;
207 }
208
209 cineon->depth = header.imageHeader.elements_per_image;
210 cineon->srcFormat = format_Cineon;
211
212 if (header.imageHeader.interleave == 0) {
213 cineon->numElements = 1;
214 }
215 else if (header.imageHeader.interleave == 2) {
217 }
218 else {
219 if (verbose) {
220 printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
221 }
222 logImageClose(cineon);
223 return nullptr;
224 }
225
226 if (cineon->depth == 1) {
227 /* Gray-scale image. */
229 cineon->element[0].transfer = transfer_Linear;
230 cineon->element[0].depth = 1;
231 }
232 else if (cineon->depth == 3) {
233 /* RGB image. */
234 if (cineon->numElements == 1) {
235 cineon->element[0].descriptor = descriptor_RGB;
237 cineon->element[0].depth = 3;
238 }
239 else if (cineon->numElements == 3) {
240 cineon->element[0].descriptor = descriptor_Red;
242 cineon->element[0].depth = 1;
245 cineon->element[1].depth = 1;
248 cineon->element[2].depth = 1;
249 }
250 }
251 else {
252 if (verbose) {
253 printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
254 }
255 logImageClose(cineon);
256 return nullptr;
257 }
258
259 dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
260
261 for (i = 0; i < cineon->numElements; i++) {
263 cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
265 cineon->isMSB);
267 cineon->isMSB);
269 cineon->isMSB);
271 header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);
272
273 switch (header.imageHeader.packing) {
274 case 0:
275 cineon->element[i].packing = 0;
276 break;
277
278 case 5:
279 cineon->element[i].packing = 1;
280 break;
281
282 case 6:
283 cineon->element[i].packing = 2;
284 break;
285
286 default:
287 /* Not supported */
288 if (verbose) {
289 printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
290 }
291 logImageClose(cineon);
292 return nullptr;
293 }
294
295 if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) {
296 cineon->element[i].refLowData = 0;
297 }
298
299 if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) {
300 cineon->element[i].refHighData = uint(cineon->element[i].maxValue);
301 }
302
303 if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 ||
304 std::isnan(cineon->element[i].refLowQuantity))
305 {
306 cineon->element[i].refLowQuantity = 0.0f;
307 }
308
309 if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 ||
310 std::isnan(cineon->element[i].refHighQuantity))
311 {
312 if (cineon->element[i].transfer == transfer_PrintingDensity) {
313 cineon->element[i].refHighQuantity = 2.048f;
314 }
315 else {
316 cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
317 }
318 }
319
320 cineon->element[i].dataOffset = dataOffset;
321 dataOffset += cineon->height * getRowLength(cineon->width, &cineon->element[i]);
322 }
323
324 cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
325 cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
326 cineon->gamma = 1.7f;
327
328 if (verbose) {
329 printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
330 for (i = 0; i < cineon->numElements; i++) {
331 printf(" Element %d:\n", i);
332 printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample);
333 printf(" Depth: %d\n", cineon->element[i].depth);
334 printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
335 printf(" Packing: %d\n", cineon->element[i].packing);
336 printf(" Descriptor: %d\n", cineon->element[i].descriptor);
337 printf(" Data offset: %d\n", cineon->element[i].dataOffset);
338 printf(" Reference low data: %u\n", cineon->element[i].refLowData);
339 printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
340 printf(" Reference high data: %u\n", cineon->element[i].refHighData);
341 printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
342 printf("\n");
343 }
344
345 printf("Gamma: %f\n", cineon->gamma);
346 printf("Reference black: %f\n", cineon->referenceBlack);
347 printf("Reference white: %f\n", cineon->referenceWhite);
348 printf("Orientation: %d\n", header.imageHeader.orientation);
349 printf("----------------------------\n");
350 }
351 return cineon;
352}
353
355 const char *filepath, int width, int height, int bitsPerSample, const char *creator)
356{
357 CineonMainHeader header;
358 const char *shortFilename = nullptr;
359 // uchar pad[6044];
360
361 LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
362 if (cineon == nullptr) {
363 if (verbose) {
364 printf("cineon: Failed to malloc cineon file structure.\n");
365 }
366 return nullptr;
367 }
368
369 /* Only 10 bits Cineon are supported */
370 if (bitsPerSample != 10) {
371 if (verbose) {
372 printf("cineon: Only 10 bits Cineon are supported.\n");
373 }
374 logImageClose(cineon);
375 return nullptr;
376 }
377
378 cineon->width = width;
379 cineon->height = height;
380 cineon->element[0].bitsPerSample = 10;
381 cineon->element[0].dataOffset = sizeof(CineonMainHeader);
382 cineon->element[0].maxValue = 1023;
383 cineon->isMSB = 1;
384 cineon->numElements = 1;
385 cineon->element[0].packing = 1;
386 cineon->depth = 3;
387 cineon->element[0].depth = 3;
388 cineon->element[0].descriptor = descriptor_RGB;
390 cineon->element[0].refHighQuantity = 2.048f;
391 cineon->element[0].refLowQuantity = 0;
392 cineon->element[0].refLowData = 0;
393 cineon->element[0].refHighData = cineon->element[0].maxValue;
394 cineon->referenceWhite = 685.0f;
395 cineon->referenceBlack = 95.0f;
396 cineon->gamma = 1.7f;
397
398 shortFilename = strrchr(filepath, PATHSEP_CHAR);
399 if (shortFilename == nullptr) {
400 shortFilename = filepath;
401 }
402 else {
403 shortFilename++;
404 }
405
406 cineon->file = BLI_fopen(filepath, "wb");
407 if (cineon->file == nullptr) {
408 if (verbose) {
409 printf("cineon: Couldn't open file %s\n", filepath);
410 }
411 logImageClose(cineon);
412 return nullptr;
413 }
414
415 fillCineonMainHeader(cineon, &header, shortFilename, creator);
416
417 if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
418 if (verbose) {
419 printf("cineon: Couldn't write image header\n");
420 }
421 logImageClose(cineon);
422 return nullptr;
423 }
424
425 return cineon;
426}
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned char uchar
unsigned long ulong
unsigned int uint
Read Guarded memory(de)allocation.
static int verbose
Definition cineonlib.cc:31
LogImageFile * cineonCreate(const char *filepath, int width, int height, int bitsPerSample, const char *creator)
Definition cineonlib.cc:354
void cineonSetVerbose(int verbosity)
Definition cineonlib.cc:33
LogImageFile * cineonOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
Definition cineonlib.cc:125
static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, const char *filepath, const char *creator)
Definition cineonlib.cc:38
#define CINEON_FILE_MAGIC
Definition cineonlib.h:20
#define CINEON_UNDEFINED_U32
Definition cineonlib.h:23
#define CINEON_UNDEFINED_R32
Definition cineonlib.h:24
#define printf
double time
#define powf(x, y)
static size_t getRowLength(size_t width, const LogImageElement &logElement)
void logImageClose(LogImageFile *logImage)
@ format_Cineon
@ descriptor_Red
@ descriptor_Luminance
@ descriptor_Green
@ descriptor_Blue
@ descriptor_RGB
BLI_INLINE float swap_float(float x, int swap)
@ transfer_PrintingDensity
@ transfer_Linear
#define PATHSEP_CHAR
BLI_INLINE unsigned int swap_uint(unsigned int x, int swap)
int logimage_fread(void *buffer, size_t size, uint count, LogImageFile *logFile)
Definition logmemfile.cc:58
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
unsigned int ref_low_data
Definition cineonlib.h:48
unsigned int ref_high_data
Definition cineonlib.h:50
unsigned int pixels_per_line
Definition cineonlib.h:46
unsigned int lines_per_image
Definition cineonlib.h:47
unsigned int file_size
Definition cineonlib.h:33
char file_name[100]
Definition cineonlib.h:35
char creation_time[12]
Definition cineonlib.h:37
unsigned int magic_num
Definition cineonlib.h:28
unsigned int offset
Definition cineonlib.h:29
char version[8]
Definition cineonlib.h:34
unsigned int gen_hdr_size
Definition cineonlib.h:30
char creation_date[12]
Definition cineonlib.h:36
unsigned int ind_hdr_size
Definition cineonlib.h:31
unsigned int user_data_size
Definition cineonlib.h:32
char label[200]
Definition cineonlib.h:67
uchar elements_per_image
Definition cineonlib.h:56
unsigned int line_padding
Definition cineonlib.h:73
float green_primary_y
Definition cineonlib.h:64
float green_primary_x
Definition cineonlib.h:63
CineonElementHeader element[8]
Definition cineonlib.h:58
unsigned int element_padding
Definition cineonlib.h:74
CineonFileHeader fileHeader
Definition cineonlib.h:109
CineonImageHeader imageHeader
Definition cineonlib.h:110
unsigned int refLowData
unsigned int refHighData
uintptr_t memBufferSize
float referenceWhite
unsigned char * memBuffer
unsigned char * memCursor
LogImageElement element[8]
float referenceBlack