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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/imbuf/intern/cineon/logImageCore.c')
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c1576
1 files changed, 1381 insertions, 195 deletions
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index f772cc7d477..3911e5c2ef3 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -1,21 +1,23 @@
/*
- * Cineon image file format library routines.
+ * Cineon image file format library routines.
*
- * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
+ * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Julien Enche.
*
*/
@@ -23,223 +25,1407 @@
* \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 "BLI_utildefines.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));
+}
-#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);
+int logImageIsCineon(const void *buffer)
+{
+ unsigned int magicNum = *(unsigned int *)buffer;
+ return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1));
}
-static double
-convertFrom(double inp, int white, float gamma) {
- return white + log10(inp) / (gamma * 0.002 / 0.6);
+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;
}
-/* set up the 10 bit to 8 bit and 8 bit to 10 bit tables */
-void
-setupLut(LogImageFile *logImage) {
+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);
- int i;
- double f_black;
- double scale;
+ 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);
- f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma);
- scale = 255.0 / (1.0 - f_black);
+ return 0;
+}
- for (i = 0; i <= logImage->params.blackPoint; ++i) {
- logImage->lut10[i] = 0;
+void logImageClose(LogImageFile *logImage)
+{
+ if (logImage != 0) {
+ if (logImage->file) {
+ fclose(logImage->file);
+ logImage->file = 0;
+ }
+ MEM_freeN(logImage);
}
- 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));
+}
+
+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;
}
- for (; i < 1024; ++i) {
- logImage->lut10[i] = 255;
+}
+
+
+/*
+ * 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;
}
- 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) {
+ 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;
- int i;
- double f_black;
- double scale;
+ case 12:
+ returnValue = logImageSetData12(logImage, logImage->element[0], elementData);
+ break;
- 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 */
+ case 16:
+ returnValue = logImageSetData16(logImage, logImage->element[0], elementData);
+ break;
-typedef union {
- U32 i;
- R32 f;
-} Hack;
+ default:
+ returnValue = 1;
+ break;
+ }
-R32
-htonf(R32 f) {
- Hack hack;
- hack.f = f;
- hack.i = htonl(hack.i);
- return hack.f;
+ MEM_freeN(elementData);
+ return returnValue;
}
-R32
-ntohf(R32 f) {
- Hack hack;
- hack.f = f;
- hack.i = ntohl(hack.i);
- return hack.f;
+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;
}
-#define UNDEF_FLOAT 0x7F800000
+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;
-R32
-undefined(void) {
- Hack hack;
- hack.i = UNDEF_FLOAT;
- return hack.f;
+ 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;
}
-/* reverse an endian-swapped U16 */
-U16
-reverseU16(U16 value) {
+static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned short *row;
+ int x, y;
- 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;
+ 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;
}
-/* reverse an endian-swapped U32 */
-U32
-reverseU32(U32 value) {
+static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int rowLength = getRowLength(logImage->width, logElement);
+ unsigned short *row;
+ int x, y;
- 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;
+ 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;
}
-/* reverse an endian-swapped R32 */
-R32
-reverseR32(R32 value) {
- 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;
+/*
+ * 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;
}
-#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 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;
+ }
}
-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 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 (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 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;
+}
+
+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;
+
+ 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;
+}
+
+static int logImageElementGetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
+{
+ unsigned int numSamples = logImage->width * logImage->height * logElement.depth;
+ unsigned int sampleIndex;
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+}
+
+static void getLogToLinLut(float *lut, LogImageFile *logImage, LogImageElement logElement)
+{
+ float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip;
+ /* float filmGamma; unused */
+ unsigned int i;
+
+ /* Building the Log -> Lin LUT */
+ step = logElement.refHighQuantity / logElement.maxValue;
+ negativeFilmGamma = 0.6;
+
+ /* these are default values */
+ /* filmGamma = 2.2f; unused */
+ softClip = 0;
+
+ breakPoint = logImage->referenceWhite - softClip;
+ gain = logElement.maxValue / (1.0f - 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);
+
+ 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;
+ }
+}
+
+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;
+ }
+}
+
+static void getSrgbToLinLut(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.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);
+ }
+}
+
+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);
+
+ 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;
+ }
+}
+
+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;
+
+ default:
+ return 1;
+ }
+}
+
+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);
+
+ 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;
+ }
+}
+
+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;
+}
+
+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;
+}