Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: 2006 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
.
..
../..
)
set(INC_SYS
)
set(SRC
cineonlib.h
dpxlib.h
logImageCore.h
logmemfile.h
cineon_dpx.cc
cineonlib.cc
dpxlib.cc
logImageCore.cc
logmemfile.cc
)
set(LIB
PRIVATE bf::blenkernel
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
)
if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_IMAGE_CINEON)
endif()
blender_add_lib(bf_imbuf_cineon "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -0,0 +1,8 @@
Files:
logImageLib.h, logImageLib.c: combined cineon/dpx image library
dpxlib.h, dpxlib.c: dpx specific library
dpxfile.h: dpx file structure
cineonlib.h, cineonlib.c: cineon specific library
cineonfile.h: cineon file structure
logImageCore.h, logImageCore.c: log image routines common to cineon amd dpx

View File

@@ -0,0 +1,196 @@
/* SPDX-FileCopyrightText: 2006 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*/
#include "logImageCore.h"
#include <cstdio>
#include <cstring>
#include "IMB_colormanagement.hh"
#include "IMB_filetype.hh"
#include "IMB_imbuf.hh"
#include "IMB_imbuf_types.hh"
#include "BKE_global.hh"
#include "MEM_guardedalloc.h"
namespace blender {
static ImBuf *imb_load_dpx_cineon(const uchar *mem,
size_t size,
int use_cineon,
ImBufFlags flags,
ImFileColorSpace &r_colorspace)
{
ImBuf *ibuf;
LogImageFile *image;
int width, height, depth;
logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0);
image = logImageOpenFromMemory(mem, size);
if (image == nullptr) {
printf("DPX/Cineon: error opening image.\n");
return nullptr;
}
logImageGetSize(image, &width, &height, &depth);
ibuf = IMB_allocImBuf(width, height, ImBufFlags::FloatData | flags);
if (ibuf == nullptr) {
logImageClose(image);
return nullptr;
}
if (!flag_is_set(flags, ImBufFlags::Test)) {
if (logImageGetDataRGBA(image, ibuf->float_data_for_write(), 1) != 0) {
logImageClose(image);
IMB_freeImBuf(ibuf);
return nullptr;
}
IMB_flipy(ibuf);
}
logImageClose(image);
ibuf->ftype = use_cineon ? IMB_FTYPE_CINEON : IMB_FTYPE_DPX;
if (flag_is_set(flags, ImBufFlags::AlphaDetect)) {
ibuf->flags |= ImBufFlags::AlphaPremul;
}
r_colorspace.is_hdr_float = true;
return ibuf;
}
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filepath, int use_cineon)
{
LogImageFile *logImage;
float *fbuf;
float *fbuf_ptr;
const uchar *rect_ptr;
int x, y, bitspersample, rvalue;
logImageSetVerbose((G.debug & G_DEBUG) ? 1 : 0);
if (!ELEM(ibuf->color_mode, ImColorMode::RGB, ImColorMode::RGBA)) {
printf("DPX/Cineon: only RGB/RGBA is supported, file: '%s'\n", filepath);
return 0;
}
if (use_cineon) {
/* Only 10bit is supported. */
bitspersample = 10;
}
else {
if (ibuf->foptions.flag & CINEON_10BIT) {
bitspersample = 10;
}
else if (ibuf->foptions.flag & CINEON_12BIT) {
bitspersample = 12;
}
else if (ibuf->foptions.flag & CINEON_16BIT) {
bitspersample = 16;
}
else {
bitspersample = 8;
}
}
const bool has_alpha = ibuf->color_mode == ImColorMode::RGBA;
logImage = logImageCreate(filepath,
use_cineon,
ibuf->x,
ibuf->y,
bitspersample,
has_alpha,
(ibuf->foptions.flag & CINEON_LOG),
-1,
-1,
-1,
"Blender");
if (logImage == nullptr) {
printf("DPX/Cineon: error creating file.\n");
return 0;
}
if (ibuf->float_data() != nullptr && bitspersample != 8) {
/* Don't use the float buffer to save 8 BPP picture to prevent color banding
* (there's no dithering algorithm behind the #logImageSetDataRGBA function). */
fbuf = MEM_new_array_uninitialized<float>(4 * size_t(ibuf->x) * size_t(ibuf->y),
"fbuf in imb_save_dpx_cineon");
for (y = 0; y < ibuf->y; y++) {
float *dst_ptr = fbuf + (4 * (size_t(ibuf->y - y - 1) * size_t(ibuf->x)));
const float *src_ptr = ibuf->float_data() + (4 * (size_t(y) * size_t(ibuf->x)));
memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float));
}
rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0);
MEM_delete(fbuf);
}
else {
if (ibuf->byte_data()) {
IMB_byte_from_float(ibuf);
}
fbuf = MEM_new_array_uninitialized<float>(4 * size_t(ibuf->x) * size_t(ibuf->y),
"fbuf in imb_save_dpx_cineon");
if (fbuf == nullptr) {
printf("DPX/Cineon: error allocating memory.\n");
logImageClose(logImage);
return 0;
}
const uint8_t *byte_data = ibuf->byte_data();
for (y = 0; y < ibuf->y; y++) {
fbuf_ptr = fbuf + (4 * (size_t(ibuf->y - y - 1) * size_t(ibuf->x)));
rect_ptr = byte_data + (4 * (size_t(y) * size_t(ibuf->x)));
for (x = 0; x < ibuf->x; x++) {
fbuf_ptr[0] = float(rect_ptr[0]) / 255.0f;
fbuf_ptr[1] = float(rect_ptr[1]) / 255.0f;
fbuf_ptr[2] = float(rect_ptr[2]) / 255.0f;
fbuf_ptr[3] = has_alpha ? (float(rect_ptr[3]) / 255.0f) : 1.0f;
fbuf_ptr += 4;
rect_ptr += 4;
}
}
rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0);
MEM_delete(fbuf);
}
logImageClose(logImage);
return rvalue;
}
bool imb_save_cineon(ImBuf *buf, const char *filepath, ImBufFlags /*flags*/)
{
return imb_save_dpx_cineon(buf, filepath, 1);
}
bool imb_is_a_cineon(const uchar *mem, size_t size)
{
return logImageIsCineon(mem, size);
}
ImBuf *imb_load_cineon(const uchar *mem,
size_t size,
ImBufFlags flags,
ImFileColorSpace &r_colorspace)
{
if (!imb_is_a_cineon(mem, size)) {
return nullptr;
}
return imb_load_dpx_cineon(mem, size, 1, flags, r_colorspace);
}
} // namespace blender

