Merging r58280 through r58329 from trunk into soc-2013-depsgaph_mt
[blender.git] / source / blender / imbuf / intern / cineon / logImageCore.c
1 /*
2  * Cineon image file format library routines.
3  *
4  * Copyright 1999,2000,2001 David Hodson <hodsond@acm.org>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; either version 2 of the License, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Julien Enche.
21  *
22  */
23
24 /** \file blender/imbuf/intern/cineon/logImageCore.c
25  *  \ingroup imbcineon
26  */
27
28
29 #include "logmemfile.h"
30 #include "logImageCore.h"
31 #include "dpxlib.h"
32 #include "cineonlib.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37
38 #include "BLI_fileops.h"
39 #include "BLI_utildefines.h"
40
41 #include "MEM_guardedalloc.h"
42
43 /*
44  * Declaration of static functions
45  */
46
47 static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data);
48 static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data);
49 static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data);
50 static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data);
51 static int logImageElementGetData(LogImageFile *dpx, LogImageElement logElement, float *data);
52 static int logImageElementGetData1(LogImageFile *dpx, LogImageElement logElement, float *data);
53 static int logImageElementGetData8(LogImageFile *dpx, LogImageElement logElement, float *data);
54 static int logImageElementGetData10(LogImageFile *dpx, LogImageElement logElement, float *data);
55 static int logImageElementGetData10Packed(LogImageFile *dpx, LogImageElement logElement, float *data);
56 static int logImageElementGetData12(LogImageFile *dpx, LogImageElement logElement, float *data);
57 static int logImageElementGetData12Packed(LogImageFile *dpx, LogImageElement logElement, float *data);
58 static int logImageElementGetData16(LogImageFile *dpx, LogImageElement logElement, float *data);
59 static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int dstIsLinearRGB);
60 static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int srcIsLinearRGB);
61
62
63 /*
64  * For debug purpose
65  */
66
67 static int verbose = 0;
68
69 void logImageSetVerbose(int verbosity)
70 {
71         verbose = verbosity;
72         cineonSetVerbose(verbosity);
73         dpxSetVerbose(verbosity);
74 }
75
76
77 /*
78  * IO stuff
79  */
80
81 int logImageIsDpx(const void *buffer)
82 {
83         unsigned int magicNum = *(unsigned int *)buffer;
84         return (magicNum == DPX_FILE_MAGIC || magicNum == swap_uint(DPX_FILE_MAGIC, 1));
85 }
86
87 int logImageIsCineon(const void *buffer)
88 {
89         unsigned int magicNum = *(unsigned int *)buffer;
90         return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1));
91 }
92
93 LogImageFile *logImageOpenFromFile(const char *filename, int cineon)
94 {
95         unsigned int magicNum;
96         FILE *f = BLI_fopen(filename, "rb");
97
98         (void)cineon;
99
100         if (f == NULL)
101                 return NULL;
102
103         if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) {
104                 fclose(f);
105                 return NULL;
106         }
107
108         fclose(f);
109
110         if (logImageIsDpx(&magicNum))
111                 return dpxOpen((const unsigned char *)filename, 0, 0);
112         else if (logImageIsCineon(&magicNum))
113                 return cineonOpen((const unsigned char *)filename, 0, 0);
114
115         return NULL;
116 }
117
118 LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size)
119 {
120         if (logImageIsDpx(buffer))
121                 return dpxOpen(buffer, 1, size);
122         else if (logImageIsCineon(buffer))
123                 return cineonOpen(buffer, 1, size);
124
125         return NULL;
126 }
127
128 LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample,
129                              int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack,
130                              float gamma, const char *creator)
131 {
132         /* referenceWhite, referenceBlack and gamma values are only supported for DPX file */
133         if (cineon)
134                 return cineonCreate(filename, width, height, bitsPerSample, creator);
135         else
136                 return dpxCreate(filename, width, height, bitsPerSample, isLogarithmic, hasAlpha,
137                                  referenceWhite, referenceBlack, gamma, creator);
138
139         return NULL;
140 }
141
142 void logImageClose(LogImageFile *logImage)
143 {
144         if (logImage != NULL) {
145                 if (logImage->file) {
146                         fclose(logImage->file);
147                         logImage->file = NULL;
148                 }
149                 MEM_freeN(logImage);
150         }
151 }
152
153 void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth)
154 {
155         *width = logImage->width;
156         *height = logImage->height;
157         *depth = logImage->depth;
158 }
159
160
161 /*
162  * Helper
163  */
164
165 unsigned int getRowLength(int width, LogImageElement logElement)
166 {
167         /* return the row length in bytes according to width and packing method */
168         switch (logElement.bitsPerSample) {
169                 case 1:
170                         return ((width * logElement.depth - 1) / 32 + 1) * 4;
171
172                 case 8:
173                         return ((width * logElement.depth - 1) / 4 + 1) * 4;
174
175                 case 10:
176                         if (logElement.packing == 0)
177                                 return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4;
178                         else if (logElement.packing == 1 || logElement.packing == 2)
179                                 return ((width * logElement.depth - 1) / 3 + 1) * 4;
180
181                 case 12:
182                         if (logElement.packing == 0)
183                                 return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4;
184                         else if (logElement.packing == 1 || logElement.packing == 2)
185                                 return width * logElement.depth * 2;
186
187                 case 16:
188                         return width * logElement.depth * 2;
189
190                 default:
191                         return 0;
192         }
193 }
194
195
196 /*
197  * Data writing
198  */
199
200 int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB)
201 {
202         float *elementData;
203         int returnValue;
204
205         elementData = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->depth * sizeof(float), __func__);
206         if (elementData == NULL)
207                 return 1;
208
209         if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) {
210                 MEM_freeN(elementData);
211                 return 1;
212         }
213
214         switch (logImage->element[0].bitsPerSample) {
215                 case 8:
216                         returnValue = logImageSetData8(logImage, logImage->element[0], elementData);
217                         break;
218
219                 case 10:
220                         returnValue = logImageSetData10(logImage, logImage->element[0], elementData);
221                         break;
222
223                 case 12:
224                         returnValue = logImageSetData12(logImage, logImage->element[0], elementData);
225                         break;
226
227                 case 16:
228                         returnValue = logImageSetData16(logImage, logImage->element[0], elementData);
229                         break;
230
231                 default:
232                         returnValue = 1;
233                         break;
234         }
235
236         MEM_freeN(elementData);
237         return returnValue;
238 }
239
240 static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data)
241 {
242         unsigned int rowLength = getRowLength(logImage->width, logElement);
243         unsigned char *row;
244         int x, y;
245
246         row = (unsigned char *)MEM_mallocN(rowLength, __func__);
247         if (row == NULL) {
248                 if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
249                 return 1;
250         }
251         memset(row, 0, rowLength);
252
253         for (y = 0; y < logImage->height; y++) {
254                 for (x = 0; x < logImage->width * logImage->depth; x++)
255                         row[x] = (unsigned char)float_uint(data[y * logImage->width * logImage->depth + x], 255);
256
257                 if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
258                         if (verbose) printf("DPX/Cineon: Error while writing file.\n");
259                         MEM_freeN(row);
260                         return 1;
261                 }
262         }
263         MEM_freeN(row);
264         return 0;
265 }
266
267 static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data)
268 {
269         unsigned int rowLength = getRowLength(logImage->width, logElement);
270         unsigned int pixel, index;
271         unsigned int *row;
272         int x, y, offset;
273
274         row = (unsigned int *)MEM_mallocN(rowLength, __func__);
275         if (row == NULL) {
276                 if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
277                 return 1;
278         }
279
280         for (y = 0; y < logImage->height; y++) {
281                 offset = 22;
282                 index = 0;
283                 pixel = 0;
284
285                 for (x = 0; x < logImage->width * logImage->depth; x++) {
286                         pixel |= (unsigned int)float_uint(data[y * logImage->width * logImage->depth + x], 1023) << offset;
287                         offset -= 10;
288                         if (offset < 0) {
289                                 row[index] = swap_uint(pixel, logImage->isMSB);
290                                 index++;
291                                 pixel = 0;
292                                 offset = 22;
293                         }
294                 }
295                 if (pixel != 0)
296                         row[index] = swap_uint(pixel, logImage->isMSB);
297
298                 if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
299                         if (verbose) printf("DPX/Cineon: Error while writing file.\n"); {
300                                 MEM_freeN(row);
301                                 return 1;
302                         }
303                 }
304         }
305         MEM_freeN(row);
306         return 0;
307 }
308
309 static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data)
310 {
311         unsigned int rowLength = getRowLength(logImage->width, logElement);
312         unsigned short *row;
313         int x, y;
314
315         row = (unsigned short *)MEM_mallocN(rowLength, __func__);
316         if (row == NULL) {
317                 if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
318                 return 1;
319         }
320
321         for (y = 0; y < logImage->height; y++) {
322                 for (x = 0; x < logImage->width * logImage->depth; x++)
323                         row[x] = swap_ushort(((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 4095)) << 4, logImage->isMSB);
324
325                 if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
326                         if (verbose) printf("DPX/Cineon: Error while writing file.\n");
327                         MEM_freeN(row);
328                         return 1;
329                 }
330         }
331         MEM_freeN(row);
332         return 0;
333 }
334
335 static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
336 {
337         unsigned int rowLength = getRowLength(logImage->width, logElement);
338         unsigned short *row;
339         int x, y;
340
341         row = (unsigned short *)MEM_mallocN(rowLength, __func__);
342         if (row == NULL) {
343                 if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
344                 return 1;
345         }
346
347         for (y = 0; y < logImage->height; y++) {
348                 for (x = 0; x < logImage->width * logImage->depth; x++)
349                         row[x] = swap_ushort((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 65535), logImage->isMSB);
350
351                 if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
352                         if (verbose) printf("DPX/Cineon: Error while writing file.\n");
353                         MEM_freeN(row);
354                         return 1;
355                 }
356         }
357         MEM_freeN(row);
358         return 0;
359 }
360
361
362 /*
363  * Data reading
364  */
365
366 int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB)
367 {
368         /* Fills data with 32 bits float RGBA values */
369         int i, j, returnValue, sortedElementData[8], hasAlpha;
370         float *elementData[8];
371         float *elementData_ptr[8];
372         float *mergedData;
373         unsigned int sampleIndex;
374         LogImageElement mergedElement;
375
376         /* Determine the depth of the picture and if there's a separate alpha element.
377          * If the element is supported, load it into an unsigned ints array. */
378         memset(&elementData, 0, 8 * sizeof(float *));
379         hasAlpha = 0;
380
381         for (i = 0; i < logImage->numElements; i++) {
382                 /* descriptor_Depth and descriptor_Composite are not supported */
383                 if (logImage->element[i].descriptor != descriptor_Depth && logImage->element[i].descriptor != descriptor_Composite) {
384                         /* Allocate memory */
385                         elementData[i] = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->element[i].depth * sizeof(float), __func__);
386                         if (elementData[i] == NULL) {
387                                 if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i);
388                                 for (j = 0; j < i; j++)
389                                         if (elementData[j] != NULL)
390                                                 MEM_freeN(elementData[j]);
391                                 return 1;
392                         }
393                         elementData_ptr[i] = elementData[i];
394
395                         /* Load data */
396                         if (logImageElementGetData(logImage, logImage->element[i], elementData[i]) != 0) {
397                                 if (verbose) printf("DPX/Cineon: Cannot read elementData[%d]\n.", i);
398                                 for (j = 0; j < i; j++)
399                                         if (elementData[j] != NULL)
400                                                 MEM_freeN(elementData[j]);
401                                 return 1;
402                         }
403                 }
404
405                 if (logImage->element[i].descriptor == descriptor_Alpha)
406                         hasAlpha = 1;
407         }
408
409         /* only one element, easy case, no need to do anything  */
410         if (logImage->numElements == 1) {
411                 returnValue = convertLogElementToRGBA(elementData[0], data, logImage, logImage->element[0], dataIsLinearRGB);
412                 MEM_freeN(elementData[0]);
413         }
414         else {
415                 /* The goal here is to merge every elements into only one
416                  * to recreate a classic 16 bits RGB, RGBA or YCbCr element.
417                  * Unsupported elements are skipped (depth, composite) */
418
419                 memcpy(&mergedElement, &logImage->element[0], sizeof(LogImageElement));
420                 mergedElement.descriptor = -1;
421                 mergedElement.depth = logImage->depth;
422                 memset(&sortedElementData, -1, 8 * sizeof(int));
423
424                 /* Try to know how to assemble the elements */
425                 for (i = 0; i < logImage->numElements; i++) {
426                         switch (logImage->element[i].descriptor) {
427                                 case descriptor_Red:
428                                 case descriptor_RGB:
429                                         if (hasAlpha == 0)
430                                                 mergedElement.descriptor = descriptor_RGB;
431                                         else
432                                                 mergedElement.descriptor = descriptor_RGBA;
433
434                                         sortedElementData[0] = i;
435                                         break;
436
437                                 case descriptor_Green:
438                                         if (hasAlpha == 0)
439                                                 mergedElement.descriptor = descriptor_RGB;
440                                         else
441                                                 mergedElement.descriptor = descriptor_RGBA;
442
443                                         sortedElementData[1] = i;
444                                         break;
445
446                                 case descriptor_Blue:
447                                         if (hasAlpha == 0)
448                                                 mergedElement.descriptor = descriptor_RGB;
449                                         else
450                                                 mergedElement.descriptor = descriptor_RGBA;
451
452                                         sortedElementData[2] = i;
453                                         break;
454
455                                 case descriptor_Alpha:
456                                         /* Alpha component is always the last one */
457                                         sortedElementData[mergedElement.depth - 1] = i;
458                                         break;
459
460                                 case descriptor_Luminance:
461                                         if (mergedElement.descriptor == -1)
462                                                 if (hasAlpha == 0)
463                                                         mergedElement.descriptor = descriptor_Luminance;
464                                                 else
465                                                         mergedElement.descriptor = descriptor_YA;
466                                         else if (mergedElement.descriptor == descriptor_Chrominance) {
467                                                 if (mergedElement.depth == 2)
468                                                         mergedElement.descriptor = descriptor_CbYCrY;
469                                                 else if (mergedElement.depth == 3)
470                                                         if (hasAlpha == 0)
471                                                                 mergedElement.descriptor = descriptor_CbYCr;
472                                                         else
473                                                                 mergedElement.descriptor = descriptor_CbYACrYA;
474                                                 else if (mergedElement.depth == 4)
475                                                         mergedElement.descriptor = descriptor_CbYCrA;
476                                         }
477
478                                         /* Y component always in 1 except if it's alone or with alpha */
479                                         if (mergedElement.depth == 1 || (mergedElement.depth == 2 && hasAlpha == 1))
480                                                 sortedElementData[0] = i;
481                                         else
482                                                 sortedElementData[1] = i;
483                                         break;
484
485                                 case descriptor_Chrominance:
486                                         if (mergedElement.descriptor == -1)
487                                                 mergedElement.descriptor = descriptor_Chrominance;
488                                         else if (mergedElement.descriptor == descriptor_Luminance) {
489                                                 if (mergedElement.depth == 2)
490                                                         mergedElement.descriptor = descriptor_CbYCrY;
491                                                 else if (mergedElement.depth == 3)
492                                                         if (hasAlpha == 0)
493                                                                 mergedElement.descriptor = descriptor_CbYCr;
494                                                         else
495                                                                 mergedElement.descriptor = descriptor_CbYACrYA;
496                                                 else if (mergedElement.depth == 4)
497                                                         mergedElement.descriptor = descriptor_CbYCrA;
498                                         }
499
500                                         /* Cb and Cr always in 0 or 2 */
501                                         if (sortedElementData[0] == -1)
502                                                 sortedElementData[0] = i;
503                                         else
504                                                 sortedElementData[2] = i;
505                                         break;
506
507                                 case descriptor_CbYCr:
508                                         if (hasAlpha == 0)
509                                                 mergedElement.descriptor = descriptor_CbYCr;
510                                         else
511                                                 mergedElement.descriptor = descriptor_CbYCrA;
512
513                                         sortedElementData[0] = i;
514                                         break;
515
516                                 case descriptor_RGBA:
517                                 case descriptor_ABGR:
518                                 case descriptor_CbYACrYA:
519                                 case descriptor_CbYCrY:
520                                 case descriptor_CbYCrA:
521                                         /* I don't think these ones can be seen in a planar image */
522                                         mergedElement.descriptor = logImage->element[i].descriptor;
523                                         sortedElementData[0] = i;
524                                         break;
525
526                                 case descriptor_Depth:
527                                 case descriptor_Composite:
528                                         /* Not supported */
529                                         break;
530                         }
531                 }
532
533                 mergedData = (float *)MEM_mallocN(logImage->width * logImage->height * mergedElement.depth * sizeof(float), __func__);
534                 if (mergedData == NULL) {
535                         if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n");
536                         for (i = 0; i < logImage->numElements; i++)
537                                 if (elementData[i] != NULL)
538                                         MEM_freeN(elementData[i]);
539                         return 1;
540                 }
541
542                 sampleIndex = 0;
543                 while (sampleIndex < logImage->width * logImage->height * mergedElement.depth) {
544                         for (i = 0; i < logImage->numElements; i++)
545                                 for (j = 0; j < logImage->element[sortedElementData[i]].depth; j++)
546                                         mergedData[sampleIndex++] = *(elementData_ptr[sortedElementData[i]]++);
547                 }
548
549                 /* Done with elements data, clean-up */
550                 for (i = 0; i < logImage->numElements; i++)
551                         if (elementData[i] != NULL)
552                                 MEM_freeN(elementData[i]);
553
554                 returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB);
555                 MEM_freeN(mergedData);
556         }
557         return returnValue;
558 }
559
560 static int logImageElementGetData(LogImageFile *logImage, LogImageElement logElement, float *data)
561 {
562         switch (logElement.bitsPerSample) {
563                 case 1:
564                         return logImageElementGetData1(logImage, logElement, data);
565
566                 case 8:
567                         return logImageElementGetData8(logImage, logElement, data);
568
569                 case 10:
570                         if (logElement.packing == 0)
571                                 return logImageElementGetData10Packed(logImage, logElement, data);
572                         else if (logElement.packing == 1 || logElement.packing == 2)
573                                 return logImageElementGetData10(logImage, logElement, data);
574
575                 case 12:
576                         if (logElement.packing == 0)
577                                 return logImageElementGetData12Packed(logImage, logElement, data);
578                         else if (logElement.packing == 1 || logElement.packing == 2)
579                                 return logImageElementGetData12(logImage, logElement, data);
580
581                 case 16:
582                         return logImageElementGetData16(logImage, logElement, data);
583
584                 default:
585                         /* format not supported */
586                         return 1;
587         }
588 }
589
590 static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data)
591 {
592         unsigned int pixel;
593         int x, y, offset;
594
595         /* seek at the right place */
596         if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
597                 if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
598                 return 1;
599         }
600
601         /* read 1 bit data padded to 32 bits */
602         for (y = 0; y < logImage->height; y++) {
603                 for (x = 0; x < logImage->width * logElement.depth; x += 32) {
604                         if (logimage_read_uint(&pixel, logImage) != 0) {
605                                 if (verbose) printf("DPX/Cineon: EOF reached\n");
606                                 return 1;
607                         }
608                         pixel = swap_uint(pixel, logImage->isMSB);
609                         for (offset = 0; offset < 32 && x + offset < logImage->width; offset++)
610                                 data[y * logImage->width * logElement.depth + x + offset] = (float)((pixel >> offset) & 0x01);
611                 }
612         }
613         return 0;
614 }
615
616 static int logImageElementGetData8(LogImageFile *logImage, LogImageElement logElement, float *data)
617 {
618         unsigned int rowLength = getRowLength(logImage->width, logElement);
619         unsigned char pixel;
620         int x, y;
621
622         /* extract required pixels */
623         for (y = 0; y < logImage->height; y++) {
624                 /* 8 bits are 32-bits padded so we need to seek at each row */
625                 if (logimage_fseek(logImage, logElement.dataOffset + y * rowLength, SEEK_SET) != 0) {
626                         if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * rowLength);
627                         return 1;
628                 }
629
630                 for (x = 0; x < logImage->width * logElement.depth; x++) {
631                         if (logimage_read_uchar(&pixel, logImage) != 0) {
632                                 if (verbose) printf("DPX/Cineon: EOF reached\n");
633                                 return 1;
634                         }
635                         data[y * logImage->width * logElement.depth + x] = (float)pixel / 255.0f;
636                 }
637         }
638         return 0;
639 }
640
641 static int logImageElementGetData10(LogImageFile *logImage, LogImageElement logElement, float *data)
642 {
643         unsigned int pixel;
644         int x, y, offset;
645
646         /* seek to data */
647         if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
648                 if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
649                 return 1;
650         }
651
652         if (logImage->depth == 1 && logImage->srcFormat == format_DPX) {
653                 for (y = 0; y < logImage->height; y++) {
654                         offset = 32;
655                         for (x = 0; x < logImage->width * logElement.depth; x++) {
656                                 /* we need to read the next long */
657                                 if (offset >= 30) {
658                                         if (logElement.packing == 1)
659                                                 offset = 2;
660                                         else if (logElement.packing == 2)
661                                                 offset = 0;
662
663                                         if (logimage_read_uint(&pixel, logImage) != 0) {
664                                                 if (verbose) printf("DPX/Cineon: EOF reached\n");
665                                                 return 1;
666                                         }
667                                         pixel = swap_uint(pixel, logImage->isMSB);
668                                 }
669                                 data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f;
670                                 offset += 10;
671                         }
672                 }
673         }
674         else {
675                 for (y = 0; y < logImage->height; y++) {
676                         offset = -1;
677                         for (x = 0; x < logImage->width * logElement.depth; x++) {
678                                 /* we need to read the next long */
679                                 if (offset < 0) {
680                                         if (logElement.packing == 1)
681                                                 offset = 22;
682                                         else if (logElement.packing == 2)
683                                                 offset = 20;
684
685                                         if (logimage_read_uint(&pixel, logImage) != 0) {
686                                                 if (verbose) printf("DPX/Cineon: EOF reached\n");
687                                                 return 1;
688                                         }
689                                         pixel = swap_uint(pixel, logImage->isMSB);
690                                 }
691                                 data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f;
692                                 offset -= 10;
693                         }
694                 }
695         }
696
697         return 0;
698 }
699
700 static int logImageElementGetData10Packed(LogImageFile *logImage, LogImageElement logElement, float *data)
701 {
702         unsigned int rowLength = getRowLength(logImage->width, logElement);
703         unsigned int pixel, oldPixel;
704         int offset, offset2, x, y;
705
706         /* converting bytes to pixels */
707         for (y = 0; y < logImage->height; y++) {
708                 /* seek to data */
709                 if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) {
710                         if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset);
711                         return 1;
712                 }
713
714                 oldPixel = 0;
715                 offset = 0;
716                 offset2 = 0;
717
718                 for (x = 0; x < logImage->width * logElement.depth; x++) {
719                         if (offset2 != 0) {
720                                 offset = 10 - offset2;
721                                 offset2 = 0;
722                                 oldPixel = 0;
723                         }
724                         else if (offset == 32) {
725                                 offset = 0;
726                         }
727                         else if (offset + 10 > 32) {
728                                 /* next pixel is on two different longs */
729                                 oldPixel = (pixel >> offset);
730                                 offset2 = 32 - offset;
731                                 offset = 0;
732                         }
733
734                         if (offset == 0) {
735                                 /* we need to read the next long */
736                                 if (logimage_read_uint(&pixel, logImage) != 0) {
737                                         if (verbose) printf("DPX/Cineon: EOF reached\n");
738                                         return 1;
739                                 }
740                                 pixel = swap_uint(pixel, logImage->isMSB);
741                         }
742                         data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0x3ff) | oldPixel) / 1023.0f;
743                         offset += 10;
744                 }
745         }
746         return 0;
747 }
748
749 static int logImageElementGetData12(LogImageFile *logImage, LogImageElement logElement, float *data)
750 {
751         unsigned int sampleIndex;
752         unsigned int numSamples = logImage->width * logImage->height * logElement.depth;
753         unsigned short pixel;
754
755         /* seek to data */
756         if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
757                 if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
758                 return 1;
759         }
760
761         /* convert bytes to pixels */
762         sampleIndex = 0;
763
764         for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
765                 if (logimage_read_ushort(&pixel, logImage) != 0) {
766                         if (verbose) printf("DPX/Cineon: EOF reached\n");
767                         return 1;
768                 }
769                 pixel = swap_ushort(pixel, logImage->isMSB);
770
771                 if (logElement.packing == 1) /* padded to the right */
772                         data[sampleIndex] = (float)(pixel >> 4) / 4095.0f;
773                 else if (logElement.packing == 2) /* padded to the left */
774                         data[sampleIndex] = (float)pixel / 4095.0f;
775         }
776         return 0;
777 }
778
779 static int logImageElementGetData12Packed(LogImageFile *logImage, LogImageElement logElement, float *data)
780 {
781         unsigned int rowLength = getRowLength(logImage->width, logElement);
782         unsigned int pixel, oldPixel;
783         int offset, offset2, x, y;
784
785         /* converting bytes to pixels */
786         for (y = 0; y < logImage->height; y++) {
787                 /* seek to data */
788                 if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) {
789                         if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset);
790                         return 1;
791                 }
792
793                 oldPixel = 0;
794                 offset = 0;
795                 offset2 = 0;
796
797                 for (x = 0; x < logImage->width * logElement.depth; x++) {
798                         if (offset2 != 0) {
799                                 offset = 12 - offset2;
800                                 offset2 = 0;
801                                 oldPixel = 0;
802                         }
803                         else if (offset == 32) {
804                                 offset = 0;
805                         }
806                         else if (offset + 12 > 32) {
807                                 /* next pixel is on two different longs */
808                                 oldPixel = (pixel >> offset);
809                                 offset2 = 32 - offset;
810                                 offset = 0;
811                         }
812
813                         if (offset == 0) {
814                                 /* we need to read the next long */
815                                 if (logimage_read_uint(&pixel, logImage) != 0) {
816                                         if (verbose) printf("DPX/Cineon: EOF reached\n");
817                                         return 1;
818                                 }
819                                 pixel = swap_uint(pixel, logImage->isMSB);
820                         }
821                         data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0xfff) | oldPixel) / 4095.0f;
822                         offset += 12;
823                 }
824         }
825         return 0;
826 }
827
828 static int logImageElementGetData16(LogImageFile *logImage, LogImageElement logElement, float *data)
829 {
830         unsigned int numSamples = logImage->width * logImage->height * logElement.depth;
831         unsigned int sampleIndex;
832         unsigned short pixel;
833
834         /* seek to data */
835         if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) {
836                 if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset);
837                 return 1;
838         }
839
840         for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
841                 if (logimage_read_ushort(&pixel, logImage) != 0) {
842                         if (verbose) printf("DPX/Cineon: EOF reached\n");
843                         return 1;
844                 }
845                 pixel = swap_ushort(pixel, logImage->isMSB);
846                 data[sampleIndex] = (float)pixel / 65535.0f;
847         }
848
849         return 0;
850 }
851
852
853 /*
854  * Color conversion
855  */
856
857 static int getYUVtoRGBMatrix(float *matrix, LogImageElement logElement)
858 {
859         float scaleY, scaleCbCr;
860         float refHighData = (float)logElement.refHighData / logElement.maxValue;
861         float refLowData = (float)logElement.refLowData / logElement.maxValue;
862
863         scaleY = 1.0f / (refHighData - refLowData);
864         scaleCbCr = scaleY * ((940.0f - 64.0f) / (960.0f - 64.0f));
865
866         switch (logElement.transfer) {
867                 case 2: /* linear */
868                         matrix[0] =  1.0f * scaleY;
869                         matrix[1] =  1.0f * scaleCbCr;
870                         matrix[2] =  1.0f * scaleCbCr;
871                         matrix[3] =  1.0f * scaleY;
872                         matrix[4] =  1.0f * scaleCbCr;
873                         matrix[5] =  1.0f * scaleCbCr;
874                         matrix[6] =  1.0f * scaleY;
875                         matrix[7] =  1.0f * scaleCbCr;
876                         matrix[8] =  1.0f * scaleCbCr;
877                         return 0;
878
879                 case 5: /* SMPTE 240M */
880                         matrix[0] =  1.0000f * scaleY;
881                         matrix[1] =  0.0000f * scaleCbCr;
882                         matrix[2] =  1.5756f * scaleCbCr;
883                         matrix[3] =  1.0000f * scaleY;
884                         matrix[4] = -0.2253f * scaleCbCr;
885                         matrix[5] = -0.5000f * scaleCbCr;
886                         matrix[6] =  1.0000f * scaleY;
887                         matrix[7] =  1.8270f * scaleCbCr;
888                         matrix[8] =  0.0000f * scaleCbCr;
889                         return 0;
890
891                 case 6: /* CCIR 709-1 */
892                         matrix[0] =  1.000000f * scaleY;
893                         matrix[1] =  0.000000f * scaleCbCr;
894                         matrix[2] =  1.574800f * scaleCbCr;
895                         matrix[3] =  1.000000f * scaleY;
896                         matrix[4] = -0.187324f * scaleCbCr;
897                         matrix[5] = -0.468124f * scaleCbCr;
898                         matrix[6] =  1.000000f * scaleY;
899                         matrix[7] =  1.855600f * scaleCbCr;
900                         matrix[8] =  0.000000f * scaleCbCr;
901                         return 0;
902
903                 case 7: /* CCIR 601 */
904                 case 8: /* I'm not sure 7 and 8 should share the same matrix */
905                         matrix[0] =  1.000000f * scaleY;
906                         matrix[1] =  0.000000f * scaleCbCr;
907                         matrix[2] =  1.402000f * scaleCbCr;
908                         matrix[3] =  1.000000f * scaleY;
909                         matrix[4] = -0.344136f * scaleCbCr;
910                         matrix[5] = -0.714136f * scaleCbCr;
911                         matrix[6] =  1.000000f * scaleY;
912                         matrix[7] =  1.772000f * scaleCbCr;
913                         matrix[8] =  0.000000f * scaleCbCr;
914                         return 0;
915
916                 default:
917                         return 1;
918         }
919 }
920
921 static float *getLinToLogLut(LogImageFile *logImage, LogImageElement logElement)
922 {
923         float *lut;
924         float gain, negativeFilmGamma, offset, step;
925         unsigned int lutsize = (unsigned int)(logElement.maxValue + 1);
926         unsigned int i;
927         
928         lut = MEM_mallocN(sizeof(float)*lutsize, "getLinToLogLut");
929
930         negativeFilmGamma = 0.6;
931         step = logElement.refHighQuantity / logElement.maxValue;
932         gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
933         offset = gain - logElement.maxValue;
934
935         for (i = 0; i < lutsize; i++)
936                 lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue;
937         
938         return lut;
939 }
940
941 static float *getLogToLinLut(LogImageFile *logImage, LogImageElement logElement)
942 {
943         float *lut;
944         float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip;
945         /* float filmGamma; unused */
946         unsigned int lutsize = (unsigned int)(logElement.maxValue + 1);
947         unsigned int i;
948         
949         lut = MEM_mallocN(sizeof(float)*lutsize, "getLogToLinLut");
950
951         /* Building the Log -> Lin LUT */
952         step = logElement.refHighQuantity / logElement.maxValue;
953         negativeFilmGamma = 0.6;
954
955         /* these are default values */
956         /* filmGamma = 2.2f;  unused */
957         softClip = 0;
958
959         breakPoint = logImage->referenceWhite - softClip;
960         gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
961         offset = gain - logElement.maxValue;
962         kneeOffset = powf(10, (breakPoint - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset;
963         kneeGain = (logElement.maxValue - kneeOffset) / powf(5 * softClip, softClip / 100);
964
965         for (i = 0; i < lutsize; i++) {
966                 if (i < logImage->referenceBlack)
967                         lut[i] = 0.0f;
968                 else if (i > breakPoint)
969                         lut[i] = (powf(i - breakPoint, softClip / 100) * kneeGain + kneeOffset) / logElement.maxValue;
970                 else
971                         lut[i] = (powf(10, ((float)i - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset) / logElement.maxValue;
972         }
973
974         return lut;
975 }
976
977 static float *getLinToSrgbLut(LogImageElement logElement)
978 {
979         float col, *lut;
980         unsigned int lutsize = (unsigned int)(logElement.maxValue + 1);
981         unsigned int i;
982
983         lut = MEM_mallocN(sizeof(float)*lutsize, "getLogToLinLut");
984
985         for (i = 0; i < lutsize; i++) {
986                 col = (float)i / logElement.maxValue;
987                 if (col < 0.0031308f)
988                         lut[i] = (col < 0.0f) ? 0.0f : col * 12.92f;
989                 else
990                         lut[i] = 1.055f * powf(col, 1.0f / 2.4f) - 0.055f;
991         }
992
993         return lut;
994 }
995
996 static float *getSrgbToLinLut(LogImageElement logElement)
997 {
998         float col, *lut;
999         unsigned int lutsize = (unsigned int)(logElement.maxValue + 1);
1000         unsigned int i;
1001
1002         lut = MEM_mallocN(sizeof(float)*lutsize, "getLogToLinLut");
1003
1004         for (i = 0; i < lutsize; i++) {
1005                 col = (float)i / logElement.maxValue;
1006                 if (col < 0.04045f)
1007                         lut[i] = (col < 0.0f) ? 0.0f : col * (1.0f / 12.92f);
1008                 else
1009                         lut[i] = powf((col + 0.055f) * (1.0f / 1.055f), 2.4f);
1010         }
1011
1012         return lut;
1013 }
1014
1015 static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage,
1016                            LogImageElement logElement, int elementIsSource)
1017 {
1018         unsigned int i;
1019         float *src_ptr = src;
1020         float *dst_ptr = dst;
1021
1022         switch (logElement.transfer) {
1023                 case transfer_UserDefined:
1024                 case transfer_Linear:
1025                 case transfer_Logarithmic: {
1026                         for (i = 0; i < logImage->width * logImage->height; i++) {
1027                                 *(dst_ptr++) = *(src_ptr++);
1028                                 *(dst_ptr++) = *(src_ptr++);
1029                                 *(dst_ptr++) = *(src_ptr++);
1030                                 src_ptr++;
1031                         }
1032
1033                         return 0;
1034                 }
1035
1036                 case transfer_PrintingDensity: {
1037                         float *lut;
1038
1039                         if (elementIsSource == 1)
1040                                 lut = getLogToLinLut(logImage, logElement);
1041                         else
1042                                 lut = getLinToLogLut(logImage, logElement);
1043
1044                         for (i = 0; i < logImage->width * logImage->height; i++) {
1045                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1046                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1047                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1048                                 src_ptr++;
1049                         }
1050
1051                         MEM_freeN(lut);
1052
1053                         return 0;
1054                 }
1055
1056                 default:
1057                         return 1;
1058         }
1059 }
1060
1061 static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage,
1062                            LogImageElement logElement, int elementIsSource)
1063 {
1064         unsigned int i;
1065         float *src_ptr = src;
1066         float *dst_ptr = dst;
1067
1068         switch (logElement.transfer) {
1069                 case transfer_UserDefined:
1070                 case transfer_Linear:
1071                 case transfer_Logarithmic: {
1072                         for (i = 0; i < logImage->width * logImage->height; i++) {
1073                                 *(dst_ptr++) = *(src_ptr++);
1074                                 *(dst_ptr++) = *(src_ptr++);
1075                                 *(dst_ptr++) = *(src_ptr++);
1076                                 *(dst_ptr++) = 1.0f;
1077                         }
1078
1079                         return 0;
1080                 }
1081
1082                 case transfer_PrintingDensity: {
1083                         float *lut;
1084
1085                         if (elementIsSource == 1)
1086                                 lut = getLogToLinLut(logImage, logElement);
1087                         else
1088                                 lut = getLinToLogLut(logImage, logElement);
1089
1090                         for (i = 0; i < logImage->width * logImage->height; i++) {
1091                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1092                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1093                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1094                                 *(dst_ptr++) = 1.0f;
1095                         }
1096
1097                         MEM_freeN(lut);
1098
1099                         return 0;
1100                 }
1101
1102                 default:
1103                         return 1;
1104         }
1105 }
1106
1107 static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage,
1108                             LogImageElement logElement, int elementIsSource)
1109 {
1110         unsigned int i;
1111         float *src_ptr = src;
1112         float *dst_ptr = dst;
1113
1114         switch (logElement.transfer) {
1115                 case transfer_UserDefined:
1116                 case transfer_Linear:
1117                 case transfer_Logarithmic: {
1118                         memcpy(dst, src, 4 * logImage->width * logImage->height * sizeof(float));
1119                         return 0;
1120                 }
1121
1122                 case transfer_PrintingDensity: {
1123                         float *lut;
1124
1125                         if (elementIsSource == 1)
1126                                 lut = getLogToLinLut(logImage, logElement);
1127                         else
1128                                 lut = getLinToLogLut(logImage, logElement);
1129
1130                         for (i = 0; i < logImage->width * logImage->height; i++) {
1131                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1132                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1133                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1134                                 *(dst_ptr++) = *(src_ptr++);
1135                         }
1136
1137                         MEM_freeN(lut);
1138
1139                         return 0;
1140                 }
1141
1142                 default:
1143                         return 1;
1144         }
1145 }
1146
1147 static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage,
1148                             LogImageElement logElement, int elementIsSource)
1149 {
1150         unsigned int i;
1151         float *src_ptr = src;
1152         float *dst_ptr = dst;
1153
1154         switch (logElement.transfer) {
1155                 case transfer_UserDefined:
1156                 case transfer_Linear:
1157                 case transfer_Logarithmic: {
1158                         for (i = 0; i < logImage->width * logImage->height; i++) {
1159                                 src_ptr += 4;
1160                                 *(dst_ptr++) = *(src_ptr--);
1161                                 *(dst_ptr++) = *(src_ptr--);
1162                                 *(dst_ptr++) = *(src_ptr--);
1163                                 *(dst_ptr++) = *(src_ptr--);
1164                                 src_ptr += 4;
1165                         }
1166                         return 0;
1167                 }
1168
1169                 case transfer_PrintingDensity: {
1170                         float *lut;
1171
1172                         if (elementIsSource == 1)
1173                                 lut = getLogToLinLut(logImage, logElement);
1174                         else
1175                                 lut = getLinToLogLut(logImage, logElement);
1176
1177                         for (i = 0; i < logImage->width * logImage->height; i++) {
1178                                 src_ptr += 4;
1179                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1180                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1181                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1182                                 *(dst_ptr++) = *(src_ptr--);
1183                                 src_ptr += 4;
1184                         }
1185
1186                         MEM_freeN(lut);
1187
1188                         return 0;
1189                 }
1190
1191                 default:
1192                         return 1;
1193         }
1194 }
1195
1196 static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1197 {
1198         unsigned int i;
1199         float conversionMatrix[9], refLowData, y, cb, cr;
1200         float *src_ptr = src;
1201         float *dst_ptr = dst;
1202
1203         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1204                 return 1;
1205
1206         refLowData = (float)logElement.refLowData / logElement.maxValue;
1207
1208         for (i = 0; i < logImage->width * logImage->height; i++) {
1209                 cb = *(src_ptr++) - 0.5f;
1210                 y = *(src_ptr++) - refLowData;
1211                 cr = *(src_ptr++) - 0.5f;
1212
1213                 *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1214                 *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1215                 *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1216                 *(dst_ptr++) = 1.0f;
1217         }
1218         return 0;
1219 }
1220
1221 static int convertCbYCrA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1222 {
1223         unsigned int i;
1224         float conversionMatrix[9], refLowData, y, cb, cr, a;
1225         float *src_ptr = src;
1226         float *dst_ptr = dst;
1227
1228         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1229                 return 1;
1230
1231         refLowData = (float)logElement.refLowData / logElement.maxValue;
1232
1233         for (i = 0; i < logImage->width * logImage->height; i++) {
1234                 cb = *(src_ptr++) - 0.5f;
1235                 y = *(src_ptr++) - refLowData;
1236                 cr = *(src_ptr++) - 0.5f;
1237                 a = *(src_ptr++);
1238
1239                 *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1240                 *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1241                 *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1242                 *(dst_ptr++) = a;
1243         }
1244         return 0;
1245 }
1246
1247 static int convertCbYCrY_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1248 {
1249         unsigned int i;
1250         float conversionMatrix[9], refLowData, y1, y2, cb, cr;
1251         float *src_ptr = src;
1252         float *dst_ptr = dst;
1253
1254         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1255                 return 1;
1256
1257         refLowData = (float)logElement.refLowData / logElement.maxValue;
1258
1259         for (i = 0; i < logImage->width * logImage->height / 2; i++) {
1260                 cb = *(src_ptr++) - 0.5f;
1261                 y1 = *(src_ptr++) - refLowData;
1262                 cr = *(src_ptr++) - 0.5f;
1263                 y2 = *(src_ptr++) - refLowData;
1264
1265                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1266                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1267                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1268                 *(dst_ptr++) = 1.0f;
1269                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1270                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1271                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1272                 *(dst_ptr++) = 1.0f;
1273         }
1274         return 0;
1275 }
1276
1277 static int convertCbYACrYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1278 {
1279         unsigned int i;
1280         float conversionMatrix[9], refLowData, y1, y2, cb, cr, a1, a2;
1281         float *src_ptr = src;
1282         float *dst_ptr = dst;
1283
1284         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1285                 return 1;
1286
1287         refLowData = (float)logElement.refLowData / logElement.maxValue;
1288
1289         for (i = 0; i < logImage->width * logImage->height / 2; i++) {
1290                 cb = *(src_ptr++) - 0.5f;
1291                 y1 = *(src_ptr++) - refLowData;
1292                 a1 = *(src_ptr++);
1293                 cr = *(src_ptr++) - 0.5f;
1294                 y2 = *(src_ptr++) - refLowData;
1295                 a2 = *(src_ptr++);
1296
1297                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1298                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1299                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1300                 *(dst_ptr++) = a1;
1301                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1302                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1303                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1304                 *(dst_ptr++) = a2;
1305         }
1306         return 0;
1307 }
1308
1309 static int convertLuminance_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1310 {
1311         unsigned int i;
1312         float conversionMatrix[9], value, refLowData;
1313         float *src_ptr = src;
1314         float *dst_ptr = dst;
1315
1316         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1317                 return 1;
1318
1319         refLowData = (float)logElement.refLowData / logElement.maxValue;
1320
1321         for (i = 0; i < logImage->width * logImage->height; i++) {
1322                 value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
1323                 *(dst_ptr++) = value;
1324                 *(dst_ptr++) = value;
1325                 *(dst_ptr++) = value;
1326                 *(dst_ptr++) = 1.0f;
1327         }
1328         return 0;
1329 }
1330
1331 static int convertYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1332 {
1333         unsigned int i;
1334         float conversionMatrix[9], value, refLowData;
1335         float *src_ptr = src;
1336         float *dst_ptr = dst;
1337
1338         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1339                 return 1;
1340
1341         refLowData = (float)logElement.refLowData / logElement.maxValue;
1342
1343         for (i = 0; i < logImage->width * logImage->height; i++) {
1344                 value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
1345                 *(dst_ptr++) = value;
1346                 *(dst_ptr++) = value;
1347                 *(dst_ptr++) = value;
1348                 *(dst_ptr++) = *(src_ptr++);
1349         }
1350         return 0;
1351 }
1352
1353 static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage,
1354                                    LogImageElement logElement, int dstIsLinearRGB)
1355 {
1356         int rvalue;
1357         unsigned int i;
1358         float *src_ptr;
1359         float *dst_ptr;
1360
1361         /* Convert data in src to linear RGBA in dst */
1362         switch (logElement.descriptor) {
1363                 case descriptor_RGB:
1364                         rvalue = convertRGB_RGBA(src, dst, logImage, logElement, 1);
1365                         break;
1366
1367                 case descriptor_RGBA:
1368                         rvalue = convertRGBA_RGBA(src, dst, logImage, logElement, 1);
1369                         break;
1370
1371                 case descriptor_ABGR:
1372                         rvalue = convertABGR_RGBA(src, dst, logImage, logElement, 1);
1373                         break;
1374
1375                 case descriptor_Luminance:
1376                         rvalue = convertLuminance_RGBA(src, dst, logImage, logElement);
1377                         break;
1378
1379                 case descriptor_CbYCr:
1380                         rvalue = convertCbYCr_RGBA(src, dst, logImage, logElement);
1381                         break;
1382
1383                 case descriptor_CbYCrY:
1384                         rvalue = convertCbYCrY_RGBA(src, dst, logImage, logElement);
1385                         break;
1386
1387                 case descriptor_CbYACrYA:
1388                         rvalue = convertCbYACrYA_RGBA(src, dst, logImage, logElement);
1389                         break;
1390
1391                 case descriptor_CbYCrA:
1392                         rvalue = convertCbYCrA_RGBA(src, dst, logImage, logElement);
1393                         break;
1394
1395                 case descriptor_YA: /* this descriptor is for internal use only */
1396                         rvalue = convertYA_RGBA(src, dst, logImage, logElement);
1397                         break;
1398
1399                 default:
1400                         return 1;
1401         }
1402
1403         if (rvalue == 1)
1404                 return 1;
1405         else if (dstIsLinearRGB) {
1406                 /* convert data from sRGB to Linear RGB via lut */
1407                 float *lut = getSrgbToLinLut(logElement);
1408                 src_ptr = dst; // no error here
1409                 dst_ptr = dst;
1410                 for (i = 0; i < logImage->width * logImage->height; i++) {
1411                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1412                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1413                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1414                         dst_ptr++; src_ptr++;
1415                 }
1416                 MEM_freeN(lut);
1417         }
1418         return 0;
1419 }
1420
1421 static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage,
1422                                    LogImageElement logElement, int srcIsLinearRGB)
1423 {
1424         unsigned int i;
1425         int rvalue;
1426         float *srgbSrc;
1427         float *srgbSrc_ptr;
1428         float *src_ptr = src;
1429         float *lut;
1430
1431         if (srcIsLinearRGB != 0) {
1432                 /* we need to convert src to sRGB */
1433                 srgbSrc = (float *)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__);
1434                 if (srgbSrc == NULL)
1435                         return 1;
1436
1437                 memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float));
1438                 srgbSrc_ptr = srgbSrc;
1439
1440                 /* convert data from Linear RGB to sRGB via lut */
1441                 lut = getLinToSrgbLut(logElement);
1442                 for (i = 0; i < logImage->width * logImage->height; i++) {
1443                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1444                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1445                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1446                         srgbSrc_ptr++; src_ptr++;
1447                 }
1448                 MEM_freeN(lut);
1449         }
1450         else
1451                 srgbSrc = src;
1452
1453         /* Convert linear RGBA data in src to format described by logElement in dst */
1454         switch (logElement.descriptor) {
1455                 case descriptor_RGB:
1456                         rvalue = convertRGBA_RGB(srgbSrc, dst, logImage, logElement, 0);
1457                         break;
1458
1459                 case descriptor_RGBA:
1460                         rvalue = convertRGBA_RGBA(srgbSrc, dst, logImage, logElement, 0);
1461                         break;
1462
1463                 /* these ones are not supported for the moment */
1464                 case descriptor_ABGR:
1465                 case descriptor_Luminance:
1466                 case descriptor_CbYCr:
1467                 case descriptor_CbYCrY:
1468                 case descriptor_CbYACrYA:
1469                 case descriptor_CbYCrA:
1470                 case descriptor_YA: /* this descriptor is for internal use only */
1471                 default:
1472                         rvalue = 1;
1473         }
1474
1475         if (srcIsLinearRGB != 0) {
1476                 MEM_freeN(srgbSrc);
1477         }
1478
1479         return rvalue;
1480 }