svn merge ^/trunk/blender -r42920:42927
[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 "BKE_colortools.h"
46
47 #include "MEM_guardedalloc.h"
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
104 /* assume converting from linear float to sRGB byte */
105 void IMB_rect_from_float(struct ImBuf *ibuf)
106 {
107         /* quick method to convert floatbuf to byte */
108         float *tof = (float *)ibuf->rect_float;
109 //      int do_dither = ibuf->dither != 0.f;
110         float dither= ibuf->dither / 255.0f;
111         float srgb[4];
112         int i, channels= ibuf->channels;
113         short profile= ibuf->profile;
114         unsigned char *to = (unsigned char *) ibuf->rect;
115         
116         if(tof==NULL) return;
117         if(to==NULL) {
118                 imb_addrectImBuf(ibuf);
119                 to = (unsigned char *) ibuf->rect;
120         }
121         
122         if(channels==1) {
123                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++)
124                         to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]);
125         }
126         else if (profile == IB_PROFILE_LINEAR_RGB) {
127                 if(channels == 3) {
128                         for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
129                                 srgb[0]= linearrgb_to_srgb(tof[0]);
130                                 srgb[1]= linearrgb_to_srgb(tof[1]);
131                                 srgb[2]= linearrgb_to_srgb(tof[2]);
132
133                                 to[0] = FTOCHAR(srgb[0]);
134                                 to[1] = FTOCHAR(srgb[1]);
135                                 to[2] = FTOCHAR(srgb[2]);
136                                 to[3] = 255;
137                         }
138                 }
139                 else if (channels == 4) {
140                         if (dither != 0.f) {
141                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
142                                         const float d = (BLI_frand()-0.5f)*dither;
143                                         
144                                         srgb[0]= d + linearrgb_to_srgb(tof[0]);
145                                         srgb[1]= d + linearrgb_to_srgb(tof[1]);
146                                         srgb[2]= d + linearrgb_to_srgb(tof[2]);
147                                         srgb[3]= d + tof[3]; 
148                                         
149                                         to[0] = FTOCHAR(srgb[0]);
150                                         to[1] = FTOCHAR(srgb[1]);
151                                         to[2] = FTOCHAR(srgb[2]);
152                                         to[3] = FTOCHAR(srgb[3]);
153                                 }
154                         } else {
155                                 floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x);
156                         }
157                 }
158         }
159         else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
160                 if(channels==3) {
161                         for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
162                                 to[0] = FTOCHAR(tof[0]);
163                                 to[1] = FTOCHAR(tof[1]);
164                                 to[2] = FTOCHAR(tof[2]);
165                                 to[3] = 255;
166                         }
167                 }
168                 else {
169                         if (dither != 0.f) {
170                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
171                                         const float d = (BLI_frand()-0.5f)*dither;
172                                         float col[4];
173
174                                         col[0]= d + tof[0];
175                                         col[1]= d + tof[1];
176                                         col[2]= d + tof[2];
177                                         col[3]= d + tof[3];
178
179                                         to[0] = FTOCHAR(col[0]);
180                                         to[1] = FTOCHAR(col[1]);
181                                         to[2] = FTOCHAR(col[2]);
182                                         to[3] = FTOCHAR(col[3]);
183                                 }
184                         } else {
185                                 for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
186                                         to[0] = FTOCHAR(tof[0]);
187                                         to[1] = FTOCHAR(tof[1]);
188                                         to[2] = FTOCHAR(tof[2]);
189                                         to[3] = FTOCHAR(tof[3]);
190                                 }
191                         }
192                 }
193         }
194         /* ensure user flag is reset */
195         ibuf->userflags &= ~IB_RECT_INVALID;
196 }
197
198  
199
200 /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
201 void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h)
202 {
203         /* indices to source and destination image pixels */
204         float *srcFloatPxl;
205         unsigned char *dstBytePxl;
206         /* buffer index will fill buffer */
207         float *bufferIndex;
208
209         /* convenience pointers to start of image buffers */
210         float *init_srcFloatPxl = (float *)ibuf->rect_float;
211         unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect;
212
213         /* Dithering factor */
214         float dither= ibuf->dither / 255.0f;
215         /* respective attributes of image */
216         short profile= ibuf->profile;
217         int channels= ibuf->channels;
218         
219         int i, j;
220         
221         /*
222                 if called -only- from GPU_paint_update_image this test will never fail
223                 but leaving it here for better or worse
224         */
225         if(init_srcFloatPxl==NULL || (buffer == NULL)){
226                 return;
227         }
228         if(init_dstBytePxl==NULL) {
229                 imb_addrectImBuf(ibuf);
230                 init_dstBytePxl = (unsigned char *) ibuf->rect;
231         }
232         if(channels==1) {
233                         for (j = 0; j < h; j++){
234                                 bufferIndex = buffer + w*j*4;
235                                 dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
236                                 srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x);
237                                 for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) {
238                                         dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]);
239                                         bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0];
240                                 }
241                         }
242         }
243         else if (profile == IB_PROFILE_LINEAR_RGB) {
244                 if(channels == 3) {
245                         for (j = 0; j < h; j++){
246                                 bufferIndex = buffer + w*j*4;
247                                 dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
248                                 srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
249                                 for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) {
250                                         linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
251                                         F3TOCHAR4(bufferIndex, dstBytePxl);
252                                         bufferIndex[3]= 1.0;
253                                 }
254                         }
255                 }
256                 else if (channels == 4) {
257                         if (dither != 0.f) {
258                                 for (j = 0; j < h; j++){
259                                         bufferIndex = buffer + w*j*4;
260                                         dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
261                                         srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
262                                         for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
263                                                 const float d = (BLI_frand()-0.5f)*dither;
264                                                 linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
265                                                 bufferIndex[3] = srcFloatPxl[3];
266                                                 add_v4_fl(bufferIndex, d);
267                                                 F4TOCHAR4(bufferIndex, dstBytePxl);
268                                         }
269                                 }
270                         } else {
271                                 for (j = 0; j < h; j++){
272                                         bufferIndex = buffer + w*j*4;
273                                         dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
274                                         srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
275                                         for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
276                                                 linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
277                                                 bufferIndex[3]= srcFloatPxl[3];
278                                                 F4TOCHAR4(bufferIndex, dstBytePxl);
279                                         }
280                                 }
281                         }
282                 }
283         }
284         else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
285                 if(channels==3) {
286                         for (j = 0; j < h; j++){
287                                 bufferIndex = buffer + w*j*4;
288                                 dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
289                                 srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
290                                 for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) {
291                                         copy_v3_v3(bufferIndex, srcFloatPxl);
292                                         F3TOCHAR4(bufferIndex, dstBytePxl);
293                                         bufferIndex[3] = 1.0;
294                                 }
295                         }
296                 }
297                 else {
298                         if (dither != 0.f) {
299                                 for (j = 0; j < h; j++){
300                                         bufferIndex = buffer + w*j*4;
301                                         dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
302                                         srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
303                                         for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
304                                                 const float d = (BLI_frand()-0.5f)*dither;
305                                                 copy_v4_v4(bufferIndex, srcFloatPxl);
306                                                 add_v4_fl(bufferIndex,d);
307                                                 F4TOCHAR4(bufferIndex, dstBytePxl);
308                                         }
309                                 }
310                         } else {
311                                 for (j = 0; j < h; j++){
312                                         bufferIndex = buffer + w*j*4;
313                                         dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
314                                         srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
315                                         for(i = 0;  i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
316                                                 copy_v4_v4(bufferIndex, srcFloatPxl);
317                                                 F4TOCHAR4(bufferIndex, dstBytePxl);
318                                         }
319                                 }
320                         }
321                 }
322         }
323         /* ensure user flag is reset */
324         ibuf->userflags &= ~IB_RECT_INVALID;
325 }
326
327 static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf)
328 {
329         float *tof = fbuf;
330         int i;
331         unsigned char *to = (unsigned char *) ibuf->rect;
332
333         for (i = ibuf->x * ibuf->y; i > 0; i--) 
334         {
335                 tof[0] = ((float)to[0])*(1.0f/255.0f);
336                 tof[1] = ((float)to[1])*(1.0f/255.0f);
337                 tof[2] = ((float)to[2])*(1.0f/255.0f);
338                 tof[3] = ((float)to[3])*(1.0f/255.0f);
339                 to += 4; 
340                 tof += 4;
341         }
342 }
343
344
345 static void imb_float_from_rect_linear(struct ImBuf *ibuf, float *fbuf)
346 {
347         float *tof = fbuf;
348         int i;
349         unsigned char *to = (unsigned char *) ibuf->rect;
350
351         for (i = ibuf->x * ibuf->y; i > 0; i--) 
352         {
353                 tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f));
354                 tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f));
355                 tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f));
356                 tof[3] = ((float)to[3])*(1.0f/255.0f);
357                 to += 4; 
358                 tof += 4;
359         }
360 }
361
362 void IMB_float_from_rect(struct ImBuf *ibuf)
363 {
364         /* quick method to convert byte to floatbuf */
365         if(ibuf->rect==NULL) return;
366         if(ibuf->rect_float==NULL) {
367                 if (imb_addrectfloatImBuf(ibuf) == 0) return;
368         }
369         
370         /* Float bufs should be stored linear */
371
372         if (ibuf->profile != IB_PROFILE_NONE) {
373                 /* if the image has been given a profile then we're working 
374                  * with color management in mind, so convert it to linear space */
375                 imb_float_from_rect_linear(ibuf, ibuf->rect_float);
376         } else {
377                 imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
378         }
379 }
380
381 /* no profile conversion */
382 void IMB_float_from_rect_simple(struct ImBuf *ibuf)
383 {
384         if(ibuf->rect_float==NULL)
385                 imb_addrectfloatImBuf(ibuf);
386         imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
387 }
388
389 void IMB_convert_profile(struct ImBuf *ibuf, int profile)
390 {
391         int ok= FALSE;
392         int i;
393
394         unsigned char *rct= (unsigned char *)ibuf->rect;
395         float *rctf= ibuf->rect_float;
396
397         if(ibuf->profile == profile)
398                 return;
399
400         if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */
401                 if(profile == IB_PROFILE_LINEAR_RGB) { /* to */
402                         if(ibuf->rect_float) {
403                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
404                                         rctf[0]= srgb_to_linearrgb(rctf[0]);
405                                         rctf[1]= srgb_to_linearrgb(rctf[1]);
406                                         rctf[2]= srgb_to_linearrgb(rctf[2]);
407                                 }
408                         }
409                         if(ibuf->rect) {
410                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
411                                         rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
412                                         rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
413                                         rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
414                                 }
415                         }
416                         ok= TRUE;
417                 }
418         }
419         else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */
420                 if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */
421                         if(ibuf->rect_float) {
422                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
423                                         rctf[0]= linearrgb_to_srgb(rctf[0]);
424                                         rctf[1]= linearrgb_to_srgb(rctf[1]);
425                                         rctf[2]= linearrgb_to_srgb(rctf[2]);
426                                 }
427                         }
428                         if(ibuf->rect) {
429                                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
430                                         rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
431                                         rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
432                                         rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
433                                 }
434                         }
435                         ok= TRUE;
436                 }
437         }
438
439         if(ok==FALSE){
440                 printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile);
441                 return;
442         }
443
444         ibuf->profile= profile;
445 }
446
447 /* use when you need to get a buffer with a certain profile
448  * if the return  */
449 float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc)
450 {
451         /* stupid but it works like this everywhere now */
452         const short is_lin_from= (ibuf->profile != IB_PROFILE_NONE);
453         const short is_lin_to= (profile != IB_PROFILE_NONE);
454
455         
456         if(is_lin_from == is_lin_to) {
457                 *alloc= 0;
458
459                 /* simple case, just allocate the buffer and return */
460                 if(ibuf->rect_float == NULL) {
461                         IMB_float_from_rect(ibuf);
462                 }
463
464                 return ibuf->rect_float;
465         }
466         else {
467                 /* conversion is needed, first check */
468                 float *fbuf= MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "IMB_float_profile_ensure");
469                 *alloc= 1;
470
471                 if(ibuf->rect_float == NULL) {
472                         if(is_lin_to) {
473                                 imb_float_from_rect_linear(ibuf, fbuf);
474                         }
475                         else {
476                                 imb_float_from_rect_nonlinear(ibuf, fbuf);
477                         }
478                 }
479                 else {
480                         if(is_lin_to) { /* lin -> nonlin */
481                                 linearrgb_to_srgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
482                         }
483                         else { /* nonlin -> lin */
484                                 srgb_to_linearrgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
485                         }
486                 }
487
488                 return fbuf;
489         }
490 }
491
492
493 /* no profile conversion */
494 void IMB_color_to_bw(struct ImBuf *ibuf)
495 {
496         float *rctf= ibuf->rect_float;
497         unsigned char *rct= (unsigned char *)ibuf->rect;
498         int i;
499         if(rctf) {
500                 for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
501                         rctf[0]= rctf[1]= rctf[2]= rgb_to_grayscale(rctf);
502                 }
503         }
504
505         if(rct) {
506                 for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
507                         rct[0]= rct[1]= rct[2]= rgb_to_grayscale_byte(rct);
508                 }
509         }
510 }