View File

@@ -0,0 +1,429 @@
/* SPDX-FileCopyrightText: 1999-2001 David Hodson <hodsond@acm.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* Cineon image file format library routines.
*/
#include "cineonlib.h"
#include "logmemfile.h"
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <sys/types.h>
#include "BLI_fileops.h"
#include "BLI_string.h"
#include "MEM_guardedalloc.h"
namespace blender {
/*
* For debug purpose
*/
static int verbose = 0;
void cineonSetVerbose(int verbosity)
{
verbose = verbosity;
}
static void fillCineonMainHeader(LogImageFile *cineon,
CineonMainHeader *header,
const char *filepath,
const char *creator)
{
time_t fileClock;
const tm *fileTime;
int i;
memset(header, 0, sizeof(CineonMainHeader));
/* --- File header --- */
header->fileHeader.magic_num = swap_uint(CINEON_FILE_MAGIC, cineon->isMSB);
header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB);
header->fileHeader.gen_hdr_size = swap_uint(
sizeof(CineonFileHeader) + sizeof(CineonImageHeader) + sizeof(CineonOriginationHeader),
cineon->isMSB);
header->fileHeader.ind_hdr_size = 0;
header->fileHeader.user_data_size = 0;
header->fileHeader.file_size = swap_uint(
cineon->element[0].dataOffset +
cineon->height * getRowLength(cineon->width, &cineon->element[0]),
cineon->isMSB);
STRNCPY(header->fileHeader.version, "v4.5");
STRNCPY(header->fileHeader.file_name, filepath);
fileClock = time(nullptr);
fileTime = localtime(&fileClock);
strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
header->fileHeader.creation_time[11] = 0;
/* --- Image header --- */
header->imageHeader.orientation = 0;
header->imageHeader.elements_per_image = cineon->depth;
for (i = 0; i < 3; i++) {
header->imageHeader.element[i].descriptor1 = 0;
header->imageHeader.element[i].descriptor2 = i;
header->imageHeader.element[i].bits_per_sample = cineon->element[0].bitsPerSample;
header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB);
header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB);
header->imageHeader.element[i].ref_low_data = swap_uint(cineon->element[0].refLowData,
cineon->isMSB);
header->imageHeader.element[i].ref_low_quantity = swap_float(cineon->element[0].refLowQuantity,
cineon->isMSB);
header->imageHeader.element[i].ref_high_data = swap_uint(cineon->element[0].refHighData,
cineon->isMSB);
header->imageHeader.element[i].ref_high_quantity = swap_float(
cineon->element[0].refHighQuantity, cineon->isMSB);
}
header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB);
header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB);
header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB);
header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB);
header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB);
header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB);
header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB);
header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB);
STRNCPY(header->imageHeader.label, creator);
header->imageHeader.interleave = 0;
header->imageHeader.data_sign = 0;
header->imageHeader.sense = 0;
header->imageHeader.line_padding = swap_uint(0, cineon->isMSB);
header->imageHeader.element_padding = swap_uint(0, cineon->isMSB);
switch (cineon->element[0].packing) {
case 0:
header->imageHeader.packing = 0;
break;
case 1:
header->imageHeader.packing = 5;
break;
case 2:
header->imageHeader.packing = 6;
break;
}
/* --- Origination header --- */
/* we leave it blank */
/* --- Film header --- */
/* we leave it blank */
}
LogImageFile *cineonOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
{
CineonMainHeader header;
LogImageFile *cineon = MEM_new_uninitialized<LogImageFile>(__func__);
const char *filepath = reinterpret_cast<const char *>(byteStuff);
int i;
uint dataOffset;
if (cineon == nullptr) {
if (verbose) {
printf("Cineon: Failed to malloc cineon file structure.\n");
}
return nullptr;
}
/* zero the header */
memset(&header, 0, sizeof(CineonMainHeader));
/* for close routine */
cineon->file = nullptr;
if (fromMemory == 0) {
/* byteStuff is then the filepath */
cineon->file = BLI_fopen(filepath, "rb");
if (cineon->file == nullptr) {
if (verbose) {
printf("Cineon: Failed to open file \"%s\".\n", filepath);
}
logImageClose(cineon);
return nullptr;
}
/* not used in this case */
cineon->memBuffer = nullptr;
cineon->memCursor = nullptr;
cineon->memBufferSize = 0;
}
else {
cineon->memBuffer = const_cast<uchar *>(byteStuff);
cineon->memCursor = const_cast<uchar *>(byteStuff);
cineon->memBufferSize = bufferSize;
}
if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
if (verbose) {
printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
}
logImageClose(cineon);
return nullptr;
}
/* endianness determination */
if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) {
cineon->isMSB = 1;
if (verbose) {
printf("Cineon: File is MSB.\n");
}
}
else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) {
cineon->isMSB = 0;
if (verbose) {
printf("Cineon: File is LSB.\n");
}
}
else {
if (verbose) {
printf("Cineon: Bad magic number %lu in \"%s\".\n",
ulong(header.fileHeader.magic_num),
byteStuff);
}
logImageClose(cineon);
return nullptr;
}
cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
if (cineon->width == 0 || cineon->height == 0) {
if (verbose) {
printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height);
}
logImageClose(cineon);
return nullptr;
}
cineon->depth = header.imageHeader.elements_per_image;
cineon->srcFormat = format_Cineon;
if (header.imageHeader.interleave == 0) {
cineon->numElements = 1;
}
else if (header.imageHeader.interleave == 2) {
cineon->numElements = header.imageHeader.elements_per_image;
}
else {
if (verbose) {
printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
}
logImageClose(cineon);
return nullptr;
}
if (cineon->depth == 1) {
/* Gray-scale image. */
cineon->element[0].descriptor = descriptor_Luminance;
cineon->element[0].transfer = transfer_Linear;
cineon->element[0].depth = 1;
}
else if (cineon->depth == 3) {
/* RGB image. */
if (cineon->numElements == 1) {
cineon->element[0].descriptor = descriptor_RGB;
cineon->element[0].transfer = transfer_PrintingDensity;
cineon->element[0].depth = 3;
}
else if (cineon->numElements == 3) {
cineon->element[0].descriptor = descriptor_Red;
cineon->element[0].transfer = transfer_PrintingDensity;
cineon->element[0].depth = 1;
cineon->element[1].descriptor = descriptor_Green;
cineon->element[1].transfer = transfer_PrintingDensity;
cineon->element[1].depth = 1;
cineon->element[2].descriptor = descriptor_Blue;
cineon->element[2].transfer = transfer_PrintingDensity;
cineon->element[2].depth = 1;
}
}
else {
if (verbose) {
printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
}
logImageClose(cineon);
return nullptr;
}
dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
for (i = 0; i < cineon->numElements; i++) {
cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f;
cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data,
cineon->isMSB);
cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity,
cineon->isMSB);
cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data,
cineon->isMSB);
cineon->element[i].refHighQuantity = swap_float(
header.imageHeader.element[i].ref_high_quantity, cineon->isMSB);
switch (header.imageHeader.packing) {
case 0:
cineon->element[i].packing = 0;
break;
case 5:
cineon->element[i].packing = 1;
break;
case 6:
cineon->element[i].packing = 2;
break;
default:
/* Not supported */
if (verbose) {
printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
}
logImageClose(cineon);
return nullptr;
}
if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32) {
cineon->element[i].refLowData = 0;
}
if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32) {
cineon->element[i].refHighData = uint(cineon->element[i].maxValue);
}
if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 ||
std::isnan(cineon->element[i].refLowQuantity))
{
cineon->element[i].refLowQuantity = 0.0f;
}
if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 ||
std::isnan(cineon->element[i].refHighQuantity))
{
if (cineon->element[i].transfer == transfer_PrintingDensity) {
cineon->element[i].refHighQuantity = 2.048f;
}
else {
cineon->element[i].refHighQuantity = cineon->element[i].maxValue;
}
}
cineon->element[i].dataOffset = dataOffset;
dataOffset += cineon->height * getRowLength(cineon->width, &cineon->element[i]);
}
cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue;
cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue;
cineon->gamma = 1.7f;
if (verbose) {
printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements);
for (i = 0; i < cineon->numElements; i++) {
printf(" Element %d:\n", i);
printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample);
printf(" Depth: %d\n", cineon->element[i].depth);
printf(" Transfer characteristics: %d\n", cineon->element[i].transfer);
printf(" Packing: %d\n", cineon->element[i].packing);
printf(" Descriptor: %d\n", cineon->element[i].descriptor);
printf(" Data offset: %d\n", cineon->element[i].dataOffset);
printf(" Reference low data: %u\n", cineon->element[i].refLowData);
printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity);
printf(" Reference high data: %u\n", cineon->element[i].refHighData);
printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity);
printf("\n");
}
printf("Gamma: %f\n", cineon->gamma);
printf("Reference black: %f\n", cineon->referenceBlack);
printf("Reference white: %f\n", cineon->referenceWhite);
printf("Orientation: %d\n", header.imageHeader.orientation);
printf("----------------------------\n");
}
return cineon;
}
LogImageFile *cineonCreate(
const char *filepath, int width, int height, int bitsPerSample, const char *creator)
{
CineonMainHeader header;
const char *shortFilename = nullptr;
// uchar pad[6044];
LogImageFile *cineon = MEM_new_uninitialized<LogImageFile>(__func__);
if (cineon == nullptr) {
if (verbose) {
printf("cineon: Failed to malloc cineon file structure.\n");
}
return nullptr;
}
/* Only 10 bits Cineon are supported */
if (bitsPerSample != 10) {
if (verbose) {
printf("cineon: Only 10 bits Cineon are supported.\n");
}
logImageClose(cineon);
return nullptr;
}
cineon->width = width;
cineon->height = height;
cineon->element[0].bitsPerSample = 10;
cineon->element[0].dataOffset = sizeof(CineonMainHeader);
cineon->element[0].maxValue = 1023;
cineon->isMSB = 1;
cineon->numElements = 1;
cineon->element[0].packing = 1;
cineon->depth = 3;
cineon->element[0].depth = 3;
cineon->element[0].descriptor = descriptor_RGB;
cineon->element[0].transfer = transfer_PrintingDensity;
cineon->element[0].refHighQuantity = 2.048f;
cineon->element[0].refLowQuantity = 0;
cineon->element[0].refLowData = 0;
cineon->element[0].refHighData = cineon->element[0].maxValue;
cineon->referenceWhite = 685.0f;
cineon->referenceBlack = 95.0f;
cineon->gamma = 1.7f;
shortFilename = strrchr(filepath, PATHSEP_CHAR);
if (shortFilename == nullptr) {
shortFilename = filepath;
}
else {
shortFilename++;
}
cineon->file = BLI_fopen(filepath, "wb");
if (cineon->file == nullptr) {
if (verbose) {
printf("cineon: Couldn't open file %s\n", filepath);
}
logImageClose(cineon);
return nullptr;
}
fillCineonMainHeader(cineon, &header, shortFilename, creator);
if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
if (verbose) {
printf("cineon: Couldn't write image header\n");
}
logImageClose(cineon);
return nullptr;
}
return cineon;
}
} // namespace blender

