Blender  V2.93
cineonlib.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
17  */
18 
25 #include "cineonlib.h"
26 #include "logmemfile.h"
27 
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <time.h>
34 
35 #include "BLI_fileops.h"
36 #include "BLI_utildefines.h"
37 
38 #include "MEM_guardedalloc.h"
39 
40 /*
41  * For debug purpose
42  */
43 
44 static int verbose = 0;
45 
46 void cineonSetVerbose(int verbosity)
47 {
48  verbose = verbosity;
49 }
50 
51 static void fillCineonMainHeader(LogImageFile *cineon,
52  CineonMainHeader *header,
53  const char *filename,
54  const char *creator)
55 {
56  time_t fileClock;
57  struct tm *fileTime;
58  int i;
59 
60  memset(header, 0, sizeof(CineonMainHeader));
61 
62  /* --- File header --- */
64  header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
67  cineon->isMSB);
68  header->fileHeader.ind_hdr_size = 0;
69  header->fileHeader.user_data_size = 0;
70  header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset +
71  cineon->height *
72  getRowLength(cineon->width, cineon->element[0]),
73  cineon->isMSB);
74  strcpy(header->fileHeader.version, "v4.5");
75  strncpy(header->fileHeader.file_name, filename, 99);
76  header->fileHeader.file_name[99] = 0;
77  fileClock = time(NULL);
78  fileTime = localtime(&fileClock);
79  strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
80  strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
81  header->fileHeader.creation_time[11] = 0;
82 
83  /* --- Image header --- */
84  header->imageHeader.orientation = 0;
85  header->imageHeader.elements_per_image = cineon->depth;
86 
87  for (i = 0; i < 3; i++) {
88  header->imageHeader.element[i].descriptor1 = 0;
89  header->imageHeader.element[i].descriptor2 = i;
91  header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB);
92  header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB);
94  cineon->isMSB);
96  cineon->isMSB);
98  cineon->isMSB);
100  cineon->element[0].refHighQuantity, cineon->isMSB);
101  }
102 
103  header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB);
104  header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB);
105  header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB);
106  header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB);
107  header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB);
108  header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB);
109  header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB);
110  header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB);
111  strncpy(header->imageHeader.label, creator, 199);
112  header->imageHeader.label[199] = 0;
113  header->imageHeader.interleave = 0;
114  header->imageHeader.data_sign = 0;
115  header->imageHeader.sense = 0;
116  header->imageHeader.line_padding = swap_uint(0, cineon->isMSB);
117  header->imageHeader.element_padding = swap_uint(0, cineon->isMSB);
118 
119  switch (cineon->element[0].packing) {
120  case 0:
121  header->imageHeader.packing = 0;
122  break;
123 
124  case 1:
125  header->imageHeader.packing = 5;
126  break;
127 
128  case 2:
129  header->imageHeader.packing = 6;
130  break;
131  }
132 
133  /* --- Origination header --- */
134  /* we leave it blank */
135 
136  /* --- Film header --- */
137  /* we leave it blank */
138 }
139 
140 LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
141 {
142  CineonMainHeader header;
143  LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
144  const char *filename = (const char *)byteStuff;
145  int i;
146  unsigned int dataOffset;
147 
148  if (cineon == NULL) {
149  if (verbose) {
150  printf("Cineon: Failed to malloc cineon file structure.\n");
151  }
152  return NULL;
153  }
154 
155  /* zero the header */
156  memset(&header, 0, sizeof(CineonMainHeader));
157 
158  /* for close routine */
159  cineon->file = NULL;
160 
161  if (fromMemory == 0) {
162  /* byteStuff is then the filename */
163  cineon->file = BLI_fopen(filename, "rb");
164  if (cineon->file == NULL) {
165  if (verbose) {
166  printf("Cineon: Failed to open file \"%s\".\n", filename);
167  }
168  logImageClose(cineon);
169  return NULL;
170  }
171  /* not used in this case */
172  cineon->memBuffer = NULL;
173  cineon->memCursor = NULL;
174  cineon->memBufferSize = 0;
175  }
176  else {
177  cineon->memBuffer = (unsigned char *)byteStuff;
178  cineon->memCursor = (unsigned char *)byteStuff;
179  cineon->memBufferSize = bufferSize;
180  }
181 
182  if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
183  if (verbose) {
184  printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
185  }
186  logImageClose(cineon);
187  return NULL;
188  }
189 
190  /* endianness determination */
191  if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
192  cineon->isMSB = 1;
193  if (verbose) {
194  printf("Cineon: File is MSB.\n");
195  }
196  }
197  else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
198  cineon->isMSB = 0;
199  if (verbose) {
200  printf("Cineon: File is LSB.\n");
201  }
202  }
203  else {
204  if (verbose) {
205  printf("Cineon: Bad magic number %lu in \"%s\".\n",
206  (unsigned long)header.fileHeader.magic_num,
207  byteStuff);
208  }
209  logImageClose(cineon);
210  return NULL;
211  }
212 
213  cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
214  cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
215 
216  if (cineon->width == 0 || cineon->height == 0) {
217  if (verbose) {
218  printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height);
219  }
220  logImageClose(cineon);
221  return NULL;
222  }
223 
224  cineon->depth = header.imageHeader.elements_per_image;
225  cineon->srcFormat = format_Cineon;
226 
227  if (header.imageHeader.interleave == 0) {
228  cineon->numElements = 1;
229  }
230  else if (header.imageHeader.interleave == 2) {
231  cineon->numElements = header.imageHeader.elements_per_image;
232  }
233  else {
234  if (verbose) {
235  printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
236  }
237  logImageClose(cineon);
238  return NULL;
239  }
240 
241  if (cineon->depth == 1) {
242  /* Grayscale image */
244  cineon->element[0].transfer = transfer_Linear;
245  cineon->element[0].depth = 1;
246  }
247  else if (cineon->depth == 3) {
248  /* RGB image */
249  if (cineon->numElements == 1) {
250  cineon->element[0].descriptor = descriptor_RGB;
252  cineon->element[0].depth = 3;
253  }
254  else if (cineon->numElements == 3) {
255  cineon->element[0].descriptor = descriptor_Red;
257  cineon->element[0].depth = 1;
258  cineon->element[1].descriptor = descriptor_Green;
260  cineon->element[1].depth = 1;
261  cineon->element[2].descriptor = descriptor_Blue;
263  cineon->element[2].depth = 1;
264  }
265  }
266  else {
267  if (verbose) {
268  printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
269  }
270  logImageClose(cineon);
271  return NULL;
272  }
273 
274  dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
275 
276  for (i = 0; i < cineon->numElements; i++) {
278  cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
280  cineon->isMSB);
282  cineon->isMSB);
284  cineon->isMSB);
285  cineon->element[i].refHighQuantity = swap_float(
286  header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);
287 
288  switch (header.imageHeader.packing) {
289  case 0:
290  cineon->element[i].packing = 0;
291  break;
292 
293  case 5:
294  cineon->element[i].packing = 1;
295  break;
296 
297  case 6:
298  cineon->element[i].packing = 2;
299  break;
300 
301  default:
302  /* Not supported */
303  if (verbose) {
304  printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
305  }
306  logImageClose(cineon);
307  return NULL;
308  }
309 
310  if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) {
311  cineon->element[i].refLowData = 0;
312  }
313 
314  if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) {
315  cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue;
316  }
317 
318  if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 ||
319  isnan(cineon->element[i].refLowQuantity)) {
320  cineon->element[i].refLowQuantity = 0.0f;
321  }
322 
323  if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 ||
324  isnan(cineon->element[i].refHighQuantity)) {
325  if (cineon->element[i].transfer == transfer_PrintingDensity) {
326  cineon->element[i].refHighQuantity = 2.048f;
327  }
328  else {
329  cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
330  }
331  }
332 
333  cineon->element[i].dataOffset = dataOffset;
334  dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
335  }
336 
337  cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
338  cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
339  cineon->gamma = 1.7f;
340 
341  if (verbose) {
342  printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
343  for (i = 0; i < cineon->numElements; i++) {
344  printf(" Element %d:\n", i);
345  printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample);
346  printf(" Depth: %d\n", cineon->element[i].depth);
347  printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
348  printf(" Packing: %d\n", cineon->element[i].packing);
349  printf(" Descriptor: %d\n", cineon->element[i].descriptor);
350  printf(" Data offset: %d\n", cineon->element[i].dataOffset);
351  printf(" Reference low data: %u\n", cineon->element[i].refLowData);
352  printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
353  printf(" Reference high data: %u\n", cineon->element[i].refHighData);
354  printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
355  printf("\n");
356  }
357 
358  printf("Gamma: %f\n", cineon->gamma);
359  printf("Reference black: %f\n", cineon->referenceBlack);
360  printf("Reference white: %f\n", cineon->referenceWhite);
361  printf("Orientation: %d\n", header.imageHeader.orientation);
362  printf("----------------------------\n");
363  }
364  return cineon;
365 }
366 
368  const char *filename, int width, int height, int bitsPerSample, const char *creator)
369 {
370  CineonMainHeader header;
371  const char *shortFilename = NULL;
372  /* unsigned char pad[6044]; */
373 
374  LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
375  if (cineon == NULL) {
376  if (verbose) {
377  printf("cineon: Failed to malloc cineon file structure.\n");
378  }
379  return NULL;
380  }
381 
382  /* Only 10 bits Cineon are supported */
383  if (bitsPerSample != 10) {
384  if (verbose) {
385  printf("cineon: Only 10 bits Cineon are supported.\n");
386  }
387  logImageClose(cineon);
388  return NULL;
389  }
390 
391  cineon->width = width;
392  cineon->height = height;
393  cineon->element[0].bitsPerSample = 10;
394  cineon->element[0].dataOffset = sizeof(CineonMainHeader);
395  cineon->element[0].maxValue = 1023;
396  cineon->isMSB = 1;
397  cineon->numElements = 1;
398  cineon->element[0].packing = 1;
399  cineon->depth = 3;
400  cineon->element[0].depth = 3;
401  cineon->element[0].descriptor = descriptor_RGB;
403  cineon->element[0].refHighQuantity = 2.048f;
404  cineon->element[0].refLowQuantity = 0;
405  cineon->element[0].refLowData = 0;
406  cineon->element[0].refHighData = cineon->element[0].maxValue;
407  cineon->referenceWhite = 685.0f;
408  cineon->referenceBlack = 95.0f;
409  cineon->gamma = 1.7f;
410 
411  shortFilename = strrchr(filename, '/');
412  if (shortFilename == NULL) {
413  shortFilename = filename;
414  }
415  else {
416  shortFilename++;
417  }
418 
419  cineon->file = BLI_fopen(filename, "wb");
420  if (cineon->file == NULL) {
421  if (verbose) {
422  printf("cineon: Couldn't open file %s\n", filename);
423  }
424  logImageClose(cineon);
425  return NULL;
426  }
427 
428  fillCineonMainHeader(cineon, &header, shortFilename, creator);
429 
430  if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
431  if (verbose) {
432  printf("cineon: Couldn't write image header\n");
433  }
434  logImageClose(cineon);
435  return NULL;
436  }
437 
438  return cineon;
439 }
File and directory operations.
FILE * BLI_fopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:1003
_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
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
Read Guarded memory(de)allocation.
static int verbose
Definition: cineonlib.c:44
void cineonSetVerbose(int verbosity)
Definition: cineonlib.c:46
static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, const char *filename, const char *creator)
Definition: cineonlib.c:51
LogImageFile * cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
Definition: cineonlib.c:140
LogImageFile * cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
Definition: cineonlib.c:367
#define CINEON_FILE_MAGIC
Definition: cineonlib.h:34
#define CINEON_UNDEFINED_U32
Definition: cineonlib.h:37
#define CINEON_UNDEFINED_R32
Definition: cineonlib.h:38
double time
#define powf(x, y)
void logImageClose(LogImageFile *logImage)
Definition: logImageCore.c:190
size_t getRowLength(size_t width, LogImageElement logElement)
Definition: logImageCore.c:212
@ format_Cineon
Definition: logImageCore.h:49
@ descriptor_Red
Definition: logImageCore.h:155
@ descriptor_Luminance
Definition: logImageCore.h:159
@ descriptor_Green
Definition: logImageCore.h:156
@ descriptor_Blue
Definition: logImageCore.h:157
@ descriptor_RGB
Definition: logImageCore.h:163
BLI_INLINE float swap_float(float x, int swap)
Definition: logImageCore.h:233
@ transfer_PrintingDensity
Definition: logImageCore.h:113
@ transfer_Linear
Definition: logImageCore.h:114
BLI_INLINE unsigned int swap_uint(unsigned int x, int swap)
Definition: logImageCore.h:223
int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile)
Definition: logmemfile.c:72
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
bool isnan(double i)
Definition: numeric.h:451
unsigned int ref_low_data
Definition: cineonlib.h:62
unsigned char descriptor2
Definition: cineonlib.h:57
unsigned int ref_high_data
Definition: cineonlib.h:64
unsigned int pixels_per_line
Definition: cineonlib.h:60
float ref_low_quantity
Definition: cineonlib.h:63
unsigned int lines_per_image
Definition: cineonlib.h:61
unsigned char bits_per_sample
Definition: cineonlib.h:58
unsigned char descriptor1
Definition: cineonlib.h:56
float ref_high_quantity
Definition: cineonlib.h:65
unsigned int file_size
Definition: cineonlib.h:47
char file_name[100]
Definition: cineonlib.h:49
char creation_time[12]
Definition: cineonlib.h:51
unsigned int magic_num
Definition: cineonlib.h:42
unsigned int offset
Definition: cineonlib.h:43
char version[8]
Definition: cineonlib.h:48
unsigned int gen_hdr_size
Definition: cineonlib.h:44
char creation_date[12]
Definition: cineonlib.h:50
unsigned int ind_hdr_size
Definition: cineonlib.h:45
unsigned int user_data_size
Definition: cineonlib.h:46
char label[200]
Definition: cineonlib.h:81
unsigned char packing
Definition: cineonlib.h:84
unsigned char sense
Definition: cineonlib.h:86
unsigned int line_padding
Definition: cineonlib.h:87
float blue_primary_x
Definition: cineonlib.h:79
unsigned char elements_per_image
Definition: cineonlib.h:70
float white_point_x
Definition: cineonlib.h:73
float red_primary_y
Definition: cineonlib.h:76
float blue_primary_y
Definition: cineonlib.h:80
unsigned char data_sign
Definition: cineonlib.h:85
unsigned char interleave
Definition: cineonlib.h:83
float green_primary_y
Definition: cineonlib.h:78
float red_primary_x
Definition: cineonlib.h:75
float green_primary_x
Definition: cineonlib.h:77
unsigned char orientation
Definition: cineonlib.h:69
CineonElementHeader element[8]
Definition: cineonlib.h:72
unsigned int element_padding
Definition: cineonlib.h:88
float white_point_y
Definition: cineonlib.h:74
CineonFileHeader fileHeader
Definition: cineonlib.h:123
CineonImageHeader imageHeader
Definition: cineonlib.h:124
unsigned int refLowData
Definition: logImageCore.h:59
float refLowQuantity
Definition: logImageCore.h:61
float refHighQuantity
Definition: logImageCore.h:62
unsigned int refHighData
Definition: logImageCore.h:60
uintptr_t memBufferSize
Definition: logImageCore.h:82
float referenceWhite
Definition: logImageCore.h:76
unsigned char * memBuffer
Definition: logImageCore.h:81
unsigned char * memCursor
Definition: logImageCore.h:83
LogImageElement element[8]
Definition: logImageCore.h:72
float referenceBlack
Definition: logImageCore.h:75