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