View File

@@ -0,0 +1,118 @@
/* SPDX-FileCopyrightText: 1999-2001 David Hodson <hodsond@acm.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* Cineon image file format library definitions.
* Also handles DPX files (almost)
*/
#pragma once
#include "logImageCore.h"
namespace blender {
#define CINEON_FILE_MAGIC 0x802A5FD7
#define CINEON_UNDEFINED_U8 0xFF
#define CINEON_UNDEFINED_U16 0xFFFF
#define CINEON_UNDEFINED_U32 0xFFFFFFFF
#define CINEON_UNDEFINED_R32 0x7F800000
#define CINEON_UNDEFINED_CHAR 0
struct CineonFileHeader {
unsigned int magic_num;
unsigned int offset;
unsigned int gen_hdr_size;
unsigned int ind_hdr_size;
unsigned int user_data_size;
unsigned int file_size;
char version[8];
char file_name[100];
char creation_date[12];
char creation_time[12];
char reserved[36];
};
struct CineonElementHeader {
uchar descriptor1;
uchar descriptor2;
uchar bits_per_sample;
uchar filler;
unsigned int pixels_per_line;
unsigned int lines_per_image;
unsigned int ref_low_data;
float ref_low_quantity;
unsigned int ref_high_data;
float ref_high_quantity;
};
struct CineonImageHeader {
uchar orientation;
uchar elements_per_image;
unsigned short filler;
CineonElementHeader element[8];
float white_point_x;
float white_point_y;
float red_primary_x;
float red_primary_y;
float green_primary_x;
float green_primary_y;
float blue_primary_x;
float blue_primary_y;
char label[200];
char reserved[28];
uchar interleave;
uchar packing;
uchar data_sign;
uchar sense;
unsigned int line_padding;
unsigned int element_padding;
char reserved2[20];
};
struct CineonOriginationHeader {
int x_offset;
int y_offset;
char file_name[100];
char creation_date[12];
char creation_time[12];
char input_device[64];
char model_number[32];
char input_serial_number[32];
float x_input_samples_per_mm;
float y_input_samples_per_mm;
float input_device_gamma;
char reserved[40];
};
struct CineonFilmHeader {
uchar film_code;
uchar film_type;
uchar edge_code_perforation_offset;
uchar filler;
unsigned int prefix;
unsigned int count;
char format[32];
unsigned int frame_position;
float frame_rate;
char attribute[32];
char slate[200];
char reserved[740];
};
struct CineonMainHeader {
CineonFileHeader fileHeader;
CineonImageHeader imageHeader;
CineonOriginationHeader originationHeader;
CineonFilmHeader filmHeader;
};
void cineonSetVerbose(int);
LogImageFile *cineonOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize);
LogImageFile *cineonCreate(
const char *filepath, int width, int height, int bitsPerSample, const char *creator);
} // namespace blender

