Merging r50237 through r50240 from 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_filter.h"
42 #include "IMB_allocimbuf.h"
43
44 #include "MEM_guardedalloc.h"
45
46 #ifdef WITH_OCIO
47 #include <ocio_capi.h>
48 #endif
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 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_tonecurve(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                                           imb_tonecurveCb tonecurve_func)
197 {
198         float tmp[4];
199         float corrected[4];
200         int x, y;
201         DitherContext *di;
202
203         /* we need valid profiles */
204         BLI_assert(profile_to != IB_PROFILE_NONE);
205         BLI_assert(profile_from != IB_PROFILE_NONE);
206
207         if (dither)
208                 di = create_dither_context(width, dither);
209
210         if (!tonecurve_func)
211                 tonecurve_func = copy_v3_v3;
212
213         for (y = 0; y < height; y++) {
214                 if (channels_from == 1) {
215                         /* single channel input */
216                         const float *from = rect_from + stride_from * y;
217                         uchar *to = rect_to + stride_to * y * 4;
218
219                         for (x = 0; x < width; x++, from++, to += 4)
220                                 to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
221                 }
222                 else if (channels_from == 3) {
223                         /* RGB input */
224                         const float *from = rect_from + stride_from * y * 3;
225                         uchar *to = rect_to + stride_to * y * 4;
226
227                         if (profile_to == profile_from) {
228                                 /* no color space conversion */
229                                 for (x = 0; x < width; x++, from += 3, to += 4) {
230                                         rgb_float_to_uchar(to, from);
231                                         to[3] = 255;
232                                 }
233                         }
234                         else if (profile_to == IB_PROFILE_SRGB) {
235                                 /* convert from linear to sRGB */
236                                 for (x = 0; x < width; x++, from += 3, to += 4) {
237                                         tonecurve_func(corrected, from);
238                                         linearrgb_to_srgb_v3_v3(tmp, corrected);
239                                         rgb_float_to_uchar(to, tmp);
240                                         to[3] = 255;
241                                 }
242                         }
243                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
244                                 /* convert from sRGB to linear */
245                                 for (x = 0; x < width; x++, from += 3, to += 4) {
246                                         srgb_to_linearrgb_v3_v3(tmp, from);
247                                         rgb_float_to_uchar(to, tmp);
248                                         to[3] = 255;
249                                 }
250                         }
251                 }
252                 else if (channels_from == 4) {
253                         /* RGBA input */
254                         const float *from = rect_from + stride_from * y * 4;
255                         uchar *to = rect_to + stride_to * y * 4;
256
257                         if (profile_to == profile_from) {
258                                 /* no color space conversion */
259                                 if (dither) {
260                                         for (x = 0; x < width; x++, from += 4, to += 4)
261                                                 float_to_byte_dither_v4(to, from, di);
262                                 }
263                                 else {
264                                         for (x = 0; x < width; x++, from += 4, to += 4)
265                                                 rgba_float_to_uchar(to, from);
266                                 }
267                         }
268                         else if (profile_to == IB_PROFILE_SRGB) {
269                                 /* convert from linear to sRGB */
270                                 unsigned short us[4];
271
272                                 if (dither && predivide) {
273                                         for (x = 0; x < width; x++, from += 4, to += 4) {
274                                                 tonecurve_func(corrected, from);
275                                                 corrected[3] = from[3];
276
277                                                 linearrgb_to_srgb_ushort4_predivide(us, corrected);
278                                                 ushort_to_byte_dither_v4(to, us, di);
279                                         }
280                                 }
281                                 else if (dither) {
282                                         for (x = 0; x < width; x++, from += 4, to += 4) {
283                                                 tonecurve_func(corrected, from);
284                                                 corrected[3] = from[3];
285
286                                                 linearrgb_to_srgb_ushort4(us, corrected);
287                                                 ushort_to_byte_dither_v4(to, us, di);
288                                         }
289                                 }
290                                 else if (predivide) {
291                                         for (x = 0; x < width; x++, from += 4, to += 4) {
292                                                 tonecurve_func(corrected, from);
293                                                 corrected[3] = from[3];
294
295                                                 linearrgb_to_srgb_ushort4_predivide(us, corrected);
296                                                 ushort_to_byte_v4(to, us);
297                                         }
298                                 }
299                                 else {
300                                         for (x = 0; x < width; x++, from += 4, to += 4) {
301                                                 tonecurve_func(corrected, from);
302                                                 corrected[3] = from[3];
303
304                                                 linearrgb_to_srgb_ushort4(us, corrected);
305                                                 ushort_to_byte_v4(to, us);
306                                         }
307                                 }
308                         }
309                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
310                                 /* convert from sRGB to linear */
311                                 if (dither && predivide) {
312                                         for (x = 0; x < width; x++, from += 4, to += 4) {
313                                                 srgb_to_linearrgb_predivide_v4(tmp, from);
314                                                 float_to_byte_dither_v4(to, tmp, di);
315                                         }
316                                 }
317                                 else if (dither) {
318                                         for (x = 0; x < width; x++, from += 4, to += 4) {
319                                                 srgb_to_linearrgb_v4(tmp, from);
320                                                 float_to_byte_dither_v4(to, tmp, di);
321                                         }
322                                 }
323                                 else if (predivide) {
324                                         for (x = 0; x < width; x++, from += 4, to += 4) {
325                                                 srgb_to_linearrgb_predivide_v4(tmp, from);
326                                                 rgba_float_to_uchar(to, tmp);
327                                         }
328                                 }
329                                 else {
330                                         for (x = 0; x < width; x++, from += 4, to += 4) {
331                                                 srgb_to_linearrgb_v4(tmp, from);
332                                                 rgba_float_to_uchar(to, tmp);
333                                         }
334                                 }
335                         }
336                 }
337
338                 if (dither)
339                         dither_finish_row(di);
340         }
341
342         if (dither)
343                 clear_dither_context(di);
344 }
345
346 void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
347                                 int channels_from, float dither, int profile_to, int profile_from, int predivide,
348                                 int width, int height, int stride_to, int stride_from)
349 {
350         IMB_buffer_byte_from_float_tonecurve(rect_to, rect_from, channels_from, dither, profile_to, profile_from, predivide,
351                                              width, height, stride_to, stride_from, NULL);
352 }
353
354
355 /* byte to float pixels, input and output 4-channel RGBA  */
356 void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
357                                 int profile_to, int profile_from, int predivide,
358                                 int width, int height, int stride_to, int stride_from)
359 {
360         float tmp[4];
361         int x, y;
362
363         /* we need valid profiles */
364         BLI_assert(profile_to != IB_PROFILE_NONE);
365         BLI_assert(profile_from != IB_PROFILE_NONE);
366
367         /* RGBA input */
368         for (y = 0; y < height; y++) {
369                 const uchar *from = rect_from + stride_from * y * 4;
370                 float *to = rect_to + stride_to * y * 4;
371
372                 if (profile_to == profile_from) {
373                         /* no color space conversion */
374                         for (x = 0; x < width; x++, from += 4, to += 4)
375                                 rgba_uchar_to_float(to, from);
376                 }
377                 else if (profile_to == IB_PROFILE_LINEAR_RGB) {
378                         /* convert sRGB to linear */
379                         if (predivide) {
380                                 for (x = 0; x < width; x++, from += 4, to += 4) {
381                                         srgb_to_linearrgb_uchar4_predivide(to, from);
382                                 }
383                         }
384                         else {
385                                 for (x = 0; x < width; x++, from += 4, to += 4) {
386                                         srgb_to_linearrgb_uchar4(to, from);
387                                 }
388                         }
389                 }
390                 else if (profile_to == IB_PROFILE_SRGB) {
391                         /* convert linear to sRGB */
392                         if (predivide) {
393                                 for (x = 0; x < width; x++, from += 4, to += 4) {
394                                         rgba_uchar_to_float(tmp, from);
395                                         linearrgb_to_srgb_predivide_v4(to, tmp);
396                                 }
397                         }
398                         else {
399                                 for (x = 0; x < width; x++, from += 4, to += 4) {
400                                         rgba_uchar_to_float(tmp, from);
401                                         linearrgb_to_srgb_v4(to, tmp);
402                                 }
403                         }
404                 }
405         }
406 }
407
408 /* float to float pixels, output 4-channel RGBA */
409 void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
410                                  int channels_from, int profile_to, int profile_from, int predivide,
411                                  int width, int height, int stride_to, int stride_from)
412 {
413         int x, y;
414
415         /* we need valid profiles */
416         BLI_assert(profile_to != IB_PROFILE_NONE);
417         BLI_assert(profile_from != IB_PROFILE_NONE);
418
419         if (channels_from == 1) {
420                 /* single channel input */
421                 for (y = 0; y < height; y++) {
422                         const float *from = rect_from + stride_from * y;
423                         float *to = rect_to + stride_to * y * 4;
424
425                         for (x = 0; x < width; x++, from++, to += 4)
426                                 to[0] = to[1] = to[2] = to[3] = from[0];
427                 }
428         }
429         else if (channels_from == 3) {
430                 /* RGB input */
431                 for (y = 0; y < height; y++) {
432                         const float *from = rect_from + stride_from * y * 3;
433                         float *to = rect_to + stride_to * y * 4;
434
435                         if (profile_to == profile_from) {
436                                 /* no color space conversion */
437                                 for (x = 0; x < width; x++, from += 3, to += 4) {
438                                         copy_v3_v3(to, from);
439                                         to[3] = 1.0f;
440                                 }
441                         }
442                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
443                                 /* convert from sRGB to linear */
444                                 for (x = 0; x < width; x++, from += 3, to += 4) {
445                                         srgb_to_linearrgb_v3_v3(to, from);
446                                         to[3] = 1.0f;
447                                 }
448                         }
449                         else if (profile_to == IB_PROFILE_SRGB) {
450                                 /* convert from linear to sRGB */
451                                 for (x = 0; x < width; x++, from += 3, to += 4) {
452                                         linearrgb_to_srgb_v3_v3(to, from);
453                                         to[3] = 1.0f;
454                                 }
455                         }
456                 }
457         }
458         else if (channels_from == 4) {
459                 /* RGBA input */
460                 for (y = 0; y < height; y++) {
461                         const float *from = rect_from + stride_from * y * 4;
462                         float *to = rect_to + stride_to * y * 4;
463
464                         if (profile_to == profile_from) {
465                                 /* same profile, copy */
466                                 memcpy(to, from, sizeof(float) * 4 * width);
467                         }
468                         else if (profile_to == IB_PROFILE_LINEAR_RGB) {
469                                 /* convert to sRGB to linear */
470                                 if (predivide) {
471                                         for (x = 0; x < width; x++, from += 4, to += 4)
472                                                 srgb_to_linearrgb_predivide_v4(to, from);
473                                 }
474                                 else {
475                                         for (x = 0; x < width; x++, from += 4, to += 4)
476                                                 srgb_to_linearrgb_v4(to, from);
477                                 }
478                         }
479                         else if (profile_to == IB_PROFILE_SRGB) {
480                                 /* convert from linear to sRGB */
481                                 if (predivide) {
482                                         for (x = 0; x < width; x++, from += 4, to += 4)
483                                                 linearrgb_to_srgb_predivide_v4(to, from);
484                                 }
485                                 else {
486                                         for (x = 0; x < width; x++, from += 4, to += 4)
487                                                 linearrgb_to_srgb_v4(to, from);
488                                 }
489                         }
490                 }
491         }
492 }
493
494 /* byte to byte pixels, input and output 4-channel RGBA */
495 void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
496                                int profile_to, int profile_from, int predivide,
497                                int width, int height, int stride_to, int stride_from)
498 {
499         float tmp[4];
500         int x, y;
501
502         /* we need valid profiles */
503         BLI_assert(profile_to != IB_PROFILE_NONE);
504         BLI_assert(profile_from != IB_PROFILE_NONE);
505
506         /* always RGBA input */
507         for (y = 0; y < height; y++) {
508                 const uchar *from = rect_from + stride_from * y * 4;
509                 uchar *to = rect_to + stride_to * y * 4;
510
511                 if (profile_to == profile_from) {
512                         /* same profile, copy */
513                         memcpy(to, from, sizeof(uchar) * 4 * width);
514                 }
515                 else if (profile_to == IB_PROFILE_LINEAR_RGB) {
516                         /* convert to sRGB to linear */
517                         if (predivide) {
518                                 for (x = 0; x < width; x++, from += 4, to += 4) {
519                                         rgba_uchar_to_float(tmp, from);
520                                         srgb_to_linearrgb_predivide_v4(tmp, tmp);
521                                         rgba_float_to_uchar(to, tmp);
522                                 }
523                         }
524                         else {
525                                 for (x = 0; x < width; x++, from += 4, to += 4) {
526                                         rgba_uchar_to_float(tmp, from);
527                                         srgb_to_linearrgb_v4(tmp, tmp);
528                                         rgba_float_to_uchar(to, tmp);
529                                 }
530                         }
531                 }
532                 else if (profile_to == IB_PROFILE_SRGB) {
533                         /* convert from linear to sRGB */
534                         if (predivide) {
535                                 for (x = 0; x < width; x++, from += 4, to += 4) {
536                                         rgba_uchar_to_float(tmp, from);
537                                         linearrgb_to_srgb_predivide_v4(tmp, tmp);
538                                         rgba_float_to_uchar(to, tmp);
539                                 }
540                         }
541                         else {
542                                 for (x = 0; x < width; x++, from += 4, to += 4) {
543                                         rgba_uchar_to_float(tmp, from);
544                                         linearrgb_to_srgb_v4(tmp, tmp);
545                                         rgba_float_to_uchar(to, tmp);
546                                 }
547                         }
548                 }
549         }
550 }
551
552 /****************************** ImBuf Conversion *****************************/
553
554 void IMB_rect_from_float(ImBuf *ibuf)
555 {
556         int predivide = (ibuf->flags & IB_cm_predivide);
557         int profile_from;
558
559         /* verify we have a float buffer */
560         if (ibuf->rect_float == NULL)
561                 return;
562
563         /* create byte rect if it didn't exist yet */
564         if (ibuf->rect == NULL)
565                 imb_addrectImBuf(ibuf);
566
567         /* determine profiles */
568         if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
569                 profile_from = IB_PROFILE_LINEAR_RGB;
570         }
571         else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) {
572                 profile_from = IB_PROFILE_SRGB;
573         }
574         else {
575                 profile_from = IB_PROFILE_SRGB; /* should never happen */
576                 BLI_assert(0);
577         }
578
579         /* do conversion */
580         IMB_buffer_byte_from_float((uchar *)ibuf->rect, ibuf->rect_float,
581                                    ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
582                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
583
584         /* ensure user flag is reset */
585         ibuf->userflags &= ~IB_RECT_INVALID;
586 }
587
588 /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
589 void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
590 {
591         float *rect_float;
592         uchar *rect_byte;
593         int predivide = (ibuf->flags & IB_cm_predivide);
594         int profile_from;
595
596         /* verify we have a float buffer */
597         if (ibuf->rect_float == NULL || buffer == NULL)
598                 return;
599
600         /* create byte rect if it didn't exist yet */
601         if (ibuf->rect == NULL)
602                 imb_addrectImBuf(ibuf);
603
604         /* determine profiles */
605         if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
606                 profile_from = IB_PROFILE_LINEAR_RGB;
607         }
608         else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) {
609                 profile_from = IB_PROFILE_SRGB;
610         }
611         else {
612                 profile_from = IB_PROFILE_SRGB; /* should never happen */
613                 BLI_assert(0);
614         }
615
616         /* do conversion */
617         rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
618         rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4;
619
620         IMB_buffer_float_from_float(buffer, rect_float,
621                                     ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
622                                     w, h, w, ibuf->x);
623
624         IMB_buffer_byte_from_float(rect_byte, buffer,
625                                    4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
626                                    w, h, ibuf->x, w);
627
628         /* ensure user flag is reset */
629         ibuf->userflags &= ~IB_RECT_INVALID;
630 }
631
632 void IMB_float_from_rect(ImBuf *ibuf)
633 {
634         int predivide = (ibuf->flags & IB_cm_predivide);
635         int profile_from;
636
637         /* verify if we byte and float buffers */
638         if (ibuf->rect == NULL)
639                 return;
640
641         if (ibuf->rect_float == NULL)
642                 if (imb_addrectfloatImBuf(ibuf) == 0)
643                         return;
644         
645         /* determine profiles */
646         if (ibuf->profile == IB_PROFILE_NONE)
647                 profile_from = IB_PROFILE_LINEAR_RGB;
648         else
649                 profile_from = IB_PROFILE_SRGB;
650         
651         /* do conversion */
652         IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
653                                    IB_PROFILE_LINEAR_RGB, profile_from, predivide,
654                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
655 }
656
657 /* no profile conversion */
658 void IMB_float_from_rect_simple(ImBuf *ibuf)
659 {
660         int predivide = (ibuf->flags & IB_cm_predivide);
661
662         if (ibuf->rect_float == NULL)
663                 imb_addrectfloatImBuf(ibuf);
664
665         IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
666                                    IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
667                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
668 }
669
670 void IMB_convert_profile(ImBuf *ibuf, int profile)
671 {
672         int predivide = (ibuf->flags & IB_cm_predivide);
673         int profile_from, profile_to;
674
675         if (ibuf->profile == profile)
676                 return;
677
678         /* determine profiles */
679         if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
680                 profile_from = IB_PROFILE_LINEAR_RGB;
681         else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
682                 profile_from = IB_PROFILE_SRGB;
683         else {
684                 BLI_assert(0);
685                 profile_from = IB_PROFILE_SRGB; /* dummy, should never happen */
686         }
687
688         if (profile == IB_PROFILE_LINEAR_RGB)
689                 profile_to = IB_PROFILE_LINEAR_RGB;
690         else if (ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
691                 profile_to = IB_PROFILE_SRGB;
692         else {
693                 BLI_assert(0);
694                 profile_to = IB_PROFILE_SRGB; /* dummy, should never happen */
695         }
696         
697         /* do conversion */
698         if (ibuf->rect_float) {
699                 IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float,
700                                             4, profile_to, profile_from, predivide,
701                                             ibuf->x, ibuf->y, ibuf->x, ibuf->x);
702         }
703
704         if (ibuf->rect) {
705                 IMB_buffer_byte_from_byte((uchar *)ibuf->rect, (uchar *)ibuf->rect,
706                                           profile_to, profile_from, predivide,
707                                           ibuf->x, ibuf->y, ibuf->x, ibuf->x);
708         }
709
710         /* set new profile */
711         ibuf->profile = profile;
712 }
713
714 /* use when you need to get a buffer with a certain profile
715  * if the return  */
716 float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
717 {
718         int predivide = (ibuf->flags & IB_cm_predivide);
719         int profile_from, profile_to;
720
721         /* determine profiles */
722         if (ibuf->profile == IB_PROFILE_NONE)
723                 profile_from = IB_PROFILE_LINEAR_RGB;
724         else
725                 profile_from = IB_PROFILE_SRGB;
726
727         if (profile == IB_PROFILE_NONE)
728                 profile_to = IB_PROFILE_LINEAR_RGB;
729         else
730                 profile_to = IB_PROFILE_SRGB;
731         
732         if (profile_from == profile_to) {
733                 /* simple case, just allocate the buffer and return */
734                 *alloc = 0;
735
736                 if (ibuf->rect_float == NULL)
737                         IMB_float_from_rect(ibuf);
738
739                 return ibuf->rect_float;
740         }
741         else {
742                 /* conversion is needed, first check */
743                 float *fbuf = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "IMB_float_profile_ensure");
744                 *alloc = 1;
745
746                 if (ibuf->rect_float == NULL) {
747                         IMB_buffer_float_from_byte(fbuf, (uchar *)ibuf->rect,
748                                                    profile_to, profile_from, predivide,
749                                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
750                 }
751                 else {
752                         IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
753                                                     4, profile_to, profile_from, predivide,
754                                                     ibuf->x, ibuf->y, ibuf->x, ibuf->x);
755                 }
756
757                 return fbuf;
758         }
759 }
760
761 /**************************** Color to Grayscale *****************************/
762
763 /* no profile conversion */
764 void IMB_color_to_bw(ImBuf *ibuf)
765 {
766         float *rctf = ibuf->rect_float;
767         uchar *rct = (uchar *)ibuf->rect;
768         int i;
769
770         if (rctf) {
771                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4)
772                         rctf[0] = rctf[1] = rctf[2] = rgb_to_grayscale(rctf);
773         }
774
775         if (rct) {
776                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4)
777                         rct[0] = rct[1] = rct[2] = rgb_to_grayscale_byte(rct);
778         }
779 }
780
781 void IMB_buffer_float_clamp(float *buf, int width, int height)
782 {
783         int i, total = width * height * 4;
784         for (i = 0; i < total; i++) {
785                 buf[i] = minf(1.0, buf[i]);
786         }
787 }
788
789 /**************************** alter saturation *****************************/
790
791 void IMB_saturation(ImBuf *ibuf, float sat)
792 {
793         int i;
794         unsigned char *rct = (unsigned char *)ibuf->rect;
795         float *rctf = ibuf->rect_float;
796         float hsv[3];
797
798         if (rct) {
799                 float rgb[3];
800                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) {
801                         rgb_uchar_to_float(rgb, rct);
802                         rgb_to_hsv_v(rgb, hsv);
803                         hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
804                         rgb_float_to_uchar(rct, rgb);
805                 }
806         }
807
808         if (rctf) {
809                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4) {
810                         rgb_to_hsv_v(rctf, hsv);
811                         hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf + 1, rctf + 2);
812                 }
813         }
814 }