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