Patch #27397: Improved DPX/Cineon code
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 22 Oct 2012 12:49:00 +0000 (12:49 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 22 Oct 2012 12:49:00 +0000 (12:49 +0000)
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.

23 files changed:
source/blender/blenkernel/intern/image.c
source/blender/editors/space_image/image_buttons.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/IMB_filetype.h
source/blender/imbuf/intern/cineon/CMakeLists.txt
source/blender/imbuf/intern/cineon/cin_debug_stuff.h
source/blender/imbuf/intern/cineon/cineon_dpx.c
source/blender/imbuf/intern/cineon/cineonfile.h
source/blender/imbuf/intern/cineon/cineonlib.c
source/blender/imbuf/intern/cineon/cineonlib.h
source/blender/imbuf/intern/cineon/dpxfile.h
source/blender/imbuf/intern/cineon/dpxlib.c
source/blender/imbuf/intern/cineon/dpxlib.h
source/blender/imbuf/intern/cineon/logImageCore.c
source/blender/imbuf/intern/cineon/logImageCore.h
source/blender/imbuf/intern/cineon/logImageLib.c
source/blender/imbuf/intern/cineon/logImageLib.h
source/blender/imbuf/intern/cineon/logmemfile.c
source/blender/imbuf/intern/cineon/logmemfile.h
source/blender/imbuf/intern/filetype.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c

index 9a1ea15da97113dadf014e764b5df0432efbe4d5..d291380b9419c7c46bb807c660722fe9585a4e8f 100644 (file)
@@ -1063,6 +1063,7 @@ char BKE_imtype_valid_channels(const char imtype)
                case R_IMF_IMTYPE_DDS:
                case R_IMF_IMTYPE_JP2:
                case R_IMF_IMTYPE_QUICKTIME:
+               case R_IMF_IMTYPE_DPX:
                        chan_flag |= IMA_CHAN_FLAG_ALPHA;
        }
 
@@ -1091,10 +1092,11 @@ char BKE_imtype_valid_depths(const char imtype)
                        return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
                case R_IMF_IMTYPE_MULTILAYER:
                        return R_IMF_CHAN_DEPTH_32;
-               /* eeh, cineone does some strange 10bits per channel */
+               /* eeh, cineon does some strange 10bits per channel */
                case R_IMF_IMTYPE_DPX:
+                       return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_10 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
                case R_IMF_IMTYPE_CINEON:
-                       return R_IMF_CHAN_DEPTH_12;
+                       return R_IMF_CHAN_DEPTH_10;
                case R_IMF_IMTYPE_JP2:
                        return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
                /* most formats are 8bit only */
