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