844478e03cb659c29761cc40cf56cc3562319b6e
[blender.git] / source / blender / imbuf / intern / rectop.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * allocimbuf.c
28  *
29  * $Id$
30  */
31
32 /** \file blender/imbuf/intern/rectop.c
33  *  \ingroup imbuf
34  */
35
36
37 #include "BLI_blenlib.h"
38 #include "BLI_utildefines.h"
39
40 #include "imbuf.h"
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"
43
44 #include "IMB_allocimbuf.h"
45
46
47 /* blend modes */
48
49 static void blend_color_mix(char *cp, char *cp1, char *cp2, int fac)
50 {
51         /* this and other blending modes previously used >>8 instead of /255. both
52            are not equivalent (>>8 is /256), and the former results in rounding
53            errors that can turn colors black fast after repeated blending */
54         int mfac= 255-fac;
55
56         cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
57         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
58         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
59 }
60
61 static void blend_color_add(char *cp, char *cp1, char *cp2, int fac)
62 {
63         int temp;
64
65         temp= cp1[0] + ((fac*cp2[0])/255);
66         if(temp>254) cp[0]= 255; else cp[0]= temp;
67         temp= cp1[1] + ((fac*cp2[1])/255);
68         if(temp>254) cp[1]= 255; else cp[1]= temp;
69         temp= cp1[2] + ((fac*cp2[2])/255);
70         if(temp>254) cp[2]= 255; else cp[2]= temp;
71 }
72
73 static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac)
74 {
75         int temp;
76
77         temp= cp1[0] - ((fac*cp2[0])/255);
78         if(temp<0) cp[0]= 0; else cp[0]= temp;
79         temp= cp1[1] - ((fac*cp2[1])/255);
80         if(temp<0) cp[1]= 0; else cp[1]= temp;
81         temp= cp1[2] - ((fac*cp2[2])/255);
82         if(temp<0) cp[2]= 0; else cp[2]= temp;
83 }
84
85 static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac)
86 {
87         int mfac= 255-fac;
88         
89         /* first mul, then blend the fac */
90         cp[0]= (mfac*cp1[0] + fac*((cp1[0]*cp2[0])/255))/255;
91         cp[1]= (mfac*cp1[1] + fac*((cp1[1]*cp2[1])/255))/255;
92         cp[2]= (mfac*cp1[2] + fac*((cp1[2]*cp2[2])/255))/255;
93 }
94
95 static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac)
96 {
97         /* See if are lighter, if so mix, else dont do anything.
98         if the paint col is darker then the original, then ignore */
99         if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
100                 cp[0]= cp1[0];
101                 cp[1]= cp1[1];
102                 cp[2]= cp1[2];
103         }
104         else
105                 blend_color_mix(cp, cp1, cp2, fac);
106 }
107
108 static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac)
109 {
110         /* See if were darker, if so mix, else dont do anything.
111         if the paint col is brighter then the original, then ignore */
112         if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
113                 cp[0]= cp1[0];
114                 cp[1]= cp1[1];
115                 cp[2]= cp1[2];
116         }
117         else
118                 blend_color_mix(cp, cp1, cp2, fac);
119 }
120
121 unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode)
122 {
123         unsigned int dst;
124         int temp;
125         char *cp, *cp1, *cp2;
126
127         if (fac==0)
128                 return src1;
129
130         cp = (char*)&dst;
131         cp1 = (char*)&src1;
132         cp2 = (char*)&src2;
133
134         switch (mode) {
135                 case IMB_BLEND_MIX:
136                         blend_color_mix(cp, cp1, cp2, fac); break;
137                 case IMB_BLEND_ADD:
138                         blend_color_add(cp, cp1, cp2, fac); break;
139                 case IMB_BLEND_SUB:
140                         blend_color_sub(cp, cp1, cp2, fac); break;
141                 case IMB_BLEND_MUL:
142                         blend_color_mul(cp, cp1, cp2, fac); break;
143                 case IMB_BLEND_LIGHTEN:
144                         blend_color_lighten(cp, cp1, cp2, fac); break;
145                 case IMB_BLEND_DARKEN:
146                         blend_color_darken(cp, cp1, cp2, fac); break;
147                 default:
148                         cp[0]= cp1[0];
149                         cp[1]= cp1[1];
150                         cp[2]= cp1[2];
151         }
152
153         if (mode == IMB_BLEND_ERASE_ALPHA) {
154                 temp= (cp1[3] - fac*cp2[3]/255);
155                 cp[3]= (temp < 0)? 0: temp;
156         }
157         else { /* this does ADD_ALPHA also */
158                 temp= (cp1[3] + fac*cp2[3]/255);
159                 cp[3]= (temp > 255)? 255: temp;
160         }
161
162         return dst;
163 }
164
165 static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac)
166 {
167         float mfac= 1.0f-fac;
168         cp[0]= mfac*cp1[0] + fac*cp2[0];
169         cp[1]= mfac*cp1[1] + fac*cp2[1];
170         cp[2]= mfac*cp1[2] + fac*cp2[2];
171 }
172
173 static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac)
174 {
175         cp[0] = cp1[0] + fac*cp2[0];
176         cp[1] = cp1[1] + fac*cp2[1];
177         cp[2] = cp1[2] + fac*cp2[2];
178
179         if (cp[0] > 1.0f) cp[0]= 1.0f;
180         if (cp[1] > 1.0f) cp[1]= 1.0f;
181         if (cp[2] > 1.0f) cp[2]= 1.0f;
182 }
183
184 static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac)
185 {
186         cp[0] = cp1[0] - fac*cp2[0];
187         cp[1] = cp1[1] - fac*cp2[1];
188         cp[2] = cp1[2] - fac*cp2[2];
189
190         if (cp[0] < 0.0f) cp[0]= 0.0f;
191         if (cp[1] < 0.0f) cp[1]= 0.0f;
192         if (cp[2] < 0.0f) cp[2]= 0.0f;
193 }
194
195 static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac)
196 {
197         float mfac= 1.0f-fac;
198         
199         cp[0]= mfac*cp1[0] + fac*(cp1[0]*cp2[0]);
200         cp[1]= mfac*cp1[1] + fac*(cp1[1]*cp2[1]);
201         cp[2]= mfac*cp1[2] + fac*(cp1[2]*cp2[2]);
202 }
203
204 static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float fac)
205 {
206         /* See if are lighter, if so mix, else dont do anything.
207         if the pafloat col is darker then the original, then ignore */
208         if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) {
209                 cp[0]= cp1[0];
210                 cp[1]= cp1[1];
211                 cp[2]= cp1[2];
212         }
213         else
214                 blend_color_mix_float(cp, cp1, cp2, fac);
215 }
216
217 static void blend_color_darken_float(float *cp, float *cp1, float *cp2, float fac)
218 {
219         /* See if were darker, if so mix, else dont do anything.
220         if the pafloat col is brighter then the original, then ignore */
221         if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) {
222                 cp[0]= cp1[0];
223                 cp[1]= cp1[1];
224                 cp[2]= cp1[2];
225         }
226         else
227                 blend_color_mix_float(cp, cp1, cp2, fac);
228 }
229
230 void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode)
231 {
232         if (fac==0) {
233                 dst[0]= src1[0];
234                 dst[1]= src1[1];
235                 dst[2]= src1[2];
236                 dst[3]= src1[3];
237                 return;
238         }
239
240         switch (mode) {
241                 case IMB_BLEND_MIX:
242                         blend_color_mix_float(dst, src1, src2, fac); break;
243                 case IMB_BLEND_ADD:
244                         blend_color_add_float(dst, src1, src2, fac); break;
245                 case IMB_BLEND_SUB:
246                         blend_color_sub_float(dst, src1, src2, fac); break;
247                 case IMB_BLEND_MUL:
248                         blend_color_mul_float(dst, src1, src2, fac); break;
249                 case IMB_BLEND_LIGHTEN:
250                         blend_color_lighten_float(dst, src1, src2, fac); break;
251                 case IMB_BLEND_DARKEN:
252                         blend_color_darken_float(dst, src1, src2, fac); break;
253                 default:
254                         dst[0]= src1[0];
255                         dst[1]= src1[1];
256                         dst[2]= src1[2];
257         }
258
259         if (mode == IMB_BLEND_ERASE_ALPHA) {
260                 dst[3]= (src1[3] - fac*src2[3]);
261                 if (dst[3] < 0.0f) dst[3] = 0.0f;
262         }
263         else { /* this does ADD_ALPHA also */
264                 dst[3]= (src1[3] + fac*src2[3]);
265                 if (dst[3] > 1.0f) dst[3] = 1.0f;
266         }
267 }
268
269 /* clipping */
270
271 void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx, 
272         int *desty, int *srcx, int *srcy, int *width, int *height)
273 {
274         int tmp;
275
276         if (dbuf == NULL) return;
277         
278         if (*destx < 0) {
279                 *srcx -= *destx;
280                 *width += *destx;
281                 *destx = 0;
282         }
283         if (*srcx < 0) {
284                 *destx -= *srcx;
285                 *width += *srcx;
286                 *srcx = 0;
287         }
288         if (*desty < 0) {
289                 *srcy -= *desty;
290                 *height += *desty;
291                 *desty = 0;
292         }
293         if (*srcy < 0) {
294                 *desty -= *srcy;
295                 *height += *srcy;
296                 *srcy = 0;
297         }
298
299         tmp = dbuf->x - *destx;
300         if (*width > tmp) *width = tmp;
301         tmp = dbuf->y - *desty;
302         if (*height > tmp) *height = tmp;
303
304         if (sbuf) {
305                 tmp = sbuf->x - *srcx;
306                 if (*width > tmp) *width = tmp;
307                 tmp = sbuf->y - *srcy;
308                 if (*height > tmp) *height = tmp;
309         }
310
311         if ((*height <= 0) || (*width <= 0)) {
312                 *width = 0;
313                 *height = 0;
314         }
315 }
316
317 /* copy and blend */
318
319 void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 
320         int desty, int srcx, int srcy, int width, int height)
321 {
322         IMB_rectblend(dbuf, sbuf, destx, desty, srcx, srcy, width, height,
323                 IMB_BLEND_COPY);
324 }
325
326 void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 
327         int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode)
328 {
329         unsigned int *drect = NULL, *srect = NULL, *dr, *sr;
330         float *drectf = NULL, *srectf = NULL, *drf, *srf;
331         int do_float, do_char, srcskip, destskip, x;
332
333         if (dbuf == NULL) return;
334
335         IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &width, &height);
336
337         if (width == 0 || height == 0) return;
338         if (sbuf && sbuf->channels!=4) return;
339         if (dbuf->channels!=4) return;
340         
341         do_char = (sbuf && sbuf->rect && dbuf->rect);
342         do_float = (sbuf && sbuf->rect_float && dbuf->rect_float);
343
344         if (do_char) drect = dbuf->rect + desty * dbuf->x + destx;
345         if (do_float) drectf = dbuf->rect_float + (desty * dbuf->x + destx)*4;
346
347         destskip = dbuf->x;
348
349         if (sbuf) {
350                 if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
351                 if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx)*4;
352                 srcskip = sbuf->x;
353         } else {
354                 srect = drect;
355                 srectf = drectf;
356                 srcskip = destskip;
357         }
358
359         if (mode == IMB_BLEND_COPY) {
360                 /* copy */
361                 for (;height > 0; height--) {
362                         if (do_char) {
363                                 memcpy(drect,srect, width * sizeof(int));
364                                 drect += destskip;
365                                 srect += srcskip;
366                         }
367
368                         if (do_float) {
369                                 memcpy(drectf,srectf, width * sizeof(float) * 4);
370                                 drectf += destskip*4;
371                                 srectf += srcskip*4;
372                         }
373                 }
374         }
375         else if (mode == IMB_BLEND_COPY_RGB) {
376                 /* copy rgb only */
377                 for (;height > 0; height--) {
378                         if (do_char) {
379                                 dr = drect;
380                                 sr = srect;
381                                 for (x=width; x > 0; x--, dr++, sr++) {
382                                         ((char*)dr)[0]= ((char*)sr)[0];
383                                         ((char*)dr)[1]= ((char*)sr)[1];
384                                         ((char*)dr)[2]= ((char*)sr)[2];
385                                 }
386                                 drect += destskip;
387                                 srect += srcskip;
388                         }
389
390                         if (do_float) {
391                                 drf = drectf;
392                                 srf = srectf;
393                                 for (x=width; x > 0; x--, drf+=4, srf+=4) {
394                                         drf[0]= srf[0];
395                                         drf[1]= srf[1];
396                                         drf[2]= srf[2];
397                                 }
398                                 drectf += destskip*4;
399                                 srectf += srcskip*4;
400                         }
401                 }
402         }
403         else if (mode == IMB_BLEND_COPY_ALPHA) {
404                 /* copy alpha only */
405                 for (;height > 0; height--) {
406                         if (do_char) {
407                                 dr = drect;
408                                 sr = srect;
409                                 for (x=width; x > 0; x--, dr++, sr++)
410                                         ((char*)dr)[3]= ((char*)sr)[3];
411                                 drect += destskip;
412                                 srect += srcskip;
413                         }
414
415                         if (do_float) {
416                                 drf = drectf;
417                                 srf = srectf;
418                                 for (x=width; x > 0; x--, drf+=4, srf+=4)
419                                         drf[3]= srf[3];
420                                 drectf += destskip*4;
421                                 srectf += srcskip*4;
422                         }
423                 }
424         }
425         else {
426                 /* blend */
427                 for (;height > 0; height--) {
428                         if (do_char) {
429                                 dr = drect;
430                                 sr = srect;
431                                 for (x=width; x > 0; x--, dr++, sr++)
432                                         *dr = IMB_blend_color(*dr, *sr, ((char*)sr)[3], mode);
433
434                                 drect += destskip;
435                                 srect += srcskip;
436                         }
437
438                         if (do_float) {
439                                 drf = drectf;
440                                 srf = srectf;
441                                 for (x=width; x > 0; x--, drf+=4, srf+=4)
442                                         IMB_blend_color_float(drf, drf, srf, srf[3], mode);
443
444                                 drectf += destskip*4;
445                                 srectf += srcskip*4;
446                         }               
447                 }
448         }
449 }
450
451 /* fill */
452
453 void IMB_rectfill(struct ImBuf *drect, const float col[4])
454 {
455         int num;
456
457         if(drect->rect) {
458                 unsigned int *rrect = drect->rect;
459                 char ccol[4];
460                 
461                 ccol[0]= (int)(col[0]*255);
462                 ccol[1]= (int)(col[1]*255);
463                 ccol[2]= (int)(col[2]*255);
464                 ccol[3]= (int)(col[3]*255);
465                 
466                 num = drect->x * drect->y;
467                 for (;num > 0; num--)
468                         *rrect++ = *((unsigned int*)ccol);
469         }
470         
471         if(drect->rect_float) {
472                 float *rrectf = drect->rect_float;
473                 
474                 num = drect->x * drect->y;
475                 for (;num > 0; num--) {
476                         *rrectf++ = col[0];
477                         *rrectf++ = col[1];
478                         *rrectf++ = col[2];
479                         *rrectf++ = col[3];
480                 }
481         }       
482 }
483
484
485 void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, float *col, int x1, int y1, int x2, int y2)
486 {
487         int i, j;
488         float a; /* alpha */
489         float ai; /* alpha inverted */
490         float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
491         if ((!rect && !rectf) || (!col) || col[3]==0.0f)
492                 return;
493         
494         /* sanity checks for coords */
495         CLAMP(x1, 0, width);
496         CLAMP(x2, 0, width);
497         CLAMP(y1, 0, height);
498         CLAMP(y2, 0, height);
499
500         if (x1>x2) SWAP(int,x1,x2);
501         if (y1>y2) SWAP(int,y1,y2);
502         if (x1==x2 || y1==y2) return;
503         
504         a = col[3];
505         ai = 1-a;
506         aich = ai/255.0f;
507
508         if (rect) {
509                 unsigned char *pixel; 
510                 unsigned char chr=0, chg=0, chb=0;
511                 float fr=0, fg=0, fb=0;
512                 
513                 if (a == 1.0f) {
514                         chr = FTOCHAR(col[0]);
515                         chg = FTOCHAR(col[1]);
516                         chb = FTOCHAR(col[2]);
517                 } else {
518                         fr = col[0]*a;
519                         fg = col[1]*a;
520                         fb = col[2]*a;
521                 }
522                 for (j = 0; j < y2-y1; j++) {
523                         for (i = 0; i < x2-x1; i++) {
524                                 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
525                                 if (pixel >= rect && pixel < rect+ (4 * (width * height))) {
526                                         if (a == 1.0f) {
527                                                 pixel[0] = chr;
528                                                 pixel[1] = chg;
529                                                 pixel[2] = chb;
530                                         } else {
531                                                 pixel[0] = (char)((fr + ((float)pixel[0]*aich))*255.0f);
532                                                 pixel[1] = (char)((fg + ((float)pixel[1]*aich))*255.0f);
533                                                 pixel[2] = (char)((fb + ((float)pixel[2]*aich))*255.0f);
534                                         }
535                                 }
536                         }
537                 }
538         }
539         
540         if (rectf) {
541                 float *pixel;
542                 for (j = 0; j < y2-y1; j++) {
543                         for (i = 0; i < x2-x1; i++) {
544                                 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
545                                 if (a == 1.0f) {
546                                         pixel[0] = col[0];
547                                         pixel[1] = col[1];
548                                         pixel[2] = col[2];
549                                 } else {
550                                         pixel[0] = (col[0]*a) + (pixel[0]*ai);
551                                         pixel[1] = (col[1]*a) + (pixel[1]*ai);
552                                         pixel[2] = (col[2]*a) + (pixel[2]*ai);
553                                 }
554                         }
555                 }
556         }
557 }
558
559 void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2)
560 {
561         if (!ibuf) return;
562         buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, x1, y1, x2, y2);
563 }
564
565
566 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
567 {
568         int i;
569         if (ibuf->rect_float) {
570                 float *fbuf= ibuf->rect_float + 3;
571                 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf+= 4) { *fbuf = value; }
572         }
573         else {
574                 const unsigned char cvalue= value * 255;
575                 unsigned char *cbuf= ((unsigned char *)ibuf->rect) + 3;
576                 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf+= 4) { *cbuf = cvalue; }
577         }
578 }