diff options
Diffstat (limited to 'source/blender/imbuf/intern/cineon/logImageCore.c')
-rw-r--r-- | source/blender/imbuf/intern/cineon/logImageCore.c | 1576 |
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..5c734db323d 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.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); + + 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; +} |