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