|
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: scaling.c 36895 2011-05-25 11:06:30Z campbellbarton $ 00030 */ 00031 00037 #include "BLI_blenlib.h" 00038 #include "BLI_utildefines.h" 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "imbuf.h" 00042 #include "IMB_imbuf_types.h" 00043 #include "IMB_imbuf.h" 00044 00045 #include "IMB_allocimbuf.h" 00046 #include "IMB_filter.h" 00047 00048 #include "BLO_sys_types.h" // for intptr_t support 00049 00050 /************************************************************************/ 00051 /* SCALING */ 00052 /************************************************************************/ 00053 00054 00055 struct ImBuf *IMB_half_x(struct ImBuf *ibuf1) 00056 { 00057 struct ImBuf *ibuf2; 00058 uchar *p1,*_p1,*dest; 00059 short a,r,g,b; 00060 int x,y; 00061 float af,rf,gf,bf, *p1f, *_p1f, *destf; 00062 int do_rect, do_float; 00063 00064 if (ibuf1==NULL) return (NULL); 00065 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00066 00067 do_rect= (ibuf1->rect != NULL); 00068 do_float= (ibuf1->rect_float != NULL); 00069 00070 if (ibuf1->x <= 1) return(IMB_dupImBuf(ibuf1)); 00071 00072 ibuf2 = IMB_allocImBuf((ibuf1->x)/2, ibuf1->y, ibuf1->depth, ibuf1->flags); 00073 if (ibuf2==NULL) return (NULL); 00074 00075 _p1 = (uchar *) ibuf1->rect; 00076 dest=(uchar *) ibuf2->rect; 00077 00078 _p1f = ibuf1->rect_float; 00079 destf= ibuf2->rect_float; 00080 00081 for(y=ibuf2->y;y>0;y--){ 00082 p1 = _p1; 00083 p1f = _p1f; 00084 for(x = ibuf2->x ; x>0 ; x--){ 00085 if (do_rect) { 00086 a = *(p1++) ; 00087 b = *(p1++) ; 00088 g = *(p1++) ; 00089 r = *(p1++); 00090 a += *(p1++) ; 00091 b += *(p1++) ; 00092 g += *(p1++) ; 00093 r += *(p1++); 00094 *(dest++) = a >> 1; 00095 *(dest++) = b >> 1; 00096 *(dest++) = g >> 1; 00097 *(dest++) = r >> 1; 00098 } 00099 if (do_float) { 00100 af = *(p1f++); 00101 bf = *(p1f++); 00102 gf = *(p1f++); 00103 rf = *(p1f++); 00104 af += *(p1f++); 00105 bf += *(p1f++); 00106 gf += *(p1f++); 00107 rf += *(p1f++); 00108 *(destf++) = 0.5f*af; 00109 *(destf++) = 0.5f*bf; 00110 *(destf++) = 0.5f*gf; 00111 *(destf++) = 0.5f*rf; 00112 } 00113 } 00114 if (do_rect) _p1 += (ibuf1->x << 2); 00115 if (do_float) _p1f += (ibuf1->x << 2); 00116 } 00117 return (ibuf2); 00118 } 00119 00120 00121 struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1) 00122 { 00123 struct ImBuf *ibuf2; 00124 int *p1,*dest, i, col, do_rect, do_float; 00125 float *p1f, *destf; 00126 00127 if (ibuf1==NULL) return (NULL); 00128 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00129 00130 do_rect= (ibuf1->rect != NULL); 00131 do_float= (ibuf1->rect_float != NULL); 00132 00133 ibuf2 = IMB_allocImBuf(2 * ibuf1->x , ibuf1->y , ibuf1->depth, ibuf1->flags); 00134 if (ibuf2==NULL) return (NULL); 00135 00136 p1 = (int *) ibuf1->rect; 00137 dest=(int *) ibuf2->rect; 00138 p1f = (float *)ibuf1->rect_float; 00139 destf = (float *)ibuf2->rect_float; 00140 00141 for(i = ibuf1->y * ibuf1->x ; i>0 ; i--) { 00142 if (do_rect) { 00143 col = *p1++; 00144 *dest++ = col; 00145 *dest++ = col; 00146 } 00147 if (do_float) { 00148 destf[0]= destf[4] =p1f[0]; 00149 destf[1]= destf[5] =p1f[1]; 00150 destf[2]= destf[6] =p1f[2]; 00151 destf[3]= destf[7] =p1f[3]; 00152 destf+= 8; 00153 p1f+= 4; 00154 } 00155 } 00156 00157 return (ibuf2); 00158 } 00159 00160 struct ImBuf *IMB_double_x(struct ImBuf *ibuf1) 00161 { 00162 struct ImBuf *ibuf2; 00163 00164 if (ibuf1==NULL) return (NULL); 00165 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00166 00167 ibuf2 = IMB_double_fast_x(ibuf1); 00168 00169 imb_filterx(ibuf2); 00170 return (ibuf2); 00171 } 00172 00173 00174 struct ImBuf *IMB_half_y(struct ImBuf *ibuf1) 00175 { 00176 struct ImBuf *ibuf2; 00177 uchar *p1,*p2,*_p1,*dest; 00178 short a,r,g,b; 00179 int x,y; 00180 int do_rect, do_float; 00181 float af,rf,gf,bf,*p1f,*p2f,*_p1f,*destf; 00182 00183 p1= p2= NULL; 00184 p1f= p2f= NULL; 00185 if (ibuf1==NULL) return (NULL); 00186 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00187 if (ibuf1->y <= 1) return(IMB_dupImBuf(ibuf1)); 00188 00189 do_rect= (ibuf1->rect != NULL); 00190 do_float= (ibuf1->rect_float != NULL); 00191 00192 ibuf2 = IMB_allocImBuf(ibuf1->x , (ibuf1->y) / 2 , ibuf1->depth, ibuf1->flags); 00193 if (ibuf2==NULL) return (NULL); 00194 00195 _p1 = (uchar *) ibuf1->rect; 00196 dest=(uchar *) ibuf2->rect; 00197 _p1f = (float *) ibuf1->rect_float; 00198 destf= (float *) ibuf2->rect_float; 00199 00200 for(y=ibuf2->y ; y>0 ; y--){ 00201 if (do_rect) { 00202 p1 = _p1; 00203 p2 = _p1 + (ibuf1->x << 2); 00204 } 00205 if (do_float) { 00206 p1f = _p1f; 00207 p2f = _p1f + (ibuf1->x << 2); 00208 } 00209 for(x = ibuf2->x ; x>0 ; x--){ 00210 if (do_rect) { 00211 a = *(p1++) ; 00212 b = *(p1++) ; 00213 g = *(p1++) ; 00214 r = *(p1++); 00215 a += *(p2++) ; 00216 b += *(p2++) ; 00217 g += *(p2++) ; 00218 r += *(p2++); 00219 *(dest++) = a >> 1; 00220 *(dest++) = b >> 1; 00221 *(dest++) = g >> 1; 00222 *(dest++) = r >> 1; 00223 } 00224 if (do_float) { 00225 af = *(p1f++) ; 00226 bf = *(p1f++) ; 00227 gf = *(p1f++) ; 00228 rf = *(p1f++); 00229 af += *(p2f++) ; 00230 bf += *(p2f++) ; 00231 gf += *(p2f++) ; 00232 rf += *(p2f++); 00233 *(destf++) = 0.5f*af; 00234 *(destf++) = 0.5f*bf; 00235 *(destf++) = 0.5f*gf; 00236 *(destf++) = 0.5f*rf; 00237 } 00238 } 00239 if (do_rect) _p1 += (ibuf1->x << 3); 00240 if (do_float) _p1f += (ibuf1->x << 3); 00241 } 00242 return (ibuf2); 00243 } 00244 00245 00246 struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1) 00247 { 00248 struct ImBuf *ibuf2; 00249 int *p1, *dest1, *dest2; 00250 float *p1f, *dest1f, *dest2f; 00251 int x,y; 00252 int do_rect, do_float; 00253 00254 if (ibuf1==NULL) return (NULL); 00255 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00256 00257 do_rect= (ibuf1->rect != NULL); 00258 do_float= (ibuf1->rect_float != NULL); 00259 00260 ibuf2 = IMB_allocImBuf(ibuf1->x , 2 * ibuf1->y , ibuf1->depth, ibuf1->flags); 00261 if (ibuf2==NULL) return (NULL); 00262 00263 p1 = (int *) ibuf1->rect; 00264 dest1= (int *) ibuf2->rect; 00265 p1f = (float *) ibuf1->rect_float; 00266 dest1f= (float *) ibuf2->rect_float; 00267 00268 for(y = ibuf1->y ; y>0 ; y--){ 00269 if (do_rect) { 00270 dest2 = dest1 + ibuf2->x; 00271 for(x = ibuf2->x ; x>0 ; x--) *dest1++ = *dest2++ = *p1++; 00272 dest1 = dest2; 00273 } 00274 if (do_float) { 00275 dest2f = dest1f + (4*ibuf2->x); 00276 for(x = ibuf2->x*4 ; x>0 ; x--) *dest1f++ = *dest2f++ = *p1f++; 00277 dest1f = dest2f; 00278 } 00279 } 00280 00281 return (ibuf2); 00282 } 00283 00284 struct ImBuf *IMB_double_y(struct ImBuf *ibuf1) 00285 { 00286 struct ImBuf *ibuf2; 00287 00288 if (ibuf1==NULL) return (NULL); 00289 if (ibuf1->rect==NULL) return (NULL); 00290 00291 ibuf2 = IMB_double_fast_y(ibuf1); 00292 00293 IMB_filtery(ibuf2); 00294 return (ibuf2); 00295 } 00296 00297 /* result in ibuf2, scaling should be done correctly */ 00298 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) 00299 { 00300 uchar *p1, *p2 = NULL, *dest; 00301 float *p1f, *destf, *p2f = NULL; 00302 int x,y; 00303 const short do_rect= (ibuf1->rect != NULL); 00304 const short do_float= (ibuf1->rect_float != NULL) && (ibuf2->rect_float != NULL); 00305 00306 if(do_rect && (ibuf2->rect == NULL)) { 00307 imb_addrectImBuf(ibuf2); 00308 } 00309 00310 p1f = ibuf1->rect_float; 00311 destf=ibuf2->rect_float; 00312 p1 = (uchar *) ibuf1->rect; 00313 dest=(uchar *) ibuf2->rect; 00314 00315 for(y=ibuf2->y;y>0;y--){ 00316 if (do_rect) p2 = p1 + (ibuf1->x << 2); 00317 if (do_float) p2f = p1f + (ibuf1->x << 2); 00318 for(x=ibuf2->x;x>0;x--){ 00319 if (do_rect) { 00320 dest[0] = (p1[0] + p2[0] + p1[4] + p2[4]) >> 2; 00321 dest[1] = (p1[1] + p2[1] + p1[5] + p2[5]) >> 2; 00322 dest[2] = (p1[2] + p2[2] + p1[6] + p2[6]) >> 2; 00323 dest[3] = (p1[3] + p2[3] + p1[7] + p2[7]) >> 2; 00324 p1 += 8; 00325 p2 += 8; 00326 dest += 4; 00327 } 00328 if (do_float){ 00329 destf[0] = 0.25f*(p1f[0] + p2f[0] + p1f[4] + p2f[4]); 00330 destf[1] = 0.25f*(p1f[1] + p2f[1] + p1f[5] + p2f[5]); 00331 destf[2] = 0.25f*(p1f[2] + p2f[2] + p1f[6] + p2f[6]); 00332 destf[3] = 0.25f*(p1f[3] + p2f[3] + p1f[7] + p2f[7]); 00333 p1f += 8; 00334 p2f += 8; 00335 destf += 4; 00336 } 00337 } 00338 if (do_rect) p1=p2; 00339 if (do_float) p1f=p2f; 00340 if(ibuf1->x & 1) { 00341 if (do_rect) p1+=4; 00342 if (do_float) p1f+=4; 00343 } 00344 } 00345 00346 } 00347 00348 struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1) 00349 { 00350 struct ImBuf *ibuf2; 00351 00352 if (ibuf1==NULL) return (NULL); 00353 if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (NULL); 00354 00355 if (ibuf1->x <= 1) return(IMB_half_y(ibuf1)); 00356 if (ibuf1->y <= 1) return(IMB_half_x(ibuf1)); 00357 00358 ibuf2=IMB_allocImBuf((ibuf1->x)/2, (ibuf1->y)/2, ibuf1->depth, ibuf1->flags); 00359 if (ibuf2==NULL) return (NULL); 00360 00361 imb_onehalf_no_alloc(ibuf2, ibuf1); 00362 00363 return (ibuf2); 00364 } 00365 00366 /* q_scale_linear_interpolation helper functions */ 00367 00368 static void enlarge_picture_byte( 00369 unsigned char* src, unsigned char* dst, int src_width, 00370 int src_height, int dst_width, int dst_height) 00371 { 00372 double ratiox = (double) (dst_width - 1.0) 00373 / (double) (src_width - 1.001); 00374 double ratioy = (double) (dst_height - 1.0) 00375 / (double) (src_height - 1.001); 00376 uintptr_t x_src, dx_src, x_dst; 00377 uintptr_t y_src, dy_src, y_dst; 00378 00379 dx_src = 65536.0 / ratiox; 00380 dy_src = 65536.0 / ratioy; 00381 00382 y_src = 0; 00383 for (y_dst = 0; y_dst < dst_height; y_dst++) { 00384 unsigned char* line1 = src + (y_src >> 16) * 4 * src_width; 00385 unsigned char* line2 = line1 + 4 * src_width; 00386 uintptr_t weight1y = 65536 - (y_src & 0xffff); 00387 uintptr_t weight2y = 65536 - weight1y; 00388 00389 if ((y_src >> 16) == src_height - 1) { 00390 line2 = line1; 00391 } 00392 00393 x_src = 0; 00394 for (x_dst = 0; x_dst < dst_width; x_dst++) { 00395 uintptr_t weight1x = 65536 - (x_src & 0xffff); 00396 uintptr_t weight2x = 65536 - weight1x; 00397 00398 unsigned long x = (x_src >> 16) * 4; 00399 00400 *dst++ = ((((line1[x] * weight1y) >> 16) 00401 * weight1x) >> 16) 00402 + ((((line2[x] * weight2y) >> 16) 00403 * weight1x) >> 16) 00404 + ((((line1[4 + x] * weight1y) >> 16) 00405 * weight2x) >> 16) 00406 + ((((line2[4 + x] * weight2y) >> 16) 00407 * weight2x) >> 16); 00408 00409 *dst++ = ((((line1[x + 1] * weight1y) >> 16) 00410 * weight1x) >> 16) 00411 + ((((line2[x + 1] * weight2y) >> 16) 00412 * weight1x) >> 16) 00413 + ((((line1[4 + x + 1] * weight1y) >> 16) 00414 * weight2x) >> 16) 00415 + ((((line2[4 + x + 1] * weight2y) >> 16) 00416 * weight2x) >> 16); 00417 00418 *dst++ = ((((line1[x + 2] * weight1y) >> 16) 00419 * weight1x) >> 16) 00420 + ((((line2[x + 2] * weight2y) >> 16) 00421 * weight1x) >> 16) 00422 + ((((line1[4 + x + 2] * weight1y) >> 16) 00423 * weight2x) >> 16) 00424 + ((((line2[4 + x + 2] * weight2y) >> 16) 00425 * weight2x) >> 16); 00426 00427 *dst++ = ((((line1[x + 3] * weight1y) >> 16) 00428 * weight1x) >> 16) 00429 + ((((line2[x + 3] * weight2y) >> 16) 00430 * weight1x) >> 16) 00431 + ((((line1[4 + x + 3] * weight1y) >> 16) 00432 * weight2x) >> 16) 00433 + ((((line2[4 + x + 3] * weight2y) >> 16) 00434 * weight2x) >> 16); 00435 00436 x_src += dx_src; 00437 } 00438 y_src += dy_src; 00439 } 00440 } 00441 00442 struct scale_outpix_byte { 00443 uintptr_t r; 00444 uintptr_t g; 00445 uintptr_t b; 00446 uintptr_t a; 00447 00448 uintptr_t weight; 00449 }; 00450 00451 static void shrink_picture_byte( 00452 unsigned char* src, unsigned char* dst, int src_width, 00453 int src_height, int dst_width, int dst_height) 00454 { 00455 double ratiox = (double) (dst_width) / (double) (src_width); 00456 double ratioy = (double) (dst_height) / (double) (src_height); 00457 uintptr_t x_src, dx_dst, x_dst; 00458 uintptr_t y_src, dy_dst, y_dst; 00459 intptr_t y_counter; 00460 unsigned char * dst_begin = dst; 00461 00462 struct scale_outpix_byte * dst_line1 = NULL; 00463 struct scale_outpix_byte * dst_line2 = NULL; 00464 00465 dst_line1 = (struct scale_outpix_byte*) MEM_callocN( 00466 (dst_width + 1) * sizeof(struct scale_outpix_byte), 00467 "shrink_picture_byte 1"); 00468 dst_line2 = (struct scale_outpix_byte*) MEM_callocN( 00469 (dst_width + 1) * sizeof(struct scale_outpix_byte), 00470 "shrink_picture_byte 2"); 00471 00472 dx_dst = 65536.0 * ratiox; 00473 dy_dst = 65536.0 * ratioy; 00474 00475 y_dst = 0; 00476 y_counter = 65536; 00477 for (y_src = 0; y_src < src_height; y_src++) { 00478 unsigned char* line = src + y_src * 4 * src_width; 00479 uintptr_t weight1y = 65535 - (y_dst & 0xffff); 00480 uintptr_t weight2y = 65535 - weight1y; 00481 x_dst = 0; 00482 for (x_src = 0; x_src < src_width; x_src++) { 00483 uintptr_t weight1x = 65535 - (x_dst & 0xffff); 00484 uintptr_t weight2x = 65535 - weight1x; 00485 00486 uintptr_t x = x_dst >> 16; 00487 00488 uintptr_t w; 00489 00490 w = (weight1y * weight1x) >> 16; 00491 00492 /* ensure correct rounding, without this you get ugly banding, or too low color values (ton) */ 00493 dst_line1[x].r += (line[0] * w + 32767) >> 16; 00494 dst_line1[x].g += (line[1] * w + 32767) >> 16; 00495 dst_line1[x].b += (line[2] * w + 32767) >> 16; 00496 dst_line1[x].a += (line[3] * w + 32767) >> 16; 00497 dst_line1[x].weight += w; 00498 00499 w = (weight2y * weight1x) >> 16; 00500 00501 dst_line2[x].r += (line[0] * w + 32767) >> 16; 00502 dst_line2[x].g += (line[1] * w + 32767) >> 16; 00503 dst_line2[x].b += (line[2] * w + 32767) >> 16; 00504 dst_line2[x].a += (line[3] * w + 32767) >> 16; 00505 dst_line2[x].weight += w; 00506 00507 w = (weight1y * weight2x) >> 16; 00508 00509 dst_line1[x+1].r += (line[0] * w + 32767) >> 16; 00510 dst_line1[x+1].g += (line[1] * w + 32767) >> 16; 00511 dst_line1[x+1].b += (line[2] * w + 32767) >> 16; 00512 dst_line1[x+1].a += (line[3] * w + 32767) >> 16; 00513 dst_line1[x+1].weight += w; 00514 00515 w = (weight2y * weight2x) >> 16; 00516 00517 dst_line2[x+1].r += (line[0] * w + 32767) >> 16; 00518 dst_line2[x+1].g += (line[1] * w + 32767) >> 16; 00519 dst_line2[x+1].b += (line[2] * w + 32767) >> 16; 00520 dst_line2[x+1].a += (line[3] * w + 32767) >> 16; 00521 dst_line2[x+1].weight += w; 00522 00523 x_dst += dx_dst; 00524 line += 4; 00525 } 00526 00527 y_dst += dy_dst; 00528 y_counter -= dy_dst; 00529 if (y_counter < 0) { 00530 int val; 00531 uintptr_t x; 00532 struct scale_outpix_byte * temp; 00533 00534 y_counter += 65536; 00535 00536 for (x=0; x < dst_width; x++) { 00537 uintptr_t f = 0x80000000UL / dst_line1[x].weight; 00538 *dst++ = (val= (dst_line1[x].r * f) >> 15) > 255 ? 255: val; 00539 *dst++ = (val= (dst_line1[x].g * f) >> 15) > 255 ? 255: val; 00540 *dst++ = (val= (dst_line1[x].b * f) >> 15) > 255 ? 255: val; 00541 *dst++ = (val= (dst_line1[x].a * f) >> 15) > 255 ? 255: val; 00542 } 00543 memset(dst_line1, 0, dst_width * 00544 sizeof(struct scale_outpix_byte)); 00545 temp = dst_line1; 00546 dst_line1 = dst_line2; 00547 dst_line2 = temp; 00548 } 00549 } 00550 if (dst - dst_begin < dst_width * dst_height * 4) { 00551 int val; 00552 uintptr_t x; 00553 for (x = 0; x < dst_width; x++) { 00554 uintptr_t f = 0x80000000UL / dst_line1[x].weight; 00555 *dst++ = (val= (dst_line1[x].r * f) >> 15) > 255 ? 255: val; 00556 *dst++ = (val= (dst_line1[x].g * f) >> 15) > 255 ? 255: val; 00557 *dst++ = (val= (dst_line1[x].b * f) >> 15) > 255 ? 255: val; 00558 *dst++ = (val= (dst_line1[x].a * f) >> 15) > 255 ? 255: val; 00559 } 00560 } 00561 MEM_freeN(dst_line1); 00562 MEM_freeN(dst_line2); 00563 } 00564 00565 00566 static void q_scale_byte(unsigned char* in, unsigned char* out, int in_width, 00567 int in_height, int dst_width, int dst_height) 00568 { 00569 if (dst_width > in_width && dst_height > in_height) { 00570 enlarge_picture_byte(in, out, in_width, in_height, 00571 dst_width, dst_height); 00572 } else if (dst_width < in_width && dst_height < in_height) { 00573 shrink_picture_byte(in, out, in_width, in_height, 00574 dst_width, dst_height); 00575 } 00576 } 00577 00578 static void enlarge_picture_float( 00579 float* src, float* dst, int src_width, 00580 int src_height, int dst_width, int dst_height) 00581 { 00582 double ratiox = (double) (dst_width - 1.0) 00583 / (double) (src_width - 1.001); 00584 double ratioy = (double) (dst_height - 1.0) 00585 / (double) (src_height - 1.001); 00586 uintptr_t x_dst; 00587 uintptr_t y_dst; 00588 double x_src, dx_src; 00589 double y_src, dy_src; 00590 00591 dx_src = 1.0 / ratiox; 00592 dy_src = 1.0 / ratioy; 00593 00594 y_src = 0; 00595 for (y_dst = 0; y_dst < dst_height; y_dst++) { 00596 float* line1 = src + ((int) y_src) * 4 * src_width; 00597 float* line2 = line1 + 4 * src_width; 00598 const float weight1y = (float)(1.0 - (y_src - (int) y_src)); 00599 const float weight2y = 1.0f - weight1y; 00600 00601 if ((int) y_src == src_height - 1) { 00602 line2 = line1; 00603 } 00604 00605 x_src = 0; 00606 for (x_dst = 0; x_dst < dst_width; x_dst++) { 00607 const float weight1x = (float)(1.0 - (x_src - (int) x_src)); 00608 const float weight2x = (float)(1.0f - weight1x); 00609 00610 const float w11 = weight1y * weight1x; 00611 const float w21 = weight2y * weight1x; 00612 const float w12 = weight1y * weight2x; 00613 const float w22 = weight2y * weight2x; 00614 00615 uintptr_t x = ((int) x_src) * 4; 00616 00617 *dst++ = line1[x] * w11 00618 + line2[x] * w21 00619 + line1[4 + x] * w12 00620 + line2[4 + x] * w22; 00621 00622 *dst++ = line1[x + 1] * w11 00623 + line2[x + 1] * w21 00624 + line1[4 + x + 1] * w12 00625 + line2[4 + x + 1] * w22; 00626 00627 *dst++ = line1[x + 2] * w11 00628 + line2[x + 2] * w21 00629 + line1[4 + x + 2] * w12 00630 + line2[4 + x + 2] * w22; 00631 00632 *dst++ = line1[x + 3] * w11 00633 + line2[x + 3] * w21 00634 + line1[4 + x + 3] * w12 00635 + line2[4 + x + 3] * w22; 00636 00637 x_src += dx_src; 00638 } 00639 y_src += dy_src; 00640 } 00641 } 00642 00643 struct scale_outpix_float { 00644 float r; 00645 float g; 00646 float b; 00647 float a; 00648 00649 float weight; 00650 }; 00651 00652 static void shrink_picture_float( 00653 float* src, float* dst, int src_width, 00654 int src_height, int dst_width, int dst_height) 00655 { 00656 double ratiox = (double) (dst_width) / (double) (src_width); 00657 double ratioy = (double) (dst_height) / (double) (src_height); 00658 uintptr_t x_src; 00659 uintptr_t y_src; 00660 float dx_dst, x_dst; 00661 float dy_dst, y_dst; 00662 float y_counter; 00663 float * dst_begin = dst; 00664 00665 struct scale_outpix_float * dst_line1; 00666 struct scale_outpix_float * dst_line2; 00667 00668 dst_line1 = (struct scale_outpix_float*) MEM_callocN( 00669 (dst_width + 1) * sizeof(struct scale_outpix_float), 00670 "shrink_picture_float 1"); 00671 dst_line2 = (struct scale_outpix_float*) MEM_callocN( 00672 (dst_width + 1) * sizeof(struct scale_outpix_float), 00673 "shrink_picture_float 2"); 00674 00675 dx_dst = ratiox; 00676 dy_dst = ratioy; 00677 00678 y_dst = 0; 00679 y_counter = 1.0; 00680 for (y_src = 0; y_src < src_height; y_src++) { 00681 float* line = src + y_src * 4 * src_width; 00682 uintptr_t weight1y = 1.0f - (y_dst - (int) y_dst); 00683 uintptr_t weight2y = 1.0f - weight1y; 00684 x_dst = 0; 00685 for (x_src = 0; x_src < src_width; x_src++) { 00686 uintptr_t weight1x = 1.0f - (x_dst - (int) x_dst); 00687 uintptr_t weight2x = 1.0f - weight1x; 00688 00689 uintptr_t x = (int) x_dst; 00690 00691 float w; 00692 00693 w = weight1y * weight1x; 00694 00695 dst_line1[x].r += line[0] * w; 00696 dst_line1[x].g += line[1] * w; 00697 dst_line1[x].b += line[2] * w; 00698 dst_line1[x].a += line[3] * w; 00699 dst_line1[x].weight += w; 00700 00701 w = weight2y * weight1x; 00702 00703 dst_line2[x].r += line[0] * w; 00704 dst_line2[x].g += line[1] * w; 00705 dst_line2[x].b += line[2] * w; 00706 dst_line2[x].a += line[3] * w; 00707 dst_line2[x].weight += w; 00708 00709 w = weight1y * weight2x; 00710 00711 dst_line1[x+1].r += line[0] * w; 00712 dst_line1[x+1].g += line[1] * w; 00713 dst_line1[x+1].b += line[2] * w; 00714 dst_line1[x+1].a += line[3] * w; 00715 dst_line1[x+1].weight += w; 00716 00717 w = weight2y * weight2x; 00718 00719 dst_line2[x+1].r += line[0] * w; 00720 dst_line2[x+1].g += line[1] * w; 00721 dst_line2[x+1].b += line[2] * w; 00722 dst_line2[x+1].a += line[3] * w; 00723 dst_line2[x+1].weight += w; 00724 00725 x_dst += dx_dst; 00726 line += 4; 00727 } 00728 00729 y_dst += dy_dst; 00730 y_counter -= dy_dst; 00731 if (y_counter < 0) { 00732 uintptr_t x; 00733 struct scale_outpix_float * temp; 00734 00735 y_counter += 1.0f; 00736 00737 for (x=0; x < dst_width; x++) { 00738 float f = 1.0f / dst_line1[x].weight; 00739 *dst++ = dst_line1[x].r * f; 00740 *dst++ = dst_line1[x].g * f; 00741 *dst++ = dst_line1[x].b * f; 00742 *dst++ = dst_line1[x].a * f; 00743 } 00744 memset(dst_line1, 0, dst_width * 00745 sizeof(struct scale_outpix_float)); 00746 temp = dst_line1; 00747 dst_line1 = dst_line2; 00748 dst_line2 = temp; 00749 } 00750 } 00751 if (dst - dst_begin < dst_width * dst_height * 4) { 00752 uintptr_t x; 00753 for (x = 0; x < dst_width; x++) { 00754 float f = 1.0f / dst_line1[x].weight; 00755 *dst++ = dst_line1[x].r * f; 00756 *dst++ = dst_line1[x].g * f; 00757 *dst++ = dst_line1[x].b * f; 00758 *dst++ = dst_line1[x].a * f; 00759 } 00760 } 00761 MEM_freeN(dst_line1); 00762 MEM_freeN(dst_line2); 00763 } 00764 00765 00766 static void q_scale_float(float* in, float* out, int in_width, 00767 int in_height, int dst_width, int dst_height) 00768 { 00769 if (dst_width > in_width && dst_height > in_height) { 00770 enlarge_picture_float(in, out, in_width, in_height, 00771 dst_width, dst_height); 00772 } else if (dst_width < in_width && dst_height < in_height) { 00773 shrink_picture_float(in, out, in_width, in_height, 00774 dst_width, dst_height); 00775 } 00776 } 00777 00778 /* q_scale_linear_interpolation (derived from ppmqscale, http://libdv.sf.net) 00779 00780 q stands for quick _and_ quality :) 00781 00782 only handles common cases when we either 00783 00784 scale both, x and y or 00785 shrink both, x and y 00786 00787 but that is pretty fast: 00788 * does only blit once instead of two passes like the old code 00789 (fewer cache misses) 00790 * uses fixed point integer arithmetic for byte buffers 00791 * doesn't branch in tight loops 00792 00793 Should be comparable in speed to the ImBuf ..._fast functions at least 00794 for byte-buffers. 00795 00796 NOTE: disabled, due to inacceptable inaccuracy and quality loss, see bug #18609 (ton) 00797 00798 */ 00799 static int q_scale_linear_interpolation( 00800 struct ImBuf *ibuf, int newx, int newy) 00801 { 00802 if ((newx >= ibuf->x && newy <= ibuf->y) || 00803 (newx <= ibuf->x && newy >= ibuf->y)) { 00804 return FALSE; 00805 } 00806 00807 if (ibuf->rect) { 00808 unsigned char * newrect = 00809 MEM_mallocN(newx * newy * sizeof(int), "q_scale rect"); 00810 q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y, 00811 newx, newy); 00812 00813 imb_freerectImBuf(ibuf); 00814 ibuf->mall |= IB_rect; 00815 ibuf->rect = (unsigned int *) newrect; 00816 } 00817 if (ibuf->rect_float) { 00818 float * newrect = 00819 MEM_mallocN(newx * newy * 4 *sizeof(float), 00820 "q_scale rectfloat"); 00821 q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y, 00822 newx, newy); 00823 imb_freerectfloatImBuf(ibuf); 00824 ibuf->mall |= IB_rectfloat; 00825 ibuf->rect_float = newrect; 00826 } 00827 ibuf->x = newx; 00828 ibuf->y = newy; 00829 00830 return TRUE; 00831 } 00832 00833 static struct ImBuf *scaledownx(struct ImBuf *ibuf, int newx) 00834 { 00835 const int do_rect= (ibuf->rect != NULL); 00836 const int do_float= (ibuf->rect_float != NULL); 00837 const size_t rect_size= ibuf->x * ibuf->y * 4; 00838 00839 uchar *rect, *_newrect, *newrect; 00840 float *rectf, *_newrectf, *newrectf; 00841 float sample, add, val[4], nval[4], valf[4], nvalf[4]; 00842 int x, y; 00843 00844 rectf= _newrectf= newrectf= NULL; 00845 rect=_newrect= newrect= NULL; 00846 nval[0]= nval[1]= nval[2]= nval[3]= 0.0f; 00847 nvalf[0]=nvalf[1]=nvalf[2]=nvalf[3]= 0.0f; 00848 00849 if (!do_rect && !do_float) return (ibuf); 00850 00851 if (do_rect) { 00852 _newrect = MEM_mallocN(newx * ibuf->y * sizeof(uchar) * 4, "scaledownx"); 00853 if (_newrect==NULL) return(ibuf); 00854 } 00855 if (do_float) { 00856 _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaledownxf"); 00857 if (_newrectf==NULL) { 00858 if (_newrect) MEM_freeN(_newrect); 00859 return(ibuf); 00860 } 00861 } 00862 00863 add = (ibuf->x - 0.01) / newx; 00864 00865 if (do_rect) { 00866 rect = (uchar *) ibuf->rect; 00867 newrect = _newrect; 00868 } 00869 if (do_float) { 00870 rectf = ibuf->rect_float; 00871 newrectf = _newrectf; 00872 } 00873 00874 for (y = ibuf->y; y>0 ; y--) { 00875 sample = 0.0f; 00876 val[0]= val[1]= val[2]= val[3]= 0.0f; 00877 valf[0]=valf[1]=valf[2]=valf[3]= 0.0f; 00878 00879 for (x = newx ; x>0 ; x--) { 00880 if (do_rect) { 00881 nval[0] = - val[0] * sample; 00882 nval[1] = - val[1] * sample; 00883 nval[2] = - val[2] * sample; 00884 nval[3] = - val[3] * sample; 00885 } 00886 if (do_float) { 00887 nvalf[0] = - valf[0] * sample; 00888 nvalf[1] = - valf[1] * sample; 00889 nvalf[2] = - valf[2] * sample; 00890 nvalf[3] = - valf[3] * sample; 00891 } 00892 00893 sample += add; 00894 00895 while (sample >= 1.0f){ 00896 sample -= 1.0f; 00897 00898 if (do_rect) { 00899 nval[0] += rect[0]; 00900 nval[1] += rect[1]; 00901 nval[2] += rect[2]; 00902 nval[3] += rect[3]; 00903 rect += 4; 00904 } 00905 if (do_float) { 00906 nvalf[0] += rectf[0]; 00907 nvalf[1] += rectf[1]; 00908 nvalf[2] += rectf[2]; 00909 nvalf[3] += rectf[3]; 00910 rectf += 4; 00911 } 00912 } 00913 00914 if (do_rect) { 00915 val[0]= rect[0];val[1]= rect[1];val[2]= rect[2];val[3]= rect[3]; 00916 rect += 4; 00917 00918 newrect[0] = ((nval[0] + sample * val[0])/add + 0.5f); 00919 newrect[1] = ((nval[1] + sample * val[1])/add + 0.5f); 00920 newrect[2] = ((nval[2] + sample * val[2])/add + 0.5f); 00921 newrect[3] = ((nval[3] + sample * val[3])/add + 0.5f); 00922 00923 newrect += 4; 00924 } 00925 if (do_float) { 00926 00927 valf[0]= rectf[0];valf[1]= rectf[1];valf[2]= rectf[2];valf[3]= rectf[3]; 00928 rectf += 4; 00929 00930 newrectf[0] = ((nvalf[0] + sample * valf[0])/add); 00931 newrectf[1] = ((nvalf[1] + sample * valf[1])/add); 00932 newrectf[2] = ((nvalf[2] + sample * valf[2])/add); 00933 newrectf[3] = ((nvalf[3] + sample * valf[3])/add); 00934 00935 newrectf += 4; 00936 } 00937 00938 sample -= 1.0f; 00939 } 00940 } 00941 00942 if (do_rect) { 00943 // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); 00944 BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ 00945 imb_freerectImBuf(ibuf); 00946 ibuf->mall |= IB_rect; 00947 ibuf->rect = (unsigned int *) _newrect; 00948 } 00949 if (do_float) { 00950 // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); 00951 BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ 00952 imb_freerectfloatImBuf(ibuf); 00953 ibuf->mall |= IB_rectfloat; 00954 ibuf->rect_float = _newrectf; 00955 } 00956 (void)rect_size; /* UNUSED in release builds */ 00957 00958 ibuf->x = newx; 00959 return(ibuf); 00960 } 00961 00962 00963 static struct ImBuf *scaledowny(struct ImBuf *ibuf, int newy) 00964 { 00965 const int do_rect= (ibuf->rect != NULL); 00966 const int do_float= (ibuf->rect_float != NULL); 00967 const size_t rect_size= ibuf->x * ibuf->y * 4; 00968 00969 uchar *rect, *_newrect, *newrect; 00970 float *rectf, *_newrectf, *newrectf; 00971 float sample, add, val[4], nval[4], valf[4], nvalf[4]; 00972 int x, y, skipx; 00973 00974 rectf= _newrectf= newrectf= NULL; 00975 rect= _newrect= newrect= NULL; 00976 nval[0]= nval[1]= nval[2]= nval[3]= 0.0f; 00977 nvalf[0]=nvalf[1]=nvalf[2]=nvalf[3]= 0.0f; 00978 00979 if (!do_rect && !do_float) return (ibuf); 00980 00981 if (do_rect) { 00982 _newrect = MEM_mallocN(newy * ibuf->x * sizeof(uchar) * 4, "scaledowny"); 00983 if (_newrect==NULL) return(ibuf); 00984 } 00985 if (do_float) { 00986 _newrectf = MEM_mallocN(newy * ibuf->x * sizeof(float) * 4, "scaledownyf"); 00987 if (_newrectf==NULL) { 00988 if (_newrect) MEM_freeN(_newrect); 00989 return(ibuf); 00990 } 00991 } 00992 00993 add = (ibuf->y - 0.01) / newy; 00994 skipx = 4 * ibuf->x; 00995 00996 for (x = skipx - 4; x>=0 ; x-= 4) { 00997 if (do_rect) { 00998 rect = ((uchar *) ibuf->rect) + x; 00999 newrect = _newrect + x; 01000 } 01001 if (do_float) { 01002 rectf = ibuf->rect_float + x; 01003 newrectf = _newrectf + x; 01004 } 01005 01006 sample = 0.0f; 01007 val[0]= val[1]= val[2]= val[3]= 0.0f; 01008 valf[0]=valf[1]=valf[2]=valf[3]= 0.0f; 01009 01010 for (y = newy ; y>0 ; y--) { 01011 if (do_rect) { 01012 nval[0] = - val[0] * sample; 01013 nval[1] = - val[1] * sample; 01014 nval[2] = - val[2] * sample; 01015 nval[3] = - val[3] * sample; 01016 } 01017 if (do_float) { 01018 nvalf[0] = - valf[0] * sample; 01019 nvalf[1] = - valf[1] * sample; 01020 nvalf[2] = - valf[2] * sample; 01021 nvalf[3] = - valf[3] * sample; 01022 } 01023 01024 sample += add; 01025 01026 while (sample >= 1.0f) { 01027 sample -= 1.0f; 01028 01029 if (do_rect) { 01030 nval[0] += rect[0]; 01031 nval[1] += rect[1]; 01032 nval[2] += rect[2]; 01033 nval[3] += rect[3]; 01034 rect += skipx; 01035 } 01036 if (do_float) { 01037 nvalf[0] += rectf[0]; 01038 nvalf[1] += rectf[1]; 01039 nvalf[2] += rectf[2]; 01040 nvalf[3] += rectf[3]; 01041 rectf += skipx; 01042 } 01043 } 01044 01045 if (do_rect) { 01046 val[0]= rect[0];val[1]= rect[1];val[2]= rect[2];val[3]= rect[3]; 01047 rect += skipx; 01048 01049 newrect[0] = ((nval[0] + sample * val[0])/add + 0.5f); 01050 newrect[1] = ((nval[1] + sample * val[1])/add + 0.5f); 01051 newrect[2] = ((nval[2] + sample * val[2])/add + 0.5f); 01052 newrect[3] = ((nval[3] + sample * val[3])/add + 0.5f); 01053 01054 newrect += skipx; 01055 } 01056 if (do_float) { 01057 01058 valf[0]= rectf[0];valf[1]= rectf[1];valf[2]= rectf[2];valf[3]= rectf[3]; 01059 rectf += skipx; 01060 01061 newrectf[0] = ((nvalf[0] + sample * valf[0])/add); 01062 newrectf[1] = ((nvalf[1] + sample * valf[1])/add); 01063 newrectf[2] = ((nvalf[2] + sample * valf[2])/add); 01064 newrectf[3] = ((nvalf[3] + sample * valf[3])/add); 01065 01066 newrectf += skipx; 01067 } 01068 01069 sample -= 1.0f; 01070 } 01071 } 01072 01073 if (do_rect) { 01074 // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); 01075 BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug [#26502] */ 01076 imb_freerectImBuf(ibuf); 01077 ibuf->mall |= IB_rect; 01078 ibuf->rect = (unsigned int *) _newrect; 01079 } 01080 if (do_float) { 01081 // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); 01082 BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug [#26502] */ 01083 imb_freerectfloatImBuf(ibuf); 01084 ibuf->mall |= IB_rectfloat; 01085 ibuf->rect_float = (float *) _newrectf; 01086 } 01087 (void)rect_size; /* UNUSED in release builds */ 01088 01089 ibuf->y = newy; 01090 return(ibuf); 01091 } 01092 01093 01094 static struct ImBuf *scaleupx(struct ImBuf *ibuf, int newx) 01095 { 01096 uchar *rect,*_newrect=NULL,*newrect; 01097 float *rectf,*_newrectf=NULL,*newrectf; 01098 float sample,add; 01099 float val_a,nval_a,diff_a; 01100 float val_b,nval_b,diff_b; 01101 float val_g,nval_g,diff_g; 01102 float val_r,nval_r,diff_r; 01103 float val_af,nval_af,diff_af; 01104 float val_bf,nval_bf,diff_bf; 01105 float val_gf,nval_gf,diff_gf; 01106 float val_rf,nval_rf,diff_rf; 01107 int x,y, do_rect = 0, do_float = 0; 01108 01109 val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; 01110 val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; 01111 val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; 01112 val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; 01113 if (ibuf==NULL) return(NULL); 01114 if (ibuf->rect==NULL && ibuf->rect_float==NULL) return (ibuf); 01115 01116 if (ibuf->rect) { 01117 do_rect = 1; 01118 _newrect = MEM_mallocN(newx * ibuf->y * sizeof(int), "scaleupx"); 01119 if (_newrect==NULL) return(ibuf); 01120 } 01121 if (ibuf->rect_float) { 01122 do_float = 1; 01123 _newrectf = MEM_mallocN(newx * ibuf->y * sizeof(float) * 4, "scaleupxf"); 01124 if (_newrectf==NULL) { 01125 if (_newrect) MEM_freeN(_newrect); 01126 return(ibuf); 01127 } 01128 } 01129 01130 add = (ibuf->x - 1.001) / (newx - 1.0); 01131 01132 rect = (uchar *) ibuf->rect; 01133 rectf = (float *) ibuf->rect_float; 01134 newrect = _newrect; 01135 newrectf = _newrectf; 01136 01137 for (y = ibuf->y; y>0 ; y--){ 01138 01139 sample = 0; 01140 01141 if (do_rect) { 01142 val_a = rect[0] ; 01143 nval_a = rect[4]; 01144 diff_a = nval_a - val_a ; 01145 val_a += 0.5f; 01146 01147 val_b = rect[1] ; 01148 nval_b = rect[5]; 01149 diff_b = nval_b - val_b ; 01150 val_b += 0.5f; 01151 01152 val_g = rect[2] ; 01153 nval_g = rect[6]; 01154 diff_g = nval_g - val_g ; 01155 val_g += 0.5f; 01156 01157 val_r = rect[3] ; 01158 nval_r = rect[7]; 01159 diff_r = nval_r - val_r ; 01160 val_r += 0.5f; 01161 01162 rect += 8; 01163 } 01164 if (do_float) { 01165 val_af = rectf[0] ; 01166 nval_af = rectf[4]; 01167 diff_af = nval_af - val_af; 01168 01169 val_bf = rectf[1] ; 01170 nval_bf = rectf[5]; 01171 diff_bf = nval_bf - val_bf; 01172 01173 val_gf = rectf[2] ; 01174 nval_gf = rectf[6]; 01175 diff_gf = nval_gf - val_gf; 01176 01177 val_rf = rectf[3] ; 01178 nval_rf = rectf[7]; 01179 diff_rf = nval_rf - val_rf; 01180 01181 rectf += 8; 01182 } 01183 for (x = newx ; x>0 ; x--){ 01184 if (sample >= 1.0f){ 01185 sample -= 1.0f; 01186 01187 if (do_rect) { 01188 val_a = nval_a ; 01189 nval_a = rect[0] ; 01190 diff_a = nval_a - val_a ; 01191 val_a += 0.5f; 01192 01193 val_b = nval_b ; 01194 nval_b = rect[1] ; 01195 diff_b = nval_b - val_b ; 01196 val_b += 0.5f; 01197 01198 val_g = nval_g ; 01199 nval_g = rect[2] ; 01200 diff_g = nval_g - val_g ; 01201 val_g += 0.5f; 01202 01203 val_r = nval_r ; 01204 nval_r = rect[3] ; 01205 diff_r = nval_r - val_r ; 01206 val_r += 0.5f; 01207 rect += 4; 01208 } 01209 if (do_float) { 01210 val_af = nval_af ; 01211 nval_af = rectf[0] ; 01212 diff_af = nval_af - val_af ; 01213 01214 val_bf = nval_bf ; 01215 nval_bf = rectf[1] ; 01216 diff_bf = nval_bf - val_bf ; 01217 01218 val_gf = nval_gf ; 01219 nval_gf = rectf[2] ; 01220 diff_gf = nval_gf - val_gf ; 01221 01222 val_rf = nval_rf ; 01223 nval_rf = rectf[3] ; 01224 diff_rf = nval_rf - val_rf; 01225 rectf += 4; 01226 } 01227 } 01228 if (do_rect) { 01229 newrect[0] = val_a + sample * diff_a; 01230 newrect[1] = val_b + sample * diff_b; 01231 newrect[2] = val_g + sample * diff_g; 01232 newrect[3] = val_r + sample * diff_r; 01233 newrect += 4; 01234 } 01235 if (do_float) { 01236 newrectf[0] = val_af + sample * diff_af; 01237 newrectf[1] = val_bf + sample * diff_bf; 01238 newrectf[2] = val_gf + sample * diff_gf; 01239 newrectf[3] = val_rf + sample * diff_rf; 01240 newrectf += 4; 01241 } 01242 sample += add; 01243 } 01244 } 01245 01246 if (do_rect) { 01247 imb_freerectImBuf(ibuf); 01248 ibuf->mall |= IB_rect; 01249 ibuf->rect = (unsigned int *) _newrect; 01250 } 01251 if (do_float) { 01252 imb_freerectfloatImBuf(ibuf); 01253 ibuf->mall |= IB_rectfloat; 01254 ibuf->rect_float = (float *) _newrectf; 01255 } 01256 01257 ibuf->x = newx; 01258 return(ibuf); 01259 } 01260 01261 static struct ImBuf *scaleupy(struct ImBuf *ibuf, int newy) 01262 { 01263 uchar *rect,*_newrect=NULL,*newrect; 01264 float *rectf,*_newrectf=NULL,*newrectf; 01265 float sample,add; 01266 float val_a,nval_a,diff_a; 01267 float val_b,nval_b,diff_b; 01268 float val_g,nval_g,diff_g; 01269 float val_r,nval_r,diff_r; 01270 float val_af,nval_af,diff_af; 01271 float val_bf,nval_bf,diff_bf; 01272 float val_gf,nval_gf,diff_gf; 01273 float val_rf,nval_rf,diff_rf; 01274 int x,y, do_rect = 0, do_float = 0, skipx; 01275 01276 val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; 01277 val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; 01278 val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; 01279 val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; 01280 if (ibuf==NULL) return(NULL); 01281 if (ibuf->rect==NULL && ibuf->rect_float==NULL) return (ibuf); 01282 01283 if (ibuf->rect) { 01284 do_rect = 1; 01285 _newrect = MEM_mallocN(ibuf->x * newy * sizeof(int), "scaleupy"); 01286 if (_newrect==NULL) return(ibuf); 01287 } 01288 if (ibuf->rect_float) { 01289 do_float = 1; 01290 _newrectf = MEM_mallocN(ibuf->x * newy * sizeof(float) * 4, "scaleupyf"); 01291 if (_newrectf==NULL) { 01292 if (_newrect) MEM_freeN(_newrect); 01293 return(ibuf); 01294 } 01295 } 01296 01297 add = (ibuf->y - 1.001) / (newy - 1.0); 01298 skipx = 4 * ibuf->x; 01299 01300 rect = (uchar *) ibuf->rect; 01301 rectf = (float *) ibuf->rect_float; 01302 newrect = _newrect; 01303 newrectf = _newrectf; 01304 01305 for (x = ibuf->x; x>0 ; x--){ 01306 01307 sample = 0; 01308 if (do_rect) { 01309 rect = ((uchar *)ibuf->rect) + 4*(x-1); 01310 newrect = _newrect + 4*(x-1); 01311 01312 val_a = rect[0] ; 01313 nval_a = rect[skipx]; 01314 diff_a = nval_a - val_a ; 01315 val_a += 0.5f; 01316 01317 val_b = rect[1] ; 01318 nval_b = rect[skipx+1]; 01319 diff_b = nval_b - val_b ; 01320 val_b += 0.5f; 01321 01322 val_g = rect[2] ; 01323 nval_g = rect[skipx+2]; 01324 diff_g = nval_g - val_g ; 01325 val_g += 0.5f; 01326 01327 val_r = rect[3] ; 01328 nval_r = rect[skipx+4]; 01329 diff_r = nval_r - val_r ; 01330 val_r += 0.5f; 01331 01332 rect += 2*skipx; 01333 } 01334 if (do_float) { 01335 rectf = ((float *)ibuf->rect_float) + 4*(x-1); 01336 newrectf = _newrectf + 4*(x-1); 01337 01338 val_af = rectf[0] ; 01339 nval_af = rectf[skipx]; 01340 diff_af = nval_af - val_af; 01341 01342 val_bf = rectf[1] ; 01343 nval_bf = rectf[skipx+1]; 01344 diff_bf = nval_bf - val_bf; 01345 01346 val_gf = rectf[2] ; 01347 nval_gf = rectf[skipx+2]; 01348 diff_gf = nval_gf - val_gf; 01349 01350 val_rf = rectf[3] ; 01351 nval_rf = rectf[skipx+3]; 01352 diff_rf = nval_rf - val_rf; 01353 01354 rectf += 2*skipx; 01355 } 01356 01357 for (y = newy ; y>0 ; y--){ 01358 if (sample >= 1.0f){ 01359 sample -= 1.0f; 01360 01361 if (do_rect) { 01362 val_a = nval_a ; 01363 nval_a = rect[0] ; 01364 diff_a = nval_a - val_a ; 01365 val_a += 0.5f; 01366 01367 val_b = nval_b ; 01368 nval_b = rect[1] ; 01369 diff_b = nval_b - val_b ; 01370 val_b += 0.5f; 01371 01372 val_g = nval_g ; 01373 nval_g = rect[2] ; 01374 diff_g = nval_g - val_g ; 01375 val_g += 0.5f; 01376 01377 val_r = nval_r ; 01378 nval_r = rect[3] ; 01379 diff_r = nval_r - val_r ; 01380 val_r += 0.5f; 01381 rect += skipx; 01382 } 01383 if (do_float) { 01384 val_af = nval_af ; 01385 nval_af = rectf[0] ; 01386 diff_af = nval_af - val_af ; 01387 01388 val_bf = nval_bf ; 01389 nval_bf = rectf[1] ; 01390 diff_bf = nval_bf - val_bf ; 01391 01392 val_gf = nval_gf ; 01393 nval_gf = rectf[2] ; 01394 diff_gf = nval_gf - val_gf ; 01395 01396 val_rf = nval_rf ; 01397 nval_rf = rectf[3] ; 01398 diff_rf = nval_rf - val_rf; 01399 rectf += skipx; 01400 } 01401 } 01402 if (do_rect) { 01403 newrect[0] = val_a + sample * diff_a; 01404 newrect[1] = val_b + sample * diff_b; 01405 newrect[2] = val_g + sample * diff_g; 01406 newrect[3] = val_r + sample * diff_r; 01407 newrect += skipx; 01408 } 01409 if (do_float) { 01410 newrectf[0] = val_af + sample * diff_af; 01411 newrectf[1] = val_bf + sample * diff_bf; 01412 newrectf[2] = val_gf + sample * diff_gf; 01413 newrectf[3] = val_rf + sample * diff_rf; 01414 newrectf += skipx; 01415 } 01416 sample += add; 01417 } 01418 } 01419 01420 if (do_rect) { 01421 imb_freerectImBuf(ibuf); 01422 ibuf->mall |= IB_rect; 01423 ibuf->rect = (unsigned int *) _newrect; 01424 } 01425 if (do_float) { 01426 imb_freerectfloatImBuf(ibuf); 01427 ibuf->mall |= IB_rectfloat; 01428 ibuf->rect_float = (float *) _newrectf; 01429 } 01430 01431 ibuf->y = newy; 01432 return(ibuf); 01433 } 01434 01435 01436 /* no float buf needed here! */ 01437 static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) 01438 { 01439 unsigned int *rect, *_newrect, *newrect; 01440 int x, y; 01441 int ofsx, ofsy, stepx, stepy; 01442 01443 if (ibuf->zbuf) { 01444 _newrect = MEM_mallocN(newx * newy * sizeof(int), "z rect"); 01445 if (_newrect==NULL) return; 01446 01447 stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; 01448 stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; 01449 ofsy = 32768; 01450 01451 newrect = _newrect; 01452 01453 for (y = newy; y > 0 ; y--){ 01454 rect = (unsigned int*) ibuf->zbuf; 01455 rect += (ofsy >> 16) * ibuf->x; 01456 ofsy += stepy; 01457 ofsx = 32768; 01458 for (x = newx ; x > 0 ; x--){ 01459 *newrect++ = rect[ofsx >> 16]; 01460 ofsx += stepx; 01461 } 01462 } 01463 01464 IMB_freezbufImBuf(ibuf); 01465 ibuf->mall |= IB_zbuf; 01466 ibuf->zbuf = (int*) _newrect; 01467 } 01468 } 01469 01470 struct ImBuf *IMB_scaleImBuf(struct ImBuf * ibuf, unsigned int newx, unsigned int newy) 01471 { 01472 if (ibuf==NULL) return (NULL); 01473 if (ibuf->rect==NULL && ibuf->rect_float==NULL) return (ibuf); 01474 01475 if (newx == ibuf->x && newy == ibuf->y) { return ibuf; } 01476 01477 /* scaleup / scaledown functions below change ibuf->x and ibuf->y 01478 so we first scale the Z-buffer (if any) */ 01479 scalefast_Z_ImBuf(ibuf, newx, newy); 01480 01481 /* try to scale common cases in a fast way */ 01482 /* disabled, quality loss is inacceptable, see report #18609 (ton) */ 01483 if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) { 01484 return ibuf; 01485 } 01486 01487 if (newx < ibuf->x) if (newx) scaledownx(ibuf,newx); 01488 if (newy < ibuf->y) if (newy) scaledowny(ibuf,newy); 01489 if (newx > ibuf->x) if (newx) scaleupx(ibuf,newx); 01490 if (newy > ibuf->y) if (newy) scaleupy(ibuf,newy); 01491 01492 return(ibuf); 01493 } 01494 01495 struct imbufRGBA { 01496 float r, g, b, a; 01497 }; 01498 01499 struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) 01500 { 01501 unsigned int *rect,*_newrect,*newrect; 01502 struct imbufRGBA *rectf, *_newrectf, *newrectf; 01503 int x,y, do_float=0, do_rect=0; 01504 int ofsx,ofsy,stepx,stepy; 01505 01506 rect = NULL; _newrect = NULL; newrect = NULL; 01507 rectf = NULL; _newrectf = NULL; newrectf = NULL; 01508 01509 if (ibuf==NULL) return(NULL); 01510 if (ibuf->rect) do_rect = 1; 01511 if (ibuf->rect_float) do_float = 1; 01512 if (do_rect==0 && do_float==0) return(ibuf); 01513 01514 if (newx == ibuf->x && newy == ibuf->y) return(ibuf); 01515 01516 if(do_rect) { 01517 _newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf"); 01518 if (_newrect==NULL) return(ibuf); 01519 newrect = _newrect; 01520 } 01521 01522 if (do_float) { 01523 _newrectf = MEM_mallocN(newx * newy * sizeof(float) * 4, "scalefastimbuf f"); 01524 if (_newrectf==NULL) { 01525 if (_newrect) MEM_freeN(_newrect); 01526 return(ibuf); 01527 } 01528 newrectf = _newrectf; 01529 } 01530 01531 stepx = (65536.0 * (ibuf->x - 1.0) / (newx - 1.0)) + 0.5; 01532 stepy = (65536.0 * (ibuf->y - 1.0) / (newy - 1.0)) + 0.5; 01533 ofsy = 32768; 01534 01535 for (y = newy; y > 0 ; y--){ 01536 if(do_rect) { 01537 rect = ibuf->rect; 01538 rect += (ofsy >> 16) * ibuf->x; 01539 } 01540 if (do_float) { 01541 rectf = (struct imbufRGBA *)ibuf->rect_float; 01542 rectf += (ofsy >> 16) * ibuf->x; 01543 } 01544 ofsy += stepy; 01545 ofsx = 32768; 01546 01547 if (do_rect) { 01548 for (x = newx ; x>0 ; x--){ 01549 *newrect++ = rect[ofsx >> 16]; 01550 ofsx += stepx; 01551 } 01552 } 01553 01554 if (do_float) { 01555 ofsx = 32768; 01556 for (x = newx ; x>0 ; x--){ 01557 *newrectf++ = rectf[ofsx >> 16]; 01558 ofsx += stepx; 01559 } 01560 } 01561 } 01562 01563 if (do_rect) { 01564 imb_freerectImBuf(ibuf); 01565 ibuf->mall |= IB_rect; 01566 ibuf->rect = _newrect; 01567 } 01568 01569 if (do_float) { 01570 imb_freerectfloatImBuf(ibuf); 01571 ibuf->mall |= IB_rectfloat; 01572 ibuf->rect_float = (float *)_newrectf; 01573 } 01574 01575 scalefast_Z_ImBuf(ibuf, newx, newy); 01576 01577 ibuf->x = newx; 01578 ibuf->y = newy; 01579 return(ibuf); 01580 } 01581