style cleanup: trailing tabs & expand some non prefix tabs into spaces.
[blender.git] / source / blender / imbuf / intern / divers.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * allocimbuf.c
27  *
28  */
29
30 /** \file blender/imbuf/intern/divers.c
31  *  \ingroup imbuf
32  */
33
34 #include "BLI_rand.h"
35 #include "BLI_math.h"
36 #include "BLI_utildefines.h"
37
38 #include "imbuf.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41 #include "IMB_allocimbuf.h"
42
43 #include "IMB_colormanagement.h"
44 #include "IMB_colormanagement_intern.h"
45
46 #include "BLI_threads.h"
47
48 #include "MEM_guardedalloc.h"
49
50 /**************************** Interlace/Deinterlace **************************/
51
52 void IMB_de_interlace(ImBuf *ibuf)
53 {
54         ImBuf *tbuf1, *tbuf2;
55         
56         if (ibuf == NULL) return;
57         if (ibuf->flags & IB_fields) return;
58         ibuf->flags |= IB_fields;
59         
60         if (ibuf->rect) {
61                 /* make copies */
62                 tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
63                 tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
64                 
65                 ibuf->x *= 2;
66                 IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
67                 IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y);
68         
69                 ibuf->x /= 2;
70                 IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y);
71                 IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y);
72                 
73                 IMB_freeImBuf(tbuf1);
74                 IMB_freeImBuf(tbuf2);
75         }
76         ibuf->y /= 2;
77 }
78
79 void IMB_interlace(ImBuf *ibuf)
80 {
81         ImBuf *tbuf1, *tbuf2;
82
83         if (ibuf == NULL) return;
84         ibuf->flags &= ~IB_fields;
85
86         ibuf->y *= 2;
87
88         if (ibuf->rect) {
89                 /* make copies */
90                 tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
91                 tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect);
92
93                 IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
94                 IMB_rectcpy(tbuf2, ibuf, 0, 0, 0, tbuf2->y, ibuf->x, ibuf->y);
95
96                 ibuf->x *= 2;
97                 IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y);
98                 IMB_rectcpy(ibuf, tbuf2, tbuf2->x, 0, 0, 0, tbuf2->x, tbuf2->y);
99                 ibuf->x /= 2;
100
101                 IMB_freeImBuf(tbuf1);
102                 IMB_freeImBuf(tbuf2);
103         }
104 }
105
106 /************************* Floyd-Steinberg dithering *************************/
107
108 typedef struct DitherContext {
109         int *error_buf, *e;
110         int v[4], v0[4], v1[4];
111         float f;
112 } DitherContext;
113
114 static DitherContext *create_dither_context(int w, float factor)
115 {
116         DitherContext *di;
117         int i;
118         
119         di = MEM_callocN(sizeof(DitherContext), "dithering context");
120         di->f = factor / 16.0f;
121         di->error_buf = MEM_callocN(4 * (w + 1) * sizeof(int), "dithering error");
122         di->e = di->error_buf;
123
124         for (i = 0; i < 4; ++i)
125                 di->v[i] = di->v0[i] = di->v1[i] = 1024.0f * (BLI_frand() - 0.5f);
126
127         return di;
128 }
129
130 static void clear_dither_context(DitherContext *di)
131 {
132         MEM_freeN(di->error_buf);
133         MEM_freeN(di);
134 }
135
136 static void dither_finish_row(DitherContext *di)
137 {
138         int i;
139
140         for (i = 0; i < 4; i++)
141                 di->v[i] = di->v0[i] = di->v1[i] = 0;
142
143         di->e = di->error_buf;
144 }
145
146 MINLINE unsigned char dither_value(unsigned short v_in, DitherContext *di, int i)
147 {
148         int dv, d2;
149         unsigned char v_out;
150
151         di->v[i] = v_in + (2 * di->v[i] + di->e[4]) * di->f;
152         CLAMP(di->v[i], 0, 0xFF00);
153         v_out = USHORTTOUCHAR(di->v[i]);
154         di->v[i] -= v_out << 8;
155         dv = di->v[i];
156         d2 = di->v[i] << 1;
157         di->v[i] += d2;
158         *(di->e++) = di->v[i] + di->v0[i];
159         di->v[i] += d2;
160
161         di->v0[i] = di->v[i] + di->v1[i];
162         di->v1[i] = dv;
163         di->v[i] += d2;
164
165         return v_out;
166 }
167
168 /************************* Generic Buffer Conversion *************************/
169
170 MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4])
171 {
172         b[0] = USHORTTOUCHAR(us[0]);
173         b[1] = USHORTTOUCHAR(us[1]);
174         b[2] = USHORTTOUCHAR(us[2]);
175         b[3] = USHORTTOUCHAR(us[3]);
176 }
177
178 MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di)
179 {
180         b[0] = dither_value(us[0], di, 0);
181         b[1] = dither_value(us[1], di, 1);
182         b[2] = dither_value(us[2], di, 2);
183         b[3] = dither_value(us[3], di, 3);
184 }
185
186 MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di)
187 {
188         unsigned short us[4] = {FTOUSHORT(f[0]), FTOUSHORT(f[1]), FTOUSHORT(f[2]), FTOUSHORT(f[3])};
189         ushort_to_byte_dither_v4(b, us, di);
190 }
191
192 /* float to byte pixels, output 4-channel RGBA */
193 void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
194                                 int channels_from, float dither, int profile_to, int profile_from, int predivide,
195                                 int width, int height, int stride_to, int stride_from)
196 {
197         float tmp[4];
198         int x, y;
199         DitherContext *di;
200
201         /* we need valid profiles */
202         BLI_assert(profile_to != IB_PROFILE_NONE);
203         BLI_assert(profile_from != IB_PROFILE_NONE);
204
205         if (dither)
206                 di = create_dither_context(width, dither);
207
208         for (y = 0; y < height; y++) {
209                 if (channels_from == 1) {
210                         /* single channel input */
211                         const float *from = rect_from + stride_from * y;
212                         uchar *to = rect_to + stride_to * y * 4;
213
214                         for (x = 0; x < width; x++, from++, to += 4)
215                                 to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
216                 }
217                 else if (channels_from == 3) {
218                         /* RGB input */
219                         const float *from = rect_from + stride_from * y * 3;
220                         uchar *to = rect_to + stride_to * y * 4;
221
222                         if (profile_to == profile_from) {
223                                 /* no color space conversion */
224                                 for (x = 0; x < width; x++, from += 3, to += 4) {
225                                         rgb_float_to_uchar(to, from);
226                                         to[3] = 255;
227                                 }
228                         }
229                         else if (profile_to == IB_PROFILE_SRGB) {
230                                 /* convert from linear to sRGB */
231                                 for (x = 0; x < width; x++, from += 3, to += 4) {
232                                         linearrgb_to_srgb_v3_v3(tmp, from);
233                                         rgb_float_to_uchar(to, tmp);
234                                         to[3] = 255;
235                                 }
236                         }
237                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
238                                 /* convert from sRGB to linear */
239                                 for (x = 0; x < width; x++, from += 3, to += 4) {
240                                         srgb_to_linearrgb_v3_v3(tmp, from);
241                                         rgb_float_to_uchar(to, tmp);
242                                         to[3] = 255;
243                                 }
244                         }
245                 }
246                 else if (channels_from == 4) {
247                         /* RGBA input */
248                         const float *from = rect_from + stride_from * y * 4;
249                         uchar *to = rect_to + stride_to * y * 4;
250
251                         if (profile_to == profile_from) {
252                                 /* no color space conversion */
253                                 if (dither) {
254                                         for (x = 0; x < width; x++, from += 4, to += 4)
255                                                 float_to_byte_dither_v4(to, from, di);
256                                 }
257                                 else {
258                                         for (x = 0; x < width; x++, from += 4, to += 4)
259                                                 rgba_float_to_uchar(to, from);
260                                 }
261                         }
262                         else if (profile_to == IB_PROFILE_SRGB) {
263                                 /* convert from linear to sRGB */
264                                 unsigned short us[4];
265
266                                 if (dither && predivide) {
267                                         for (x = 0; x < width; x++, from += 4, to += 4) {
268                                                 linearrgb_to_srgb_ushort4_predivide(us, from);
269                                                 ushort_to_byte_dither_v4(to, us, di);
270                                         }
271                                 }
272                                 else if (dither) {
273                                         for (x = 0; x < width; x++, from += 4, to += 4) {
274                                                 linearrgb_to_srgb_ushort4(us, from);
275                                                 ushort_to_byte_dither_v4(to, us, di);
276                                         }
277                                 }
278                                 else if (predivide) {
279                                         for (x = 0; x < width; x++, from += 4, to += 4) {
280                                                 linearrgb_to_srgb_ushort4_predivide(us, from);
281                                                 ushort_to_byte_v4(to, us);
282                                         }
283                                 }
284                                 else {
285                                         for (x = 0; x < width; x++, from += 4, to += 4) {
286                                                 linearrgb_to_srgb_ushort4(us, from);
287                                                 ushort_to_byte_v4(to, us);
288                                         }
289                                 }
290                         }
291                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
292                                 /* convert from sRGB to linear */
293                                 if (dither && predivide) {
294                                         for (x = 0; x < width; x++, from += 4, to += 4) {
295                                                 srgb_to_linearrgb_predivide_v4(tmp, from);
296                                                 float_to_byte_dither_v4(to, tmp, di);
297                                         }
298                                 }
299                                 else if (dither) {
300                                         for (x = 0; x < width; x++, from += 4, to += 4) {
301                                                 srgb_to_linearrgb_v4(tmp, from);
302                                                 float_to_byte_dither_v4(to, tmp, di);
303                                         }
304                                 }
305                                 else if (predivide) {
306                                         for (x = 0; x < width; x++, from += 4, to += 4) {
307                                                 srgb_to_linearrgb_predivide_v4(tmp, from);
308                                                 rgba_float_to_uchar(to, tmp);
309                                         }
310                                 }
311                                 else {
312                                         for (x = 0; x < width; x++, from += 4, to += 4) {
313                                                 srgb_to_linearrgb_v4(tmp, from);
314                                                 rgba_float_to_uchar(to, tmp);
315                                         }
316                                 }
317                         }
318                 }
319
320                 if (dither)
321                         dither_finish_row(di);
322         }
323
324         if (dither)
325                 clear_dither_context(di);
326 }
327
328 /* byte to float pixels, input and output 4-channel RGBA  */
329 void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
330                                 int profile_to, int profile_from, int predivide,
331                                 int width, int height, int stride_to, int stride_from)
332 {
333         float tmp[4];
334         int x, y;
335
336         /* we need valid profiles */
337         BLI_assert(profile_to != IB_PROFILE_NONE);
338         BLI_assert(profile_from != IB_PROFILE_NONE);
339
340         /* RGBA input */
341         for (y = 0; y < height; y++) {
342                 const uchar *from = rect_from + stride_from * y * 4;
343                 float *to = rect_to + stride_to * y * 4;
344
345                 if (profile_to == profile_from) {
346                         /* no color space conversion */
347                         for (x = 0; x < width; x++, from += 4, to += 4)
348                                 rgba_uchar_to_float(to, from);
349                 }
350                 else if (profile_to == IB_PROFILE_LINEAR_RGB) {
351                         /* convert sRGB to linear */
352                         if (predivide) {
353                                 for (x = 0; x < width; x++, from += 4, to += 4) {
354                                         srgb_to_linearrgb_uchar4_predivide(to, from);
355                                 }
356                         }
357                         else {
358                                 for (x = 0; x < width; x++, from += 4, to += 4) {
359                                         srgb_to_linearrgb_uchar4(to, from);
360                                 }
361                         }
362                 }
363                 else if (profile_to == IB_PROFILE_SRGB) {
364                         /* convert linear to sRGB */
365                         if (predivide) {
366                                 for (x = 0; x < width; x++, from += 4, to += 4) {
367                                         rgba_uchar_to_float(tmp, from);
368                                         linearrgb_to_srgb_predivide_v4(to, tmp);
369                                 }
370                         }
371                         else {
372                                 for (x = 0; x < width; x++, from += 4, to += 4) {
373                                         rgba_uchar_to_float(tmp, from);
374                                         linearrgb_to_srgb_v4(to, tmp);
375                                 }
376                         }
377                 }
378         }
379 }
380
381 /* float to float pixels, output 4-channel RGBA */
382 void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
383                                  int channels_from, int profile_to, int profile_from, int predivide,
384                                  int width, int height, int stride_to, int stride_from)
385 {
386         int x, y;
387
388         /* we need valid profiles */
389         BLI_assert(profile_to != IB_PROFILE_NONE);
390         BLI_assert(profile_from != IB_PROFILE_NONE);
391
392         if (channels_from == 1) {
393                 /* single channel input */
394                 for (y = 0; y < height; y++) {
395                         const float *from = rect_from + stride_from * y;
396                         float *to = rect_to + stride_to * y * 4;
397
398                         for (x = 0; x < width; x++, from++, to += 4)
399                                 to[0] = to[1] = to[2] = to[3] = from[0];
400                 }
401         }
402         else if (channels_from == 3) {
403                 /* RGB input */
404                 for (y = 0; y < height; y++) {
405                         const float *from = rect_from + stride_from * y * 3;
406                         float *to = rect_to + stride_to * y * 4;
407
408                         if (profile_to == profile_from) {
409                                 /* no color space conversion */
410                                 for (x = 0; x < width; x++, from += 3, to += 4) {
411                                         copy_v3_v3(to, from);
412                                         to[3] = 1.0f;
413                                 }
414                         }
415                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
416                                 /* convert from sRGB to linear */
417                                 for (x = 0; x < width; x++, from += 3, to += 4) {
418                                         srgb_to_linearrgb_v3_v3(to, from);
419                                         to[3] = 1.0f;
420                                 }
421                         }
422                         else if (profile_to == IB_PROFILE_SRGB) {
423                                 /* convert from linear to sRGB */
424                                 for (x = 0; x < width; x++, from += 3, to += 4) {
425                                         linearrgb_to_srgb_v3_v3(to, from);
426                                         to[3] = 1.0f;
427                                 }
428                         }
429                 }
430         }
431         else if (channels_from == 4) {
432                 /* RGBA input */
433                 for (y = 0; y < height; y++) {
434                         const float *from = rect_from + stride_from * y * 4;
435                         float *to = rect_to + stride_to * y * 4;
436
437                         if (profile_to == profile_from) {
438                                 /* same profile, copy */
439                                 memcpy(to, from, sizeof(float) * 4 * width);
440                         }
441                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
442                                 /* convert to sRGB to linear */
443                                 if (predivide) {
444                                         for (x = 0; x < width; x++, from += 4, to += 4)
445                                                 srgb_to_linearrgb_predivide_v4(to, from);
446                                 }
447                                 else {
448                                         for (x = 0; x < width; x++, from += 4, to += 4)
449                                                 srgb_to_linearrgb_v4(to, from);
450                                 }
451                         }
452                         else if (profile_to == IB_PROFILE_SRGB) {
453                                 /* convert from linear to sRGB */
454                                 if (predivide) {
455                                         for (x = 0; x < width; x++, from += 4, to += 4)
456                                                 linearrgb_to_srgb_predivide_v4(to, from);
457                                 }
458                                 else {
459                                         for (x = 0; x < width; x++, from += 4, to += 4)
460                                                 linearrgb_to_srgb_v4(to, from);
461                                 }
462                         }
463                 }
464         }
465 }
466
467 /* byte to byte pixels, input and output 4-channel RGBA */
468 void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
469                                int profile_to, int profile_from, int predivide,
470                                int width, int height, int stride_to, int stride_from)
471 {
472         float tmp[4];
473         int x, y;
474
475         /* we need valid profiles */
476         BLI_assert(profile_to != IB_PROFILE_NONE);
477         BLI_assert(profile_from != IB_PROFILE_NONE);
478
479         /* always RGBA input */
480         for (y = 0; y < height; y++) {
481                 const uchar *from = rect_from + stride_from * y * 4;
482                 uchar *to = rect_to + stride_to * y * 4;
483
484                 if (profile_to == profile_from) {
485                         /* same profile, copy */
486                         memcpy(to, from, sizeof(uchar) * 4 * width);
487                 }
488                 else if (profile_to == IB_PROFILE_LINEAR_RGB) {
489                         /* convert to sRGB to linear */
490                         if (predivide) {
491                                 for (x = 0; x < width; x++, from += 4, to += 4) {
492                                         rgba_uchar_to_float(tmp, from);
493                                         srgb_to_linearrgb_predivide_v4(tmp, tmp);
494                                         rgba_float_to_uchar(to, tmp);
495                                 }
496                         }
497                         else {
498                                 for (x = 0; x < width; x++, from += 4, to += 4) {
499                                         rgba_uchar_to_float(tmp, from);
500                                         srgb_to_linearrgb_v4(tmp, tmp);
501                                         rgba_float_to_uchar(to, tmp);
502                                 }
503                         }
504                 }
505                 else if (profile_to == IB_PROFILE_SRGB) {
506                         /* convert from linear to sRGB */
507                         if (predivide) {
508                                 for (x = 0; x < width; x++, from += 4, to += 4) {
509                                         rgba_uchar_to_float(tmp, from);
510                                         linearrgb_to_srgb_predivide_v4(tmp, tmp);
511                                         rgba_float_to_uchar(to, tmp);
512                                 }
513                         }
514                         else {
515                                 for (x = 0; x < width; x++, from += 4, to += 4) {
516                                         rgba_uchar_to_float(tmp, from);
517                                         linearrgb_to_srgb_v4(tmp, tmp);
518                                         rgba_float_to_uchar(to, tmp);
519                                 }
520                         }
521                 }
522         }
523 }
524
525 /****************************** ImBuf Conversion *****************************/
526
527 void IMB_rect_from_float(ImBuf *ibuf)
528 {
529         int predivide = (ibuf->flags & IB_cm_predivide);
530         float *buffer;
531         const char *from_colorspace;
532
533         /* verify we have a float buffer */
534         if (ibuf->rect_float == NULL)
535                 return;
536
537         /* create byte rect if it didn't exist yet */
538         if (ibuf->rect == NULL) {
539                 if (imb_addrectImBuf(ibuf) == 0)
540                         return;
541         }
542
543         if (ibuf->float_colorspace == NULL)
544                 from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
545         else
546                 from_colorspace = ibuf->float_colorspace->name;
547
548         buffer = MEM_dupallocN(ibuf->rect_float);
549
550         /* first make float buffer in byte space */
551         IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide);
552
553         /* convert float to byte */
554         IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
555                                    FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
556
557         MEM_freeN(buffer);
558
559         /* ensure user flag is reset */
560         ibuf->userflags &= ~IB_RECT_INVALID;
561 }
562
563 /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
564 void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
565 {
566         float *rect_float;
567         uchar *rect_byte;
568         int predivide = (ibuf->flags & IB_cm_predivide);
569         int profile_from = IB_PROFILE_LINEAR_RGB;
570
571         /* verify we have a float buffer */
572         if (ibuf->rect_float == NULL || buffer == NULL)
573                 return;
574
575         /* create byte rect if it didn't exist yet */
576         if (ibuf->rect == NULL)
577                 imb_addrectImBuf(ibuf);
578
579         /* do conversion */
580         rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
581         rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4;
582
583         IMB_buffer_float_from_float(buffer, rect_float,
584                                     ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
585                                     w, h, w, ibuf->x);
586
587         /* XXX: need to convert to image buffer's rect space */
588         IMB_buffer_byte_from_float(rect_byte, buffer,
589                                    4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
590                                    w, h, ibuf->x, w);
591
592         /* ensure user flag is reset */
593         ibuf->userflags &= ~IB_RECT_INVALID;
594 }
595
596 void IMB_float_from_rect(ImBuf *ibuf)
597 {
598         int predivide = (ibuf->flags & IB_cm_predivide);
599
600         /* verify if we byte and float buffers */
601         if (ibuf->rect == NULL)
602                 return;
603
604         /* lock the color management thread
605          * need this because allocated but not filled float buffer will confuse
606          * display transform which lead to black areas across the frame
607          */
608         BLI_lock_thread(LOCK_COLORMANAGE);
609
610         if (ibuf->rect_float == NULL) {
611                 if (imb_addrectfloatImBuf(ibuf) == 0) {
612                         BLI_unlock_thread(LOCK_COLORMANAGE);
613
614                         return;
615                 }
616         }
617
618         /* first, create float buffer in non-linear space */
619         IMB_buffer_float_from_byte(ibuf->rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
620                                    FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
621
622         /* then make float be in linear space */
623         IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
624                                                        ibuf->rect_colorspace, predivide);
625
626         BLI_unlock_thread(LOCK_COLORMANAGE);
627 }
628
629 /* no profile conversion */
630 void IMB_float_from_rect_simple(ImBuf *ibuf)
631 {
632         int predivide = (ibuf->flags & IB_cm_predivide);
633
634         if (ibuf->rect_float == NULL)
635                 imb_addrectfloatImBuf(ibuf);
636
637         IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
638                                    IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
639                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
640 }
641
642 /* use when you need to get a buffer with a certain profile
643  * if the return  */
644
645 /* OCIO_TODO: used only by Cineon/DPX exporter which is still broken, so can not guarantee
646  *            this function is working properly
647  */
648 float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
649 {
650         int predivide = (ibuf->flags & IB_cm_predivide);
651         int profile_from = IB_PROFILE_LINEAR_RGB;
652         int profile_to;
653
654         /* determine profile */
655         if (profile == IB_PROFILE_NONE)
656                 profile_to = IB_PROFILE_LINEAR_RGB;
657         else
658                 profile_to = IB_PROFILE_SRGB;
659         
660         if (profile_from == profile_to) {
661                 /* simple case, just allocate the buffer and return */
662                 *alloc = 0;
663
664                 if (ibuf->rect_float == NULL)
665                         IMB_float_from_rect(ibuf);
666
667                 return ibuf->rect_float;
668         }
669         else {
670                 /* conversion is needed, first check */
671                 float *fbuf = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "IMB_float_profile_ensure");
672                 *alloc = 1;
673
674                 if (ibuf->rect_float == NULL) {
675                         IMB_buffer_float_from_byte(fbuf, (uchar *)ibuf->rect,
676                                                    profile_to, profile_from, predivide,
677                                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
678                 }
679                 else {
680                         IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
681                                                     4, profile_to, profile_from, predivide,
682                                                     ibuf->x, ibuf->y, ibuf->x, ibuf->x);
683                 }
684
685                 return fbuf;
686         }
687 }
688
689 /**************************** Color to Grayscale *****************************/
690
691 /* no profile conversion */
692 void IMB_color_to_bw(ImBuf *ibuf)
693 {
694         float *rctf = ibuf->rect_float;
695         uchar *rct = (uchar *)ibuf->rect;
696         int i;
697
698         if (rctf) {
699                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4)
700                         rctf[0] = rctf[1] = rctf[2] = rgb_to_grayscale(rctf);
701         }
702
703         if (rct) {
704                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4)
705                         rct[0] = rct[1] = rct[2] = rgb_to_grayscale_byte(rct);
706         }
707 }
708
709 void IMB_buffer_float_clamp(float *buf, int width, int height)
710 {
711         int i, total = width * height * 4;
712         for (i = 0; i < total; i++) {
713                 buf[i] = minf(1.0, buf[i]);
714         }
715 }
716
717 /**************************** alter saturation *****************************/
718
719 void IMB_saturation(ImBuf *ibuf, float sat)
720 {
721         int i;
722         unsigned char *rct = (unsigned char *)ibuf->rect;
723         float *rctf = ibuf->rect_float;
724         float hsv[3];
725
726         if (rct) {
727                 float rgb[3];
728                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) {
729                         rgb_uchar_to_float(rgb, rct);
730                         rgb_to_hsv_v(rgb, hsv);
731                         hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
732                         rgb_float_to_uchar(rct, rgb);
733                 }
734         }
735
736         if (rctf) {
737                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4) {
738                         rgb_to_hsv_v(rctf, hsv);
739                         hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf + 1, rctf + 2);
740                 }
741         }
742 }