View File

@@ -0,0 +1,550 @@
/* SPDX-FileCopyrightText: 1999-2002 David Hodson <hodsond@acm.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* DPX image file format library routines.
*/
#include "dpxlib.h"
#include "logmemfile.h"
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <sys/types.h>
#include "BLI_fileops.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
namespace blender {
/*
* For debug purpose
*/
static int verbose = 0;
void dpxSetVerbose(int verbosity)
{
verbose = verbosity;
}
/*
* Headers
*/
static void fillDpxMainHeader(LogImageFile *dpx,
DpxMainHeader *header,
const char *filename,
const char *creator)
{
time_t fileClock;
const tm *fileTime;
memset(header, 0, sizeof(DpxMainHeader));
/* --- File header --- */
header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB);
header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
STRNCPY(header->fileHeader.version, "V2.0");
header->fileHeader.file_size = swap_uint(
dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, &dpx->element[0]),
dpx->isMSB);
header->fileHeader.ditto_key = 0;
header->fileHeader.gen_hdr_size = swap_uint(
sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB);
header->fileHeader.ind_hdr_size = swap_uint(sizeof(DpxFilmHeader) + sizeof(DpxTelevisionHeader),
dpx->isMSB);
header->fileHeader.user_data_size = DPX_UNDEFINED_U32;
STRNCPY(header->fileHeader.file_name, filename);
fileClock = time(nullptr);
fileTime = localtime(&fileClock);
strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
header->fileHeader.creation_date[23] = 0;
STRNCPY(header->fileHeader.creator, creator);
header->fileHeader.project[0] = 0;
header->fileHeader.copyright[0] = 0;
header->fileHeader.key = 0xFFFFFFFF;
/* --- Image header --- */
header->imageHeader.orientation = 0;
header->imageHeader.elements_per_image = swap_ushort(1, dpx->isMSB);
header->imageHeader.pixels_per_line = swap_uint(dpx->width, dpx->isMSB);
header->imageHeader.lines_per_element = swap_uint(dpx->height, dpx->isMSB);
/* Fills element */
header->imageHeader.element[0].data_sign = 0;
header->imageHeader.element[0].ref_low_data = swap_uint(dpx->element[0].refLowData, dpx->isMSB);
header->imageHeader.element[0].ref_low_quantity = swap_float(dpx->element[0].refLowQuantity,
dpx->isMSB);
header->imageHeader.element[0].ref_high_data = swap_uint(dpx->element[0].refHighData,
dpx->isMSB);
header->imageHeader.element[0].ref_high_quantity = swap_float(dpx->element[0].refHighQuantity,
dpx->isMSB);
header->imageHeader.element[0].descriptor = dpx->element[0].descriptor;
header->imageHeader.element[0].transfer = dpx->element[0].transfer;
header->imageHeader.element[0].colorimetric = 0;
header->imageHeader.element[0].bits_per_sample = dpx->element[0].bitsPerSample;
header->imageHeader.element[0].packing = swap_ushort(dpx->element[0].packing, dpx->isMSB);
header->imageHeader.element[0].encoding = 0;
header->imageHeader.element[0].data_offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
header->imageHeader.element[0].line_padding = 0;
header->imageHeader.element[0].element_padding = 0;
header->imageHeader.element[0].description[0] = 0;
/* --- Orientation header --- */
/* we leave it blank */
/* --- Television header --- */
header->televisionHeader.time_code = DPX_UNDEFINED_U32;
header->televisionHeader.user_bits = DPX_UNDEFINED_U32;
header->televisionHeader.interlace = DPX_UNDEFINED_U8;
header->televisionHeader.field_number = DPX_UNDEFINED_U8;
header->televisionHeader.video_signal = DPX_UNDEFINED_U8;
header->televisionHeader.padding = DPX_UNDEFINED_U8;
header->televisionHeader.horizontal_sample_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.vertical_sample_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.frame_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.time_offset = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB);
header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB);
header->televisionHeader.black_gain = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.breakpoint = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB);
header->televisionHeader.integration_times = swap_float(DPX_UNDEFINED_R32, dpx->isMSB);
}
LogImageFile *dpxOpen(const uchar *byteStuff, int fromMemory, size_t bufferSize)
{
DpxMainHeader header;
LogImageFile *dpx = MEM_new_uninitialized<LogImageFile>(__func__);
const char *filepath = reinterpret_cast<const char *>(byteStuff);
int i;
if (dpx == nullptr) {
if (verbose) {
printf("DPX: Failed to malloc dpx file structure.\n");
}
return nullptr;
}
/* zero the header */
memset(&header, 0, sizeof(DpxMainHeader));
/* for close routine */
dpx->file = nullptr;
if (fromMemory == 0) {
/* byteStuff is then the filepath */
dpx->file = BLI_fopen(filepath, "rb");
if (dpx->file == nullptr) {
if (verbose) {
printf("DPX: Failed to open file \"%s\".\n", filepath);
}
logImageClose(dpx);
return nullptr;
}
/* not used in this case */
dpx->memBuffer = nullptr;
dpx->memCursor = nullptr;
dpx->memBufferSize = 0;
}
else {
dpx->memBuffer = const_cast<uchar *>(byteStuff);
dpx->memCursor = const_cast<uchar *>(byteStuff);
dpx->memBufferSize = bufferSize;
}
if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
if (verbose) {
printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
}
logImageClose(dpx);
return nullptr;
}
/* endianness determination */
if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) {
dpx->isMSB = 1;
if (verbose) {
printf("DPX: File is MSB.\n");
}
}
else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) {
dpx->isMSB = 0;
if (verbose) {
printf("DPX: File is LSB.\n");
}
}
else {
if (verbose) {
printf("DPX: Bad magic number %u in \"%s\".\n", header.fileHeader.magic_num, byteStuff);
}
logImageClose(dpx);
return nullptr;
}
dpx->srcFormat = format_DPX;
dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
size_t max_elements = ARRAY_SIZE(header.imageHeader.element);
if (dpx->numElements == 0 || dpx->numElements >= max_elements) {
if (verbose) {
printf("DPX: Wrong number of elements: %d\n", dpx->numElements);
}
logImageClose(dpx);
return nullptr;
}
dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB);
if (dpx->width == 0 || dpx->height == 0) {
if (verbose) {
printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height);
}
logImageClose(dpx);
return nullptr;
}
dpx->depth = 0;
for (i = 0; i < dpx->numElements; i++) {
dpx->element[i].descriptor = header.imageHeader.element[i].descriptor;
switch (dpx->element[i].descriptor) {
case descriptor_Red:
case descriptor_Green:
case descriptor_Blue:
case descriptor_Alpha:
case descriptor_Luminance:
case descriptor_Chrominance:
dpx->depth++;
dpx->element[i].depth = 1;
break;
case descriptor_CbYCrY:
dpx->depth += 2;
dpx->element[i].depth = 2;
break;
case descriptor_RGB:
case descriptor_CbYCr:
case descriptor_CbYACrYA:
dpx->depth += 3;
dpx->element[i].depth = 3;
break;
case descriptor_RGBA:
case descriptor_ABGR:
case descriptor_CbYCrA:
dpx->depth += 4;
dpx->element[i].depth = 4;
break;
case descriptor_Depth:
case descriptor_Composite:
/* unsupported */
break;
}
if (dpx->depth == 0 || dpx->depth > 4) {
if (verbose) {
printf("DPX: Unsupported image depth: %d\n", dpx->depth);
}
logImageClose(dpx);
return nullptr;
}
dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
if (!ELEM(dpx->element[i].bitsPerSample, 1, 8, 10, 12, 16)) {
if (verbose) {
printf("DPX: Unsupported bitsPerSample for elements %d: %d\n",
i,
dpx->element[i].bitsPerSample);
}
logImageClose(dpx);
return nullptr;
}
dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f;
dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB);
if (dpx->element[i].packing > 2) {
if (verbose) {
printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing);
}
logImageClose(dpx);
return nullptr;
}
/* Sometimes, the offset is not set correctly in the header */
dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB);
if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) {
dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB);
}
if (dpx->element[i].dataOffset == 0) {
if (verbose) {
printf("DPX: Image header is corrupted.\n");
}
logImageClose(dpx);
return nullptr;
}
dpx->element[i].transfer = header.imageHeader.element[i].transfer;
/* if undefined, assign default */
dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB);
dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity,
dpx->isMSB);
dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data,
dpx->isMSB);
dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity,
dpx->isMSB);
switch (dpx->element[i].descriptor) {
case descriptor_Red:
case descriptor_Green:
case descriptor_Blue:
case descriptor_Alpha:
case descriptor_RGB:
case descriptor_RGBA:
case descriptor_ABGR:
if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) {
dpx->element[i].refLowData = 0;
}
if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) {
dpx->element[i].refHighData = uint(dpx->element[i].maxValue);
}
if (IS_DPX_UNDEFINED_R32(dpx->element[i].refLowQuantity)) {
dpx->element[i].refLowQuantity = 0.0f;
}
if (IS_DPX_UNDEFINED_R32(dpx->element[i].refHighQuantity)) {
if (ELEM(dpx->element[i].transfer, transfer_PrintingDensity, transfer_Logarithmic)) {
dpx->element[i].refHighQuantity = 2.048f;
}
else {
dpx->element[i].refHighQuantity = dpx->element[i].maxValue;
}
}
break;
case descriptor_Luminance:
case descriptor_Chrominance:
case descriptor_CbYCrY:
case descriptor_CbYCr:
case descriptor_CbYACrYA:
case descriptor_CbYCrA:
if (dpx->element[i].refLowData == DPX_UNDEFINED_U32) {
dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue;
}
if (dpx->element[i].refHighData == DPX_UNDEFINED_U32) {
dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue;
}
if (IS_DPX_UNDEFINED_R32(dpx->element[i].refLowQuantity)) {
dpx->element[i].refLowQuantity = 0.0f;
}
if (IS_DPX_UNDEFINED_R32(dpx->element[i].refHighQuantity)) {
dpx->element[i].refHighQuantity = 0.7f;
}
break;
default:
break;
}
}
dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB);
dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB);
dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB);
if (IS_DPX_UNDEFINED_R32(dpx->referenceBlack) ||
(dpx->referenceWhite <= dpx->referenceBlack || IS_DPX_UNDEFINED_R32(dpx->referenceWhite)) ||
(dpx->gamma <= 0 || IS_DPX_UNDEFINED_R32(dpx->gamma)))
{
dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
dpx->gamma = 1.7f;
}
if (verbose) {
printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements);
for (i = 0; i < dpx->numElements; i++) {
printf(" Element %d:\n", i);
printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample);
printf(" Depth: %d\n", dpx->element[i].depth);
printf(" Transfer characteristics: %d\n", dpx->element[i].transfer);
printf(" Packing: %d\n", dpx->element[i].packing);
printf(" Descriptor: %d\n", dpx->element[i].descriptor);
printf(" Data offset: %d\n", dpx->element[i].dataOffset);
printf(" Reference low data: %u\n", dpx->element[i].refLowData);
printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity);
printf(" Reference high data: %u\n", dpx->element[i].refHighData);
printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity);
printf("\n");
}
printf("Gamma: %f\n", dpx->gamma);
printf("Reference black: %f\n", dpx->referenceBlack);
printf("Reference white: %f\n", dpx->referenceWhite);
printf("Orientation: %d\n", header.imageHeader.orientation);
printf("----------------------------\n");
}
return dpx;
}
LogImageFile *dpxCreate(const char *filepath,
int width,
int height,
int bitsPerSample,
int hasAlpha,
int isLogarithmic,
int referenceWhite,
int referenceBlack,
float gamma,
const char *creator)
{
DpxMainHeader header;
const char *shortFilename = nullptr;
uchar pad[6044];
LogImageFile *dpx = MEM_new_uninitialized<LogImageFile>(__func__);
if (dpx == nullptr) {
if (verbose) {
printf("DPX: Failed to malloc dpx file structure.\n");
}
return nullptr;
}
dpx->width = width;
dpx->height = height;
dpx->element[0].bitsPerSample = bitsPerSample;
dpx->element[0].dataOffset = 8092;
dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f;
dpx->isMSB = 1;
dpx->numElements = 1;
switch (bitsPerSample) {
case 8:
case 16:
dpx->element[0].packing = 0;
break;
case 10:
case 12:
/* Packed Type A padding is the most common 10/12 bits format */
dpx->element[0].packing = 1;
break;
default:
if (verbose) {
printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample);
}
logImageClose(dpx);
return nullptr;
}
if (hasAlpha == 0) {
dpx->depth = 3;
dpx->element[0].depth = 3;
dpx->element[0].descriptor = descriptor_RGB;
}
else {
dpx->depth = 4;
dpx->element[0].depth = 4;
dpx->element[0].descriptor = descriptor_RGBA;
}
if (isLogarithmic == 0) {
dpx->element[0].transfer = transfer_Linear;
dpx->element[0].refHighQuantity = dpx->element[0].maxValue;
}
else {
dpx->element[0].transfer = transfer_PrintingDensity;
dpx->element[0].refHighQuantity = 2.048f;
}
dpx->element[0].refLowQuantity = 0;
dpx->element[0].refLowData = 0;
dpx->element[0].refHighData = dpx->element[0].maxValue;
if (referenceWhite > 0) {
dpx->referenceWhite = referenceWhite;
}
else {
dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
}
if (referenceBlack > 0) {
dpx->referenceBlack = referenceBlack;
}
else {
dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
}
if (gamma > 0.0f) {
dpx->gamma = gamma;
}
else {
dpx->gamma = 1.7f;
}
shortFilename = strrchr(filepath, PATHSEP_CHAR);
if (shortFilename == nullptr) {
shortFilename = filepath;
}
else {
shortFilename++;
}
dpx->file = BLI_fopen(filepath, "wb");
if (dpx->file == nullptr) {
if (verbose) {
printf("DPX: Couldn't open file %s\n", filepath);
}
logImageClose(dpx);
return nullptr;
}
fillDpxMainHeader(dpx, &header, shortFilename, creator);
if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
if (verbose) {
printf("DPX: Couldn't write image header\n");
}
logImageClose(dpx);
return nullptr;
}
/* Header should be rounded to next 8k block
* 6044 = 8092 - sizeof(DpxMainHeader) */
memset(&pad, 0, 6044);
if (fwrite(&pad, 6044, 1, dpx->file) == 0) {
if (verbose) {
printf("DPX: Couldn't write image header\n");
}
logImageClose(dpx);
return nullptr;
}
return dpx;
}
} // namespace blender

