332ad913d19b27e95b15f6ed5b7578d8baa92462
[blender-staging.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 == 0)
101                 return 0;
102
103         if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) {
104                 fclose(f);
105                 return 0;
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 0;
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 0;
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 0;
140 }
141
142 void logImageClose(LogImageFile *logImage)
143 {
144         if (logImage != 0) {
145                 if (logImage->file) {
146                         fclose(logImage->file);
147                         logImage->file = 0;
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 == 0)
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 == 0) {
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 == 0) {
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 == 0) {
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 == 0) {
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] == 0) {
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] != 0)
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] != 0)
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 == 0) {
535                         if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n");
536                         for (i = 0; i < logImage->numElements; i++)
537                                 if (elementData[i] != 0)
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] != 0)
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 void getLinToLogLut(float *lut, LogImageFile *logImage, LogImageElement logElement)
922 {
923         float gain, negativeFilmGamma, offset, step;
924         unsigned int i;
925
926         negativeFilmGamma = 0.6;
927         step = logElement.refHighQuantity / logElement.maxValue;
928         gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
929         offset = gain - logElement.maxValue;
930
931         for (i = 0; i < (int)(logElement.maxValue + 1); i++)
932                 lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue;
933 }
934
935 static void getLogToLinLut(float *lut, LogImageFile *logImage, LogImageElement logElement)
936 {
937         float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip;
938         /* float filmGamma; unused */
939         unsigned int i;
940
941         /* Building the Log -> Lin LUT */
942         step = logElement.refHighQuantity / logElement.maxValue;
943         negativeFilmGamma = 0.6;
944
945         /* these are default values */
946         /* filmGamma = 2.2f;  unused */
947         softClip = 0;
948
949         breakPoint = logImage->referenceWhite - softClip;
950         gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f));
951         offset = gain - logElement.maxValue;
952         kneeOffset = powf(10, (breakPoint - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset;
953         kneeGain = (logElement.maxValue - kneeOffset) / powf(5 * softClip, softClip / 100);
954
955         for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
956                 if (i < logImage->referenceBlack)
957                         lut[i] = 0.0f;
958                 else if (i > breakPoint)
959                         lut[i] = (powf(i - breakPoint, softClip / 100) * kneeGain + kneeOffset) / logElement.maxValue;
960                 else
961                         lut[i] = (powf(10, ((float)i - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset) / logElement.maxValue;
962         }
963 }
964
965 static void getLinToSrgbLut(float *lut, LogImageElement logElement)
966 {
967         unsigned int i;
968         float col;
969
970         for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
971                 col = (float)i / logElement.maxValue;
972                 if (col < 0.0031308f)
973                         lut[i] = (col < 0.0f) ? 0.0f : col * 12.92f;
974                 else
975                         lut[i] = 1.055f * powf(col, 1.0f / 2.4f) - 0.055f;
976         }
977 }
978
979 static void getSrgbToLinLut(float *lut, LogImageElement logElement)
980 {
981         unsigned int i;
982         float col;
983
984         for (i = 0; i < (int)(logElement.maxValue + 1); i++) {
985                 col = (float)i / logElement.maxValue;
986                 if (col < 0.04045f)
987                         lut[i] = (col < 0.0f) ? 0.0f : col * (1.0f / 12.92f);
988                 else
989                         lut[i] = powf((col + 0.055f) * (1.0f / 1.055f), 2.4f);
990         }
991 }
992
993 static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage,
994                            LogImageElement logElement, int elementIsSource)
995 {
996         unsigned int i;
997         float lut[65536];
998         float *src_ptr = src;
999         float *dst_ptr = dst;
1000
1001         switch (logElement.transfer) {
1002                 case transfer_UserDefined:
1003                 case transfer_Linear:
1004                 case transfer_Logarithmic:
1005                         for (i = 0; i < logImage->width * logImage->height; i++) {
1006                                 *(dst_ptr++) = *(src_ptr++);
1007                                 *(dst_ptr++) = *(src_ptr++);
1008                                 *(dst_ptr++) = *(src_ptr++);
1009                                 src_ptr++;
1010                         }
1011                         return 0;
1012
1013                 case transfer_PrintingDensity:
1014                         if (elementIsSource == 1)
1015                                 getLogToLinLut((float *)&lut, logImage, logElement);
1016                         else
1017                                 getLinToLogLut((float *)&lut, logImage, logElement);
1018
1019                         for (i = 0; i < logImage->width * logImage->height; i++) {
1020                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1021                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1022                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1023                                 src_ptr++;
1024                         }
1025                         return 0;
1026
1027                 default:
1028                         return 1;
1029         }
1030 }
1031
1032 static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage,
1033                            LogImageElement logElement, int elementIsSource)
1034 {
1035         unsigned int i;
1036         float lut[65536];
1037         float *src_ptr = src;
1038         float *dst_ptr = dst;
1039
1040         switch (logElement.transfer) {
1041                 case transfer_UserDefined:
1042                 case transfer_Linear:
1043                 case transfer_Logarithmic:
1044                         for (i = 0; i < logImage->width * logImage->height; i++) {
1045                                 *(dst_ptr++) = *(src_ptr++);
1046                                 *(dst_ptr++) = *(src_ptr++);
1047                                 *(dst_ptr++) = *(src_ptr++);
1048                                 *(dst_ptr++) = 1.0f;
1049                         }
1050                         return 0;
1051
1052                 case transfer_PrintingDensity:
1053                         if (elementIsSource == 1)
1054                                 getLogToLinLut((float *)&lut, logImage, logElement);
1055                         else
1056                                 getLinToLogLut((float *)&lut, logImage, logElement);
1057
1058                         for (i = 0; i < logImage->width * logImage->height; i++) {
1059                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1060                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1061                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1062                                 *(dst_ptr++) = 1.0f;
1063                         }
1064                         return 0;
1065
1066                 default:
1067                         return 1;
1068         }
1069 }
1070
1071 static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage,
1072                             LogImageElement logElement, int elementIsSource)
1073 {
1074         unsigned int i;
1075         float lut[65536];
1076         float *src_ptr = src;
1077         float *dst_ptr = dst;
1078
1079         switch (logElement.transfer) {
1080                 case transfer_UserDefined:
1081                 case transfer_Linear:
1082                 case transfer_Logarithmic:
1083                         memcpy(dst, src, 4 * logImage->width * logImage->height * sizeof(float));
1084                         return 0;
1085
1086                 case transfer_PrintingDensity:
1087                         if (elementIsSource == 1)
1088                                 getLogToLinLut((float *)&lut, logImage, logElement);
1089                         else
1090                                 getLinToLogLut((float *)&lut, logImage, logElement);
1091
1092                         for (i = 0; i < logImage->width * logImage->height; i++) {
1093                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1094                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1095                                 *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1096                                 *(dst_ptr++) = *(src_ptr++);
1097                         }
1098                         return 0;
1099
1100                 default:
1101                         return 1;
1102         }
1103 }
1104
1105 static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage,
1106                             LogImageElement logElement, int elementIsSource)
1107 {
1108         unsigned int i;
1109         float lut[65536];
1110         float *src_ptr = src;
1111         float *dst_ptr = dst;
1112
1113         switch (logElement.transfer) {
1114                 case transfer_UserDefined:
1115                 case transfer_Linear:
1116                 case transfer_Logarithmic:
1117                         for (i = 0; i < logImage->width * logImage->height; i++) {
1118                                 src_ptr += 4;
1119                                 *(dst_ptr++) = *(src_ptr--);
1120                                 *(dst_ptr++) = *(src_ptr--);
1121                                 *(dst_ptr++) = *(src_ptr--);
1122                                 *(dst_ptr++) = *(src_ptr--);
1123                                 src_ptr += 4;
1124                         }
1125                         return 0;
1126
1127                 case transfer_PrintingDensity:
1128                         if (elementIsSource == 1)
1129                                 getLogToLinLut((float *)&lut, logImage, logElement);
1130                         else
1131                                 getLinToLogLut((float *)&lut, logImage, logElement);
1132
1133                         for (i = 0; i < logImage->width * logImage->height; i++) {
1134                                 src_ptr += 4;
1135                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1136                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1137                                 *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)];
1138                                 *(dst_ptr++) = *(src_ptr--);
1139                                 src_ptr += 4;
1140                         }
1141                         return 0;
1142
1143                 default:
1144                         return 1;
1145         }
1146 }
1147
1148 static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1149 {
1150         unsigned int i;
1151         float conversionMatrix[9], refLowData, y, cb, cr;
1152         float *src_ptr = src;
1153         float *dst_ptr = dst;
1154
1155         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1156                 return 1;
1157
1158         refLowData = (float)logElement.refLowData / logElement.maxValue;
1159
1160         for (i = 0; i < logImage->width * logImage->height; i++) {
1161                 cb = *(src_ptr++) - 0.5f;
1162                 y = *(src_ptr++) - refLowData;
1163                 cr = *(src_ptr++) - 0.5f;
1164
1165                 *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1166                 *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1167                 *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1168                 *(dst_ptr++) = 1.0f;
1169         }
1170         return 0;
1171 }
1172
1173 static int convertCbYCrA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1174 {
1175         unsigned int i;
1176         float conversionMatrix[9], refLowData, y, cb, cr, a;
1177         float *src_ptr = src;
1178         float *dst_ptr = dst;
1179
1180         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1181                 return 1;
1182
1183         refLowData = (float)logElement.refLowData / logElement.maxValue;
1184
1185         for (i = 0; i < logImage->width * logImage->height; i++) {
1186                 cb = *(src_ptr++) - 0.5f;
1187                 y = *(src_ptr++) - refLowData;
1188                 cr = *(src_ptr++) - 0.5f;
1189                 a = *(src_ptr++);
1190
1191                 *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1192                 *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1193                 *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1194                 *(dst_ptr++) = a;
1195         }
1196         return 0;
1197 }
1198
1199 static int convertCbYCrY_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1200 {
1201         unsigned int i;
1202         float conversionMatrix[9], refLowData, y1, y2, cb, cr;
1203         float *src_ptr = src;
1204         float *dst_ptr = dst;
1205
1206         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1207                 return 1;
1208
1209         refLowData = (float)logElement.refLowData / logElement.maxValue;
1210
1211         for (i = 0; i < logImage->width * logImage->height / 2; i++) {
1212                 cb = *(src_ptr++) - 0.5f;
1213                 y1 = *(src_ptr++) - refLowData;
1214                 cr = *(src_ptr++) - 0.5f;
1215                 y2 = *(src_ptr++) - refLowData;
1216
1217                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1218                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1219                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1220                 *(dst_ptr++) = 1.0f;
1221                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1222                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1223                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1224                 *(dst_ptr++) = 1.0f;
1225         }
1226         return 0;
1227 }
1228
1229 static int convertCbYACrYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1230 {
1231         unsigned int i;
1232         float conversionMatrix[9], refLowData, y1, y2, cb, cr, a1, a2;
1233         float *src_ptr = src;
1234         float *dst_ptr = dst;
1235
1236         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1237                 return 1;
1238
1239         refLowData = (float)logElement.refLowData / logElement.maxValue;
1240
1241         for (i = 0; i < logImage->width * logImage->height / 2; i++) {
1242                 cb = *(src_ptr++) - 0.5f;
1243                 y1 = *(src_ptr++) - refLowData;
1244                 a1 = *(src_ptr++);
1245                 cr = *(src_ptr++) - 0.5f;
1246                 y2 = *(src_ptr++) - refLowData;
1247                 a2 = *(src_ptr++);
1248
1249                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1250                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1251                 *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1252                 *(dst_ptr++) = a1;
1253                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f);
1254                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f);
1255                 *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f);
1256                 *(dst_ptr++) = a2;
1257         }
1258         return 0;
1259 }
1260
1261 static int convertLuminance_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1262 {
1263         unsigned int i;
1264         float conversionMatrix[9], value, refLowData;
1265         float *src_ptr = src;
1266         float *dst_ptr = dst;
1267
1268         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1269                 return 1;
1270
1271         refLowData = (float)logElement.refLowData / logElement.maxValue;
1272
1273         for (i = 0; i < logImage->width * logImage->height; i++) {
1274                 value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
1275                 *(dst_ptr++) = value;
1276                 *(dst_ptr++) = value;
1277                 *(dst_ptr++) = value;
1278                 *(dst_ptr++) = 1.0f;
1279         }
1280         return 0;
1281 }
1282
1283 static int convertYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement)
1284 {
1285         unsigned int i;
1286         float conversionMatrix[9], value, refLowData;
1287         float *src_ptr = src;
1288         float *dst_ptr = dst;
1289
1290         if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0)
1291                 return 1;
1292
1293         refLowData = (float)logElement.refLowData / logElement.maxValue;
1294
1295         for (i = 0; i < logImage->width * logImage->height; i++) {
1296                 value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f);
1297                 *(dst_ptr++) = value;
1298                 *(dst_ptr++) = value;
1299                 *(dst_ptr++) = value;
1300                 *(dst_ptr++) = *(src_ptr++);
1301         }
1302         return 0;
1303 }
1304
1305 static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage,
1306                                    LogImageElement logElement, int dstIsLinearRGB)
1307 {
1308         int rvalue;
1309         unsigned int i;
1310         float *src_ptr;
1311         float *dst_ptr;
1312         float lut[65536];
1313
1314         /* Convert data in src to linear RGBA in dst */
1315         switch (logElement.descriptor) {
1316                 case descriptor_RGB:
1317                         rvalue = convertRGB_RGBA(src, dst, logImage, logElement, 1);
1318                         break;
1319
1320                 case descriptor_RGBA:
1321                         rvalue = convertRGBA_RGBA(src, dst, logImage, logElement, 1);
1322                         break;
1323
1324                 case descriptor_ABGR:
1325                         rvalue = convertABGR_RGBA(src, dst, logImage, logElement, 1);
1326                         break;
1327
1328                 case descriptor_Luminance:
1329                         rvalue = convertLuminance_RGBA(src, dst, logImage, logElement);
1330                         break;
1331
1332                 case descriptor_CbYCr:
1333                         rvalue = convertCbYCr_RGBA(src, dst, logImage, logElement);
1334                         break;
1335
1336                 case descriptor_CbYCrY:
1337                         rvalue = convertCbYCrY_RGBA(src, dst, logImage, logElement);
1338                         break;
1339
1340                 case descriptor_CbYACrYA:
1341                         rvalue = convertCbYACrYA_RGBA(src, dst, logImage, logElement);
1342                         break;
1343
1344                 case descriptor_CbYCrA:
1345                         rvalue = convertCbYCrA_RGBA(src, dst, logImage, logElement);
1346                         break;
1347
1348                 case descriptor_YA: /* this descriptor is for internal use only */
1349                         rvalue = convertYA_RGBA(src, dst, logImage, logElement);
1350                         break;
1351
1352                 default:
1353                         return 1;
1354         }
1355
1356         if (rvalue == 1)
1357                 return 1;
1358         else if (dstIsLinearRGB) {
1359                 /* convert data from sRGB to Linear RGB via lut */
1360                 getSrgbToLinLut((float *)&lut, logElement);
1361                 src_ptr = dst; // no error here
1362                 dst_ptr = dst;
1363                 for (i = 0; i < logImage->width * logImage->height; i++) {
1364                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1365                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1366                         *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1367                         dst_ptr++; src_ptr++;
1368                 }
1369         }
1370         return 0;
1371 }
1372
1373 static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage,
1374                                    LogImageElement logElement, int srcIsLinearRGB)
1375 {
1376         unsigned int i;
1377         int rvalue;
1378         float *srgbSrc;
1379         float *srgbSrc_ptr;
1380         float *src_ptr = src;
1381         float lut[65536];
1382
1383         if (srcIsLinearRGB != 0) {
1384                 /* we need to convert src to sRGB */
1385                 srgbSrc = (float *)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__);
1386                 if (srgbSrc == 0)
1387                         return 1;
1388
1389                 memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float));
1390                 srgbSrc_ptr = srgbSrc;
1391
1392                 /* convert data from Linear RGB to sRGB via lut */
1393                 getLinToSrgbLut((float *)&lut, logElement);
1394                 for (i = 0; i < logImage->width * logImage->height; i++) {
1395                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1396                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1397                         *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)];
1398                         srgbSrc_ptr++; src_ptr++;
1399                 }
1400         }
1401         else
1402                 srgbSrc = src;
1403
1404         /* Convert linear RGBA data in src to format described by logElement in dst */
1405         switch (logElement.descriptor) {
1406                 case descriptor_RGB:
1407                         rvalue = convertRGBA_RGB(srgbSrc, dst, logImage, logElement, 0);
1408                         break;
1409
1410                 case descriptor_RGBA:
1411                         rvalue = convertRGBA_RGBA(srgbSrc, dst, logImage, logElement, 0);
1412                         break;
1413
1414                 /* these ones are not supported for the moment */
1415                 case descriptor_ABGR:
1416                 case descriptor_Luminance:
1417                 case descriptor_CbYCr:
1418                 case descriptor_CbYCrY:
1419                 case descriptor_CbYACrYA:
1420                 case descriptor_CbYCrA:
1421                 case descriptor_YA: /* this descriptor is for internal use only */
1422                 default:
1423                         rvalue = 1;
1424         }
1425
1426         if (srcIsLinearRGB != 0) {
1427                 MEM_freeN(srgbSrc);
1428         }
1429
1430         return rvalue;
1431 }