Blender V4.3
dpxlib.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 1999-2002 David Hodson <hodsond@acm.org>.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "dpxlib.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 dpxSetVerbose(int verbosity)
34{
35 verbose = verbosity;
36}
37
38/*
39 * Headers
40 */
41
43 DpxMainHeader *header,
44 const char *filename,
45 const char *creator)
46{
47 time_t fileClock;
48 const tm *fileTime;
49
50 memset(header, 0, sizeof(DpxMainHeader));
51
52 /* --- File header --- */
54 header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
55 STRNCPY(header->fileHeader.version, "V2.0");
57 dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, &dpx->element[0]),
58 dpx->isMSB);
59 header->fileHeader.ditto_key = 0;
61 sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB);
63 dpx->isMSB);
65 STRNCPY(header->fileHeader.file_name, filename);
66 fileClock = time(nullptr);
67 fileTime = localtime(&fileClock);
68 strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
69 header->fileHeader.creation_date[23] = 0;
70 STRNCPY(header->fileHeader.creator, creator);
71 header->fileHeader.project[0] = 0;
72 header->fileHeader.copyright[0] = 0;
73 header->fileHeader.key = 0xFFFFFFFF;
74
75 /* --- Image header --- */
76 header->imageHeader.orientation = 0;
78 header->imageHeader.pixels_per_line = swap_uint(dpx->width, dpx->isMSB);
80
81 /* Fills element */
82 header->imageHeader.element[0].data_sign = 0;
85 dpx->isMSB);
87 dpx->isMSB);
89 dpx->isMSB);
90 header->imageHeader.element[0].descriptor = dpx->element[0].descriptor;
91 header->imageHeader.element[0].transfer = dpx->element[0].transfer;
92 header->imageHeader.element[0].colorimetric = 0;
94 header->imageHeader.element[0].packing = swap_ushort(dpx->element[0].packing, dpx->isMSB);
95 header->imageHeader.element[0].encoding = 0;
97 header->imageHeader.element[0].line_padding = 0;
98 header->imageHeader.element[0].element_padding = 0;
99 header->imageHeader.element[0].description[0] = 0;
100
101 /* --- Orientation header --- */
102 /* we leave it blank */
103
104 /* --- Television header --- */
115 header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB);
121}
122
123LogImageFile *dpxOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
124{
125 DpxMainHeader header;
126 LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
127 const char *filepath = (const char *)byteStuff;
128 int i;
129
130 if (dpx == nullptr) {
131 if (verbose) {
132 printf("DPX: Failed to malloc dpx file structure.\n");
133 }
134 return nullptr;
135 }
136
137 /* zero the header */
138 memset(&header, 0, sizeof(DpxMainHeader));
139
140 /* for close routine */
141 dpx->file = nullptr;
142
143 if (fromMemory == 0) {
144 /* byteStuff is then the filepath */
145 dpx->file = BLI_fopen(filepath, "rb");
146 if (dpx->file == nullptr) {
147 if (verbose) {
148 printf("DPX: Failed to open file \"%s\".\n", filepath);
149 }
150 logImageClose(dpx);
151 return nullptr;
152 }
153 /* not used in this case */
154 dpx->memBuffer = nullptr;
155 dpx->memCursor = nullptr;
156 dpx->memBufferSize = 0;
157 }
158 else {
159 dpx->memBuffer = (uchar *)byteStuff;
160 dpx->memCursor = (uchar *)byteStuff;
161 dpx->memBufferSize = bufferSize;
162 }
163
164 if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
165 if (verbose) {
166 printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
167 }
168 logImageClose(dpx);
169 return nullptr;
170 }
171
172 /* endianness determination */
173 if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) {
174 dpx->isMSB = 1;
175 if (verbose) {
176 printf("DPX: File is MSB.\n");
177 }
178 }
179 else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) {
180 dpx->isMSB = 0;
181 if (verbose) {
182 printf("DPX: File is LSB.\n");
183 }
184 }
185 else {
186 if (verbose) {
187 printf("DPX: Bad magic number %u in \"%s\".\n", header.fileHeader.magic_num, byteStuff);
188 }
189 logImageClose(dpx);
190 return nullptr;
191 }
192
193 dpx->srcFormat = format_DPX;
195 size_t max_elements = ARRAY_SIZE(header.imageHeader.element);
196 if (dpx->numElements == 0 || dpx->numElements >= max_elements) {
197 if (verbose) {
198 printf("DPX: Wrong number of elements: %d\n", dpx->numElements);
199 }
200 logImageClose(dpx);
201 return nullptr;
202 }
203
204 dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
206
207 if (dpx->width == 0 || dpx->height == 0) {
208 if (verbose) {
209 printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height);
210 }
211 logImageClose(dpx);
212 return nullptr;
213 }
214
215 dpx->depth = 0;
216
217 for (i = 0; i < dpx->numElements; i++) {
218 dpx->element[i].descriptor = header.imageHeader.element[i].descriptor;
219
220 switch (dpx->element[i].descriptor) {
221 case descriptor_Red:
222 case descriptor_Green:
223 case descriptor_Blue:
224 case descriptor_Alpha:
227 dpx->depth++;
228 dpx->element[i].depth = 1;
229 break;
230
232 dpx->depth += 2;
233 dpx->element[i].depth = 2;
234 break;
235
236 case descriptor_RGB:
237 case descriptor_CbYCr:
239 dpx->depth += 3;
240 dpx->element[i].depth = 3;
241 break;
242
243 case descriptor_RGBA:
244 case descriptor_ABGR:
246 dpx->depth += 4;
247 dpx->element[i].depth = 4;
248 break;
249
250 case descriptor_Depth:
252 /* unsupported */
253 break;
254 }
255
256 if (dpx->depth == 0 || dpx->depth > 4) {
257 if (verbose) {
258 printf("DPX: Unsupported image depth: %d\n", dpx->depth);
259 }
260 logImageClose(dpx);
261 return nullptr;
262 }
263
265 if (!ELEM(dpx->element[i].bitsPerSample, 1, 8, 10, 12, 16)) {
266 if (verbose) {
267 printf("DPX: Unsupported bitsPerSample for elements %d: %d\n",
268 i,
269 dpx->element[i].bitsPerSample);
270 }
271 logImageClose(dpx);
272 return nullptr;
273 }
274
275 dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f;
276
277 dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB);
278 if (dpx->element[i].packing > 2) {
279 if (verbose) {
280 printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing);
281 }
282 logImageClose(dpx);
283 return nullptr;
284 }
285
286 /* Sometimes, the offset is not set correctly in the header */
288 if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) {
289 dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB);
290 }
291
292 if (dpx->element[i].dataOffset == 0) {
293 if (verbose) {
294 printf("DPX: Image header is corrupted.\n");
295 }
296 logImageClose(dpx);
297 return nullptr;
298 }
299
300 dpx->element[i].transfer = header.imageHeader.element[i].transfer;
301
302 /* if undefined, assign default */
305 dpx->isMSB);
307 dpx->isMSB);
309 dpx->isMSB);
310
311 switch (dpx->element[i].descriptor) {
312 case descriptor_Red:
313 case descriptor_Green:
314 case descriptor_Blue:
315 case descriptor_Alpha:
316 case descriptor_RGB:
317 case descriptor_RGBA:
318 case descriptor_ABGR:
319 if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) {
320 dpx->element[i].refLowData = 0;
321 }
322
323 if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) {
324 dpx->element[i].refHighData = uint(dpx->element[i].maxValue);
325 }
326
328 dpx->element[i].refLowQuantity = 0.0f;
329 }
330
333 dpx->element[i].refHighQuantity = 2.048f;
334 }
335 else {
336 dpx->element[i].refHighQuantity = dpx->element[i].maxValue;
337 }
338 }
339
340 break;
341
345 case descriptor_CbYCr:
348 if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) {
349 dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue;
350 }
351
352 if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) {
353 dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue;
354 }
355
357 dpx->element[i].refLowQuantity = 0.0f;
358 }
359
361 dpx->element[i].refHighQuantity = 0.7f;
362 }
363
364 break;
365
366 default:
367 break;
368 }
369 }
370
373 dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB);
374
377 (dpx->gamma <= 0 || IS_DPX_UNDEFINED_R32(dpx->gamma)))
378 {
379 dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
380 dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
381 dpx->gamma = 1.7f;
382 }
383
384 if (verbose) {
385 printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements);
386 for (i = 0; i < dpx->numElements; i++) {
387 printf(" Element %d:\n", i);
388 printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample);
389 printf(" Depth: %d\n", dpx->element[i].depth);
390 printf(" Transfer characteristics: %d\n", dpx->element[i].transfer);
391 printf(" Packing: %d\n", dpx->element[i].packing);
392 printf(" Descriptor: %d\n", dpx->element[i].descriptor);
393 printf(" Data offset: %d\n", dpx->element[i].dataOffset);
394 printf(" Reference low data: %u\n", dpx->element[i].refLowData);
395 printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity);
396 printf(" Reference high data: %u\n", dpx->element[i].refHighData);
397 printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity);
398 printf("\n");
399 }
400
401 printf("Gamma: %f\n", dpx->gamma);
402 printf("Reference black: %f\n", dpx->referenceBlack);
403 printf("Reference white: %f\n", dpx->referenceWhite);
404 printf("Orientation: %d\n", header.imageHeader.orientation);
405 printf("----------------------------\n");
406 }
407 return dpx;
408}
409
410LogImageFile *dpxCreate(const char *filepath,
411 int width,
412 int height,
413 int bitsPerSample,
414 int hasAlpha,
415 int isLogarithmic,
416 int referenceWhite,
417 int referenceBlack,
418 float gamma,
419 const char *creator)
420{
421 DpxMainHeader header;
422 const char *shortFilename = nullptr;
423 uchar pad[6044];
424
425 LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
426 if (dpx == nullptr) {
427 if (verbose) {
428 printf("DPX: Failed to malloc dpx file structure.\n");
429 }
430 return nullptr;
431 }
432
433 dpx->width = width;
434 dpx->height = height;
435 dpx->element[0].bitsPerSample = bitsPerSample;
436 dpx->element[0].dataOffset = 8092;
437 dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f;
438 dpx->isMSB = 1;
439 dpx->numElements = 1;
440
441 switch (bitsPerSample) {
442 case 8:
443 case 16:
444 dpx->element[0].packing = 0;
445 break;
446
447 case 10:
448 case 12:
449 /* Packed Type A padding is the most common 10/12 bits format */
450 dpx->element[0].packing = 1;
451 break;
452
453 default:
454 if (verbose) {
455 printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample);
456 }
457 logImageClose(dpx);
458 return nullptr;
459 }
460
461 if (hasAlpha == 0) {
462 dpx->depth = 3;
463 dpx->element[0].depth = 3;
465 }
466 else {
467 dpx->depth = 4;
468 dpx->element[0].depth = 4;
470 }
471
472 if (isLogarithmic == 0) {
474 dpx->element[0].refHighQuantity = dpx->element[0].maxValue;
475 }
476 else {
478 dpx->element[0].refHighQuantity = 2.048f;
479 }
480
481 dpx->element[0].refLowQuantity = 0;
482 dpx->element[0].refLowData = 0;
483 dpx->element[0].refHighData = dpx->element[0].maxValue;
484
485 if (referenceWhite > 0) {
486 dpx->referenceWhite = referenceWhite;
487 }
488 else {
489 dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
490 }
491
492 if (referenceBlack > 0) {
493 dpx->referenceBlack = referenceBlack;
494 }
495 else {
496 dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
497 }
498
499 if (gamma > 0.0f) {
500 dpx->gamma = gamma;
501 }
502 else {
503 dpx->gamma = 1.7f;
504 }
505
506 shortFilename = strrchr(filepath, PATHSEP_CHAR);
507 if (shortFilename == nullptr) {
508 shortFilename = filepath;
509 }
510 else {
511 shortFilename++;
512 }
513
514 dpx->file = BLI_fopen(filepath, "wb");
515
516 if (dpx->file == nullptr) {
517 if (verbose) {
518 printf("DPX: Couldn't open file %s\n", filepath);
519 }
520 logImageClose(dpx);
521 return nullptr;
522 }
523
524 fillDpxMainHeader(dpx, &header, shortFilename, creator);
525
526 if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
527 if (verbose) {
528 printf("DPX: Couldn't write image header\n");
529 }
530 logImageClose(dpx);
531 return nullptr;
532 }
533
534 /* Header should be rounded to next 8k block
535 * 6044 = 8092 - sizeof(DpxMainHeader) */
536 memset(&pad, 0, 6044);
537 if (fwrite(&pad, 6044, 1, dpx->file) == 0) {
538 if (verbose) {
539 printf("DPX: Couldn't write image header\n");
540 }
541 logImageClose(dpx);
542 return nullptr;
543 }
544
545 return dpx;
546}
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 int uint
#define ARRAY_SIZE(arr)
#define ELEM(...)
Read Guarded memory(de)allocation.
int pad[32 - sizeof(int)]
#define printf
double time
#define powf(x, y)
void dpxSetVerbose(int verbosity)
Definition dpxlib.cc:33
static int verbose
Definition dpxlib.cc:31
static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator)
Definition dpxlib.cc:42
LogImageFile * dpxCreate(const char *filepath, int width, int height, int bitsPerSample, int hasAlpha, int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, const char *creator)
Definition dpxlib.cc:410
LogImageFile * dpxOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
Definition dpxlib.cc:123
#define DPX_UNDEFINED_U32
Definition dpxlib.h:24
#define DPX_UNDEFINED_U8
Definition dpxlib.h:22
#define DPX_UNDEFINED_R32
Definition dpxlib.h:25
#define IS_DPX_UNDEFINED_R32(x)
Definition dpxlib.h:26
#define DPX_FILE_MAGIC
Definition dpxlib.h:21
static size_t getRowLength(size_t width, const LogImageElement &logElement)
void logImageClose(LogImageFile *logImage)
@ format_DPX
@ descriptor_Chrominance
@ descriptor_CbYCr
@ descriptor_Red
@ descriptor_Composite
@ descriptor_Depth
@ descriptor_CbYCrA
@ descriptor_Luminance
@ descriptor_Green
@ descriptor_ABGR
@ descriptor_CbYCrY
@ descriptor_Blue
@ descriptor_RGB
@ descriptor_CbYACrYA
@ descriptor_Alpha
@ descriptor_RGBA
BLI_INLINE float swap_float(float x, int swap)
@ transfer_PrintingDensity
@ transfer_Linear
@ transfer_Logarithmic
BLI_INLINE unsigned short swap_ushort(unsigned short x, int swap)
#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 line_padding
Definition dpxlib.h:60
unsigned int ref_low_data
Definition dpxlib.h:49
float ref_high_quantity
Definition dpxlib.h:52
unsigned int element_padding
Definition dpxlib.h:61
unsigned int data_offset
Definition dpxlib.h:59
unsigned char bits_per_sample
Definition dpxlib.h:56
unsigned short encoding
Definition dpxlib.h:58
unsigned short packing
Definition dpxlib.h:57
unsigned char colorimetric
Definition dpxlib.h:55
unsigned char transfer
Definition dpxlib.h:54
unsigned int ref_high_data
Definition dpxlib.h:51
float ref_low_quantity
Definition dpxlib.h:50
unsigned int data_sign
Definition dpxlib.h:48
char description[32]
Definition dpxlib.h:62
unsigned char descriptor
Definition dpxlib.h:53
unsigned int file_size
Definition dpxlib.h:33
unsigned int magic_num
Definition dpxlib.h:30
char copyright[200]
Definition dpxlib.h:42
char version[8]
Definition dpxlib.h:32
unsigned int user_data_size
Definition dpxlib.h:37
unsigned int key
Definition dpxlib.h:43
unsigned int ind_hdr_size
Definition dpxlib.h:36
char file_name[100]
Definition dpxlib.h:38
char project[200]
Definition dpxlib.h:41
unsigned int offset
Definition dpxlib.h:31
unsigned int ditto_key
Definition dpxlib.h:34
unsigned int gen_hdr_size
Definition dpxlib.h:35
char creation_date[24]
Definition dpxlib.h:39
char creator[100]
Definition dpxlib.h:40
DpxElementHeader element[8]
Definition dpxlib.h:70
unsigned int lines_per_element
Definition dpxlib.h:69
unsigned int pixels_per_line
Definition dpxlib.h:68
unsigned short elements_per_image
Definition dpxlib.h:67
unsigned short orientation
Definition dpxlib.h:66
DpxFileHeader fileHeader
Definition dpxlib.h:128
DpxTelevisionHeader televisionHeader
Definition dpxlib.h:132
DpxImageHeader imageHeader
Definition dpxlib.h:129
unsigned char interlace
Definition dpxlib.h:110
unsigned int time_code
Definition dpxlib.h:108
unsigned char padding
Definition dpxlib.h:113
float horizontal_sample_rate
Definition dpxlib.h:114
unsigned int user_bits
Definition dpxlib.h:109
float vertical_sample_rate
Definition dpxlib.h:115
unsigned char field_number
Definition dpxlib.h:111
float integration_times
Definition dpxlib.h:123
unsigned char video_signal
Definition dpxlib.h:112
unsigned int refLowData
unsigned int refHighData
uintptr_t memBufferSize
float referenceWhite
unsigned char * memBuffer
unsigned char * memCursor
LogImageElement element[8]
float referenceBlack