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