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