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