View File

@@ -0,0 +1,146 @@
/* SPDX-FileCopyrightText: 1999-2002 David Hodson <hodsond@acm.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* DPX image file format library definitions.
*/
#pragma once
#include <cmath>
#include "logImageCore.h"
namespace blender {
#define DPX_FILE_MAGIC 0x53445058
#define DPX_UNDEFINED_U8 0xFF
#define DPX_UNDEFINED_U16 0xFFFF
#define DPX_UNDEFINED_U32 0xFFFFFFFF
#define DPX_UNDEFINED_R32 NAN
#define IS_DPX_UNDEFINED_R32(x) std::isnan(x)
#define DPX_UNDEFINED_CHAR 0
struct DpxFileHeader {
unsigned int magic_num;
unsigned int offset;
char version[8];
unsigned int file_size;
unsigned int ditto_key;
unsigned int gen_hdr_size;
unsigned int ind_hdr_size;
unsigned int user_data_size;
char file_name[100];
char creation_date[24];
char creator[100];
char project[200];
char copyright[200];
unsigned int key;
char reserved[104];
};
struct DpxElementHeader {
unsigned int data_sign;
unsigned int ref_low_data;
float ref_low_quantity;
unsigned int ref_high_data;
float ref_high_quantity;
unsigned char descriptor;
unsigned char transfer;
unsigned char colorimetric;
unsigned char bits_per_sample;
unsigned short packing;
unsigned short encoding;
unsigned int data_offset;
unsigned int line_padding;
unsigned int element_padding;
char description[32];
};
struct DpxImageHeader {
unsigned short orientation;
unsigned short elements_per_image;
unsigned int pixels_per_line;
unsigned int lines_per_element;
DpxElementHeader element[8];
char reserved[52];
};
struct DpxOrientationHeader {
unsigned int x_offset;
unsigned int y_offset;
float x_center;
float y_center;
unsigned int x_original_size;
unsigned int y_original_size;
char file_name[100];
char creation_time[24];
char input_device[32];
char input_serial_number[32];
unsigned short border_validity[4];
unsigned int pixel_aspect_ratio[2];
char reserved[28];
};
struct DpxFilmHeader {
char film_manufacturer_id[2];
char film_type[2];
char edge_code_perforation_offset[2];
char edge_code_prefix[6];
char edge_code_count[4];
char film_format[32];
unsigned int frame_position;
unsigned int sequence_length;
unsigned int held_count;
float frame_rate;
float shutter_angle;
char frame_identification[32];
char slate_info[100];
char reserved[56];
};
struct DpxTelevisionHeader {
unsigned int time_code;
unsigned int user_bits;
unsigned char interlace;
unsigned char field_number;
unsigned char video_signal;
unsigned char padding;
float horizontal_sample_rate;
float vertical_sample_rate;
float frame_rate;
float time_offset;
float gamma;
float black_level;
float black_gain;
float breakpoint;
float white_level;
float integration_times;
unsigned char reserved[76];
};
struct DpxMainHeader {
DpxFileHeader fileHeader;
DpxImageHeader imageHeader;
DpxOrientationHeader orientationHeader;
DpxFilmHeader filmHeader;
DpxTelevisionHeader televisionHeader;
};
void dpxSetVerbose(int verbosity);
LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize);
LogImageFile *dpxCreate(const char *filepath,
int width,
int height,
int bitsPerSample,
int hasAlpha,
int isLogarithmic,
int referenceWhite,
int referenceBlack,
float gamma,
const char *creator);
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,272 @@
/* SPDX-FileCopyrightText: 1999-2001 David Hodson <hodsond@acm.org>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* Cineon image file format library definitions.
* Cineon and DPX common structures.
*
* This header file contains private details.
* User code should generally use `cineonlib.h` and `dpxlib.h` only.
* Hmm. I thought the two formats would have more in common!
*/
#pragma once
#include <cstdio>
#include "BLI_compiler_compat.h"
#include "BLI_sys_types.h"
namespace blender {
#ifdef _WIN32
# define PATHSEP_CHAR '\\'
#else
# define PATHSEP_CHAR '/'
#endif
/*
* Image structure
*/
/* There are some differences between DPX and Cineon
* so we need to know from what type of file the data came from. */
enum format {
format_DPX,
format_Cineon,
};
struct LogImageElement {
int depth;
int bitsPerSample;
int dataOffset;
int packing;
int transfer;
int descriptor;
unsigned int refLowData;
unsigned int refHighData;
float refLowQuantity;
float refHighQuantity;
float maxValue; /* = 2^bitsPerSample - 1 (used internally, doesn't come from the file header) */
};
struct LogImageFile {
/* specified in header */
int width;
int height;
int numElements;
int depth;
LogImageElement element[8];
/* used for log <-> lin conversion */
float referenceBlack;
float referenceWhite;
float gamma;
/* IO stuff. */
FILE *file;
unsigned char *memBuffer;
uintptr_t memBufferSize;
unsigned char *memCursor;
/* is the file LSB or MSB ? */
int isMSB;
/* DPX or Cineon ? */
int srcFormat;
};
/* The SMPTE defines this code:
* 0 - User-defined
* 1 - Printing density
* 2 - Linear
* 3 - Logarithmic
* 4 - Unspecified video
* 5 - SMPTE 240M
* 6 - CCIR 709-1
* 7 - CCIR 601-2 system B or G
* 8 - CCIR 601-2 system M
* 9 - NTSC composite video
* 10 - PAL composite video
* 11 - Z linear
* 12 - homogeneous
*
* Note that transfer_characteristics is U8, don't need
* check the byte order.
*/
enum transfer {
transfer_UserDefined,
transfer_PrintingDensity,
transfer_Linear,
transfer_Logarithmic,
transfer_Unspecified,
transfer_Smpte240M,
transfer_Ccir7091,
transfer_Ccir6012BG,
transfer_Ccir6012M,
transfer_NTSC,
transfer_PAL,
transfer_ZLinear,
transfer_Homogeneous,
};
/* The SMPTE defines this code:
* 0 - User-defined
* 1 - Red
* 2 - Green
* 3 - Blue
* 4 - Alpha
* 6 - Luminance
* 7 - Chrominance
* 8 - Depth
* 9 - Composite video
* 50 - RGB
* 51 - RGBA
* 52 - ABGR
* 100 - CbYCrY
* 101 - CbYACrYA
* 102 - CbYCr
* 103 - CbYCrA
* 150 - User-defined 2-component element
* 151 - User-defined 3-component element
* 152 - User-defined 4-component element
* 153 - User-defined 5-component element
* 154 - User-defined 6-component element
* 155 - User-defined 7-component element
* 156 - User-defined 8-component element
*/
enum descriptor {
descriptor_UserDefined,
descriptor_Red,
descriptor_Green,
descriptor_Blue,
descriptor_Alpha,
descriptor_Luminance = 6, /* don't ask me why there's no 5 */
descriptor_Chrominance,
descriptor_Depth,
descriptor_Composite,
descriptor_RGB = 50,
descriptor_RGBA,
descriptor_ABGR,
descriptor_CbYCrY = 100,
descriptor_CbYACrYA,
descriptor_CbYCr,
descriptor_CbYCrA,
descriptor_UserDefined2Elt = 150,
descriptor_UserDefined3Elt,
descriptor_UserDefined4Elt,
descriptor_UserDefined5Elt,
descriptor_UserDefined6Elt,
descriptor_UserDefined7Elt,
descriptor_UserDefined8Elt,
/* following descriptors are for internal use only */
descriptor_YA,
};
/* int functions return 0 for OK */
void logImageSetVerbose(int verbosity);
int logImageIsDpx(const void *buffer, unsigned int size);
int logImageIsCineon(const void *buffer, unsigned int size);
LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size);
LogImageFile *logImageOpenFromFile(const char *filepath, int cineon);
void logImageGetSize(const LogImageFile *logImage, int *width, int *height, int *depth);
LogImageFile *logImageCreate(const char *filepath,
int cineon,
int width,
int height,
int bitsPerSample,
int hasAlpha,
int isLogarithmic,
int referenceWhite,
int referenceBlack,
float gamma,
const char *creator);
void logImageClose(LogImageFile *logImage);
/* Data handling */
size_t getRowLength(size_t width, const LogImageElement *logElement);
int logImageSetDataRGBA(LogImageFile *logImage, const float *data, int dataIsLinearRGB);
int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB);
/*
* Inline routines
*/
/* Endianness swapping */
BLI_INLINE unsigned short swap_ushort(unsigned short x, int swap)
{
if (swap != 0) {
return (x >> 8) | (x << 8);
}
return x;
}
BLI_INLINE unsigned int swap_uint(unsigned int x, int swap)
{
if (swap != 0) {
return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
}
return x;
}
BLI_INLINE float swap_float(float x, int swap)
{
if (swap != 0) {
union {
float f;
unsigned char b[4];
} dat1, dat2;
dat1.f = x;
dat2.b[0] = dat1.b[3];
dat2.b[1] = dat1.b[2];
dat2.b[2] = dat1.b[1];
dat2.b[3] = dat1.b[0];
return dat2.f;
}
return x;
}
/* Other */
BLI_INLINE unsigned int clamp_uint(unsigned int x, unsigned int low, unsigned int high)
{
if (x > high) {
return high;
}
if (x < low) {
return low;
}
return x;
}
BLI_INLINE float clamp_float(float x, float low, float high)
{
if (x > high) {
return high;
}
if (x < low) {
return low;
}
return x;
}
BLI_INLINE unsigned int float_uint(float value, unsigned int max)
{
if (value < 0.0f) {
return 0;
}
if (value > (1.0f - 0.5f / float(max))) {
return max;
}
return static_cast<unsigned int>((float(max) * value) + 0.5f);
}
} // namespace blender

