|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 * allocimbuf.c 00028 * 00029 * $Id: rectop.c 37492 2011-06-15 01:56:49Z campbellbarton $ 00030 */ 00031 00037 #include "BLI_blenlib.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "imbuf.h" 00041 #include "IMB_imbuf_types.h" 00042 #include "IMB_imbuf.h" 00043 00044 #include "IMB_allocimbuf.h" 00045 00046 00047 /* blend modes */ 00048 00049 static void blend_color_mix(char *cp, char *cp1, char *cp2, int fac) 00050 { 00051 /* this and other blending modes previously used >>8 instead of /255. both 00052 are not equivalent (>>8 is /256), and the former results in rounding 00053 errors that can turn colors black fast after repeated blending */ 00054 int mfac= 255-fac; 00055 00056 cp[0]= (mfac*cp1[0]+fac*cp2[0])/255; 00057 cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; 00058 cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; 00059 } 00060 00061 static void blend_color_add(char *cp, char *cp1, char *cp2, int fac) 00062 { 00063 int temp; 00064 00065 temp= cp1[0] + ((fac*cp2[0])/255); 00066 if(temp>254) cp[0]= 255; else cp[0]= temp; 00067 temp= cp1[1] + ((fac*cp2[1])/255); 00068 if(temp>254) cp[1]= 255; else cp[1]= temp; 00069 temp= cp1[2] + ((fac*cp2[2])/255); 00070 if(temp>254) cp[2]= 255; else cp[2]= temp; 00071 } 00072 00073 static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac) 00074 { 00075 int temp; 00076 00077 temp= cp1[0] - ((fac*cp2[0])/255); 00078 if(temp<0) cp[0]= 0; else cp[0]= temp; 00079 temp= cp1[1] - ((fac*cp2[1])/255); 00080 if(temp<0) cp[1]= 0; else cp[1]= temp; 00081 temp= cp1[2] - ((fac*cp2[2])/255); 00082 if(temp<0) cp[2]= 0; else cp[2]= temp; 00083 } 00084 00085 static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac) 00086 { 00087 int mfac= 255-fac; 00088 00089 /* first mul, then blend the fac */ 00090 cp[0]= (mfac*cp1[0] + fac*((cp1[0]*cp2[0])/255))/255; 00091 cp[1]= (mfac*cp1[1] + fac*((cp1[1]*cp2[1])/255))/255; 00092 cp[2]= (mfac*cp1[2] + fac*((cp1[2]*cp2[2])/255))/255; 00093 } 00094 00095 static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac) 00096 { 00097 /* See if are lighter, if so mix, else dont do anything. 00098 if the paint col is darker then the original, then ignore */ 00099 if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) { 00100 cp[0]= cp1[0]; 00101 cp[1]= cp1[1]; 00102 cp[2]= cp1[2]; 00103 } 00104 else 00105 blend_color_mix(cp, cp1, cp2, fac); 00106 } 00107 00108 static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac) 00109 { 00110 /* See if were darker, if so mix, else dont do anything. 00111 if the paint col is brighter then the original, then ignore */ 00112 if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) { 00113 cp[0]= cp1[0]; 00114 cp[1]= cp1[1]; 00115 cp[2]= cp1[2]; 00116 } 00117 else 00118 blend_color_mix(cp, cp1, cp2, fac); 00119 } 00120 00121 unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode) 00122 { 00123 unsigned int dst; 00124 int temp; 00125 char *cp, *cp1, *cp2; 00126 00127 if (fac==0) 00128 return src1; 00129 00130 cp = (char*)&dst; 00131 cp1 = (char*)&src1; 00132 cp2 = (char*)&src2; 00133 00134 switch (mode) { 00135 case IMB_BLEND_MIX: 00136 blend_color_mix(cp, cp1, cp2, fac); break; 00137 case IMB_BLEND_ADD: 00138 blend_color_add(cp, cp1, cp2, fac); break; 00139 case IMB_BLEND_SUB: 00140 blend_color_sub(cp, cp1, cp2, fac); break; 00141 case IMB_BLEND_MUL: 00142 blend_color_mul(cp, cp1, cp2, fac); break; 00143 case IMB_BLEND_LIGHTEN: 00144 blend_color_lighten(cp, cp1, cp2, fac); break; 00145 case IMB_BLEND_DARKEN: 00146 blend_color_darken(cp, cp1, cp2, fac); break; 00147 default: 00148 cp[0]= cp1[0]; 00149 cp[1]= cp1[1]; 00150 cp[2]= cp1[2]; 00151 } 00152 00153 if (mode == IMB_BLEND_ERASE_ALPHA) { 00154 temp= (cp1[3] - fac*cp2[3]/255); 00155 cp[3]= (temp < 0)? 0: temp; 00156 } 00157 else { /* this does ADD_ALPHA also */ 00158 temp= (cp1[3] + fac*cp2[3]/255); 00159 cp[3]= (temp > 255)? 255: temp; 00160 } 00161 00162 return dst; 00163 } 00164 00165 static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac) 00166 { 00167 float mfac= 1.0f-fac; 00168 cp[0]= mfac*cp1[0] + fac*cp2[0]; 00169 cp[1]= mfac*cp1[1] + fac*cp2[1]; 00170 cp[2]= mfac*cp1[2] + fac*cp2[2]; 00171 } 00172 00173 static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac) 00174 { 00175 cp[0] = cp1[0] + fac*cp2[0]; 00176 cp[1] = cp1[1] + fac*cp2[1]; 00177 cp[2] = cp1[2] + fac*cp2[2]; 00178 00179 if (cp[0] > 1.0f) cp[0]= 1.0f; 00180 if (cp[1] > 1.0f) cp[1]= 1.0f; 00181 if (cp[2] > 1.0f) cp[2]= 1.0f; 00182 } 00183 00184 static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac) 00185 { 00186 cp[0] = cp1[0] - fac*cp2[0]; 00187 cp[1] = cp1[1] - fac*cp2[1]; 00188 cp[2] = cp1[2] - fac*cp2[2]; 00189 00190 if (cp[0] < 0.0f) cp[0]= 0.0f; 00191 if (cp[1] < 0.0f) cp[1]= 0.0f; 00192 if (cp[2] < 0.0f) cp[2]= 0.0f; 00193 } 00194 00195 static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac) 00196 { 00197 float mfac= 1.0f-fac; 00198 00199 cp[0]= mfac*cp1[0] + fac*(cp1[0]*cp2[0]); 00200 cp[1]= mfac*cp1[1] + fac*(cp1[1]*cp2[1]); 00201 cp[2]= mfac*cp1[2] + fac*(cp1[2]*cp2[2]); 00202 } 00203 00204 static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float fac) 00205 { 00206 /* See if are lighter, if so mix, else dont do anything. 00207 if the pafloat col is darker then the original, then ignore */ 00208 if (cp1[0]+cp1[1]+cp1[2] > cp2[0]+cp2[1]+cp2[2]) { 00209 cp[0]= cp1[0]; 00210 cp[1]= cp1[1]; 00211 cp[2]= cp1[2]; 00212 } 00213 else 00214 blend_color_mix_float(cp, cp1, cp2, fac); 00215 } 00216 00217 static void blend_color_darken_float(float *cp, float *cp1, float *cp2, float fac) 00218 { 00219 /* See if were darker, if so mix, else dont do anything. 00220 if the pafloat col is brighter then the original, then ignore */ 00221 if (cp1[0]+cp1[1]+cp1[2] < cp2[0]+cp2[1]+cp2[2]) { 00222 cp[0]= cp1[0]; 00223 cp[1]= cp1[1]; 00224 cp[2]= cp1[2]; 00225 } 00226 else 00227 blend_color_mix_float(cp, cp1, cp2, fac); 00228 } 00229 00230 void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode) 00231 { 00232 if (fac==0) { 00233 dst[0]= src1[0]; 00234 dst[1]= src1[1]; 00235 dst[2]= src1[2]; 00236 dst[3]= src1[3]; 00237 return; 00238 } 00239 00240 switch (mode) { 00241 case IMB_BLEND_MIX: 00242 blend_color_mix_float(dst, src1, src2, fac); break; 00243 case IMB_BLEND_ADD: 00244 blend_color_add_float(dst, src1, src2, fac); break; 00245 case IMB_BLEND_SUB: 00246 blend_color_sub_float(dst, src1, src2, fac); break; 00247 case IMB_BLEND_MUL: 00248 blend_color_mul_float(dst, src1, src2, fac); break; 00249 case IMB_BLEND_LIGHTEN: 00250 blend_color_lighten_float(dst, src1, src2, fac); break; 00251 case IMB_BLEND_DARKEN: 00252 blend_color_darken_float(dst, src1, src2, fac); break; 00253 default: 00254 dst[0]= src1[0]; 00255 dst[1]= src1[1]; 00256 dst[2]= src1[2]; 00257 } 00258 00259 if (mode == IMB_BLEND_ERASE_ALPHA) { 00260 dst[3]= (src1[3] - fac*src2[3]); 00261 if (dst[3] < 0.0f) dst[3] = 0.0f; 00262 } 00263 else { /* this does ADD_ALPHA also */ 00264 dst[3]= (src1[3] + fac*src2[3]); 00265 if (dst[3] > 1.0f) dst[3] = 1.0f; 00266 } 00267 } 00268 00269 /* clipping */ 00270 00271 void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx, 00272 int *desty, int *srcx, int *srcy, int *width, int *height) 00273 { 00274 int tmp; 00275 00276 if (dbuf == NULL) return; 00277 00278 if (*destx < 0) { 00279 *srcx -= *destx; 00280 *width += *destx; 00281 *destx = 0; 00282 } 00283 if (*srcx < 0) { 00284 *destx -= *srcx; 00285 *width += *srcx; 00286 *srcx = 0; 00287 } 00288 if (*desty < 0) { 00289 *srcy -= *desty; 00290 *height += *desty; 00291 *desty = 0; 00292 } 00293 if (*srcy < 0) { 00294 *desty -= *srcy; 00295 *height += *srcy; 00296 *srcy = 0; 00297 } 00298 00299 tmp = dbuf->x - *destx; 00300 if (*width > tmp) *width = tmp; 00301 tmp = dbuf->y - *desty; 00302 if (*height > tmp) *height = tmp; 00303 00304 if (sbuf) { 00305 tmp = sbuf->x - *srcx; 00306 if (*width > tmp) *width = tmp; 00307 tmp = sbuf->y - *srcy; 00308 if (*height > tmp) *height = tmp; 00309 } 00310 00311 if ((*height <= 0) || (*width <= 0)) { 00312 *width = 0; 00313 *height = 0; 00314 } 00315 } 00316 00317 /* copy and blend */ 00318 00319 void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 00320 int desty, int srcx, int srcy, int width, int height) 00321 { 00322 IMB_rectblend(dbuf, sbuf, destx, desty, srcx, srcy, width, height, 00323 IMB_BLEND_COPY); 00324 } 00325 00326 void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 00327 int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode) 00328 { 00329 unsigned int *drect = NULL, *srect = NULL, *dr, *sr; 00330 float *drectf = NULL, *srectf = NULL, *drf, *srf; 00331 int do_float, do_char, srcskip, destskip, x; 00332 00333 if (dbuf == NULL) return; 00334 00335 IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &width, &height); 00336 00337 if (width == 0 || height == 0) return; 00338 if (sbuf && sbuf->channels!=4) return; 00339 if (dbuf->channels!=4) return; 00340 00341 do_char = (sbuf && sbuf->rect && dbuf->rect); 00342 do_float = (sbuf && sbuf->rect_float && dbuf->rect_float); 00343 00344 if (do_char) drect = dbuf->rect + desty * dbuf->x + destx; 00345 if (do_float) drectf = dbuf->rect_float + (desty * dbuf->x + destx)*4; 00346 00347 destskip = dbuf->x; 00348 00349 if (sbuf) { 00350 if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx; 00351 if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx)*4; 00352 srcskip = sbuf->x; 00353 } else { 00354 srect = drect; 00355 srectf = drectf; 00356 srcskip = destskip; 00357 } 00358 00359 if (mode == IMB_BLEND_COPY) { 00360 /* copy */ 00361 for (;height > 0; height--) { 00362 if (do_char) { 00363 memcpy(drect,srect, width * sizeof(int)); 00364 drect += destskip; 00365 srect += srcskip; 00366 } 00367 00368 if (do_float) { 00369 memcpy(drectf,srectf, width * sizeof(float) * 4); 00370 drectf += destskip*4; 00371 srectf += srcskip*4; 00372 } 00373 } 00374 } 00375 else if (mode == IMB_BLEND_COPY_RGB) { 00376 /* copy rgb only */ 00377 for (;height > 0; height--) { 00378 if (do_char) { 00379 dr = drect; 00380 sr = srect; 00381 for (x=width; x > 0; x--, dr++, sr++) { 00382 ((char*)dr)[0]= ((char*)sr)[0]; 00383 ((char*)dr)[1]= ((char*)sr)[1]; 00384 ((char*)dr)[2]= ((char*)sr)[2]; 00385 } 00386 drect += destskip; 00387 srect += srcskip; 00388 } 00389 00390 if (do_float) { 00391 drf = drectf; 00392 srf = srectf; 00393 for (x=width; x > 0; x--, drf+=4, srf+=4) { 00394 drf[0]= srf[0]; 00395 drf[1]= srf[1]; 00396 drf[2]= srf[2]; 00397 } 00398 drectf += destskip*4; 00399 srectf += srcskip*4; 00400 } 00401 } 00402 } 00403 else if (mode == IMB_BLEND_COPY_ALPHA) { 00404 /* copy alpha only */ 00405 for (;height > 0; height--) { 00406 if (do_char) { 00407 dr = drect; 00408 sr = srect; 00409 for (x=width; x > 0; x--, dr++, sr++) 00410 ((char*)dr)[3]= ((char*)sr)[3]; 00411 drect += destskip; 00412 srect += srcskip; 00413 } 00414 00415 if (do_float) { 00416 drf = drectf; 00417 srf = srectf; 00418 for (x=width; x > 0; x--, drf+=4, srf+=4) 00419 drf[3]= srf[3]; 00420 drectf += destskip*4; 00421 srectf += srcskip*4; 00422 } 00423 } 00424 } 00425 else { 00426 /* blend */ 00427 for (;height > 0; height--) { 00428 if (do_char) { 00429 dr = drect; 00430 sr = srect; 00431 for (x=width; x > 0; x--, dr++, sr++) 00432 *dr = IMB_blend_color(*dr, *sr, ((char*)sr)[3], mode); 00433 00434 drect += destskip; 00435 srect += srcskip; 00436 } 00437 00438 if (do_float) { 00439 drf = drectf; 00440 srf = srectf; 00441 for (x=width; x > 0; x--, drf+=4, srf+=4) 00442 IMB_blend_color_float(drf, drf, srf, srf[3], mode); 00443 00444 drectf += destskip*4; 00445 srectf += srcskip*4; 00446 } 00447 } 00448 } 00449 } 00450 00451 /* fill */ 00452 00453 void IMB_rectfill(struct ImBuf *drect, const float col[4]) 00454 { 00455 int num; 00456 00457 if(drect->rect) { 00458 unsigned int *rrect = drect->rect; 00459 char ccol[4]; 00460 00461 ccol[0]= (int)(col[0]*255); 00462 ccol[1]= (int)(col[1]*255); 00463 ccol[2]= (int)(col[2]*255); 00464 ccol[3]= (int)(col[3]*255); 00465 00466 num = drect->x * drect->y; 00467 for (;num > 0; num--) 00468 *rrect++ = *((unsigned int*)ccol); 00469 } 00470 00471 if(drect->rect_float) { 00472 float *rrectf = drect->rect_float; 00473 00474 num = drect->x * drect->y; 00475 for (;num > 0; num--) { 00476 *rrectf++ = col[0]; 00477 *rrectf++ = col[1]; 00478 *rrectf++ = col[2]; 00479 *rrectf++ = col[3]; 00480 } 00481 } 00482 } 00483 00484 00485 void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, float *col, int x1, int y1, int x2, int y2) 00486 { 00487 int i, j; 00488 float a; /* alpha */ 00489 float ai; /* alpha inverted */ 00490 float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */ 00491 if ((!rect && !rectf) || (!col) || col[3]==0.0f) 00492 return; 00493 00494 /* sanity checks for coords */ 00495 CLAMP(x1, 0, width); 00496 CLAMP(x2, 0, width); 00497 CLAMP(y1, 0, height); 00498 CLAMP(y2, 0, height); 00499 00500 if (x1>x2) SWAP(int,x1,x2); 00501 if (y1>y2) SWAP(int,y1,y2); 00502 if (x1==x2 || y1==y2) return; 00503 00504 a = col[3]; 00505 ai = 1-a; 00506 aich = ai/255.0f; 00507 00508 if (rect) { 00509 unsigned char *pixel; 00510 unsigned char chr=0, chg=0, chb=0; 00511 float fr=0, fg=0, fb=0; 00512 00513 if (a == 1.0f) { 00514 chr = FTOCHAR(col[0]); 00515 chg = FTOCHAR(col[1]); 00516 chb = FTOCHAR(col[2]); 00517 } else { 00518 fr = col[0]*a; 00519 fg = col[1]*a; 00520 fb = col[2]*a; 00521 } 00522 for (j = 0; j < y2-y1; j++) { 00523 for (i = 0; i < x2-x1; i++) { 00524 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i)); 00525 if (pixel >= rect && pixel < rect+ (4 * (width * height))) { 00526 if (a == 1.0f) { 00527 pixel[0] = chr; 00528 pixel[1] = chg; 00529 pixel[2] = chb; 00530 } else { 00531 pixel[0] = (char)((fr + ((float)pixel[0]*aich))*255.0f); 00532 pixel[1] = (char)((fg + ((float)pixel[1]*aich))*255.0f); 00533 pixel[2] = (char)((fb + ((float)pixel[2]*aich))*255.0f); 00534 } 00535 } 00536 } 00537 } 00538 } 00539 00540 if (rectf) { 00541 float *pixel; 00542 for (j = 0; j < y2-y1; j++) { 00543 for (i = 0; i < x2-x1; i++) { 00544 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i)); 00545 if (a == 1.0f) { 00546 pixel[0] = col[0]; 00547 pixel[1] = col[1]; 00548 pixel[2] = col[2]; 00549 } else { 00550 pixel[0] = (col[0]*a) + (pixel[0]*ai); 00551 pixel[1] = (col[1]*a) + (pixel[1]*ai); 00552 pixel[2] = (col[2]*a) + (pixel[2]*ai); 00553 } 00554 } 00555 } 00556 } 00557 } 00558 00559 void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2) 00560 { 00561 if (!ibuf) return; 00562 buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, x1, y1, x2, y2); 00563 } 00564 00565 00566 void IMB_rectfill_alpha(ImBuf *ibuf, const float value) 00567 { 00568 int i; 00569 if (ibuf->rect_float) { 00570 float *fbuf= ibuf->rect_float + 3; 00571 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf+= 4) { *fbuf = value; } 00572 } 00573 else { 00574 const unsigned char cvalue= value * 255; 00575 unsigned char *cbuf= ((unsigned char *)ibuf->rect) + 3; 00576 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf+= 4) { *cbuf = cvalue; } 00577 } 00578 }