@@ -1825,9 +1827,29 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
 #ifdef WITH_CINEON
        else if (imtype == R_IMF_IMTYPE_CINEON) {
                ibuf->ftype = CINEON;
+               if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) {
+                       ibuf->ftype |= CINEON_LOG;
+               }
+               if (imf->depth == R_IMF_CHAN_DEPTH_16) {
+                       ibuf->ftype |= CINEON_16BIT;
+               } else if (imf->depth == R_IMF_CHAN_DEPTH_12) {
+                       ibuf->ftype |= CINEON_12BIT;
+               } else if (imf->depth == R_IMF_CHAN_DEPTH_10) {
+                       ibuf->ftype |= CINEON_10BIT;
+               }
        }
        else if (imtype == R_IMF_IMTYPE_DPX) {
                ibuf->ftype = DPX;
+               if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) {
+                 ibuf->ftype |= CINEON_LOG;
+               }
+               if (imf->depth == R_IMF_CHAN_DEPTH_16) {
+                       ibuf->ftype |= CINEON_16BIT;
+               } else if (imf->depth == R_IMF_CHAN_DEPTH_12) {
+                       ibuf->ftype |= CINEON_12BIT;
+               } else if (imf->depth == R_IMF_CHAN_DEPTH_10) {
+                       ibuf->ftype |= CINEON_10BIT;
+               }
        }
 #endif
        else if (imtype == R_IMF_IMTYPE_TARGA) {
index e406b65b53cbf6849218883045205c660144ad5a..7179ce1aedf743113f4efbe6d09521b85cc4ec7d 100644 (file)
@@ -759,9 +759,10 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
        uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
 
        /* only display depth setting if multiple depths can be used */
-       if ((ELEM6(depth_ok,
+       if ((ELEM7(depth_ok,
                   R_IMF_CHAN_DEPTH_1,
                   R_IMF_CHAN_DEPTH_8,
+                  R_IMF_CHAN_DEPTH_10,
                   R_IMF_CHAN_DEPTH_12,
                   R_IMF_CHAN_DEPTH_16,
                   R_IMF_CHAN_DEPTH_24,
@@ -801,9 +802,13 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
                uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
        }
 
+       if (imf->imtype == R_IMF_IMTYPE_DPX) {
+               uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
+       }
+
        if (imf->imtype == R_IMF_IMTYPE_CINEON) {
 #if 1
-               uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma: 1.0"), ICON_NONE);
+               uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
 #else
                uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
                uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
index 344ae604ed4f44057efb5df3ac6236cf32fe8494..511b3c64cb58abb27e481bba15b109d462508ce0 100644 (file)
@@ -81,13 +81,9 @@ set(SRC
        intern/IMB_indexer.h
        intern/IMB_metadata.h
        intern/imbuf.h
-       intern/cineon/cin_debug_stuff.h
-       intern/cineon/cineonfile.h
        intern/cineon/cineonlib.h
-       intern/cineon/dpxfile.h
        intern/cineon/dpxlib.h
        intern/cineon/logImageCore.h
-       intern/cineon/logImageLib.h
        intern/cineon/logmemfile.h
        intern/dds/BlockDXT.h
        intern/dds/Color.h
index 061f045e502985e2df8f7fe7dd6520a18a4bb693..28e62d496b2870a663c878a25d530eb18a9961d2 100644 (file)
@@ -200,6 +200,10 @@ typedef struct ImBuf {
 #ifdef WITH_CINEON
 #define CINEON                 (1 << 21)
 #define DPX                            (1 << 20)
+#define CINEON_LOG             (1 << 8)
+#define CINEON_16BIT   (1 << 7)
+#define CINEON_12BIT   (1 << 6)
+#define CINEON_10BIT   (1 << 5)
 #endif
 
 #ifdef WITH_DDS
index 56a031214098815a67575d7e6c49adcf1c00bd16..68ad4808c8026f3d7c36478223a8caa088ab3eee 100644 (file)
@@ -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 */
index fdf4f5409a5267e0df2522a1610c7870a0f62636..8e76f5e729bd31758e9da9924a5217a9cb7ae82f 100644 (file)
@@ -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}")
index a97499fb1aebd5b3944775c8f06de75242a38bbc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,4 +0,0 @@
-/** \file blender/imbuf/intern/cineon/cin_debug_stuff.h
- *  \ingroup imbcineon
- */
-#define d_printf printf
index 7705af13b1ea6335af1b217bdfd95687325be474..21f68e7913525b441662530ecaf75ae22217878d 100644 (file)
@@ -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
  *
  * 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"
 
 #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;
 }
index e681153aa6efe38da2df18f123d615d266ac47a7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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__ */
index 894e3a93b4beda1d00731a99a65109bfa2b4b506..92a984378dbf53213fa78ad8a455fb7121ce70a4 100644 (file)
@@ -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.
  *
  */
 
  *  \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);
-}
index ef992c527b0605c03a945fe8c90843c378aed12d..78403afe95514832ff7ae43f32793f9dfcdae412 100644 (file)
 /*
- *      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
index e1d95268a80ac005e2db8b7b902b70bb0827ee2c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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__ */
index 0a067af2cb99ce02f40a94231c4e75c03caf13b7..dc5f42ecaad8f741cc72f14d7b09c45d788f5ccc 100644 (file)
@@ -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.
  *
  */
 
  *  \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;
 }
index eb3937f2bf7f055e6c19c0ade8eaca68d57d333d..bd608b130577c2c8da1f7af7c151e148b22c8bab 100644 (file)
 /*
- *      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
index f772cc7d477c5e1cd0c7322653c1558d258280d4..917554cb4fe07027b16ef4c00100dc4306489f46 100644 (file)
@@ -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.
  *
  */
 
  *  \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);
+}
index 7d88c10c2d6a4c36c34a99c6c05de9d610555f39..c1f4d2eae04fb339f277fdda4cb88c0d4c266f84 100644 (file)
 /*
- *      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
index ccc6045e6e578e5a6c753718807a9a7b81e34aab..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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);
-       }
-}
index 1c24358e4ef7f68f917fa7ef1885f618e5b7d80e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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__ */
index a9938582f2a34f6f65ea5ec2da6a95f85a83fd6b..54bc62276cf55157c75f1c1be463d840b0741a8d 100644 (file)
@@ -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.
  *
  */
 
  *  \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;
+}
index df3589a70d35fd52b4d336ee5440c114539d0ec2..55ad0a9467a7f4a9876e9c04b0b79902d83e3ac0 100644 (file)
@@ -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__ */
index ed4db50035d16f407a327b1215729fa97074e89a..5c2dc0c7df911e22c5b8af851293ab357b0769e0 100644 (file)
@@ -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},
index 8c0c42bb88063d18fbdee11d6d68c357773cdce6..c59b3393236960f95e769083e7560732129737d6 100644 (file)
@@ -318,10 +318,11 @@ typedef struct ImageFormatData {
 /* return values from BKE_imtype_valid_depths, note this is depts per channel */
 #define R_IMF_CHAN_DEPTH_1  (1<<0) /* 1bits  (unused) */
 #define R_IMF_CHAN_DEPTH_8  (1<<1) /* 8bits  (default) */
-#define R_IMF_CHAN_DEPTH_12 (1<<2) /* 12bits (uncommon, jp2 supports) */
-#define R_IMF_CHAN_DEPTH_16 (1<<3) /* 16bits (tiff, halff float exr) */
-#define R_IMF_CHAN_DEPTH_24 (1<<4) /* 24bits (unused) */
-#define R_IMF_CHAN_DEPTH_32 (1<<5) /* 32bits (full float exr) */
+#define R_IMF_CHAN_DEPTH_10 (1<<2) /* 10bits (uncommon, Cineon/DPX support) */
+#define R_IMF_CHAN_DEPTH_12 (1<<3) /* 12bits (uncommon, jp2/DPX support) */
+#define R_IMF_CHAN_DEPTH_16 (1<<4) /* 16bits (tiff, halff float exr) */
+#define R_IMF_CHAN_DEPTH_24 (1<<5) /* 24bits (unused) */
+#define R_IMF_CHAN_DEPTH_32 (1<<6) /* 32bits (full float exr) */
 
 /* ImageFormatData.planes */
 #define R_IMF_PLANES_RGB   24
@@ -1301,6 +1302,7 @@ typedef struct Scene {
 /* sequencer seq_prev_type seq_rend_type */
 
 
+
 /* **************** SCENE ********************* */
 
 /* for general use */
index 46a4a6302942dfe6fe74fd3c9fe8caefb4a05987..4431eb10a823dbb4fd349230b678bb1ece83f6d1 100644 (file)
@@ -276,6 +276,7 @@ EnumPropertyItem image_color_mode_items[] = {
 EnumPropertyItem image_color_depth_items[] = {
        /* 1 (monochrome) not used */
        {R_IMF_CHAN_DEPTH_8,   "8", 0, "8",  "8 bit color channels"},
+       {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10 bit color channels"},
        {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12 bit color channels"},
        {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16 bit color channels"},
        /* 24 not used */
@@ -714,6 +715,7 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
                                           R_IMF_CHAN_DEPTH_24,
                                           R_IMF_CHAN_DEPTH_16,
                                           R_IMF_CHAN_DEPTH_12,
+                                          R_IMF_CHAN_DEPTH_10,
                                           R_IMF_CHAN_DEPTH_8,
                                           R_IMF_CHAN_DEPTH_1,
                                           0};
@@ -811,9 +813,10 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C,
                const int is_float = ELEM3(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
 
                EnumPropertyItem *item_8bit =  &image_color_depth_items[0];
-               EnumPropertyItem *item_12bit = &image_color_depth_items[1];
-               EnumPropertyItem *item_16bit = &image_color_depth_items[2];
-               EnumPropertyItem *item_32bit = &image_color_depth_items[3];
+               EnumPropertyItem *item_10bit = &image_color_depth_items[1];
+               EnumPropertyItem *item_12bit = &image_color_depth_items[2];
+               EnumPropertyItem *item_16bit = &image_color_depth_items[3];
+               EnumPropertyItem *item_32bit = &image_color_depth_items[4];
 
                int totitem = 0;
                EnumPropertyItem *item = NULL;
@@ -823,6 +826,10 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C,
                        RNA_enum_item_add(&item, &totitem, item_8bit);
                }
 
+               if (depth_ok & R_IMF_CHAN_DEPTH_10) {
+                       RNA_enum_item_add(&item, &totitem, item_10bit);
+               }
+
                if (depth_ok & R_IMF_CHAN_DEPTH_12) {
                        RNA_enum_item_add(&item, &totitem, item_12bit);
                }
@@ -2888,7 +2895,6 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
 
 #endif
 
-
 #ifdef WITH_OPENJPEG
        /* Jpeg 2000 */
        prop = RNA_def_property(srna, "use_jpeg2k_ycc", PROP_BOOLEAN, PROP_NONE);
@@ -2910,7 +2916,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
        /* Cineon and DPX */
 
        prop = RNA_def_property(srna, "use_cineon_log", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "cineon_flag", R_CINEON_LOG);
+       RNA_def_property_boolean_sdna(prop, NULL, "cineon_flag", R_IMF_CINEON_FLAG_LOG);
        RNA_def_property_ui_text(prop, "Log", "Convert to logarithmic color space");
        RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);