View File

@@ -0,0 +1,119 @@
/* SPDX-FileCopyrightText: 2006 Joseph Eagar <joeedh@gmail.com>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* Cineon image file format library routines.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "logImageCore.h"
#include "logmemfile.h"
namespace blender {
int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin)
{
if (logFile->file) {
fseek(logFile->file, offset, origin);
}
else { /* we're seeking in memory */
if (origin == SEEK_SET) {
if (offset > logFile->memBufferSize) {
return 1;
}
logFile->memCursor = logFile->memBuffer + offset;
}
else if (origin == SEEK_END) {
if (offset > logFile->memBufferSize) {
return 1;
}
logFile->memCursor = (logFile->memBuffer + logFile->memBufferSize) - offset;
}
else if (origin == SEEK_CUR) {
uintptr_t pos = uintptr_t(logFile->memCursor) - uintptr_t(logFile->memBuffer);
if (pos + offset > logFile->memBufferSize) {
return 1;
}
logFile->memCursor += offset;
}
}
return 0;
}
int logimage_fwrite(const void *buffer, size_t size, uint count, LogImageFile *logFile)
{
if (logFile->file) {
return fwrite(buffer, size, count, logFile->file);
}
/* we're writing to memory */
/* do nothing as this isn't supported yet */
return count;
}
int logimage_fread(void *buffer, size_t size, uint count, LogImageFile *logFile)
{
if (logFile->file) {
return fread(buffer, size, count, logFile->file);
}
/* we're reading from memory */
uchar *buf = static_cast<uchar *>(buffer);
uintptr_t pos = uintptr_t(logFile->memCursor) - uintptr_t(logFile->memBuffer);
size_t total_size = size * count;
if (pos + total_size > logFile->memBufferSize) {
/* how many elements can we read without overflow ? */
count = (logFile->memBufferSize - pos) / size;
/* recompute the size */
total_size = size * count;
}
if (total_size != 0) {
memcpy(buf, logFile->memCursor, total_size);
}
return count;
}
int logimage_read_uchar(uchar *x, LogImageFile *logFile)
{
uintptr_t pos = uintptr_t(logFile->memCursor) - uintptr_t(logFile->memBuffer);
if (pos + sizeof(uchar) > logFile->memBufferSize) {
return 1;
}
*x = *static_cast<uchar *>(logFile->memCursor);
logFile->memCursor += sizeof(uchar);
return 0;
}
int logimage_read_ushort(ushort *x, LogImageFile *logFile)
{
uintptr_t pos = uintptr_t(logFile->memCursor) - uintptr_t(logFile->memBuffer);
if (pos + sizeof(ushort) > logFile->memBufferSize) {
return 1;
}
*x = *reinterpret_cast<ushort *>(logFile->memCursor);
logFile->memCursor += sizeof(ushort);
return 0;
}
int logimage_read_uint(uint *x, LogImageFile *logFile)
{
uintptr_t pos = uintptr_t(logFile->memCursor) - uintptr_t(logFile->memBuffer);
if (pos + sizeof(uint) > logFile->memBufferSize) {
return 1;
}
*x = *reinterpret_cast<uint *>(logFile->memCursor);
logFile->memCursor += sizeof(uint);
return 0;
}
} // namespace blender

View File

@@ -0,0 +1,26 @@
/* SPDX-FileCopyrightText: 2006 Joseph Eagar <joeedh@gmail.com>.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbcineon
*
* Cineon image file format library routines.
*/
#pragma once
#include "logImageCore.h"
#include <cstdlib>
namespace blender {
int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin);
int logimage_fwrite(const void *buffer, size_t size, unsigned int count, LogImageFile *logFile);
int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile);
int logimage_read_uchar(unsigned char *x, LogImageFile *logFile);
int logimage_read_ushort(unsigned short *x, LogImageFile *logFile);
int logimage_read_uint(unsigned int *x, LogImageFile *logFile);
} // namespace blender