Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-10-22 16:49:00 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-10-22 16:49:00 +0400
commit4e11fe6c5aec1d609e3ecc2218138b838d253ebf (patch)
treed57b4f18280c04e50ecb562135fed058cf11b82d /source/blender/imbuf/intern
parent655e24979bb37c97a34b328238233591cfd5c924 (diff)
Patch #27397: Improved DPX/Cineon code
Patch by Julien Enche, thanks! From the patch comment: It allows Blender to load: - 1, 8, 10, 12 and 16 bits files. For 10 and 12 bits files, packed or filled type A/B are supported. - RGB, Log, Luma and YCbCr colorspaces. - Big and little endian storage. - Multi-elements (planar) storage. It allows Blender to save : - 8, 10, 12 and 16 bits file. For 10 and 12 bits files, the most used type A padding is used. - RGB and Log colorspaces (Cineon can only be saved in Log colorspace). For Log colorspace, the common default values are used for gamma, reference black and reference white (respectively 1.7, 95 and 685 for 10 bits files). - Saved DPX/Cineon files now match the viewer. Some files won't load (mostly because I haven't seen any of them): - Compressed files - 32 and 64 bits files - Image orientation information are not taken in account. Here too, I haven't seen any file that was not top-bottom/left-right oriented.
Diffstat (limited to 'source/blender/imbuf/intern')
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h6
-rw-r--r--source/blender/imbuf/intern/cineon/CMakeLists.txt5
-rw-r--r--source/blender/imbuf/intern/cineon/cin_debug_stuff.h4
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c229
-rw-r--r--source/blender/imbuf/intern/cineon/cineonfile.h134
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c1010
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.h150
-rw-r--r--source/blender/imbuf/intern/cineon/dpxfile.h128
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c975
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.h162
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c1642
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.h258
-rw-r--r--source/blender/imbuf/intern/cineon/logImageLib.c183
-rw-r--r--source/blender/imbuf/intern/cineon/logImageLib.h87
-rw-r--r--source/blender/imbuf/intern/cineon/logmemfile.c140
-rw-r--r--source/blender/imbuf/intern/cineon/logmemfile.h50
-rw-r--r--source/blender/imbuf/intern/filetype.c4
17 files changed, 2739 insertions, 2428 deletions
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 56a03121409..68ad4808c80 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -97,13 +97,13 @@ struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, cha
short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags);
/* cineon */
-int imb_savecineon(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+int imb_save_cineon(struct ImBuf *buf, const char *name, int flags);
+struct ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_is_cineon(unsigned char *buf);
/* dpx */
int imb_save_dpx(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+struct ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_is_dpx(unsigned char *buf);
/* hdr */
diff --git a/source/blender/imbuf/intern/cineon/CMakeLists.txt b/source/blender/imbuf/intern/cineon/CMakeLists.txt
index fdf4f5409a5..8e76f5e729b 100644
--- a/source/blender/imbuf/intern/cineon/CMakeLists.txt
+++ b/source/blender/imbuf/intern/cineon/CMakeLists.txt
@@ -43,8 +43,11 @@ set(SRC
cineonlib.c
dpxlib.c
logImageCore.c
- logImageLib.c
logmemfile.c
)
+if(WITH_IMAGE_CINEON)
+ add_definitions(-DWITH_CINEON)
+endif()
+
blender_add_lib(bf_imbuf_cineon "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h
index a97499fb1ae..e69de29bb2d 100644
--- a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h
+++ b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h
@@ -1,4 +0,0 @@
-/** \file blender/imbuf/intern/cineon/cin_debug_stuff.h
- * \ingroup imbcineon
- */
-#define d_printf printf
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index 7705af13b1e..21f68e79135 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -4,11 +4,11 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
@@ -20,25 +20,24 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Julien Enche.
*
* ***** END GPL LICENSE BLOCK *****
* cineon.c
- * contributors: joeedh
+ * contributors: joeedh, Julien Enche
* I hearby donate this code and all rights to the Blender Foundation.
+ * $Id$
*/
/** \file blender/imbuf/intern/cineon/cineon_dpx.c
* \ingroup imbcineon
*/
-
-#include <stdio.h>
-#include <string.h> /*for memcpy*/
-#include "logImageLib.h"
-#include "cineonlib.h"
-#include "dpxlib.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "logImageCore.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -51,167 +50,141 @@
#include "MEM_guardedalloc.h"
-#if 0
-static void cineon_conversion_parameters(LogImageByteConversionParameters *params)
-{
-// params->blackPoint = scene?scene->r.cineonblack:95;
-// params->whitePoint = scene?scene->r.cineonwhite:685;
-// params->gamma = scene?scene->r.cineongamma:1.7f;
-// params->doLogarithm = scene?scene->r.subimtype & R_CINEON_LOG:0;
-
- params->blackPoint = 95;
- params->whitePoint = 685;
- params->gamma = 1.0f;
- params->doLogarithm = 0;
-}
-#endif
-
-static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags, char colorspace[IM_MAX_SPACE])
+static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags,
+ char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
LogImageFile *image;
- int x, y;
- unsigned short *row, *upix;
int width, height, depth;
- float *frow;
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
- logImageSetVerbose((G.debug & G_DEBUG) ? 1:0);
-
- image = logImageOpenFromMem(mem, size, use_cineon);
-
- if (!image) {
- printf("no image!\n");
- return NULL;
+ logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
+
+ image = logImageOpenFromMemory(mem, size);
+
+ if (image == 0) {
+ printf("DPX/Cineon: error opening image.\n");
+ return 0;
}
-
+
logImageGetSize(image, &width, &height, &depth);
-
- if (depth != 3) { /*need to do grayscale loading eventually.*/
+
+ if (width == 0 || height == 0) {
logImageClose(image);
- return NULL;
+ return 0;
}
-
- if (width == 0 && height == 0) {
+
+ ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
+ if (ibuf == 0) {
logImageClose(image);
- return NULL;
+ return 0;
}
-
- ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
- row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c");
- frow = ibuf->rect_float+width*height*4;
-
- for (y = 0; y < height; y++) {
- logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */
- upix = row;
- frow -= width*4;
-
- for (x=0; x<width; x++) {
- *(frow++) = ((float)*(upix++)) / 65535.0f;
- *(frow++) = ((float)*(upix++)) / 65535.0f;
- *(frow++) = ((float)*(upix++)) / 65535.0f;
- *(frow++) = 1.0f;
- }
- frow -= width*4;
+ if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
+ /* Conversion not possible (probably because the format is unsupported) */
+ logImageClose(image);
+ MEM_freeN(ibuf);
+ return 0;
}
- MEM_freeN(row);
logImageClose(image);
-
- if (flags & IB_rect) {
+ ibuf->ftype = use_cineon ? CINEON : DPX;
+ IMB_flipy(ibuf);
+
+ if (flags & IB_rect)
IMB_rect_from_float(ibuf);
- }
+
return ibuf;
}
static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags)
{
- LogImageByteConversionParameters conversion;
- const int width= ibuf->x;
- const int height= ibuf->y;
- const int depth= 3;
- LogImageFile* logImage;
- unsigned short* line, *pixel;
- int i, j;
- float *fline;
+ LogImageFile *logImage;
float *fbuf;
- int is_alloc= 0;
-
- (void)flags; /* unused */
-
- // cineon_conversion_parameters(&conversion);
- logImageGetByteConversionDefaults(&conversion);
-
- /*
- * Get the drawable for the current image...
- */
+ float *fbuf_ptr;
+ unsigned char *rect_ptr;
+ int x, y, depth, bitspersample, rvalue;
- fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc);
-
- if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */
+ if (flags & IB_mem) {
+ printf("DPX/Cineon: saving in memory is not supported.\n");
return 0;
}
- logImageSetVerbose((G.debug & G_DEBUG) ? 1:0);
- logImage = logImageCreate(filename, use_cineon, width, height, depth);
+ logImageSetVerbose((G.f & G_DEBUG) ? 1:0);
- if (!logImage) return 0;
-
- if (logImageSetByteConversion(logImage, &conversion)==0) {
- printf("error setting args\n");
+ depth = (ibuf->planes + 7) >> 3;
+ if (depth > 4 || depth < 3) {
+ printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename);
+ return 0;
}
- line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line");
-
- /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/
- for (j = 0; j < height; ++j) {
- fline = &fbuf[width*j*4];
- for (i=0; i<width; i++) {
- float *fpix, fpix2[3];
- /*we have to convert to cinepaint's 16-bit-per-channel here*/
- pixel = &line[i*depth];
- fpix = &fline[i*4];
- memcpy(fpix2, fpix, sizeof(float)*3);
-
- if (fpix2[0]>=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f;
- if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f;
- if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f;
-
- pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/
- pixel[1] = (unsigned short)(fpix2[1] * 65535.0f);
- pixel[2] = (unsigned short)(fpix2[2] * 65535.0f);
- }
- logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j);
+ if (ibuf->ftype & CINEON_10BIT)
+ bitspersample = 10;
+ else if (ibuf->ftype & CINEON_12BIT)
+ bitspersample = 12;
+ else if (ibuf->ftype & CINEON_16BIT)
+ bitspersample = 16;
+ else
+ bitspersample = 8;
+
+ logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4),
+ (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender");
+
+ if (logImage == 0) {
+ printf("DPX/Cineon: error creating file.\n");
+ return 0;
}
- logImageClose(logImage);
- MEM_freeN(line);
-
- if (is_alloc) {
+ if (ibuf->rect_float != 0 && bitspersample != 8) {
+ /* don't use the float buffer to save 8 bpp picture to prevent color banding
+ (there's no dithering algorithm behing the logImageSetDataRGBA function) */
+ IMB_flipy(ibuf);
+ rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0);
+ IMB_flipy(ibuf);
+ } else {
+ if (ibuf->rect == 0)
+ IMB_rect_from_float(ibuf);
+
+ fbuf = (float*)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
+ if (fbuf == 0) {
+ printf("DPX/Cineon: error allocating memory.\n");
+ logImageClose(logImage);
+ return 0;
+ }
+ for (y = 0; y < ibuf->y; y++) {
+ for (x = 0; x < ibuf->x; x++) {
+ fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x);
+ rect_ptr = (unsigned char*)ibuf->rect + 4 * (y * 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] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f;
+ }
+ }
+ rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0);
MEM_freeN(fbuf);
}
-
- return 1;
+
+ logImageClose(logImage);
+ return rvalue;
}
-int imb_savecineon(struct ImBuf *buf, const char *myfile, int flags)
+int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags)
{
return imb_save_dpx_cineon(buf, myfile, 1, flags);
}
-
int imb_is_cineon(unsigned char *buf)
{
- return cineonIsMemFileCineon(buf);
+ return logImageIsCineon(buf);
}
-ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_cineon(mem))
- return imb_load_dpx_cineon(mem, 1, size, flags, colorspace);
- return NULL;
+ return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
+ return 0;
}
int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
@@ -221,12 +194,12 @@ int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
int imb_is_dpx(unsigned char *buf)
{
- return dpxIsMemFileCineon(buf);
+ return logImageIsDpx(buf);
}
-ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
+ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_dpx(mem))
- return imb_load_dpx_cineon(mem, 0, size, flags, colorspace);
- return NULL;
+ return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
+ return 0;
}
diff --git a/source/blender/imbuf/intern/cineon/cineonfile.h b/source/blender/imbuf/intern/cineon/cineonfile.h
index e681153aa6e..e69de29bb2d 100644
--- a/source/blender/imbuf/intern/cineon/cineonfile.h
+++ b/source/blender/imbuf/intern/cineon/cineonfile.h
@@ -1,134 +0,0 @@
-/*
- * Cineon image file format library definitions.
- * Cineon file format structures.
- *
- * This header file contains private details.
- * User code should generally use cineonlib.h only.
- *
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef __CINEONFILE_H__
-#define __CINEONFILE_H__
-
-/** \file blender/imbuf/intern/cineon/cineonfile.h
- * \ingroup imbcineon
- */
-
-#include "logImageCore.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- U32 magic_num; /* magic number */
- U32 image_offset; /* offset to image data in bytes */
- U32 gen_hdr_size; /* generic header length in bytes */
- U32 ind_hdr_size; /* industry header length in bytes */
- U32 user_data_size; /* user-defined data length in bytes */
- U32 file_size; /* file size in bytes */
- ASCII vers[8]; /* which header format version is being used (v4.5) */
- ASCII file_name[100]; /* image file name */
- ASCII create_date[12]; /* file creation date */
- ASCII create_time[12]; /* file creation time */
- ASCII Reserved[36]; /* reserved field TBD (need to pad) */
-} CineonFileInformation;
-
-typedef struct {
- U8 designator1;
- U8 designator2;
- U8 bits_per_pixel;
- U8 filler;
- U32 pixels_per_line;
- U32 lines_per_image;
- U32 ref_low_data; /* reference low data code value */
- R32 ref_low_quantity; /* reference low quantity represented */
- U32 ref_high_data; /* reference high data code value */
- R32 ref_high_quantity;/* reference high quantity represented */
-} CineonChannelInformation;
-
-typedef struct {
- U8 orientation; /* image orientation */
- U8 channels_per_image;
- U16 filler;
- CineonChannelInformation channel[8];
- R32 white_point_x;
- R32 white_point_y;
- R32 red_primary_x;
- R32 red_primary_y;
- R32 green_primary_x;
- R32 green_primary_y;
- R32 blue_primary_x;
- R32 blue_primary_y;
- ASCII label[200];
- ASCII reserved[28];
-} CineonImageInformation;
-
-typedef struct {
- U8 interleave;
- U8 packing;
- U8 signage;
- U8 sense;
- U32 line_padding;
- U32 channel_padding;
- ASCII reserved[20];
-} CineonFormatInformation;
-
-typedef struct {
- S32 x_offset;
- S32 y_offset;
- ASCII file_name[100];
- ASCII create_date[12]; /* file creation date */
- ASCII create_time[12]; /* file creation time */
- ASCII input_device[64];
- ASCII model_number[32];
- ASCII serial_number[32];
- R32 x_input_samples_per_mm;
- R32 y_input_samples_per_mm;
- R32 input_device_gamma;
- ASCII reserved[40];
-} CineonOriginationInformation;
-
-typedef struct {
- CineonFileInformation fileInfo;
- CineonImageInformation imageInfo;
- CineonFormatInformation formatInfo;
- CineonOriginationInformation originInfo;
-} CineonGenericHeader;
-
-typedef struct {
- U8 filmCode;
- U8 filmType;
- U8 perfOffset;
- U8 filler;
- U32 keycodePrefix;
- U32 keycodeCount;
- ASCII format[32];
- U32 framePosition; /* in sequence */
- R32 frameRate; /* frames per second */
- ASCII attribute[32];
- ASCII slate[200];
- ASCII reserved[740];
-} CineonMPISpecificInformation;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CINEONFILE_H__ */
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 894e3a93b4b..92a984378db 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -1,21 +1,23 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,800 +25,348 @@
* \ingroup imbcineon
*/
+
#include "cineonlib.h"
-#include "cineonfile.h"
+#include "logmemfile.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
-#include <time.h> /* strftime() */
+#include <time.h>
#include <sys/types.h>
-#ifdef WIN32
-#include <winsock.h>
-#else
-#include <netinet/in.h> /* htonl() */
-#endif
-#include <string.h> /* memset */
-
-#include "BLI_utildefines.h"
-#include "BLI_fileops.h"
-
-#include "cin_debug_stuff.h"
-#include "logmemfile.h"
-
-static void
-fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) {
+#include <string.h>
- time_t fileClock;
- struct tm* fileTime;
-
- fileInfo->magic_num = htonl(CINEON_FILE_MAGIC);
- fileInfo->image_offset = htonl(cineon->imageOffset);
- fileInfo->gen_hdr_size = htonl(
- sizeof(CineonFileInformation) +
- sizeof(CineonImageInformation) +
- sizeof(CineonFormatInformation) +
- sizeof(CineonOriginationInformation));
- fileInfo->ind_hdr_size = 0;
- fileInfo->user_data_size = 0;
- fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength);
- strcpy(fileInfo->vers, "V4.5");
- strncpy(fileInfo->file_name, filename, 99);
- fileInfo->file_name[99] = 0;
-
- fileClock = time(0);
- fileTime = localtime(&fileClock);
- strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime);
- /* Question: is %Z in strftime guaranteed to return 3 chars? */
- strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime);
- fileInfo->create_time[11] = 0;
-}
-
-static void
-dumpCineonFileInfo(CineonFileInformation* fileInfo) {
- d_printf("\n--File Information--\n");
- d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num));
- d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset));
- d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
- d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
- d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
- d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
- d_printf("Version \"%s\"\n", fileInfo->vers);
- d_printf("File name \"%s\"\n", fileInfo->file_name);
- d_printf("Creation date \"%s\"\n", fileInfo->create_date);
- d_printf("Creation time \"%s\"\n", fileInfo->create_time);
-}
-
-static void
-fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) {
-
- chan->designator1 = 0;
- chan->designator2 = des;
- chan->bits_per_pixel = 10;
- chan->pixels_per_line = htonl(cineon->width);
- chan->lines_per_image = htonl(cineon->height);
- chan->ref_low_data = htonl(0);
- chan->ref_low_quantity = htonf(0.0);
- chan->ref_high_data = htonl(1023);
- chan->ref_high_quantity = htonf(2.046);
-}
-
-static void
-dumpCineonChannelInfo(CineonChannelInformation* chan) {
- d_printf(" Metric selector: %d", chan->designator1);
- switch (chan->designator1) {
- case 0: d_printf(" (Universal)\n"); break;
- default: d_printf(" (Vendor specific)\n"); break;
- }
- d_printf(" Metric: %d,", chan->designator2);
- switch (chan->designator2) {
- case 0: d_printf(" B&W (printing density?)\n"); break;
- case 1: d_printf(" Red printing density\n"); break;
- case 2: d_printf(" Green printing density\n"); break;
- case 3: d_printf(" Blue printing density\n"); break;
- case 4: d_printf(" Red CCIR XA/11\n"); break;
- case 5: d_printf(" Green CCIR XA/11\n"); break;
- case 6: d_printf(" Blue CCIR XA/11\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf(" Bits per pixel %d\n", chan->bits_per_pixel);
- d_printf(" Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line));
- d_printf(" Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image));
- d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
- d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
- d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
- d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
-}
-
-static void
-fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) {
-
- imageInfo->orientation = 0;
- imageInfo->channels_per_image = cineon->depth;
-
- if (cineon->depth == 1) {
- fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0);
-
- }
- else if (cineon->depth == 3) {
- fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1);
- fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2);
- fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3);
- }
-
- imageInfo->white_point_x = htonf(undefined());
- imageInfo->white_point_y = htonf(undefined());
- imageInfo->red_primary_x = htonf(undefined());
- imageInfo->red_primary_y = htonf(undefined());
- imageInfo->green_primary_x = htonf(undefined());
- imageInfo->green_primary_y = htonf(undefined());
- imageInfo->blue_primary_x = htonf(undefined());
- imageInfo->blue_primary_y = htonf(undefined());
-
- strcpy(imageInfo->label, "David's Cineon writer.");
-
-}
-
-static void
-dumpCineonImageInfo(CineonImageInformation* imageInfo) {
-
- int i;
- d_printf("\n--Image Information--\n");
- d_printf("Image orientation %d,", imageInfo->orientation);
- switch (imageInfo->orientation) {
- case 0: d_printf(" LRTB\n"); break;
- case 1: d_printf(" LRBT\n"); break;
- case 2: d_printf(" RLTB\n"); break;
- case 3: d_printf(" RLBT\n"); break;
- case 4: d_printf(" TBLR\n"); break;
- case 5: d_printf(" TBRL\n"); break;
- case 6: d_printf(" BTLR\n"); break;
- case 7: d_printf(" BTRL\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Channels %d\n", imageInfo->channels_per_image);
- for (i = 0; i < imageInfo->channels_per_image; ++i) {
- d_printf(" --Channel %d--\n", i);
- dumpCineonChannelInfo(&imageInfo->channel[i]);
- }
-
- d_printf("White point x %f\n", ntohf(imageInfo->white_point_x));
- d_printf("White point y %f\n", ntohf(imageInfo->white_point_y));
- d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x));
- d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y));
- d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x));
- d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y));
- d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x));
- d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y));
- d_printf("Label \"%s\"\n", imageInfo->label);
-}
-
-static void
-fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) {
-
- (void)cineon; /* unused */
-
- formatInfo->interleave = 0;
- formatInfo->packing = 5;
- formatInfo->signage = 0;
- formatInfo->sense = 0;
- formatInfo->line_padding = htonl(0);
- formatInfo->channel_padding = htonl(0);
-}
-
-static void
-dumpCineonFormatInfo(CineonFormatInformation* formatInfo) {
- d_printf("\n--Format Information--\n");
- d_printf("Interleave %d,", formatInfo->interleave);
- switch (formatInfo->interleave) {
- case 0: d_printf(" pixel interleave\n"); break;
- case 1: d_printf(" line interleave\n"); break;
- case 2: d_printf(" channel interleave\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Packing %d,", formatInfo->packing);
- if (formatInfo->packing & 0x80) {
- d_printf(" multi pixel,");
- }
- else {
- d_printf(" single pixel,");
- }
- switch (formatInfo->packing & 0x7F) {
- case 0: d_printf(" tight\n"); break;
- case 1: d_printf(" byte packed left\n"); break;
- case 2: d_printf(" byte packed right\n"); break;
- case 3: d_printf(" word packed left\n"); break;
- case 4: d_printf(" word packed right\n"); break;
- case 5: d_printf(" long packed left\n"); break;
- case 6: d_printf(" long packed right\n"); break;
- default: d_printf(" (unknown)\n"); break;
- }
- d_printf("Sign %d,", formatInfo->signage);
- if (formatInfo->signage) {
- d_printf(" signed\n");
- }
- else {
- d_printf(" unsigned\n");
- }
- d_printf("Sense %d,", formatInfo->signage);
- if (formatInfo->signage) {
- d_printf(" negative\n");
- }
- else {
- d_printf(" positive\n");
- }
- d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding));
- d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding));
-}
-
-static void
-fillCineonOriginationInfo(CineonFile* cineon,
- CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) {
-
- (void)cineon; /* unused */
-
- originInfo->x_offset = htonl(0);
- originInfo->y_offset = htonl(0);
- strcpy(originInfo->file_name, fileInfo->file_name);
- strcpy(originInfo->create_date, fileInfo->create_date);
- strcpy(originInfo->create_time, fileInfo->create_time);
- strncpy(originInfo->input_device, "David's Cineon writer", 64);
- strncpy(originInfo->model_number, "Software", 32);
- strncpy(originInfo->serial_number, "001", 32);
- originInfo->x_input_samples_per_mm = htonf(undefined());
- originInfo->y_input_samples_per_mm = htonf(undefined());
- /* this should probably be undefined, too */
- originInfo->input_device_gamma = htonf(1.0);
-}
-
-static void
-dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) {
- d_printf("\n--Origination Information--\n");
- d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
- d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
- d_printf("File name \"%s\"\n", originInfo->file_name);
- d_printf("Creation date \"%s\"\n", originInfo->create_date);
- d_printf("Creation time \"%s\"\n", originInfo->create_time);
- d_printf("Input device \"%s\"\n", originInfo->input_device);
- d_printf("Model number \"%s\"\n", originInfo->model_number);
- d_printf("Serial number \"%s\"\n", originInfo->serial_number);
- d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm));
- d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm));
- d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma));
-}
-
-static int
-initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) {
-
- fillCineonFileInfo(cineon, &header->fileInfo, imagename);
- fillCineonImageInfo(cineon, &header->imageInfo);
- fillCineonFormatInfo(cineon, &header->formatInfo);
- fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo);
+#include "BLI_fileops.h"
- return 0;
-}
+#include "MEM_guardedalloc.h"
-static void
-UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) {
- dumpCineonFileInfo(&header->fileInfo);
- dumpCineonImageInfo(&header->imageInfo);
- dumpCineonFormatInfo(&header->formatInfo);
- dumpCineonOriginationInfo(&header->originInfo);
-}
+/*
+ * For debug purpose
+ */
static int verbose = 0;
-void
-cineonSetVerbose(int verbosity) {
- verbose = verbosity;
-}
-
-static void
-verboseMe(CineonFile* cineon) {
-
- d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth);
- d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
- cineon->imageOffset, cineon->lineBufferLength * 4,
- cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height);
-}
-
-int
-cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
-
- int longsRead;
- int pixelIndex;
- int longIndex;
- int numPixels = cineon->width * cineon->depth;
-
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
- if (longsRead != cineon->lineBufferLength) {
- if (verbose) {
- d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
- perror("cineonGetRowBytes");
- }
-
- return 1;
- }
-
- /* remember where we left the car, honey */
- ++cineon->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
- t = t >> 2;
- cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff;
- pixelIndex += 3;
- }
-
- /* extract required pixels */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (cineon->params.doLogarithm)
- row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]];
- else
- row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
- }
-
- return 0;
-}
-
-int
-cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
-
- int pixelIndex;
- int numPixels = cineon->width * cineon->depth;
- int longIndex;
- int longsWritten;
-
- /* put new pixels into pixelBuffer */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (cineon->params.doLogarithm)
- cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]];
- else
- cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
- }
-
- /* pack into longwords */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t =
- (cineon->pixelBuffer[pixelIndex] << 22) |
- (cineon->pixelBuffer[pixelIndex+1] << 12) |
- (cineon->pixelBuffer[pixelIndex+2] << 2);
- cineon->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in setRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
- if (longsWritten != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
-
- ++cineon->fileYPos;
-
- return 0;
-}
-
-int
-cineonGetRow(CineonFile* cineon, unsigned short* row, int y) {
-
- int longsRead;
- int pixelIndex;
- int longIndex;
-/* int numPixels = cineon->width * cineon->depth;
-*/
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in getRow\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon);
- if (longsRead != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
- /* remember where we left the car, honey */
- ++cineon->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t = ntohl(cineon->lineBuffer[longIndex]);
- t = t >> 2;
- row[pixelIndex+2] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- row[pixelIndex+1] = (unsigned short) t & 0x3ff;
- t = t >> 10;
- row[pixelIndex] = (unsigned short) t & 0x3ff;
- pixelIndex += 3;
- }
-
- return 0;
+void cineonSetVerbose(int verbosity) {
+ verbose = verbosity;
}
-int
-cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) {
-
- int pixelIndex;
-/* int numPixels = cineon->width * cineon->depth;
-*/ int longIndex;
- int longsWritten;
-
- /* pack into longwords */
- pixelIndex = 0;
- for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) {
- unsigned int t =
- (row[pixelIndex] << 22) |
- (row[pixelIndex+1] << 12) |
- (row[pixelIndex+2] << 2);
- cineon->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
-
- /* only seek if not reading consecutive lines */
- if (y != cineon->fileYPos) {
- int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4;
- if (verbose) d_printf("Seek in setRowBytes\n");
- if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset);
- return 1;
- }
- cineon->fileYPos = y;
- }
-
- longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file);
- if (longsWritten != cineon->lineBufferLength) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4);
- return 1;
- }
-
- ++cineon->fileYPos;
+static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header,
+ const char *filename, const char *creator)
+{
+ time_t fileClock;
+ struct tm *fileTime;
+ int i;
- return 0;
+ 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);
+ strcpy(header->fileHeader.version, "v4.5");
+ strncpy(header->fileHeader.file_name, filename, 99);
+ header->fileHeader.file_name[99] = 0;
+ fileClock = time(0);
+ 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, 199);
+ header->imageHeader.label[199] = 0;
+ 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 */
}
-CineonFile*
-cineonOpen(const char* filename) {
-
- CineonGenericHeader header;
+LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
+{
+ CineonMainHeader header;
+ LogImageFile *cineon = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
+ char *filename = (char*)byteStuff;
+ int i;
+ unsigned int dataOffset;
- CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
+ if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
return 0;
}
+ /* zero the header */
+ memset(&header, 0, sizeof(CineonMainHeader));
+
/* for close routine */
cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
- cineon->membuffer = 0;
- cineon->memcursor = 0;
- cineon->membuffersize = 0;
-
- cineon->file = BLI_fopen(filename, "rb");
- if (cineon->file == 0) {
- if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
- cineonClose(cineon);
- return 0;
- }
- cineon->reading = 1;
- if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) {
- if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
- cineonClose(cineon);
+ if (fromMemory == 0) {
+ /* byteStuff is then the filename */
+ cineon->file = BLI_fopen(filename, "rb");
+ if (cineon->file == 0) {
+ if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename);
+ logImageClose(cineon);
+ return 0;
+ }
+ /* not used in this case */
+ cineon->memBuffer = 0;
+ cineon->memCursor = 0;
+ cineon->memBufferSize = 0;
+ } else {
+ cineon->memBuffer = (unsigned char*)byteStuff;
+ cineon->memCursor = (unsigned char*)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 0;
}
- /* let's assume cineon files are always network order */
- if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
- (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
- cineonClose(cineon);
+ /* 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",
+ (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ logImageClose(cineon);
return 0;
}
- if (header.formatInfo.packing != 5) {
- if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
- cineonClose(cineon);
- return 0;
- }
+ 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);
+ cineon->depth = header.imageHeader.elements_per_image;
+ cineon->srcFormat = format_Cineon;
- cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
- cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
- cineon->depth = header.imageInfo.channels_per_image;
- /* cineon->bitsPerPixel = 10; */
- cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- cineon->imageOffset = ntohl(header.fileInfo.image_offset);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(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);
return 0;
}
- cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
+ if (cineon->depth == 1) {
+ /* Grayscale image */
+ cineon->element[0].descriptor = descriptor_Luminance;
+ cineon->element[0].transfer = transfer_Linear;
+ cineon->element[0].depth = 1;
}
- cineon->pixelBufferUsed = 0;
-
- if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
- cineonClose(cineon);
- return 0;
+ 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;
+ }
}
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
-
- cineon->getRow = &cineonGetRowBytes;
- cineon->setRow = 0;
- cineon->close = &cineonClose;
-
- if (verbose) {
- verboseMe(cineon);
+ else {
+ if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
+ return 0;
}
- return cineon;
-}
+ dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
-int cineonIsMemFileCineon(unsigned char *mem)
-{
- unsigned int num;
- memcpy(&num, mem, sizeof(unsigned int));
-
- if (num != ntohl(CINEON_FILE_MAGIC)) {
- return 0;
- }
- else return 1;
-}
+ 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);
-CineonFile*
-cineonOpenFromMem(unsigned char *mem, unsigned int size) {
+ switch (header.imageHeader.packing) {
+ case 0:
+ cineon->element[i].packing = 0;
+ break;
- CineonGenericHeader header;
-
- CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile));
- if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
- return 0;
- }
+ case 5:
+ cineon->element[i].packing = 1;
+ break;
- /* for close routine */
- cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
- cineon->membuffer = mem;
- cineon->membuffersize = size;
- cineon->memcursor = mem;
-
- cineon->file = 0;
- cineon->reading = 1;
- verbose = 0;
- if (size < sizeof(CineonGenericHeader)) {
- if (verbose) d_printf("Not enough data for header!\n");
- cineonClose(cineon);
- return 0;
- }
+ case 6:
+ cineon->element[i].packing = 2;
+ break;
- logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon);
+ default:
+ /* Not supported */
+ if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
+ return 0;
+ }
- /* let's assume cineon files are always network order */
- if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num));
+ if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData))
+ cineon->element[i].refLowData = 0;
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refHighData))
+ cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue;
- if (header.formatInfo.packing != 5) {
- if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing);
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity))
+ cineon->element[i].refLowQuantity = 0.0f;
- cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line);
- cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image);
- cineon->depth = header.imageInfo.channels_per_image;
- /* cineon->bitsPerPixel = 10; */
- cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- cineon->imageOffset = ntohl(header.fileInfo.image_offset);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(cineon);
- return 0;
- }
+ if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || 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->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
- }
- cineon->pixelBufferUsed = 0;
-
- if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset);
- cineonClose(cineon);
- return 0;
+ cineon->element[i].dataOffset = dataOffset;
+ dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]);
}
-
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
- cineon->getRow = &cineonGetRowBytes;
- cineon->setRow = 0;
- cineon->close = &cineonClose;
+ 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) {
- verboseMe(cineon);
- }
+ 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: %u\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("----------------------------\n");
+ }
return cineon;
}
+LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
+{
+ CineonMainHeader header;
+ const char *shortFilename = 0;
+ /* unsigned char pad[6044]; */
-int
-cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) {
- *width = cineon->width;
- *height = cineon->height;
- *depth = cineon->depth;
- return 0;
-}
-
-CineonFile*
-cineonCreate(const char* filename, int width, int height, int depth) {
-
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
-
- CineonGenericHeader header;
- const char* shortFilename = 0;
-
- CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile));
+ LogImageFile *cineon = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
if (cineon == 0) {
- if (verbose) d_printf("Failed to malloc cineon file structure.\n");
+ if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
return 0;
}
- memset(&header, 0, sizeof(header));
-
- /* for close routine */
- cineon->file = 0;
- cineon->lineBuffer = 0;
- cineon->pixelBuffer = 0;
-
- cineon->file = BLI_fopen(filename, "wb");
- if (cineon->file == 0) {
- if (verbose) d_printf("Couldn't open file %s\n", filename);
- cineonClose(cineon);
+ /* Only 10 bits Cineon are supported */
+ if (bitsPerSample != 10) {
+ if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n");
+ logImageClose(cineon);
return 0;
}
- cineon->reading = 0;
cineon->width = width;
cineon->height = height;
- cineon->depth = depth;
- cineon->bitsPerPixel = 10;
- cineon->imageOffset = sizeof(CineonGenericHeader);
-
- cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth);
- cineon->lineBuffer = malloc(cineon->lineBufferLength * 4);
- if (cineon->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4);
- cineonClose(cineon);
- return 0;
- }
+ 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;
- cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short));
- if (cineon->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (cineon->width * cineon->depth) * (int)sizeof(unsigned short));
- cineonClose(cineon);
- return 0;
- }
- cineon->pixelBufferUsed = 0;
-
- /* find trailing part of filename */
shortFilename = strrchr(filename, '/');
- if (shortFilename == 0) {
+ if (shortFilename == 0)
shortFilename = filename;
- }
- else {
- ++shortFilename;
- }
+ else
+ shortFilename++;
- if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) {
- cineonClose(cineon);
+ cineon->file = BLI_fopen(filename, "wb");
+ if (cineon->file == 0) {
+ if (verbose) printf("cineon: Couldn't open file %s\n", filename);
+ logImageClose(cineon);
return 0;
}
+ fillCineonMainHeader(cineon, &header, shortFilename, creator);
+
if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
- if (verbose) d_printf("Couldn't write image header\n");
- cineonClose(cineon);
+ if (verbose) printf("cineon: Couldn't write image header\n");
+ logImageClose(cineon);
return 0;
}
- cineon->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&cineon->params);
- setupLut(cineon);
-
- cineon->getRow = 0;
- cineon->setRow = &cineonSetRowBytes;
- cineon->close = &cineonClose;
return cineon;
}
-
-void
-cineonClose(CineonFile* cineon) {
-
- if (cineon == 0) {
- return;
- }
-
- if (cineon->file) {
- fclose(cineon->file);
- cineon->file = 0;
- }
-
- if (cineon->lineBuffer) {
- free(cineon->lineBuffer);
- cineon->lineBuffer = 0;
- }
-
- if (cineon->pixelBuffer) {
- free(cineon->pixelBuffer);
- cineon->pixelBuffer = 0;
- }
-
- free(cineon);
-}
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h
index ef992c527b0..78403afe955 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.h
+++ b/source/blender/imbuf/intern/cineon/cineonlib.h
@@ -1,68 +1,142 @@
/*
- * Cineon image file format library definitions.
- * Also handles DPX files (almost)
+ * Cineon image file format library definitions.
+ * Also handles DPX files (almost)
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
-#ifndef __CINEONLIB_H__
-#define __CINEONLIB_H__
-
/** \file blender/imbuf/intern/cineon/cineonlib.h
* \ingroup imbcineon
*/
-#include "logImageCore.h"
+
+#ifndef __CINEON_LIB_H__
+#define __CINEON_LIB_H__
#ifdef __cplusplus
extern "C" {
#endif
-/*
- * Cineon image structure. You don't care what this is.
- */
+#include "logImageCore.h"
-typedef struct _Log_Image_File_t_ CineonFile;
+#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
-/* int functions return 0 for OK */
+typedef struct {
+ 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];
+} CineonFileHeader;
-void cineonSetVerbose(int);
+typedef struct {
+ unsigned char descriptor1;
+ unsigned char descriptor2;
+ unsigned char bits_per_sample;
+ unsigned char 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;
+} CineonElementHeader;
-CineonFile* cineonOpenFromMem(unsigned char *mem, unsigned int size);
+typedef struct {
+ unsigned char orientation;
+ unsigned char 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];
+ unsigned char interleave;
+ unsigned char packing;
+ unsigned char data_sign;
+ unsigned char sense;
+ unsigned int line_padding;
+ unsigned int element_padding;
+ char reserved2[20];
+} CineonImageHeader;
-CineonFile* cineonOpen(const char* filename);
-int cineonGetSize(const CineonFile* cineon, int* xsize, int* ysize, int* channels);
-CineonFile* cineonCreate(const char* filename, int xsize, int ysize, int channels);
-int cineonIsMemFileCineon(unsigned char *mem);
+typedef struct {
+ 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];
+} CineonOriginationHeader;
-/* get/set scanline of converted bytes */
-int cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y);
-int cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y);
+typedef struct {
+ unsigned char film_code;
+ unsigned char film_type;
+ unsigned char edge_code_perforation_offset;
+ unsigned char 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];
+} CineonFilmHeader;
-/* get/set scanline of unconverted shorts */
-int cineonGetRow(CineonFile* cineon, unsigned short* row, int y);
-int cineonSetRow(CineonFile* cineon, const unsigned short* row, int y);
+typedef struct {
+ CineonFileHeader fileHeader;
+ CineonImageHeader imageHeader;
+ CineonOriginationHeader originationHeader;
+ CineonFilmHeader filmHeader;
+} CineonMainHeader;
-/* closes file and deletes data */
-void cineonClose(CineonFile* cineon);
+void cineonSetVerbose(int);
+LogImageFile* cineonOpen(const unsigned char* byteStuff, int fromMemory, size_t bufferSize);
+LogImageFile* cineonCreate(const char* filename, int width, int height, int bitsPerSample, const char* creator);
#ifdef __cplusplus
}
#endif
-#endif /* __CINEONLIB_H__ */
+#endif
diff --git a/source/blender/imbuf/intern/cineon/dpxfile.h b/source/blender/imbuf/intern/cineon/dpxfile.h
index e1d95268a80..e69de29bb2d 100644
--- a/source/blender/imbuf/intern/cineon/dpxfile.h
+++ b/source/blender/imbuf/intern/cineon/dpxfile.h
@@ -1,128 +0,0 @@
-/*
- * Cineon image file format library definitions.
- * Dpx file format structures.
- *
- * This header file contains private details.
- * User code should generally use cineonlib.h only.
- *
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef __DPXFILE_H__
-#define __DPXFILE_H__
-
-/** \file blender/imbuf/intern/cineon/dpxfile.h
- * \ingroup imbcineon
- */
-
-#include "logImageCore.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- U32 magic_num; /* magic number */
- U32 offset; /* offset to image data in bytes */
- ASCII vers[8]; /* which header format version is being used (v1.0) */
- U32 file_size; /* file size in bytes */
- U32 ditto_key; /* I bet some people use this */
- U32 gen_hdr_size; /* generic header length in bytes */
- U32 ind_hdr_size; /* industry header length in bytes */
- U32 user_data_size; /* user-defined data length in bytes */
- ASCII file_name[100]; /* image file name */
- ASCII create_date[24]; /* file creation date, yyyy:mm:dd:hh:mm:ss:LTZ */
- ASCII creator[100];
- ASCII project[200];
- ASCII copyright[200];
- U32 key; /* encryption key, FFFFFFF = unencrypted */
- ASCII Reserved[104]; /* reserved field TBD (need to pad) */
-} DpxFileInformation;
-
-typedef struct {
- U32 signage;
- U32 ref_low_data; /* reference low data code value */
- R32 ref_low_quantity; /* reference low quantity represented */
- U32 ref_high_data; /* reference high data code value */
- R32 ref_high_quantity;/* reference high quantity represented */
- U8 designator1;
- U8 transfer_characteristics;
- U8 colorimetry;
- U8 bits_per_pixel;
- U16 packing;
- U16 encoding;
- U32 data_offset;
- U32 line_padding;
- U32 channel_padding;
- ASCII description[32];
-} DpxChannelInformation;
-
-typedef struct {
- U16 orientation;
- U16 channels_per_image;
- U32 pixels_per_line;
- U32 lines_per_image;
- DpxChannelInformation channel[8];
- ASCII reserved[52];
-} DpxImageInformation;
-
-typedef struct {
- U32 x_offset;
- U32 y_offset;
- R32 x_centre;
- R32 y_centre;
- U32 x_original_size;
- U32 y_original_size;
- ASCII file_name[100];
- ASCII creation_time[24];
- ASCII input_device[32];
- ASCII input_serial_number[32];
- U16 border_validity[4];
- U32 pixel_aspect_ratio[2]; /* h:v */
- ASCII reserved[28];
-} DpxOriginationInformation;
-
-typedef struct {
- ASCII film_manufacturer_id[2];
- ASCII film_type[2];
- ASCII edge_code_perforation_offset[2];
- ASCII edge_code_prefix[6];
- ASCII edge_code_count[4];
- ASCII film_format[32];
- U32 frame_position;
- U32 sequence_length;
- U32 held_count;
- R32 frame_rate;
- R32 shutter_angle;
- ASCII frame_identification[32];
- ASCII slate_info[100];
- ASCII reserved[56];
-} DpxMPIInformation;
-
-typedef struct {
- DpxFileInformation fileInfo;
- DpxImageInformation imageInfo;
- DpxOriginationInformation originInfo;
- DpxMPIInformation filmHeader;
-} DpxMainHeader;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __DPXFILE_H__ */
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 0a067af2cb9..dc5f42ecaad 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -1,21 +1,23 @@
/*
- * Dpx image file format library routines.
+ * Dpx image file format library routines.
*
- * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
+ * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,689 +25,440 @@
* \ingroup imbcineon
*/
-#include "dpxfile.h"
+
#include "dpxlib.h"
+#include "logmemfile.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
-#include <time.h> /* strftime() */
+#include <time.h>
#include <sys/types.h>
-#ifdef WIN32
-#include <winsock.h>
-#else
-#include <netinet/in.h> /* htonl() */
-#endif
-#include <string.h> /* memset */
-#include "cin_debug_stuff.h"
-#include "logmemfile.h"
-#include "BLI_fileops.h"
-
-static void
-fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) {
-
- (void)dpx; /* unused */
-
- chan->signage = 0;
- chan->ref_low_data = htonl(0);
- chan->ref_low_quantity = htonf(0.0);
- chan->ref_high_data = htonl(1023);
- chan->ref_high_quantity = htonf(2.046);
- chan->designator1 = des;
- chan->transfer_characteristics = 0;
- chan->colorimetry = 0;
- chan->bits_per_pixel = 10;
- chan->packing = htons(1);
- chan->encoding = 0;
- chan->data_offset = 0;
- chan->line_padding = htonl(0);
- chan->channel_padding = htonl(0);
- chan->description[0] = 0;
-}
-
-static void
-dumpDpxChannelInfo(DpxChannelInformation* chan) {
- d_printf(" Signage %ld", (intptr_t)ntohl(chan->signage));
- d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data));
- d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity));
- d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data));
- d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity));
- d_printf(" Designator1: %d,", chan->designator1);
- d_printf(" Bits per pixel %d\n", chan->bits_per_pixel);
- d_printf(" Packing: %d,", ntohs(chan->packing));
- d_printf(" Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset));
-}
-
-static void
-fillDpxFileInfo(
- DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) {
-
- time_t fileClock;
- struct tm* fileTime;
-
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
-
- fileInfo->magic_num = htonl(DPX_FILE_MAGIC);
- fileInfo->offset = htonl(dpx->imageOffset);
- strcpy(fileInfo->vers, "v1.0");
- fileInfo->file_size = htonl(dpx->imageOffset +
- pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4);
- fileInfo->ditto_key = 0;
- fileInfo->gen_hdr_size = htonl(
- sizeof(DpxFileInformation) +
- sizeof(DpxImageInformation) +
- sizeof(DpxOriginationInformation));
- fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation));
- fileInfo->user_data_size = 0;
- strncpy(fileInfo->file_name, filename, 99);
- fileInfo->file_name[99] = 0;
+#include <string.h>
- fileClock = time(0);
- fileTime = localtime(&fileClock);
- strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
- /* Question: is %Z in strftime guaranteed to return 3 chars? */
- fileInfo->create_date[23] = 0;
-
- strcpy(fileInfo->creator, "David's DPX writer");
- fileInfo->project[0] = 0;
- fileInfo->copyright[0] = 0;
- fileInfo->key = 0xFFFFFFFF; /* same in any byte order */
-}
+#include "BLI_fileops.h"
-static void
-dumpDpxFileInfo(DpxFileInformation* fileInfo) {
- d_printf("\n--File Information--\n");
- d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num));
- d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset));
- d_printf("Version \"%s\"\n", fileInfo->vers);
- d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size));
- d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key));
- d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size));
- d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size));
- d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size));
- d_printf("File name \"%s\"\n", fileInfo->file_name);
- d_printf("Creation date \"%s\"\n", fileInfo->create_date);
- d_printf("Creator \"%s\"\n", fileInfo->creator);
- d_printf("Project \"%s\"\n", fileInfo->project);
- d_printf("Copyright \"%s\"\n", fileInfo->copyright);
- d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key));
-}
+#include "MEM_guardedalloc.h"
-static void
-fillDpxImageInfo(
- DpxFile* dpx, DpxImageInformation* imageInfo) {
- imageInfo->orientation = 0;
- imageInfo->channels_per_image = htons(1);
- imageInfo->pixels_per_line = htonl(dpx->width);
- imageInfo->lines_per_image = htonl(dpx->height);
+/*
+ * For debug purpose
+ */
- if (dpx->depth == 1) {
- fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0);
+static int verbose = 0;
- }
- else if (dpx->depth == 3) {
- fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50);
- }
+void dpxSetVerbose(int verbosity) {
+ verbose = verbosity;
}
-static void
-dumpDpxImageInfo(DpxImageInformation* imageInfo) {
- int n;
- int i;
- d_printf("\n--Image Information--\n");
- d_printf("Image orientation %d,", ntohs(imageInfo->orientation));
- n = ntohs(imageInfo->channels_per_image);
- d_printf("Channels %d\n", n);
- d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line));
- d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image));
- for (i = 0; i < n; ++i) {
- d_printf(" --Channel %d--\n", i);
- dumpDpxChannelInfo(&imageInfo->channel[i]);
- }
-}
+/*
+ * Headers
+ */
-static void
-fillDpxOriginationInfo(
- DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo)
+static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator)
{
- /* unused */
- (void)dpx;
- (void)originInfo;
- (void)fileInfo;
-}
-
-static void
-dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) {
- d_printf("\n--Origination Information--\n");
- d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset));
- d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset));
- d_printf("X centre %f\n", ntohf(originInfo->x_centre));
- d_printf("Y centre %f\n", ntohf(originInfo->y_centre));
- d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size));
- d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size));
- d_printf("File name \"%s\"\n", originInfo->file_name);
- d_printf("Creation time \"%s\"\n", originInfo->creation_time);
- d_printf("Input device \"%s\"\n", originInfo->input_device);
- d_printf("Serial number \"%s\"\n", originInfo->input_serial_number);
-}
+ time_t fileClock;
+ struct tm *fileTime;
-static void
-initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) {
memset(header, 0, sizeof(DpxMainHeader));
- fillDpxFileInfo(dpx, &header->fileInfo, shortFilename);
- fillDpxImageInfo(dpx, &header->imageInfo);
- fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo);
-#if 0
- fillDpxMPIInfo(dpx, &header->filmHeader);
-#endif
-}
-
-static void
-dumpDpxMainHeader(DpxMainHeader* header) {
- dumpDpxFileInfo(&header->fileInfo);
- dumpDpxImageInfo(&header->imageInfo);
- dumpDpxOriginationInfo(&header->originInfo);
-#if 0
- dumpDpxMPIInformation(&header->filmHeader);
-#endif
-}
-
-static int verbose = 0;
-void
-dpxSetVerbose(int verbosity) {
- verbose = verbosity;
-}
-
-static void
-verboseMe(DpxFile* dpx) {
-
- d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth);
- d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n",
- dpx->imageOffset, dpx->lineBufferLength * 4,
- dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4);
-}
-
-int
-dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) {
-
- /* Note: this code is bizarre because DPX files can wrap */
- /* packed longwords across line boundaries!!!! */
-
- size_t readLongs;
- unsigned int longIndex;
- int numPixels = dpx->width * dpx->depth;
- int pixelIndex;
-
- /* only seek if not reading consecutive lines */
- /* this is not quite right yet, need to account for leftovers */
- if (y != dpx->fileYPos) {
- int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
- return 1;
- }
- dpx->fileYPos = y;
- }
-
- /* read enough longwords */
- readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed);
- if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) {
- if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4);
- return 1;
- }
- ++dpx->fileYPos;
-
- /* convert longwords to pixels */
- pixelIndex = dpx->pixelBufferUsed;
-
- /* this is just strange */
- if (dpx->depth == 1) {
- for (longIndex = 0; longIndex < readLongs; ++longIndex) {
- unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
- dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
- pixelIndex += 3;
- }
- }
- else /* if (dpx->depth == 3) */ {
- for (longIndex = 0; longIndex < readLongs; ++longIndex) {
- unsigned int t = ntohl(dpx->lineBuffer[longIndex]);
- t = t >> 2;
- dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff;
- t = t >> 10;
- dpx->pixelBuffer[pixelIndex] = t & 0x3ff;
- pixelIndex += 3;
- }
- }
- dpx->pixelBufferUsed = pixelIndex;
-
- /* extract required pixels */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (dpx->params.doLogarithm)
- row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]];
- else
- row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
- }
-
- /* save remaining pixels */
- while (pixelIndex < dpx->pixelBufferUsed) {
- dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex];
- ++pixelIndex;
- }
- dpx->pixelBufferUsed -= numPixels;
- /* done! */
- return 0;
-}
-
-int
-dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) {
-
- /* Note: this code is bizarre because DPX files can wrap */
- /* packed longwords across line boundaries!!!! */
-
- size_t writeLongs;
- int longIndex;
- int numPixels = dpx->width * dpx->depth;
- int pixelIndex;
- int pixelIndex2;
-
- /* only seek if not reading consecutive lines */
- /* this is not quite right yet */
- if (y != dpx->fileYPos) {
- int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4;
- if (verbose) d_printf("Seek in getRowBytes\n");
- if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset);
- return 1;
- }
- dpx->fileYPos = y;
- }
-
- /* put new pixels into pixelBuffer */
- for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- if (dpx->params.doLogarithm)
- dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]];
- else
- dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
- }
- dpx->pixelBufferUsed += numPixels;
-
- /* pack into longwords */
- writeLongs = dpx->pixelBufferUsed / 3;
- /* process whole line at image end */
- if (dpx->fileYPos == (dpx->height - 1)) {
- writeLongs = pixelsToLongs(dpx->pixelBufferUsed);
- }
- pixelIndex = 0;
- if (dpx->depth == 1) {
- for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
- unsigned int t = dpx->pixelBuffer[pixelIndex] |
- (dpx->pixelBuffer[pixelIndex+1] << 10) |
- (dpx->pixelBuffer[pixelIndex+2] << 20);
- dpx->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
- }
- else {
- for (longIndex = 0; longIndex < writeLongs; ++longIndex) {
- unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 |
- (dpx->pixelBuffer[pixelIndex+1] << 12) |
- (dpx->pixelBuffer[pixelIndex] << 22);
- dpx->lineBuffer[longIndex] = htonl(t);
- pixelIndex += 3;
- }
- }
-
- /* write them */
- if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) {
- if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4);
- return 1;
- }
- ++dpx->fileYPos;
-
- /* save remaining pixels */
- pixelIndex2 = 0;
- while (pixelIndex < dpx->pixelBufferUsed) {
- dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex];
- ++pixelIndex;
- ++pixelIndex2;
- }
- dpx->pixelBufferUsed = pixelIndex2;
-
- return 0;
+ /* --- File header --- */
+ header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB);
+ header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB);
+ strcpy(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, 99);
+ header->fileHeader.file_name[99] = 0;
+ fileClock = time(0);
+ 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, 99);
+ header->fileHeader.creator[99] = 0;
+ 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 = DPX_UNDEFINED_R32;
+ header->televisionHeader.vertical_sample_rate = DPX_UNDEFINED_R32;
+ header->televisionHeader.frame_rate = DPX_UNDEFINED_R32;
+ header->televisionHeader.time_offset = DPX_UNDEFINED_R32;
+ header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB);
+ header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB);
+ header->televisionHeader.black_gain = DPX_UNDEFINED_R32;
+ header->televisionHeader.breakpoint = DPX_UNDEFINED_R32;
+ header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB);
+ header->televisionHeader.integration_times = DPX_UNDEFINED_R32;
}
-#define LFMEMFILE 0
-#define LFREALFILE 1
-
-static DpxFile*
-intern_dpxOpen(int mode, const char* bytestuff, int bufsize) {
-
+LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize)
+{
DpxMainHeader header;
- const char *filename = bytestuff;
- DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
-
+ LogImageFile *dpx = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
+ char *filename = (char*)byteStuff;
+ int i;
+
if (dpx == 0) {
- if (verbose) d_printf("Failed to malloc dpx file structure.\n");
+ if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
return 0;
}
+ /* zero the header */
+ memset(&header, 0, sizeof(DpxMainHeader));
+
/* for close routine */
dpx->file = 0;
- dpx->lineBuffer = 0;
- dpx->pixelBuffer = 0;
- if (mode == LFREALFILE) {
- filename = bytestuff;
+ if (fromMemory == 0) {
+ /* byteStuff is then the filename */
dpx->file = BLI_fopen(filename, "rb");
if (dpx->file == 0) {
- if (verbose) d_printf("Failed to open file \"%s\".\n", filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename);
+ logImageClose(dpx);
return 0;
}
- dpx->membuffer = 0;
- dpx->memcursor = 0;
- dpx->membuffersize = 0;
+ /* not used in this case */
+ dpx->memBuffer = 0;
+ dpx->memCursor = 0;
+ dpx->memBufferSize = 0;
+ } else {
+ dpx->memBuffer = (unsigned char*)byteStuff;
+ dpx->memCursor = (unsigned char*)byteStuff;
+ dpx->memBufferSize = bufferSize;
}
- else if (mode == LFMEMFILE) {
- dpx->membuffer = (unsigned char *)bytestuff;
- dpx->memcursor = (unsigned char *)bytestuff;
- dpx->membuffersize = bufsize;
- }
-
- dpx->reading = 1;
if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
- if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename);
- dpxClose(dpx);
- return 0;
- }
-
- /* let's assume dpx files are always network order */
- if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) {
- if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n",
- (uintptr_t)ntohl(header.fileInfo.magic_num), filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
+ logImageClose(dpx);
return 0;
}
- if (ntohs(header.imageInfo.channel[0].packing) != 1) {
- if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing);
- dpxClose(dpx);
+ /* 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 %lu in \"%s\".\n",
+ (uintptr_t)header.fileHeader.magic_num, byteStuff);
+ logImageClose(dpx);
return 0;
}
+ dpx->srcFormat = format_DPX;
+ dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
+ dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
+ dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB);
+ 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;
+ }
- dpx->width = ntohl(header.imageInfo.pixels_per_line);
- dpx->height = ntohl(header.imageInfo.lines_per_image);
- dpx->depth = ntohs(header.imageInfo.channels_per_image);
- /* Another DPX vs Cineon wierdness */
- if (dpx->depth == 1) {
- switch (header.imageInfo.channel[0].designator1) {
- case 50: dpx->depth = 3; break;
- case 51: dpx->depth = 4; break;
- case 52: dpx->depth = 4; break;
- default: break;
+ if (dpx->depth == 0 || dpx->depth > 4) {
+ if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth);
+ logImageClose(dpx);
+ return 0;
}
- }
- /* dpx->bitsPerPixel = 10; */
- dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel;
- if (dpx->bitsPerPixel != 10) {
- if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel);
- dpxClose(dpx);
- return 0;
- }
- dpx->imageOffset = ntohl(header.fileInfo.offset);
- dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
- dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
- if (dpx->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
- dpxClose(dpx);
- return 0;
- }
+ dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
+ 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);
- /* could have 2 pixels left over */
- dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
- if (dpx->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
- dpxClose(dpx);
- return 0;
- }
- dpx->pixelBufferUsed = 0;
+ /* 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 (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) {
- if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset);
- dpxClose(dpx);
- return 0;
- }
- dpx->fileYPos = 0;
-
- logImageGetByteConversionDefaults(&dpx->params);
- /* The SMPTE define 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.
- */
-
- switch (header.imageInfo.channel[0].transfer_characteristics) {
- case 1:
- case 2: /* linear */
- dpx->params.doLogarithm= 0;
- break;
-
- case 3:
- dpx->params.doLogarithm= 1;
- break;
-
- /* TODO - Unsupported, but for now just load them,
- * colors may look wrong, but can solve color conversion later
- */
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics);
- dpx->params.doLogarithm= 0;
- break;
- default:
- if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics);
- dpxClose(dpx);
+ if (dpx->element[i].dataOffset == 0) {
+ if (verbose) printf("DPX: Image header is corrupted.\n");
+ logImageClose(dpx);
return 0;
- break;
- }
- setupLut(dpx);
-
- dpx->getRow = &dpxGetRowBytes;
- dpx->setRow = 0;
- dpx->close = &dpxClose;
+ }
- if (verbose) {
- verboseMe(dpx);
+ 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 || isnan(dpx->element[i].refLowData))
+ dpx->element[i].refLowData = 0;
+
+ if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData))
+ dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue;
+
+ if(dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
+ dpx->element[i].refLowQuantity = 0.0f;
+
+ if(dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) {
+ if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == 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 || isnan(dpx->element[i].refLowData))
+ dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue;
+
+ if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData))
+ dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue;
+
+ if(dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity))
+ dpx->element[i].refLowQuantity = 0.0f;
+
+ if(dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity))
+ dpx->element[i].refHighQuantity = 0.7f;
+
+ break;
+
+ default:
+ break;
+ }
}
- return dpx;
-}
-
-DpxFile*
-dpxOpen(const char *filename) {
- return intern_dpxOpen(LFREALFILE, filename, 0);
-}
+ 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);
-DpxFile*
-dpxOpenFromMem(unsigned char *buffer, unsigned int size) {
- return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size);
-}
+ if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) ||
+ (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) ||
+ (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma)))
+ {
-int
-dpxIsMemFileCineon(void *buffer) {
- int magicnum = 0;
- magicnum = *((int*)buffer);
- if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1;
- else return 0;
-}
+ dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
+ dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
+ dpx->gamma = 1.7f;
+ }
-DpxFile*
-dpxCreate(const char* filename, int width, int height, int depth) {
+ 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: %u\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");
+ }
- /* Note: always write files in network order */
- /* By the spec, it shouldn't matter, but ... */
+ printf("Gamma: %f\n", dpx->gamma);
+ printf("Reference black: %f\n", dpx->referenceBlack);
+ printf("Reference white: %f\n", dpx->referenceWhite);
+ printf("----------------------------\n");
+ }
+ return dpx;
+}
+LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha,
+ int isLogarithmic, int referenceWhite, int referenceBlack, float gamma,
+ const char *creator)
+{
DpxMainHeader header;
- const char* shortFilename = 0;
+ const char *shortFilename = 0;
+ unsigned char pad[6044];
- DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile));
+ LogImageFile *dpx = (LogImageFile*)MEM_mallocN(sizeof(LogImageFile), __func__);
if (dpx == 0) {
- if (verbose) d_printf("Failed to malloc dpx file structure.\n");
- return 0;
- }
-
- memset(&header, 0, sizeof(header));
-
- /* for close routine */
- dpx->file = 0;
- dpx->lineBuffer = 0;
- dpx->pixelBuffer = 0;
-
- dpx->file = BLI_fopen(filename, "wb");
- if (dpx->file == 0) {
- if (verbose) d_printf("Couldn't open file %s\n", filename);
- dpxClose(dpx);
+ if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
return 0;
}
- dpx->reading = 0;
dpx->width = width;
dpx->height = height;
- dpx->depth = depth;
- dpx->bitsPerPixel = 10;
- dpx->imageOffset = sizeof(DpxMainHeader);
-
- dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth);
- dpx->lineBuffer = malloc(dpx->lineBufferLength * 4);
- if (dpx->lineBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4);
- dpxClose(dpx);
- return 0;
- }
+ 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;
- dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short));
- if (dpx->pixelBuffer == 0) {
- if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n",
- (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short));
- dpxClose(dpx);
- return 0;
+ 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 0;
}
- dpx->pixelBufferUsed = 0;
- /* find trailing part of filename */
- shortFilename = strrchr(filename, '/');
- if (shortFilename == 0) {
- shortFilename = filename;
+ if (hasAlpha == 0) {
+ dpx->depth = 3;
+ dpx->element[0].depth = 3;
+ dpx->element[0].descriptor = descriptor_RGB;
}
else {
- ++shortFilename;
+ dpx->depth = 4;
+ dpx->element[0].depth = 4;
+ dpx->element[0].descriptor = descriptor_RGBA;
}
- initDpxMainHeader(dpx, &header, shortFilename);
- logImageGetByteConversionDefaults(&dpx->params);
- /* Need set the file type before write the header!
- * 2 - Linear
- * 3 - Logarithmic
- *
- * Note that transfer characteristics is U8, don't need
- * check the byte order.
- */
- if (dpx->params.doLogarithm == 0)
- header.imageInfo.channel[0].transfer_characteristics= 2;
- else
- header.imageInfo.channel[0].transfer_characteristics= 3;
- if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
- if (verbose) d_printf("Couldn't write image header\n");
- dpxClose(dpx);
- return 0;
+ if (isLogarithmic == 0) {
+ dpx->element[0].transfer = transfer_Linear;
+ dpx->element[0].refHighQuantity = dpx->element[0].maxValue;
}
- dpx->fileYPos = 0;
- setupLut(dpx);
+ else {
+ dpx->element[0].transfer = transfer_PrintingDensity;
+ dpx->element[0].refHighQuantity = 2.048f;
- dpx->getRow = 0;
- dpx->setRow = &dpxSetRowBytes;
- dpx->close = &dpxClose;
+ }
- return dpx;
-}
+ dpx->element[0].refLowQuantity = 0;
+ dpx->element[0].refLowData = 0;
+ dpx->element[0].refHighData = dpx->element[0].maxValue;
-void
-dpxClose(DpxFile* dpx) {
+ if (referenceWhite > 0)
+ dpx->referenceWhite = referenceWhite;
+ else
+ dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
- if (dpx == 0) {
- return;
- }
+ if (referenceBlack > 0)
+ dpx->referenceBlack = referenceBlack;
+ else
+ dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
- if (dpx->file) {
- fclose(dpx->file);
- dpx->file = 0;
- }
+ if (gamma > 0.0f)
+ dpx->gamma = gamma;
+ else
+ dpx->gamma = 1.7f;
- if (dpx->lineBuffer) {
- free(dpx->lineBuffer);
- dpx->lineBuffer = 0;
- }
- if (dpx->pixelBuffer) {
- free(dpx->pixelBuffer);
- dpx->pixelBuffer = 0;
- }
+ shortFilename = strrchr(filename, '/');
+ if (shortFilename == 0)
+ shortFilename = filename;
+ else
+ shortFilename++;
- free(dpx);
-}
+ dpx->file = BLI_fopen(filename, "wb");
-void
-dpxDump(const char* filename) {
+ if (dpx->file == 0) {
+ if (verbose) printf("DPX: Couldn't open file %s\n", filename);
+ logImageClose(dpx);
+ return 0;
+ }
- DpxMainHeader header;
- FILE* file;
+ fillDpxMainHeader(dpx, &header, shortFilename, creator);
- file = BLI_fopen(filename, "rb");
- if (file == 0) {
- d_printf("Failed to open file \"%s\".\n", filename);
- return;
+ if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
+ if (verbose) printf("DPX: Couldn't write image header\n");
+ logImageClose(dpx);
+ return 0;
}
- if (fread(&header, sizeof(header), 1, file) == 0) {
- d_printf("Not enough data for header in \"%s\".\n", filename);
- fclose(file);
- return;
+ /* 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 0;
}
- fclose(file);
- dumpDpxMainHeader(&header);
+ return dpx;
}
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h
index eb3937f2bf7..bd608b13057 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.h
+++ b/source/blender/imbuf/intern/cineon/dpxlib.h
@@ -1,60 +1,160 @@
/*
- * DPX image file format library definitions.
+ * DPX image file format library definitions.
*
- * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
+ * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
-#ifndef __DPXLIB_H__
-#define __DPXLIB_H__
-
/** \file blender/imbuf/intern/cineon/dpxlib.h
* \ingroup imbcineon
*/
+
+#ifndef __DPX_LIB_H__
+#define __DPX_LIB_H__
+
#ifdef __cplusplus
extern "C" {
#endif
#include "logImageCore.h"
-typedef struct _Log_Image_File_t_ DpxFile;
+#define DPX_FILE_MAGIC 0x53445058
+#define DPX_UNDEFINED_U8 0xFF
+#define DPX_UNDEFINED_U16 0xFFFF
+#define DPX_UNDEFINED_U32 0xFFFFFFFF
+#define DPX_UNDEFINED_R32 0xFFFFFFFF
+#define DPX_UNDEFINED_CHAR 0
-/* int functions return 0 for OK */
+typedef struct {
+ 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];
+} DpxFileHeader;
-void dpxSetVerbose(int);
+typedef struct {
+ 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];
+} DpxElementHeader;
-DpxFile* dpxOpen(const char* filename);
-DpxFile* dpxCreate(const char* filename, int xsize, int ysize, int channels);
-DpxFile* dpxOpenFromMem(unsigned char *buffer, unsigned int size);
-int dpxIsMemFileCineon(void *buffer);
+typedef struct {
+ unsigned short orientation;
+ unsigned short elements_per_image;
+ unsigned int pixels_per_line;
+ unsigned int lines_per_element;
+ DpxElementHeader element[8];
+ char reserved[52];
+} DpxImageHeader;
-/* get/set scanline of converted bytes */
-int dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y);
-int dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y);
+typedef struct {
+ 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];
+} DpxOrientationHeader;
-/* closes file and deletes data */
-void dpxClose(DpxFile* dpx);
+typedef struct {
+ 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];
+} DpxFilmHeader;
-/* dumps file to stdout */
-void dpxDump(const char* filename);
+typedef struct {
+ 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];
+} DpxTelevisionHeader;
+
+
+typedef struct {
+ DpxFileHeader fileHeader;
+ DpxImageHeader imageHeader;
+ DpxOrientationHeader orientationHeader;
+ DpxFilmHeader filmHeader;
+ DpxTelevisionHeader televisionHeader;
+} DpxMainHeader;
+
+void dpxSetVerbose(int verbosity);
+LogImageFile* dpxOpen(const unsigned char* byteStuff, int fromMemory, size_t bufferSize);
+LogImageFile* dpxCreate(const char* filename, int width, int height, int bitsPerSample, int hasAlpha, int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, const char* creator);
#ifdef __cplusplus
}
#endif
-#endif /* __DPXLIB_H__ */
+#endif
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index f772cc7d477..917554cb4fe 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -1,21 +1,23 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,223 +25,1473 @@
* \ingroup imbcineon
*/
+
+#include "logmemfile.h"
#include "logImageCore.h"
+#include "dpxlib.h"
+#include "cineonlib.h"
-#include <time.h> /* strftime() */
+#include <stdlib.h>
+#include <string.h>
#include <math.h>
-/* Makes rint consistent in Windows and Linux: */
-#define rint(x) floor(x+0.5)
-#ifdef WIN32
-#include <winsock.h>
-#else
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/param.h>
-#endif
+#include "BLI_fileops.h"
+
+#include "MEM_guardedalloc.h"
+
+/*
+ * Declaration of static functions
+ */
+
+static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data);
+static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data);
+static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data);
+static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data);
+static int logImageElementGetData(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData1(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData8(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData10(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData10Packed(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData12(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData12Packed(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int logImageElementGetData16(LogImageFile *dpx, LogImageElement logElement, float *data);
+static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int dstIsLinearRGB);
+static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int srcIsLinearRGB);
+
+
+/*
+ * For debug purpose
+ */
+
+static int verbose = 0;
+
+void logImageSetVerbose(int verbosity)
+{
+ verbose = verbosity;
+ cineonSetVerbose(verbosity);
+ dpxSetVerbose(verbosity);
+}
+
+
+/*
+ * IO stuff
+ */
+
+int logImageIsDpx(const void *buffer)
+{
+ unsigned int magicNum = *(unsigned int*)buffer;
+ return (magicNum == DPX_FILE_MAGIC || magicNum == swap_uint(DPX_FILE_MAGIC, 1));
+}
+
+int logImageIsCineon(const void *buffer)
+{
+ unsigned int magicNum = *(unsigned int*)buffer;
+ return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1));
+}
+
+LogImageFile *logImageOpenFromFile(const char *filename, int cineon)
+{
+ unsigned int magicNum;
+ FILE *f = BLI_fopen(filename, "rb");
+
+ (void)cineon;
+
+ if (f == 0)
+ return 0;
+
+ if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) {
+ fclose(f);
+ return 0;
+ }
+
+ fclose(f);
+
+ if (logImageIsDpx(&magicNum))
+ return dpxOpen((const unsigned char *)filename, 0, 0);
+ else if (logImageIsCineon(&magicNum))
+ return cineonOpen((const unsigned char *)filename, 0, 0);
+
+ return 0;
+}
+
+LogImageFile*logImageOpenFromMemory(const unsigned char *buffer, unsigned int size)
+{
+ if (logImageIsDpx(buffer))
+ return dpxOpen(buffer, 1, size);
+ else if (logImageIsCineon(buffer))
+ return cineonOpen(buffer, 1, size);
+
+ return 0;
+}
+
+LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample,
+ int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack,
+ float gamma, const char *creator)
+{
+ /* referenceWhite, referenceBlack and gamma values are only supported for DPX file */
+ if (cineon)
+ return cineonCreate(filename, width, height, bitsPerSample, creator);
+ else
+ return dpxCreate(filename, width, height, bitsPerSample, isLogarithmic, hasAlpha,
+ referenceWhite, referenceBlack, gamma, creator);
+
+ return 0;
+}
+
+void logImageClose(LogImageFile *logImage)
+{
+ if (logImage != 0) {
+ if (logImage->file) {
+ fclose(logImage->file);
+ logImage->file = 0;
+ }
+ MEM_freeN(logImage);
+ }
+}
+
+void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth)
+{
+ *width = logImage->width;
+ *height = logImage->height;
+ *depth = logImage->depth;
+}
+
+
+/*
+ * Helper
+ */
+
+unsigned int getRowLength(int width, LogImageElement logElement)
+{
+ /* return the row length in bytes according to width and packing method */
+ switch (logElement.bitsPerSample) {
+ case 1:
+ return ((width * logElement.depth - 1) / 32 + 1) * 4;
+
+ case 8:
+ return ((width * logElement.depth - 1) / 4 + 1) * 4;
+
+ case 10:
+ if (logElement.packing == 0)
+ return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4;
+ else if (logElement.packing == 1 || logElement.packing == 2)
+ return ((width * logElement.depth - 1) / 3 + 1) * 4;
+
+ case 12:
+ if (logElement.packing == 0)
+ return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4;
+ else if (logElement.packing == 1 || logElement.packing == 2)
+ return width * logElement.depth * 2;
+
+ case 16:
+ return width * logElement.depth * 2;
+
+ default:
+ return 0;
+ }
+}
+
+
+/*
+ * Data writing
+ */
+
+int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB)
+{
+ float *elementData;
+ int returnValue;
+
+ elementData = (float*)MEM_mallocN(logImage->width * logImage->height * logImage->depth * sizeof(float), __func__);
+ if (elementData == 0)
+ return 1;
+
+ if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) {
+ MEM_freeN(elementData);
+ return 1;
+ }
+
+ switch (logImage->element[0].bitsPerSample) {
+ case 8:
+ returnValue = logImageSetData8(logImage, logImage->element[0], elementData);
+ break;
+
+ case 10:
+ returnValue = logImageSetData10(logImage, logImage->element[0], elementData);
+ break;
+
+ case 12:
+ returnValue = logImageSetData12(logImage, logImage->element[0], elementData);
+ break;
+
+ case 16:
+ returnValue = logImageSetData16(logImage, logImage->element[0], elementData);
+ break;
+
+ default:
+ returnValue = 1;
+ break;
+ }
+
+ MEM_freeN(elementData);
+ return returnValue;
+}
+
+static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned char *row;
+ int x, y;
+
+ row = (unsigned char*)MEM_mallocN(rowLength, __func__);
+ if (row == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
+ return 1;
+ }
+ memset(row, 0, rowLength);
+
+ for (y = 0; y < logImage->height; y++) {
+ for (x = 0; x < logImage->width * logImage->depth; x++)
+ row[x] = (unsigned char)float_uint(data[y * logImage->width * logImage->depth + x], 255);
+
+ if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
+ if (verbose) printf("DPX/Cineon: Error while writing file.\n");
+ MEM_freeN(row);
+ return 1;
+ }
+ }
+ MEM_freeN(row);
+ return 0;
+}
+
+static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned int pixel, index;
+ unsigned int *row;
+ int x, y, offset;
+
+ row = (unsigned int*)MEM_mallocN(rowLength, __func__);
+ if (row == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
+ return 1;
+ }
+
+ for (y = 0; y < logImage->height; y++) {
+ offset = 22;
+ index = 0;
+ pixel = 0;
+
+ for (x = 0; x < logImage->width * logImage->depth; x++) {
+ pixel |= (unsigned int)float_uint(data[y * logImage->width * logImage->depth + x], 1023) << offset;
+ offset -= 10;
+ if (offset < 0) {
+ row[index] = swap_uint(pixel, logImage->isMSB);
+ index++;
+ pixel = 0;
+ offset = 22;
+ }
+ }
+ if (pixel != 0)
+ row[index] = swap_uint(pixel, logImage->isMSB);
+
+ if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
+ if (verbose) printf("DPX/Cineon: Error while writing file.\n"); {
+ MEM_freeN(row);
+ return 1;
+ }
+ }
+ }
+ MEM_freeN(row);
+ return 0;
+}
+
+static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned short *row;
+ int x, y;
+
+ row = (unsigned short*)MEM_mallocN(rowLength, __func__);
+ if (row == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
+ return 1;
+ }
+
+ for (y = 0; y < logImage->height; y++) {
+ for (x = 0; x < logImage->width * logImage->depth; x++)
+ row[x] = swap_ushort(((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 4095)) << 4, logImage->isMSB);
+
+ if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
+ if (verbose) printf("DPX/Cineon: Error while writing file.\n");
+ MEM_freeN(row);
+ return 1;
+ }
+ }
+ MEM_freeN(row);
+ return 0;
+}
+
+static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned short *row;
+ int x, y;
+
+ row = (unsigned short*)MEM_mallocN(rowLength, __func__);
+ if (row == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
+ return 1;
+ }
+
+ for (y = 0; y < logImage->height; y++) {
+ for (x = 0; x < logImage->width * logImage->depth; x++)
+ row[x] = swap_ushort((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 65535), logImage->isMSB);
+
+ if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
+ if (verbose) printf("DPX/Cineon: Error while writing file.\n");
+ MEM_freeN(row);
+ return 1;
+ }
+ }
+ MEM_freeN(row);
+ return 0;
+}
+
+
+/*
+ * Data reading
+ */
+
+int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB)
+{
+ /* Fills data with 32 bits float RGBA values */
+ int i, j, returnValue, sortedElementData[8], hasAlpha;
+ float *elementData[8];
+ float *elementData_ptr[8];
+ float *mergedData;
+ unsigned int sampleIndex;
+ LogImageElement mergedElement;
+
+ /* Determine the depth of the picture and if there's a separate alpha element.
+ If the element is supported, load it into an unsigned ints array. */
+ memset(&elementData, 0, 8 * sizeof(float*));
+ hasAlpha = 0;
+
+ for (i = 0; i < logImage->numElements; i++) {
+ /* descriptor_Depth and descriptor_Composite are not supported */
+ if (logImage->element[i].descriptor != descriptor_Depth && logImage->element[i].descriptor != descriptor_Composite) {
+ /* Allocate memory */
+ elementData[i] = (float*)MEM_mallocN(logImage->width * logImage->height * logImage->element[i].depth * sizeof(float), __func__);
+ if (elementData[i] == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i);
+ for (j = 0; j < i; j++)
+ if (elementData[j] != 0)
+ MEM_freeN(elementData[j]);
+ return 1;
+ }
+ elementData_ptr[i] = elementData[i];
+
+ /* Load data */
+ if (logImageElementGetData(logImage, logImage->element[i], elementData[i]) != 0) {
+ if (verbose) printf("DPX/Cineon: Cannot read elementData[%d]\n.", i);
+ for (j = 0; j < i; j++)
+ if (elementData[j] != 0)
+ MEM_freeN(elementData[j]);
+ return 1;
+ }
+ }
+
+ if (logImage->element[i].descriptor == descriptor_Alpha)
+ hasAlpha = 1;
+ }
+
+ /* only one element, easy case, no need to do anything */
+ if (logImage->numElements == 1) {
+ returnValue = convertLogElementToRGBA(elementData[0], data, logImage, logImage->element[0], dataIsLinearRGB);
+ MEM_freeN(elementData[0]);
+ } else {
+ /* The goal here is to merge every elements into only one
+ * to recreate a classic 16 bits RGB, RGBA or YCbCr element.
+ * Unsupported elements are skipped (depth, composite) */
+
+ memcpy(&mergedElement, &logImage->element[0], sizeof(LogImageElement));
+ mergedElement.descriptor = -1;
+ mergedElement.depth = logImage->depth;
+ memset(&sortedElementData, -1, 8 * sizeof(int));
+
+ /* Try to know how to assemble the elements */
+ for (i = 0; i < logImage->numElements; i++) {
+ switch(logImage->element[i].descriptor) {
+ case descriptor_Red:
+ case descriptor_RGB:
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_RGB;
+ else
+ mergedElement.descriptor = descriptor_RGBA;
+
+ sortedElementData[0] = i;
+ break;
+
+ case descriptor_Green:
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_RGB;
+ else
+ mergedElement.descriptor = descriptor_RGBA;
+
+ sortedElementData[1] = i;
+ break;
+
+ case descriptor_Blue:
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_RGB;
+ else
+ mergedElement.descriptor = descriptor_RGBA;
+
+ sortedElementData[2] = i;
+ break;
+
+ case descriptor_Alpha:
+ /* Alpha component is always the last one */
+ sortedElementData[mergedElement.depth - 1] = i;
+ break;
+
+ case descriptor_Luminance:
+ if (mergedElement.descriptor == -1)
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_Luminance;
+ else
+ mergedElement.descriptor = descriptor_YA;
+ else if (mergedElement.descriptor == descriptor_Chrominance) {
+ if (mergedElement.depth == 2)
+ mergedElement.descriptor = descriptor_CbYCrY;
+ else if (mergedElement.depth == 3)
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_CbYCr;
+ else
+ mergedElement.descriptor = descriptor_CbYACrYA;
+ else if (mergedElement.depth == 4)
+ mergedElement.descriptor = descriptor_CbYCrA;
+ }
+
+ /* Y component always in 1 except if it's alone or with alpha */
+ if (mergedElement.depth == 1 || (mergedElement.depth == 2 && hasAlpha == 1))
+ sortedElementData[0] = i;
+ else
+ sortedElementData[1] = i;
+ break;
+
+ case descriptor_Chrominance:
+ if (mergedElement.descriptor == -1)
+ mergedElement.descriptor = descriptor_Chrominance;
+ else if (mergedElement.descriptor == descriptor_Luminance) {
+ if (mergedElement.depth == 2)
+ mergedElement.descriptor = descriptor_CbYCrY;
+ else if (mergedElement.depth == 3)
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_CbYCr;
+ else
+ mergedElement.descriptor = descriptor_CbYACrYA;
+ else if (mergedElement.depth == 4)
+ mergedElement.descriptor = descriptor_CbYCrA;
+ }
+
+ /* Cb and Cr always in 0 or 2 */
+ if (sortedElementData[0] == -1)
+ sortedElementData[0] = i;
+ else
+ sortedElementData[2] = i;
+ break;
+
+ case descriptor_CbYCr:
+ if (hasAlpha == 0)
+ mergedElement.descriptor = descriptor_CbYCr;
+ else
+ mergedElement.descriptor = descriptor_CbYCrA;
+
+ sortedElementData[0] = i;
+ break;
+
+ case descriptor_RGBA:
+ case descriptor_ABGR:
+ case descriptor_CbYACrYA:
+ case descriptor_CbYCrY:
+ case descriptor_CbYCrA:
+ /* I don't think these ones can be seen in a planar image */
+ mergedElement.descriptor = logImage->element[i].descriptor;
+ sortedElementData[0] = i;
+ break;
+
+ case descriptor_Depth:
+ case descriptor_Composite:
+ /* Not supported */
+ break;
+ }
+ }
+
+ mergedData = (float*)MEM_mallocN(logImage->width * logImage->height * mergedElement.depth * sizeof(float), __func__);
+ if (mergedData == 0) {
+ if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n");
+ for (i = 0; i < logImage->numElements; i++)
+ if (elementData[i] != 0)
+ MEM_freeN(elementData[i]);
+ return 1;
+ }
+
+ sampleIndex = 0;
+ while (sampleIndex < logImage->width * logImage->height * mergedElement.depth) {
+ for (i = 0; i < logImage->numElements; i++)
+ for (j = 0; j < logImage->element[sortedElementData[i]].depth; j++)
+ mergedData[sampleIndex++] = *(elementData_ptr[sortedElementData[i]]++);
+ }
+
+ /* Done with elements data, clean-up */
+ for (i = 0; i < logImage->numElements; i++)
+ if (elementData[i] != 0)
+ MEM_freeN(elementData[i]);
+
+ returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB);
+ MEM_freeN(mergedData);
+ }
+ return returnValue;
+}
+
+static int logImageElementGetData(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ switch (logElement.bitsPerSample) {
+ case 1:
+ return logImageElementGetData1(logImage, logElement, data);
+
+ case 8:
+ return logImageElementGetData8(logImage, logElement, data);
+
+ case 10:
+ if (logElement.packing == 0)
+ return logImageElementGetData10Packed(logImage, logElement, data);
+ else if (logElement.packing == 1 || logElement.packing == 2)
+ return logImageElementGetData10(logImage, logElement, data);
+
+ case 12:
+ if (logElement.packing == 0)
+ return logImageElementGetData12Packed(logImage, logElement, data);
+ else if (logElement.packing == 1 || logElement.packing == 2)
+ return logImageElementGetData12(logImage, logElement, data);
+
+ case 16:
+ return logImageElementGetData16(logImage, logElement, data);
+
+ default:
+ /* format not supported */
+ return 1;
+ }
+}
+
+static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int pixel;
+ int x, y, offset;
+
+ /* seek at the right place */
+ if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
+ return 1;
+ }
+
+ /* read 1 bit data padded to 32 bits */
+ for (y = 0; y < logImage->height; y++) {
+ for (x = 0; x < logImage->width * logElement.depth; x += 32) {
+ if (logimage_read_uint(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_uint(pixel, logImage->isMSB);
+ for (offset = 0; offset < 32 && x + offset < logImage->width; offset++)
+ data[y * logImage->width * logElement.depth + x + offset] = (float)((pixel >> offset) & 0x01);
+ }
+ }
+ return 0;
+}
+
+static int logImageElementGetData8(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned char pixel;
+ int x, y;
+
+ /* extract required pixels */
+ for (y = 0; y < logImage->height; y++) {
+ /* 8 bits are 32-bits padded so we need to seek at each row */
+ if (logimage_fseek(logImage, logElement.dataOffset + y * rowLength, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * rowLength);
+ return 1;
+ }
+
+ for (x = 0; x < logImage->width * logElement.depth; x++) {
+ if (logimage_read_uchar(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ data[y * logImage->width * logElement.depth + x] = (float)pixel / 255.0f;
+ }
+ }
+ return 0;
+}
+
+static int logImageElementGetData10(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int pixel;
+ int x, y, offset;
+
+ /* seek to data */
+ if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
+ return 1;
+ }
+
+ if (logImage->depth == 1 && logImage->srcFormat == format_DPX) {
+ for (y = 0; y < logImage->height; y++) {
+ offset = 32;
+ for (x = 0; x < logImage->width * logElement.depth; x++) {
+ /* we need to read the next long */
+ if (offset >= 30) {
+ if (logElement.packing == 1)
+ offset = 2;
+ else if (logElement.packing == 2)
+ offset = 0;
+
+ if (logimage_read_uint(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_uint(pixel, logImage->isMSB);
+ }
+ data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f;
+ offset += 10;
+ }
+ }
+ } else {
+ for (y = 0; y < logImage->height; y++) {
+ offset = -1;
+ for (x = 0; x < logImage->width * logElement.depth; x++) {
+ /* we need to read the next long */
+ if (offset < 0) {
+ if (logElement.packing == 1)
+ offset = 22;
+ else if (logElement.packing == 2)
+ offset = 20;
-#if defined(__hpux)
-/* These are macros in hpux */
-#ifdef htonl
-#undef htonl
-#undef htons
-#undef ntohl
-#undef ntohs
-#endif
-unsigned int htonl(h) unsigned int h; { return(h); }
-unsigned short htons(h) unsigned short h; { return(h); }
-unsigned int ntohl(n) unsigned int n; { return(n); }
-unsigned short ntohs(n) unsigned short n; { return(n); }
-#endif
-
-
-/* obscure LogImage conversion */
-/* from 10 bit int to 0.0 - 1.0 */
-/* magic numbers left intact */
-static double
-convertTo(int inp, int white, float gamma) {
- /* return pow(pow(10.0, ((inp - white) * 0.002 / 0.6)), gamma); */
- return pow(10.0, (inp - white) * gamma * 0.002 / 0.6);
+ if (logimage_read_uint(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_uint(pixel, logImage->isMSB);
+ }
+ data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f;
+ offset -= 10;
+ }
+ }
+ }
+
+ return 0;
}
-static double
-convertFrom(double inp, int white, float gamma) {
- return white + log10(inp) / (gamma * 0.002 / 0.6);
+static int logImageElementGetData10Packed(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned int pixel, oldPixel;
+ int offset, offset2, x, y;
+
+ /* converting bytes to pixels */
+ for (y = 0; y < logImage->height; y++) {
+ /* seek to data */
+ if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset);
+ return 1;
+ }
+
+ oldPixel = 0;
+ offset = 0;
+ offset2 = 0;
+
+ for (x = 0; x < logImage->width * logElement.depth; x++) {
+ if (offset2 != 0) {
+ offset = 10 - offset2;
+ offset2 = 0;
+ oldPixel = 0;
+ } else if (offset == 32) {
+ offset = 0;
+ } else if (offset + 10 > 32) {
+ /* next pixel is on two different longs */
+ oldPixel = (pixel >> offset);
+ offset2 = 32 - offset;
+ offset = 0;
+ }
+
+ if (offset == 0) {
+ /* we need to read the next long */
+ if (logimage_read_uint(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_uint(pixel, logImage->isMSB);
+ }
+ data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0x3ff) | oldPixel) / 1023.0f;
+ offset += 10;
+ }
+ }
+ return 0;
+}
+
+static int logImageElementGetData12(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int sampleIndex;
+ unsigned int numSamples = logImage->width * logImage->height * logElement.depth;
+ unsigned short pixel;
+
+ /* seek to data */
+ if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
+ return 1;
+ }
+
+ /* convert bytes to pixels */
+ sampleIndex = 0;
+
+ for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
+ if (logimage_read_ushort(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_ushort(pixel, logImage->isMSB);
+
+ if (logElement.packing == 1) /* padded to the right */
+ data[sampleIndex] = (float)(pixel >> 4) / 4095.0f;
+ else if (logElement.packing == 2) /* padded to the left */
+ data[sampleIndex] = (float)pixel / 4095.0f;
+ }
+ return 0;
}
-/* set up the 10 bit to 8 bit and 8 bit to 10 bit tables */
-void
-setupLut(LogImageFile *logImage) {
+static int logImageElementGetData12Packed(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned int pixel, oldPixel;
+ int offset, offset2, x, y;
+
+ /* converting bytes to pixels */
+ for (y = 0; y < logImage->height; y++) {
+ /* seek to data */
+ if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset);
+ return 1;
+ }
+
+ oldPixel = 0;
+ offset = 0;
+ offset2 = 0;
- int i;
- double f_black;
- double scale;
+ for (x = 0; x < logImage->width * logElement.depth; x++) {
+ if (offset2 != 0) {
+ offset = 12 - offset2;
+ offset2 = 0;
+ oldPixel = 0;
+ } else if (offset == 32) {
+ offset = 0;
+ } else if (offset + 12 > 32) {
+ /* next pixel is on two different longs */
+ oldPixel = (pixel >> offset);
+ offset2 = 32 - offset;
+ offset = 0;
+ }
+
+ if (offset == 0) {
+ /* we need to read the next long */
+ if (logimage_read_uint(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_uint(pixel, logImage->isMSB);
+ }
+ data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0xfff) | oldPixel) / 4095.0f;
+ offset += 12;
+ }
+ }
+ return 0;
+}
- f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma);
- scale = 255.0 / (1.0 - f_black);
+static int logImageElementGetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int numSamples = logImage->width * logImage->height * logElement.depth;
+ unsigned int sampleIndex;
+ unsigned short pixel;
- for (i = 0; i <= logImage->params.blackPoint; ++i) {
- logImage->lut10[i] = 0;
+ /* seek to data */
+ if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
+ if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
+ return 1;
}
- for (; i < logImage->params.whitePoint; ++i) {
- double f_i;
- f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma);
- logImage->lut10[i] = (int)rint(scale * (f_i - f_black));
+
+ for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
+ if (logimage_read_ushort(&pixel, logImage) != 0) {
+ if (verbose) printf("DPX/Cineon: EOF reached\n");
+ return 1;
+ }
+ pixel = swap_ushort(pixel, logImage->isMSB);
+ data[sampleIndex] = (float)pixel / 65535.0f;
}
- for (; i < 1024; ++i) {
- logImage->lut10[i] = 255;
+
+ return 0;
+}
+
+
+/*
+ * Color conversion
+ */
+
+static int getYUVtoRGBMatrix(float *matrix, LogImageElement logElement)
+{
+ float scaleY, scaleCbCr;
+ float refHighData = (float)logElement.refHighData / logElement.maxValue;
+ float refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ scaleY = 1.0f / (refHighData - refLowData);
+ scaleCbCr = scaleY * ((940.0f - 64.0f) / (960.0f - 64.0f));
+
+ switch (logElement.transfer) {
+ case 2: /* linear */
+ matrix[0] = 1.0f * scaleY;
+ matrix[1] = 1.0f * scaleCbCr;
+ matrix[2] = 1.0f * scaleCbCr;
+ matrix[3] = 1.0f * scaleY;
+ matrix[4] = 1.0f * scaleCbCr;
+ matrix[5] = 1.0f * scaleCbCr;
+ matrix[6] = 1.0f * scaleY;
+ matrix[7] = 1.0f * scaleCbCr;
+ matrix[8] = 1.0f * scaleCbCr;
+ return 0;
+
+ case 5: /* SMPTE 240M */
+ matrix[0] = 1.0000f * scaleY;
+ matrix[1] = 0.0000f * scaleCbCr;
+ matrix[2] = 1.5756f * scaleCbCr;
+ matrix[3] = 1.0000f * scaleY;
+ matrix[4] = -0.2253f * scaleCbCr;
+ matrix[5] = -0.5000f * scaleCbCr;
+ matrix[6] = 1.0000f * scaleY;
+ matrix[7] = 1.8270f * scaleCbCr;
+ matrix[8] = 0.0000f * scaleCbCr;
+ return 0;
+
+ case 6: /* CCIR 709-1 */
+ matrix[0] = 1.000000f * scaleY;
+ matrix[1] = 0.000000f * scaleCbCr;
+ matrix[2] = 1.574800f * scaleCbCr;
+ matrix[3] = 1.000000f * scaleY;
+ matrix[4] = -0.187324f * scaleCbCr;
+ matrix[5] = -0.468124f * scaleCbCr;
+ matrix[6] = 1.000000f * scaleY;
+ matrix[7] = 1.855600f * scaleCbCr;
+ matrix[8] = 0.000000f * scaleCbCr;
+ return 0;
+
+ case 7: /* CCIR 601 */
+ case 8: /* I'm not sure 7 and 8 should share the same matrix */
+ matrix[0] = 1.000000f * scaleY;
+ matrix[1] = 0.000000f * scaleCbCr;
+ matrix[2] = 1.402000f * scaleCbCr;
+ matrix[3] = 1.000000f * scaleY;
+ matrix[4] = -0.344136f * scaleCbCr;
+ matrix[5] = -0.714136f * scaleCbCr;
+ matrix[6] = 1.000000f * scaleY;
+ matrix[7] = 1.772000f * scaleCbCr;
+ matrix[8] = 0.000000f * scaleCbCr;
+ return 0;
+
+ default:
+ return 1;
}
+}
+
+static void getLinToLogLut(float *lut, LogImageFile *logImage, LogImageElement logElement)
+{
+ float gain, negativeFilmGamma, offset, step;
+ unsigned int i;
+
+ negativeFilmGamma = 0.6;
+ step = logElement.refHighQuantity / logElement.maxValue;
+ gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
+ offset = gain - logElement.maxValue;
+
+ for (i = 0; i < (int)(logElement.maxValue + 1); i++)
+ lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue;
+}
- for (i = 0; i < 256; ++i) {
- double f_i = f_black + (i / 255.0) * (1.0 - f_black);
- logImage->lut8[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma);
- }
-}
-
-/* set up the 10 bit to 16 bit and 16 bit to 10 bit tables */
-void
-setupLut16(LogImageFile *logImage) {
+static void getLogToLinLut(float *lut, LogImageFile *logImage, LogImageElement logElement)
+{
+ float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip;
+ /* float filmGamma; unused */
+ unsigned int i;
- int i;
- double f_black;
- double scale;
+ /* Building the Log -> Lin LUT */
+ step = logElement.refHighQuantity / logElement.maxValue;
+ negativeFilmGamma = 0.6;
- f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma);
- scale = 65535.0 / (1.0 - f_black);
-
- for (i = 0; i <= logImage->params.blackPoint; ++i) {
- logImage->lut10_16[i] = 0;
- }
- for (; i < logImage->params.whitePoint; ++i) {
- double f_i;
- f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma);
- logImage->lut10_16[i] = (int)rint(scale * (f_i - f_black));
- }
- for (; i < 1024; ++i) {
- logImage->lut10_16[i] = 65535;
- }
-
- for (i = 0; i < 65536; ++i) {
- double f_i = f_black + (i / 65535.0) * (1.0 - f_black);
- logImage->lut16_16[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma);
- }
-}
-
-/* how many longwords to hold this many pixels? */
-int
-pixelsToLongs(int numPixels) {
- return (numPixels + 2) / 3;
-}
-
-/* byte reversed float */
+ /* these are default values */
+ /* filmGamma = 2.2f; unused */
+ softClip = 0;
-typedef union {
- U32 i;
- R32 f;
-} Hack;
+ breakPoint = logImage->referenceWhite - softClip;
+ gain = logElement.maxValue / (1.0 - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
+ offset = gain - logElement.maxValue;
+ kneeOffset = powf(10, (breakPoint - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset;
+ kneeGain = (logElement.maxValue - kneeOffset) / powf(5 * softClip, softClip / 100);
-R32
-htonf(R32 f) {
- Hack hack;
- hack.f = f;
- hack.i = htonl(hack.i);
- return hack.f;
+ for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
+ if (i < logImage->referenceBlack)
+ lut[i] = 0.0f;
+ else if (i > breakPoint)
+ lut[i] = (powf(i - breakPoint, softClip / 100) * kneeGain + kneeOffset) / logElement.maxValue;
+ else
+ lut[i] = (powf(10, ((float)i - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset) / logElement.maxValue;
+ }
}
-R32
-ntohf(R32 f) {
- Hack hack;
- hack.f = f;
- hack.i = ntohl(hack.i);
- return hack.f;
+static void getLinToSrgbLut(float *lut, LogImageElement logElement)
+{
+ unsigned int i;
+ float col;
+
+ for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
+ col = (float)i / logElement.maxValue;
+ if (col < 0.0031308f)
+ lut[i] = (col < 0.0f) ? 0.0f : col * 12.92f;
+ else
+ lut[i] = 1.055f * powf(col, 1.0f / 2.4f) - 0.055f;
+ }
}
-#define UNDEF_FLOAT 0x7F800000
+static void getSrgbToLinLut(float *lut, LogImageElement logElement)
+{
+ unsigned int i;
+ float col;
-R32
-undefined(void) {
- Hack hack;
- hack.i = UNDEF_FLOAT;
- return hack.f;
+ for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
+ col = (float)i / logElement.maxValue;
+ if (col < 0.04045f)
+ lut[i] = (col < 0.0f) ? 0.0f : col * (1.0f / 12.92f);
+ else
+ lut[i] = powf((col + 0.055f) * (1.0f / 1.055f), 2.4f);
+ }
}
-/* reverse an endian-swapped U16 */
-U16
-reverseU16(U16 value) {
+static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int elementIsSource)
+{
+ unsigned int i;
+ float lut[65536];
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ switch (logElement.transfer) {
+ case transfer_UserDefined:
+ case transfer_Linear:
+ case transfer_Logarithmic:
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = *(src_ptr++);
+ *(dst_ptr++) = *(src_ptr++);
+ *(dst_ptr++) = *(src_ptr++);
+ src_ptr++;
+ }
+ return 0;
+
+ case transfer_PrintingDensity:
+ if (elementIsSource == 1)
+ getLogToLinLut((float*)&lut, logImage, logElement);
+ else
+ getLinToLogLut((float*)&lut, logImage, logElement);
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ src_ptr++;
+ }
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int elementIsSource)
+{
+ unsigned int i;
+ float lut[65536];
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ switch(logElement.transfer) {
+ case transfer_UserDefined:
+ case transfer_Linear:
+ case transfer_Logarithmic:
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = *(src_ptr++);
+ *(dst_ptr++) = *(src_ptr++);
+ *(dst_ptr++) = *(src_ptr++);
+ *(dst_ptr++) = 1.0f;
+ }
+ return 0;
+
+ case transfer_PrintingDensity:
+ if (elementIsSource == 1)
+ getLogToLinLut((float*)&lut, logImage, logElement);
+ else
+ getLinToLogLut((float*)&lut, logImage, logElement);
- union {
- U16 whole;
- char part[2];
- } buff;
- char temp;
- buff.whole = value;
- temp = buff.part[0];
- buff.part[0] = buff.part[1];
- buff.part[1] = temp;
- return buff.whole;
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = 1.0f;
+ }
+ return 0;
+
+ default:
+ return 1;
+ }
}
-/* reverse an endian-swapped U32 */
-U32
-reverseU32(U32 value) {
+static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int elementIsSource)
+{
+ unsigned int i;
+ float lut[65536];
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ switch (logElement.transfer) {
+ case transfer_UserDefined:
+ case transfer_Linear:
+ case transfer_Logarithmic:
+ memcpy(dst, src, 4 * logImage->width * logImage->height * sizeof(float));
+ return 0;
+
+ case transfer_PrintingDensity:
+ if (elementIsSource == 1)
+ getLogToLinLut((float*)&lut, logImage, logElement);
+ else
+ getLinToLogLut((float*)&lut, logImage, logElement);
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = *(src_ptr++);
+ }
+ return 0;
- union {
- U32 whole;
- char part[4];
- } buff;
- char temp;
- buff.whole = value;
- temp = buff.part[0];
- buff.part[0] = buff.part[3];
- buff.part[3] = temp;
- temp = buff.part[1];
- buff.part[1] = buff.part[2];
- buff.part[2] = temp;
- return buff.whole;
+ default:
+ return 1;
+ }
}
-/* reverse an endian-swapped R32 */
-R32
-reverseR32(R32 value) {
+static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int elementIsSource)
+{
+ unsigned int i;
+ float lut[65536];
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ switch (logElement.transfer) {
+ case transfer_UserDefined:
+ case transfer_Linear:
+ case transfer_Logarithmic:
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ src_ptr += 4;
+ *(dst_ptr++) = *(src_ptr--);
+ *(dst_ptr++) = *(src_ptr--);
+ *(dst_ptr++) = *(src_ptr--);
+ *(dst_ptr++) = *(src_ptr--);
+ src_ptr += 4;
+ }
+ return 0;
+
+ case transfer_PrintingDensity:
+ if (elementIsSource == 1)
+ getLogToLinLut((float*)&lut, logImage, logElement);
+ else
+ getLinToLogLut((float*)&lut, logImage, logElement);
- union {
- R32 whole;
- char part[4];
- } buff;
- char temp;
- buff.whole = value;
- temp = buff.part[0];
- buff.part[0] = buff.part[3];
- buff.part[3] = temp;
- temp = buff.part[1];
- buff.part[1] = buff.part[2];
- buff.part[2] = temp;
- return buff.whole;
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ src_ptr += 4;
+ *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
+ *(dst_ptr++) = *(src_ptr--);
+ src_ptr += 4;
+ }
+ return 0;
+
+ default:
+ return 1;
+ }
}
-#if 0
-/* bytes per line for images packed 3 10 bit pixels to 32 bits, 32 bit aligned */
-int
-bytesPerLine_10_4(int numPixels) {
- return ((numPixels + 2) / 3) * 4;
+static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], refLowData, y, cb, cr;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ cb = *(src_ptr++) - 0.5f;
+ y = *(src_ptr++) - refLowData;
+ cr = *(src_ptr++) - 0.5f;
+
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = 1.0f;
+ }
+ return 0;
}
-void
-seekLine_noPadding(LogImageFile* logImage, int lineNumber) {
- int fileOffset = bytesPerLine_10_4(lineNumber * logImage->width * logImage->depth);
- int filePos = logImage->imageOffset + fileOffset;
- if (fseek(logImage->file, filePos, SEEK_SET) != 0) {
- /* complain? */
- }
-}
-
-void
-seekLine_padding(LogImageFile* logImage, int lineNumber) {
- int fileOffset = lineNumber * bytesPerLine_10_4(logImage->width * logImage->depth);
- int filePos = logImage->imageOffset + fileOffset;
- if (fseek(logImage->file, filePos, SEEK_SET) != 0) {
- /* complain? */
- }
-}
-#endif
+static int convertCbYCrA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], refLowData, y, cb, cr, a;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ cb = *(src_ptr++) - 0.5f;
+ y = *(src_ptr++) - refLowData;
+ cr = *(src_ptr++) - 0.5f;
+ a = *(src_ptr++);
+
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = a;
+ }
+ return 0;
+}
+
+static int convertCbYCrY_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], refLowData, y1, y2, cb, cr;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height / 2; i++) {
+ cb = *(src_ptr++) - 0.5f;
+ y1 = *(src_ptr++) - refLowData;
+ cr = *(src_ptr++) - 0.5f;
+ y2 = *(src_ptr++) - refLowData;
+
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = 1.0f;
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = 1.0f;
+ }
+ return 0;
+}
+
+static int convertCbYACrYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], refLowData, y1, y2, cb, cr, a1, a2;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height / 2; i++) {
+ cb = *(src_ptr++) - 0.5f;
+ y1 = *(src_ptr++) - refLowData;
+ a1 = *(src_ptr++);
+ cr = *(src_ptr++) - 0.5f;
+ y2 = *(src_ptr++) - refLowData;
+ a2 = *(src_ptr++);
+
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = a1;
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
+ *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
+ *(dst_ptr++) = a2;
+ }
+ return 0;
+}
+
+static int convertLuminance_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], value, refLowData;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = 1.0f;
+ }
+ return 0;
+}
+
+static int convertYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
+{
+ unsigned int i;
+ float conversionMatrix[9], value, refLowData;
+ float *src_ptr = src;
+ float *dst_ptr = dst;
+
+ if (getYUVtoRGBMatrix((float*)&conversionMatrix, logElement) != 0)
+ return 1;
+
+ refLowData = (float)logElement.refLowData / logElement.maxValue;
+
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = value;
+ *(dst_ptr++) = *(src_ptr++);
+ }
+ return 0;
+}
+
+static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int dstIsLinearRGB)
+{
+ int rvalue;
+ unsigned int i;
+ float *src_ptr;
+ float *dst_ptr;
+ float lut[65536];
+
+ /* Convert data in src to linear RGBA in dst */
+ switch (logElement.descriptor) {
+ case descriptor_RGB:
+ rvalue = convertRGB_RGBA(src, dst, logImage, logElement, 1);
+ break;
+
+ case descriptor_RGBA:
+ rvalue = convertRGBA_RGBA(src, dst, logImage, logElement, 1);
+ break;
+
+ case descriptor_ABGR:
+ rvalue = convertABGR_RGBA(src, dst, logImage, logElement, 1);
+ break;
+
+ case descriptor_Luminance:
+ rvalue = convertLuminance_RGBA(src, dst, logImage, logElement);
+ break;
+
+ case descriptor_CbYCr:
+ rvalue = convertCbYCr_RGBA(src, dst, logImage, logElement);
+ break;
+
+ case descriptor_CbYCrY:
+ rvalue = convertCbYCrY_RGBA(src, dst, logImage, logElement);
+ break;
+
+ case descriptor_CbYACrYA:
+ rvalue = convertCbYACrYA_RGBA(src, dst, logImage, logElement);
+ break;
+
+ case descriptor_CbYCrA:
+ rvalue = convertCbYCrA_RGBA(src, dst, logImage, logElement);
+ break;
+
+ case descriptor_YA: /* this descriptor is for internal use only */
+ rvalue = convertYA_RGBA(src, dst, logImage, logElement);
+ break;
+
+ default:
+ return 1;
+ }
+
+ if (rvalue == 1)
+ return 1;
+ else if (dstIsLinearRGB) {
+ /* convert data from sRGB to Linear RGB via lut */
+ getSrgbToLinLut((float*)&lut, logElement);
+ src_ptr = dst; // no error here
+ dst_ptr = dst;
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ dst_ptr++; src_ptr++;
+ }
+ }
+ return 0;
+}
+
+static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage,
+ LogImageElement logElement, int srcIsLinearRGB)
+{
+ unsigned int i;
+ int rvalue;
+ float *srgbSrc;
+ float *srgbSrc_ptr;
+ float *src_ptr = src;
+ float lut[65536];
+
+ if (srcIsLinearRGB != 0) {
+ /* we need to convert src to sRGB */
+ srgbSrc = (float*)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__);
+ if (srgbSrc == 0)
+ return 1;
+
+ memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float));
+ srgbSrc_ptr = srgbSrc;
+
+ /* convert data from Linear RGB to sRGB via lut */
+ getLinToSrgbLut((float*)&lut, logElement);
+ for (i = 0; i < logImage->width * logImage->height; i++) {
+ *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
+ srgbSrc_ptr++; src_ptr++;
+ }
+ } else
+ srgbSrc = src;
+
+ /* Convert linear RGBA data in src to format described by logElement in dst */
+ switch (logElement.descriptor) {
+ case descriptor_RGB:
+ rvalue = convertRGBA_RGB(srgbSrc, dst, logImage, logElement, 0);
+ break;
+
+ case descriptor_RGBA:
+ rvalue = convertRGBA_RGBA(srgbSrc, dst, logImage, logElement, 0);
+ break;
+
+ /* these ones are not supported for the moment */
+ case descriptor_ABGR:
+ case descriptor_Luminance:
+ case descriptor_CbYCr:
+ case descriptor_CbYCrY:
+ case descriptor_CbYACrYA:
+ case descriptor_CbYCrA:
+ case descriptor_YA: /* this descriptor is for internal use only */
+ default:
+ rvalue = 1;
+ }
+
+ if (srcIsLinearRGB != 0) {
+ MEM_freeN(srgbSrc);
+ }
+
+ return rvalue;
+}
+
+/*
+ * Endianness swapping
+ */
+
+inline unsigned short swap_ushort(unsigned short x, int swap)
+{
+ if (swap != 0)
+ return (x >> 8) | (x << 8);
+ else
+ return x;
+}
+
+inline unsigned int swap_uint(unsigned int x, int swap)
+{
+ if (swap != 0)
+ return (x >> 24) | (( x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24);
+ else
+ return x;
+}
+
+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;
+ } else
+ return x;
+}
+
+
+/*
+ * Other
+ */
+
+inline unsigned int clamp_uint(unsigned int x, unsigned int low, unsigned int high)
+{
+ if (x > high)
+ return high;
+ else if (x < low)
+ return low;
+ else
+ return x;
+}
+
+inline float clamp_float(float x, float low, float high)
+{
+ if (x > high)
+ return high;
+ else if (x < low)
+ return low;
+ else
+ return x;
+}
+
+inline unsigned int float_uint(float value, unsigned int max)
+{
+ if (value < 0.0f)
+ return 0;
+ else if (value > (1.0f - 0.5f / (float)max))
+ return max;
+ else
+ return (unsigned int)(((float)max * value) + 0.5f);
+}
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h
index 7d88c10c2d6..c1f4d2eae04 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.h
+++ b/source/blender/imbuf/intern/cineon/logImageCore.h
@@ -1,123 +1,217 @@
/*
- * Cineon image file format library definitions.
- * Cineon and DPX common structures.
+ * 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!
+ * 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!
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
-#ifndef __LOGIMAGECORE_H__
-#define __LOGIMAGECORE_H__
-
/** \file blender/imbuf/intern/cineon/logImageCore.h
* \ingroup imbcineon
*/
+
+#ifndef __LOG_IMAGE_CORE_H__
+#define __LOG_IMAGE_CORE_H__
+
#include <stdio.h>
-#include "logImageLib.h"
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
-#include "BLO_sys_types.h" // for intptr_t support
-
-#ifdef _MSC_VER
-#undef ntohl
-#undef htonl
-#endif
+/*
+ * Image structure
+ */
-typedef int (GetRowFn)(LogImageFile* logImage, unsigned short* row, int lineNum);
-typedef int (SetRowFn)(LogImageFile* logImage, const unsigned short* row, int lineNum);
-typedef void (CloseFn)(LogImageFile* logImage);
+/* There are some differences between DPX and Cineon so we need to know from what type of file the datas come from */
+enum format {
+ format_DPX,
+ format_Cineon
+};
-struct _Log_Image_File_t_
+typedef 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) */
+} LogImageElement;
+
+typedef struct LogImageFile
{
/* specified in header */
int width;
int height;
+ int numElements;
int depth;
- int bitsPerPixel;
- int imageOffset;
-
- /* file buffer, measured in longwords (4 byte) */
- int lineBufferLength;
- unsigned int* lineBuffer;
+ LogImageElement element[8];
- /* pixel buffer, holds 10 bit pixel values */
- unsigned short* pixelBuffer;
- int pixelBufferUsed;
+ /* used for log <-> lin conversion */
+ float referenceBlack;
+ float referenceWhite;
+ float gamma;
- /* io stuff */
+ /* io stuff */
FILE* file;
- int reading;
- int fileYPos;
+ unsigned char* memBuffer;
+ uintptr_t memBufferSize;
+ unsigned char* memCursor;
+
+ /* is the file LSB or MSB ? */
+ int isMSB;
+
+ /* DPX or Cineon ? */
+ int srcFormat;
+} LogImageFile;
+
+
+/* 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
+};
- /* byte conversion stuff */
- LogImageByteConversionParameters params;
-#if 0
- float gamma;
- int blackPoint;
- int whitePoint;
-#endif
- unsigned char lut10[1024];
- unsigned short lut8[256];
-
- unsigned short lut10_16[1024];
- unsigned short lut16_16[65536];
-
- /* pixel access functions */
- GetRowFn* getRow;
- SetRowFn* setRow;
- CloseFn* close;
-
- unsigned char *membuffer;
- uintptr_t membuffersize;
- unsigned char *memcursor;
+/* 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
};
-void setupLut(LogImageFile*);
-void setupLut16(LogImageFile*);
+/* int functions return 0 for OK */
-int pixelsToLongs(int numPixels);
+void logImageSetVerbose(int verbosity);
+int logImageIsDpx(const void* buffer);
+int logImageIsCineon(const void* buffer);
+LogImageFile* logImageOpenFromMemory(const unsigned char *buffer, unsigned int size);
+LogImageFile* logImageOpenFromFile(const char *filename, int cineon);
+void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth);
+LogImageFile* logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample, int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack, float gamma, const char* creator);
+void logImageClose(LogImageFile* logImage);
-/* typedefs used in original docs */
-/* note size assumptions! */
+/* Data handling */
+unsigned int getRowLength(int width, LogImageElement logElement);
+int logImageSetDataRGBA(LogImageFile *logImage,float *data, int dataIsLinearRGB);
+int logImageGetDataRGBA(LogImageFile *logImage, float* data, int dataIsLinearRGB);
-typedef unsigned int U32;
-typedef unsigned short U16;
-typedef unsigned char U8;
-typedef signed int S32;
-typedef float R32;
-typedef char ASCII;
+/* Endianness conversion */
+inline unsigned short swap_ushort(unsigned short x, int swap);
+inline unsigned int swap_uint(unsigned int x, int swap);
+inline float swap_float(float x, int swap);
+
+/* Other */
+inline float clamp_float(float x, float low, float high);
+inline unsigned int clamp_uint(unsigned int x, unsigned int low, unsigned int high);
+inline unsigned int float_uint(float value, unsigned int max);
-R32 htonf(R32 f);
-R32 ntohf(R32 f);
-R32 undefined(void);
-U16 reverseU16(U16 value);
-U32 reverseU32(U32 value);
-R32 reverseR32(R32 value);
#ifdef __cplusplus
}
#endif
-#endif /* __LOGIMAGECORE_H__ */
+#endif
diff --git a/source/blender/imbuf/intern/cineon/logImageLib.c b/source/blender/imbuf/intern/cineon/logImageLib.c
index ccc6045e6e5..e69de29bb2d 100644
--- a/source/blender/imbuf/intern/cineon/logImageLib.c
+++ b/source/blender/imbuf/intern/cineon/logImageLib.c
@@ -1,183 +0,0 @@
-/*
- * Cineon and DPX image file format library routines.
- *
- * Copyright 1999 - 2002 David Hodson <hodsond@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/** \file blender/imbuf/intern/cineon/logImageLib.c
- * \ingroup imbcineon
- */
-
-#include "cineonlib.h"
-#include "dpxlib.h"
-
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <time.h> /* strftime() */
-#include <sys/types.h>
-#ifdef WIN32
-#include <winsock.h>
-#else
-#include <netinet/in.h> /* htonl() */
-#endif
-#include <string.h> /* memset */
-#include "BLI_fileops.h"
-
-#define MIN_GAMMA 0.01
-#define MAX_GAMMA 99.9
-#define DEFAULT_GAMMA 1.0
-#define DEFAULT_BLACK_POINT 95
-#define DEFAULT_WHITE_POINT 685
-
-void
-logImageSetVerbose(int verbosity)
-{
- cineonSetVerbose(verbosity);
- dpxSetVerbose(verbosity);
-}
-
-LogImageFile*
-logImageOpen(const char* filename, int cineon)
-{
- if (cineon) {
- return cineonOpen(filename);
- }
- else {
- return dpxOpen(filename);
- }
- return 0;
-}
-
-LogImageFile*
-logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon)
-{
- if (cineon) {
- return cineonOpenFromMem(buffer, size);
- }
- else {
- return dpxOpenFromMem(buffer, size);
- }
- return 0;
-}
-
-LogImageFile*
-logImageCreate(const char* filename, int cineon, int width, int height, int depth)
-{
- if (cineon) {
- return cineonCreate(filename, width, height, depth);
- }
- else {
- return dpxCreate(filename, width, height, depth);
- }
- return 0;
-}
-
-int
-logImageGetSize(const LogImageFile* logImage, int* width, int* height, int* depth)
-{
- *width = logImage->width;
- *height = logImage->height;
- *depth = logImage->depth;
- return 0;
-}
-
-int
-logImageGetByteConversionDefaults(LogImageByteConversionParameters* params)
-{
- params->gamma = DEFAULT_GAMMA;
- params->blackPoint = DEFAULT_BLACK_POINT;
- params->whitePoint = DEFAULT_WHITE_POINT;
- params->doLogarithm = 0;
- return 0;
-}
-
-int
-logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params)
-{
- params->gamma = logImage->params.gamma;
- params->blackPoint = logImage->params.blackPoint;
- params->whitePoint = logImage->params.whitePoint;
- params->doLogarithm = 0;
- return 0;
-}
-
-int
-logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params)
-{
- if ((params->gamma >= MIN_GAMMA) &&
- (params->gamma <= MAX_GAMMA) &&
- (params->blackPoint >= 0) &&
- (params->blackPoint < params->whitePoint) &&
- (params->whitePoint <= 1023))
- {
- logImage->params.gamma = params->gamma;
- logImage->params.blackPoint = params->blackPoint;
- logImage->params.whitePoint = params->whitePoint;
- logImage->params.doLogarithm = params->doLogarithm;
- setupLut16(logImage);
- return 0;
- }
- return 1;
-}
-
-int
-logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y)
-{
- return logImage->getRow(logImage, row, y);
-}
-
-int
-logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y)
-{
- return logImage->setRow(logImage, row, y);
-}
-
-void
-logImageClose(LogImageFile* logImage)
-{
- logImage->close(logImage);
-}
-
-void
-logImageDump(const char* filename)
-{
-
- U32 magic;
-
- FILE* foo = BLI_fopen(filename, "rb");
- if (foo == 0) {
- return;
- }
-
- if (fread(&magic, sizeof(magic), 1, foo) == 0) {
- fclose(foo);
- return;
- }
-
- fclose(foo);
-
- if (magic == ntohl(CINEON_FILE_MAGIC)) {
-#if 0
- cineonDump(filename);
-#endif
- }
- else if (magic == ntohl(DPX_FILE_MAGIC)) {
- dpxDump(filename);
- }
-}
diff --git a/source/blender/imbuf/intern/cineon/logImageLib.h b/source/blender/imbuf/intern/cineon/logImageLib.h
index 1c24358e4ef..e69de29bb2d 100644
--- a/source/blender/imbuf/intern/cineon/logImageLib.h
+++ b/source/blender/imbuf/intern/cineon/logImageLib.h
@@ -1,87 +0,0 @@
-/*
- * Common library definitions for Cineon and DPX image files.
- *
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef __LOGIMAGELIB_H__
-#define __LOGIMAGELIB_H__
-
-/** \file blender/imbuf/intern/cineon/logImageLib.h
- * \ingroup imbcineon
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Image structure. You don't care what this is.
- */
-
-typedef struct _Log_Image_File_t_ LogImageFile;
-
-/*
- * Magic numbers for normal and byte-swapped Cineon and Dpx files
- */
-
-#define CINEON_FILE_MAGIC 0x802A5FD7
-#define DPX_FILE_MAGIC 0x53445058
-
-/*
- * Image 8 bit <-> 10 bit conversion parameters.
- */
-
-typedef struct {
- float gamma;
- int blackPoint;
- int whitePoint;
- int doLogarithm;
-} LogImageByteConversionParameters;
-
-/* int functions return 0 for OK */
-
-void logImageSetVerbose(int);
-
-LogImageFile* logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon);
-LogImageFile* logImageOpen(const char* filename, int cineon);
-int logImageGetSize(const LogImageFile* logImage, int* xsize, int* ysize, int* channels);
-LogImageFile* logImageCreate(const char* filename, int cineon, int xsize, int ysize, int channels);
-
-/* byte conversion routines for mapping logImage (usually) 10 bit values to 8 bit */
-/* see Kodak docs for details... */
-
-int logImageGetByteConversionDefaults(LogImageByteConversionParameters* params);
-int logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params);
-int logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params);
-
-/* get/set scanline of converted bytes */
-int logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y);
-int logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y);
-
-/* closes file and deletes data */
-void logImageClose(LogImageFile* logImage);
-
-/* read file and dump header info */
-void logImageDump(const char* filename);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LOGIMAGELIB_H__ */
diff --git a/source/blender/imbuf/intern/cineon/logmemfile.c b/source/blender/imbuf/intern/cineon/logmemfile.c
index a9938582f2a..54bc62276cf 100644
--- a/source/blender/imbuf/intern/cineon/logmemfile.c
+++ b/source/blender/imbuf/intern/cineon/logmemfile.c
@@ -1,21 +1,23 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 2006 Joseph Eagar (joeedh@gmail.com)
+ * Copyright 2006 Joseph Eagar (joeedh@gmail.com)
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,64 +25,100 @@
* \ingroup imbcineon
*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "logImageCore.h"
+#include "logmemfile.h"
-#include "logmemfile.h" /* own include */
-
-int logimage_fseek(void* logfile, intptr_t offsett, int origin)
-{
- struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile;
- intptr_t offset = offsett;
-
- if (file->file) fseek(file->file, offset, origin);
- else { /*we're seeking in memory*/
- if (origin==SEEK_SET) {
- if (offset > file->membuffersize) return 1;
- file->memcursor = file->membuffer + offset;
- }
- else if (origin==SEEK_END) {
- if (offset > file->membuffersize) return 1;
- file->memcursor = (file->membuffer + file->membuffersize) - offset;
- }
- else if (origin==SEEK_CUR) {
- uintptr_t pos = (uintptr_t)file->membuffer - (uintptr_t)file->memcursor;
- if (pos + offset > file->membuffersize) return 1;
- if (pos < 0) return 1;
- file->memcursor += offset;
+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 || pos < 0)
+ return 1;
+
+ logFile->memCursor += offset;
}
}
return 0;
}
-int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile)
+int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile* logFile)
{
- struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile;
- if (file->file) return fwrite(buffer, size, count, file->file);
+ if (logFile->file)
+ return fwrite(buffer, size, count, logFile->file);
else { /*we're writing to memory*/
/*do nothing as this isn't supported yet*/
return count;
}
}
-int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile)
+int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile)
{
- struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile;
- if (file->file) return fread(buffer, size, count, file->file);
- else { /*we're reading from memory*/
- int i;
- /* we convert ot uchar just on the off chance some platform can't handle
- * pointer arithmetic with type (void*). */
- unsigned char *buf = (unsigned char *) buffer;
-
- for (i=0; i<count; i++) {
- memcpy(buf, file->memcursor, size);
- file->memcursor += size;
- buf += size;
+ if (logFile->file) {
+ return fread(buffer, size, count, logFile->file);
+ }
+ else { /* we're reading from memory */
+ unsigned char *buf = (unsigned char*)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(unsigned char *x, LogImageFile *logFile)
+{
+ uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer;
+ if (pos + sizeof(unsigned char) > logFile->memBufferSize)
+ return 1;
+
+ *x = *(unsigned char*)logFile->memCursor;
+ logFile->memCursor += sizeof(unsigned char);
+ return 0;
+}
+
+int logimage_read_ushort(unsigned short *x, LogImageFile *logFile)
+{
+ uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer;
+ if (pos + sizeof(unsigned short) > logFile->memBufferSize)
+ return 1;
+
+ *x = *(unsigned short*)logFile->memCursor;
+ logFile->memCursor += sizeof(unsigned short);
+ return 0;
+}
+
+int logimage_read_uint(unsigned int *x, LogImageFile *logFile)
+{
+ uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer;
+ if (pos + sizeof(unsigned int) > logFile->memBufferSize)
+ return 1;
+
+ *x = *(unsigned int*)logFile->memCursor;
+ logFile->memCursor += sizeof(unsigned int);
+ return 0;
+}
diff --git a/source/blender/imbuf/intern/cineon/logmemfile.h b/source/blender/imbuf/intern/cineon/logmemfile.h
index df3589a70d3..55ad0a9467a 100644
--- a/source/blender/imbuf/intern/cineon/logmemfile.h
+++ b/source/blender/imbuf/intern/cineon/logmemfile.h
@@ -1,33 +1,43 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 2006 Joseph Eagar (joeedh@gmail.com)
+ * Copyright 2006 Joseph Eagar (joeedh@gmail.com)
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
-
-#ifndef __LOGMEMFILE_H__
-#define __LOGMEMFILE_H__
/** \file blender/imbuf/intern/cineon/logmemfile.h
* \ingroup imbcineon
*/
-int logimage_fseek(void* logfile, intptr_t offsett, int origin);
-int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile);
-int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile);
-#endif /* __LOGMEMFILE_H__ */
+#ifndef __LOGMEMFILE_H__
+#define __LOGMEMFILE_H__
+
+#include "logImageCore.h"
+
+#include <stdlib.h>
+
+int logimage_fseek(LogImageFile* logFile, intptr_t offset, int origin);
+int logimage_fwrite(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);
+
+#endif /* __LOGMEMFILE_H__ */
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index ed4db50035d..5c2dc0c7df9 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -74,8 +74,8 @@ ImFileType IMB_FILE_TYPES[] = {
{NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
{NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
#ifdef WITH_CINEON
- {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
- {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_TIFF
{imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE},