Blender  V3.3
cineonlib.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 1999-2001 David Hodson <hodsond@acm.org>. */
3 
10 #include "cineonlib.h"
11 #include "logmemfile.h"
12 
13 #include <math.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <time.h>
19 
20 #include "BLI_fileops.h"
21 #include "BLI_utildefines.h"
22 
23 #include "MEM_guardedalloc.h"
24 
25 /*
26  * For debug purpose
27  */
28 
29 static int verbose = 0;
30 
31 void cineonSetVerbose(int verbosity)
32 {
33  verbose = verbosity;
34 }
35 
36 static void fillCineonMainHeader(LogImageFile *cineon,
37  CineonMainHeader *header,
38  const char *filepath,
39  const char *creator)
40 {
41  time_t fileClock;
42  struct tm *fileTime;
43  int i;
44 
45  memset(header, 0, sizeof(CineonMainHeader));
46 
47  /* --- File header --- */
49  header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
52  cineon->isMSB);
53  header->fileHeader.ind_hdr_size = 0;
54  header->fileHeader.user_data_size = 0;
55  header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset +
56  cineon->height *
57  getRowLength(cineon->width, cineon->element[0]),
58  cineon->isMSB);
59  strcpy(header->fileHeader.version, "v4.5");
60  strncpy(header->fileHeader.file_name, filepath, 99);
61  header->fileHeader.file_name[99] = 0;
62  fileClock = time(NULL);
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;
74  header->imageHeader.element[i].descriptor2 = i;
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, 199);
97  header->imageHeader.label[199] = 0;
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 
125 LogImageFile *cineonOpen(const unsigned char *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  unsigned int dataOffset;
132 
133  if (cineon == NULL) {
134  if (verbose) {
135  printf("Cineon: Failed to malloc cineon file structure.\n");
136  }
137  return NULL;
138  }
139 
140  /* zero the header */
141  memset(&header, 0, sizeof(CineonMainHeader));
142 
143  /* for close routine */
144  cineon->file = NULL;
145 
146  if (fromMemory == 0) {
147  /* byteStuff is then the filepath */
148  cineon->file = BLI_fopen(filepath, "rb");
149  if (cineon->file == NULL) {
150  if (verbose) {
151  printf("Cineon: Failed to open file \"%s\".\n", filepath);
152  }
153  logImageClose(cineon);
154  return NULL;
155  }
156  /* not used in this case */
157  cineon->memBuffer = NULL;
158  cineon->memCursor = NULL;
159  cineon->memBufferSize = 0;
160  }
161  else {
162  cineon->memBuffer = (unsigned char *)byteStuff;
163  cineon->memCursor = (unsigned char *)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 NULL;
173  }
174 
175  /* endianness determination */
176  if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
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  (unsigned long)header.fileHeader.magic_num,
192  byteStuff);
193  }
194  logImageClose(cineon);
195  return NULL;
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 NULL;
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) {
216  cineon->numElements = header.imageHeader.elements_per_image;
217  }
218  else {
219  if (verbose) {
220  printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
221  }
222  logImageClose(cineon);
223  return NULL;
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;
243  cineon->element[1].descriptor = descriptor_Green;
245  cineon->element[1].depth = 1;
246  cineon->element[2].descriptor = descriptor_Blue;
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 NULL;
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);
270  cineon->element[i].refHighQuantity = swap_float(
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 NULL;
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 = (unsigned int)cineon->element[i].maxValue;
301  }
302 
303  if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 ||
304  isnan(cineon->element[i].refLowQuantity)) {
305  cineon->element[i].refLowQuantity = 0.0f;
306  }
307 
308  if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 ||
309  isnan(cineon->element[i].refHighQuantity)) {
310  if (cineon->element[i].transfer == transfer_PrintingDensity) {
311  cineon->element[i].refHighQuantity = 2.048f;
312  }
313  else {
314  cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
315  }
316  }
317 
318  cineon->element[i].dataOffset = dataOffset;
319  dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
320  }
321 
322  cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
323  cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
324  cineon->gamma = 1.7f;
325 
326  if (verbose) {
327  printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
328  for (i = 0; i < cineon->numElements; i++) {
329  printf(" Element %d:\n", i);
330  printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample);
331  printf(" Depth: %d\n", cineon->element[i].depth);
332  printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
333  printf(" Packing: %d\n", cineon->element[i].packing);
334  printf(" Descriptor: %d\n", cineon->element[i].descriptor);
335  printf(" Data offset: %d\n", cineon->element[i].dataOffset);
336  printf(" Reference low data: %u\n", cineon->element[i].refLowData);
337  printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
338  printf(" Reference high data: %u\n", cineon->element[i].refHighData);
339  printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
340  printf("\n");
341  }
342 
343  printf("Gamma: %f\n", cineon->gamma);
344  printf("Reference black: %f\n", cineon->referenceBlack);
345  printf("Reference white: %f\n", cineon->referenceWhite);
346  printf("Orientation: %d\n", header.imageHeader.orientation);
347  printf("----------------------------\n");
348  }
349  return cineon;
350 }
351 
353  const char *filepath, int width, int height, int bitsPerSample, const char *creator)
354 {
355  CineonMainHeader header;
356  const char *shortFilename = NULL;
357  /* unsigned char pad[6044]; */
358 
359  LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
360  if (cineon == NULL) {
361  if (verbose) {
362  printf("cineon: Failed to malloc cineon file structure.\n");
363  }
364  return NULL;
365  }
366 
367  /* Only 10 bits Cineon are supported */
368  if (bitsPerSample != 10) {
369  if (verbose) {
370  printf("cineon: Only 10 bits Cineon are supported.\n");
371  }
372  logImageClose(cineon);
373  return NULL;
374  }
375 
376  cineon->width = width;
377  cineon->height = height;
378  cineon->element[0].bitsPerSample = 10;
379  cineon->element[0].dataOffset = sizeof(CineonMainHeader);
380  cineon->element[0].maxValue = 1023;
381  cineon->isMSB = 1;
382  cineon->numElements = 1;
383  cineon->element[0].packing = 1;
384  cineon->depth = 3;
385  cineon->element[0].depth = 3;
386  cineon->element[0].descriptor = descriptor_RGB;
388  cineon->element[0].refHighQuantity = 2.048f;
389  cineon->element[0].refLowQuantity = 0;
390  cineon->element[0].refLowData = 0;
391  cineon->element[0].refHighData = cineon->element[0].maxValue;
392  cineon->referenceWhite = 685.0f;
393  cineon->referenceBlack = 95.0f;
394  cineon->gamma = 1.7f;
395 
396  shortFilename = strrchr(filepath, PATHSEP_CHAR);
397  if (shortFilename == NULL) {
398  shortFilename = filepath;
399  }
400  else {
401  shortFilename++;
402  }
403 
404  cineon->file = BLI_fopen(filepath, "wb");
405  if (cineon->file == NULL) {
406  if (verbose) {
407  printf("cineon: Couldn't open file %s\n", filepath);
408  }
409  logImageClose(cineon);
410  return NULL;
411  }
412 
413  fillCineonMainHeader(cineon, &header, shortFilename, creator);
414 
415  if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
416  if (verbose) {
417  printf("cineon: Couldn't write image header\n");
418  }
419  logImageClose(cineon);
420  return NULL;
421  }
422 
423  return cineon;
424 }
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
Read Guarded memory(de)allocation.
static int verbose
Definition: cineonlib.c:29
void cineonSetVerbose(int verbosity)
Definition: cineonlib.c:31
LogImageFile * cineonCreate(const char *filepath, int width, int height, int bitsPerSample, const char *creator)
Definition: cineonlib.c:352
LogImageFile * cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
Definition: cineonlib.c:125
static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, const char *filepath, const char *creator)
Definition: cineonlib.c:36
#define CINEON_FILE_MAGIC
Definition: cineonlib.h:19
#define CINEON_UNDEFINED_U32
Definition: cineonlib.h:22
#define CINEON_UNDEFINED_R32
Definition: cineonlib.h:23
#define powf(x, y)
Definition: cuda/compat.h:103
double time
void logImageClose(LogImageFile *logImage)
Definition: logImageCore.c:175
size_t getRowLength(size_t width, LogImageElement logElement)
Definition: logImageCore.c:197
@ format_Cineon
Definition: logImageCore.h:40
@ descriptor_Red
Definition: logImageCore.h:146
@ descriptor_Luminance
Definition: logImageCore.h:150
@ descriptor_Green
Definition: logImageCore.h:147
@ descriptor_Blue
Definition: logImageCore.h:148
@ descriptor_RGB
Definition: logImageCore.h:154
BLI_INLINE float swap_float(float x, int swap)
Definition: logImageCore.h:224
@ transfer_PrintingDensity
Definition: logImageCore.h:104
@ transfer_Linear
Definition: logImageCore.h:105
#define PATHSEP_CHAR
Definition: logImageCore.h:25
BLI_INLINE unsigned int swap_uint(unsigned int x, int swap)
Definition: logImageCore.h:214
int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile)
Definition: logmemfile.c:57
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
bool isnan(double i)
Definition: numeric.h:451
unsigned int ref_low_data
Definition: cineonlib.h:47
unsigned char descriptor2
Definition: cineonlib.h:42
unsigned int ref_high_data
Definition: cineonlib.h:49
unsigned int pixels_per_line
Definition: cineonlib.h:45
float ref_low_quantity
Definition: cineonlib.h:48
unsigned int lines_per_image
Definition: cineonlib.h:46
unsigned char bits_per_sample
Definition: cineonlib.h:43
unsigned char descriptor1
Definition: cineonlib.h:41
float ref_high_quantity
Definition: cineonlib.h:50
unsigned int file_size
Definition: cineonlib.h:32
char file_name[100]
Definition: cineonlib.h:34
char creation_time[12]
Definition: cineonlib.h:36
unsigned int magic_num
Definition: cineonlib.h:27
unsigned int offset
Definition: cineonlib.h:28
char version[8]
Definition: cineonlib.h:33
unsigned int gen_hdr_size
Definition: cineonlib.h:29
char creation_date[12]
Definition: cineonlib.h:35
unsigned int ind_hdr_size
Definition: cineonlib.h:30
unsigned int user_data_size
Definition: cineonlib.h:31
char label[200]
Definition: cineonlib.h:66
unsigned char packing
Definition: cineonlib.h:69
unsigned char sense
Definition: cineonlib.h:71
unsigned int line_padding
Definition: cineonlib.h:72
float blue_primary_x
Definition: cineonlib.h:64
unsigned char elements_per_image
Definition: cineonlib.h:55
float white_point_x
Definition: cineonlib.h:58
float red_primary_y
Definition: cineonlib.h:61
float blue_primary_y
Definition: cineonlib.h:65
unsigned char data_sign
Definition: cineonlib.h:70
unsigned char interleave
Definition: cineonlib.h:68
float green_primary_y
Definition: cineonlib.h:63
float red_primary_x
Definition: cineonlib.h:60
float green_primary_x
Definition: cineonlib.h:62
unsigned char orientation
Definition: cineonlib.h:54
CineonElementHeader element[8]
Definition: cineonlib.h:57
unsigned int element_padding
Definition: cineonlib.h:73
float white_point_y
Definition: cineonlib.h:59
CineonFileHeader fileHeader
Definition: cineonlib.h:108
CineonImageHeader imageHeader
Definition: cineonlib.h:109
unsigned int refLowData
Definition: logImageCore.h:50
float refLowQuantity
Definition: logImageCore.h:52
float refHighQuantity
Definition: logImageCore.h:53
unsigned int refHighData
Definition: logImageCore.h:51
uintptr_t memBufferSize
Definition: logImageCore.h:73
float referenceWhite
Definition: logImageCore.h:67
unsigned char * memBuffer
Definition: logImageCore.h:72
unsigned char * memCursor
Definition: logImageCore.h:74
LogImageElement element[8]
Definition: logImageCore.h:63
float referenceBlack
Definition: logImageCore.h:66