| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * allocimbuf.c | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup imbuf | 
					
						
							| 
									
										
										
										
											2011-02-27 20:23:21 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 16:23:00 +02:00
										 |  |  | #include <math.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-31 13:52:13 +00:00
										 |  |  | #include "BLI_math_color.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | #include "BLI_math_interp.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-16 05:46:10 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "IMB_imbuf.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "IMB_imbuf_types.h"
 | 
					
						
							|  |  |  | #include "imbuf.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "IMB_filter.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-10 18:19:55 +11:00
										 |  |  | #include "BLI_sys_types.h" /* for intptr_t support */
 | 
					
						
							| 
									
										
										
										
											2008-08-17 17:22:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | static void imb_half_x_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uchar *p1, *_p1, *dest; | 
					
						
							|  |  |  |   short a, r, g, b; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   float af, rf, gf, bf, *p1f, *_p1f, *destf; | 
					
						
							|  |  |  |   bool do_rect, do_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   do_rect = (ibuf1->rect != NULL); | 
					
						
							|  |  |  |   do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _p1 = (uchar *)ibuf1->rect; | 
					
						
							|  |  |  |   dest = (uchar *)ibuf2->rect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _p1f = ibuf1->rect_float; | 
					
						
							|  |  |  |   destf = ibuf2->rect_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = ibuf2->y; y > 0; y--) { | 
					
						
							|  |  |  |     p1 = _p1; | 
					
						
							|  |  |  |     p1f = _p1f; | 
					
						
							|  |  |  |     for (x = ibuf2->x; x > 0; x--) { | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         a = *(p1++); | 
					
						
							|  |  |  |         b = *(p1++); | 
					
						
							|  |  |  |         g = *(p1++); | 
					
						
							|  |  |  |         r = *(p1++); | 
					
						
							|  |  |  |         a += *(p1++); | 
					
						
							|  |  |  |         b += *(p1++); | 
					
						
							|  |  |  |         g += *(p1++); | 
					
						
							|  |  |  |         r += *(p1++); | 
					
						
							|  |  |  |         *(dest++) = a >> 1; | 
					
						
							|  |  |  |         *(dest++) = b >> 1; | 
					
						
							|  |  |  |         *(dest++) = g >> 1; | 
					
						
							|  |  |  |         *(dest++) = r >> 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         af = *(p1f++); | 
					
						
							|  |  |  |         bf = *(p1f++); | 
					
						
							|  |  |  |         gf = *(p1f++); | 
					
						
							|  |  |  |         rf = *(p1f++); | 
					
						
							|  |  |  |         af += *(p1f++); | 
					
						
							|  |  |  |         bf += *(p1f++); | 
					
						
							|  |  |  |         gf += *(p1f++); | 
					
						
							|  |  |  |         rf += *(p1f++); | 
					
						
							|  |  |  |         *(destf++) = 0.5f * af; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * bf; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * gf; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * rf; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (do_rect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       _p1 += (ibuf1->x << 2); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       _p1f += (ibuf1->x << 2); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | struct ImBuf *IMB_half_x(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1->x <= 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return (IMB_dupImBuf(ibuf1)); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf2 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   imb_half_x_no_alloc(ibuf2, ibuf1); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							|  |  |  |   int *p1, *dest, i, col, do_rect, do_float; | 
					
						
							|  |  |  |   float *p1f, *destf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   do_rect = (ibuf1->rect != NULL); | 
					
						
							|  |  |  |   do_float = (ibuf1->rect_float != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf2 = IMB_allocImBuf(2 * ibuf1->x, ibuf1->y, ibuf1->planes, ibuf1->flags); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf2 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   p1 = (int *)ibuf1->rect; | 
					
						
							|  |  |  |   dest = (int *)ibuf2->rect; | 
					
						
							|  |  |  |   p1f = (float *)ibuf1->rect_float; | 
					
						
							|  |  |  |   destf = (float *)ibuf2->rect_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = ibuf1->y * ibuf1->x; i > 0; i--) { | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       col = *p1++; | 
					
						
							|  |  |  |       *dest++ = col; | 
					
						
							|  |  |  |       *dest++ = col; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       destf[0] = destf[4] = p1f[0]; | 
					
						
							|  |  |  |       destf[1] = destf[5] = p1f[1]; | 
					
						
							|  |  |  |       destf[2] = destf[6] = p1f[2]; | 
					
						
							|  |  |  |       destf[3] = destf[7] = p1f[3]; | 
					
						
							|  |  |  |       destf += 8; | 
					
						
							|  |  |  |       p1f += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ImBuf *IMB_double_x(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ibuf2 = IMB_double_fast_x(ibuf1); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   imb_filterx(ibuf2); | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | static void imb_half_y_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uchar *p1, *p2, *_p1, *dest; | 
					
						
							|  |  |  |   short a, r, g, b; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   int do_rect, do_float; | 
					
						
							|  |  |  |   float af, rf, gf, bf, *p1f, *p2f, *_p1f, *destf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   p1 = p2 = NULL; | 
					
						
							|  |  |  |   p1f = p2f = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   do_rect = (ibuf1->rect != NULL); | 
					
						
							|  |  |  |   do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _p1 = (uchar *)ibuf1->rect; | 
					
						
							|  |  |  |   dest = (uchar *)ibuf2->rect; | 
					
						
							|  |  |  |   _p1f = (float *)ibuf1->rect_float; | 
					
						
							|  |  |  |   destf = (float *)ibuf2->rect_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = ibuf2->y; y > 0; y--) { | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       p1 = _p1; | 
					
						
							|  |  |  |       p2 = _p1 + (ibuf1->x << 2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       p1f = _p1f; | 
					
						
							|  |  |  |       p2f = _p1f + (ibuf1->x << 2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (x = ibuf2->x; x > 0; x--) { | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         a = *(p1++); | 
					
						
							|  |  |  |         b = *(p1++); | 
					
						
							|  |  |  |         g = *(p1++); | 
					
						
							|  |  |  |         r = *(p1++); | 
					
						
							|  |  |  |         a += *(p2++); | 
					
						
							|  |  |  |         b += *(p2++); | 
					
						
							|  |  |  |         g += *(p2++); | 
					
						
							|  |  |  |         r += *(p2++); | 
					
						
							|  |  |  |         *(dest++) = a >> 1; | 
					
						
							|  |  |  |         *(dest++) = b >> 1; | 
					
						
							|  |  |  |         *(dest++) = g >> 1; | 
					
						
							|  |  |  |         *(dest++) = r >> 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         af = *(p1f++); | 
					
						
							|  |  |  |         bf = *(p1f++); | 
					
						
							|  |  |  |         gf = *(p1f++); | 
					
						
							|  |  |  |         rf = *(p1f++); | 
					
						
							|  |  |  |         af += *(p2f++); | 
					
						
							|  |  |  |         bf += *(p2f++); | 
					
						
							|  |  |  |         gf += *(p2f++); | 
					
						
							|  |  |  |         rf += *(p2f++); | 
					
						
							|  |  |  |         *(destf++) = 0.5f * af; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * bf; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * gf; | 
					
						
							|  |  |  |         *(destf++) = 0.5f * rf; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (do_rect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       _p1 += (ibuf1->x << 3); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       _p1f += (ibuf1->x << 3); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ImBuf *IMB_half_y(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1->y <= 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return (IMB_dupImBuf(ibuf1)); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf2 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-13 19:07:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   imb_half_y_no_alloc(ibuf2, ibuf1); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							|  |  |  |   int *p1, *dest1, *dest2; | 
					
						
							|  |  |  |   float *p1f, *dest1f, *dest2f; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   int do_rect, do_float; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   do_rect = (ibuf1->rect != NULL); | 
					
						
							|  |  |  |   do_float = (ibuf1->rect_float != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf2 = IMB_allocImBuf(ibuf1->x, 2 * ibuf1->y, ibuf1->planes, ibuf1->flags); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf2 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   p1 = (int *)ibuf1->rect; | 
					
						
							|  |  |  |   dest1 = (int *)ibuf2->rect; | 
					
						
							|  |  |  |   p1f = (float *)ibuf1->rect_float; | 
					
						
							|  |  |  |   dest1f = (float *)ibuf2->rect_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = ibuf1->y; y > 0; y--) { | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       dest2 = dest1 + ibuf2->x; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       for (x = ibuf2->x; x > 0; x--) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         *dest1++ = *dest2++ = *p1++; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       dest1 = dest2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       dest2f = dest1f + (4 * ibuf2->x); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       for (x = ibuf2->x * 4; x > 0; x--) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         *dest1f++ = *dest2f++ = *p1f++; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       dest1f = dest2f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ImBuf *IMB_double_y(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ibuf2 = IMB_double_fast_y(ibuf1); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   IMB_filtery(ibuf2); | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 20:34:06 +00:00
										 |  |  | /* pretty much specific functions which converts uchar <-> ushort but assumes
 | 
					
						
							|  |  |  |  * ushort range of 255*255 which is more convenient here | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], | 
					
						
							|  |  |  |                                              const unsigned char color[4]) | 
					
						
							| 
									
										
										
										
											2013-01-04 20:34:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned short alpha = color[3]; | 
					
						
							| 
									
										
										
										
											2013-01-04 20:34:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   result[0] = color[0] * alpha; | 
					
						
							|  |  |  |   result[1] = color[1] * alpha; | 
					
						
							|  |  |  |   result[2] = color[2] * alpha; | 
					
						
							|  |  |  |   result[3] = alpha * 256; | 
					
						
							| 
									
										
										
										
											2013-01-04 20:34:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (color[3] <= 255) { | 
					
						
							|  |  |  |     result[0] = unit_ushort_to_uchar(color[0]); | 
					
						
							|  |  |  |     result[1] = unit_ushort_to_uchar(color[1]); | 
					
						
							|  |  |  |     result[2] = unit_ushort_to_uchar(color[2]); | 
					
						
							|  |  |  |     result[3] = unit_ushort_to_uchar(color[3]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     unsigned short alpha = color[3] / 256; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result[0] = unit_ushort_to_uchar((ushort)(color[0] / alpha * 256)); | 
					
						
							|  |  |  |     result[1] = unit_ushort_to_uchar((ushort)(color[1] / alpha * 256)); | 
					
						
							|  |  |  |     result[2] = unit_ushort_to_uchar((ushort)(color[2] / alpha * 256)); | 
					
						
							|  |  |  |     result[3] = unit_ushort_to_uchar(color[3]); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-01-04 20:34:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-14 18:02:41 +00:00
										 |  |  | /* result in ibuf2, scaling should be done correctly */ | 
					
						
							|  |  |  | void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int x, y; | 
					
						
							|  |  |  |   const short do_rect = (ibuf1->rect != NULL); | 
					
						
							|  |  |  |   const short do_float = (ibuf1->rect_float != NULL) && (ibuf2->rect_float != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect && (ibuf2->rect == NULL)) { | 
					
						
							|  |  |  |     imb_addrectImBuf(ibuf2); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf1->x <= 1) { | 
					
						
							|  |  |  |     imb_half_y_no_alloc(ibuf2, ibuf1); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->y <= 1) { | 
					
						
							|  |  |  |     imb_half_x_no_alloc(ibuf2, ibuf1); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     unsigned char *cp1, *cp2, *dest; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cp1 = (unsigned char *)ibuf1->rect; | 
					
						
							|  |  |  |     dest = (unsigned char *)ibuf2->rect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (y = ibuf2->y; y > 0; y--) { | 
					
						
							|  |  |  |       cp2 = cp1 + (ibuf1->x << 2); | 
					
						
							|  |  |  |       for (x = ibuf2->x; x > 0; x--) { | 
					
						
							|  |  |  |         unsigned short p1i[8], p2i[8], desti[4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         straight_uchar_to_premul_ushort(p1i, cp1); | 
					
						
							|  |  |  |         straight_uchar_to_premul_ushort(p2i, cp2); | 
					
						
							|  |  |  |         straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4); | 
					
						
							|  |  |  |         straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         desti[0] = ((unsigned int)p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2; | 
					
						
							|  |  |  |         desti[1] = ((unsigned int)p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2; | 
					
						
							|  |  |  |         desti[2] = ((unsigned int)p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2; | 
					
						
							|  |  |  |         desti[3] = ((unsigned int)p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         premul_ushort_to_straight_uchar(dest, desti); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cp1 += 8; | 
					
						
							|  |  |  |         cp2 += 8; | 
					
						
							|  |  |  |         dest += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       cp1 = cp2; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (ibuf1->x & 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         cp1 += 4; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     float *p1f, *p2f, *destf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     p1f = ibuf1->rect_float; | 
					
						
							|  |  |  |     destf = ibuf2->rect_float; | 
					
						
							|  |  |  |     for (y = ibuf2->y; y > 0; y--) { | 
					
						
							|  |  |  |       p2f = p1f + (ibuf1->x << 2); | 
					
						
							|  |  |  |       for (x = ibuf2->x; x > 0; x--) { | 
					
						
							|  |  |  |         destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); | 
					
						
							|  |  |  |         destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); | 
					
						
							|  |  |  |         destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); | 
					
						
							|  |  |  |         destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); | 
					
						
							|  |  |  |         p1f += 8; | 
					
						
							|  |  |  |         p2f += 8; | 
					
						
							|  |  |  |         destf += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       p1f = p2f; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (ibuf1->x & 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         p1f += 4; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | ImBuf *IMB_onehalf(struct ImBuf *ibuf1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   struct ImBuf *ibuf2; | 
					
						
							| 
									
										
										
										
											2010-12-14 18:02:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf1->x <= 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return (IMB_half_y(ibuf1)); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf1->y <= 1) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return (IMB_half_x(ibuf1)); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf2 == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   imb_onehalf_no_alloc(ibuf2, ibuf1); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:04:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf2; | 
					
						
							| 
									
										
										
										
											2010-12-14 18:02:41 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | /* q_scale_linear_interpolation helper functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void enlarge_picture_byte(unsigned char *src, | 
					
						
							|  |  |  |                                  unsigned char *dst, | 
					
						
							|  |  |  |                                  int src_width, | 
					
						
							|  |  |  |                                  int src_height, | 
					
						
							|  |  |  |                                  int dst_width, | 
					
						
							|  |  |  |                                  int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001); | 
					
						
							|  |  |  |   double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001); | 
					
						
							|  |  |  |   uintptr_t x_src, dx_src, x_dst; | 
					
						
							|  |  |  |   uintptr_t y_src, dy_src, y_dst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dx_src = 65536.0 / ratiox; | 
					
						
							|  |  |  |   dy_src = 65536.0 / ratioy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   y_src = 0; | 
					
						
							|  |  |  |   for (y_dst = 0; y_dst < dst_height; y_dst++) { | 
					
						
							|  |  |  |     unsigned char *line1 = src + (y_src >> 16) * 4 * src_width; | 
					
						
							|  |  |  |     unsigned char *line2 = line1 + 4 * src_width; | 
					
						
							|  |  |  |     uintptr_t weight1y = 65536 - (y_src & 0xffff); | 
					
						
							|  |  |  |     uintptr_t weight2y = 65536 - weight1y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((y_src >> 16) == src_height - 1) { | 
					
						
							|  |  |  |       line2 = line1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x_src = 0; | 
					
						
							|  |  |  |     for (x_dst = 0; x_dst < dst_width; x_dst++) { | 
					
						
							|  |  |  |       uintptr_t weight1x = 65536 - (x_src & 0xffff); | 
					
						
							|  |  |  |       uintptr_t weight2x = 65536 - weight1x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       unsigned long x = (x_src >> 16) * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = ((((line1[x] * weight1y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[x] * weight2y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line1[4 + x] * weight1y) >> 16) * weight2x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[4 + x] * weight2y) >> 16) * weight2x) >> 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = ((((line1[x + 1] * weight1y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[x + 1] * weight2y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line1[4 + x + 1] * weight1y) >> 16) * weight2x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[4 + x + 1] * weight2y) >> 16) * weight2x) >> 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = ((((line1[x + 2] * weight1y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[x + 2] * weight2y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line1[4 + x + 2] * weight1y) >> 16) * weight2x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[4 + x + 2] * weight2y) >> 16) * weight2x) >> 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = ((((line1[x + 3] * weight1y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[x + 3] * weight2y) >> 16) * weight1x) >> 16) + | 
					
						
							|  |  |  |                ((((line1[4 + x + 3] * weight1y) >> 16) * weight2x) >> 16) + | 
					
						
							|  |  |  |                ((((line2[4 + x + 3] * weight2y) >> 16) * weight2x) >> 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       x_src += dx_src; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     y_src += dy_src; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct scale_outpix_byte { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uintptr_t r; | 
					
						
							|  |  |  |   uintptr_t g; | 
					
						
							|  |  |  |   uintptr_t b; | 
					
						
							|  |  |  |   uintptr_t a; | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uintptr_t weight; | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void shrink_picture_byte(unsigned char *src, | 
					
						
							|  |  |  |                                 unsigned char *dst, | 
					
						
							|  |  |  |                                 int src_width, | 
					
						
							|  |  |  |                                 int src_height, | 
					
						
							|  |  |  |                                 int dst_width, | 
					
						
							|  |  |  |                                 int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   double ratiox = (double)(dst_width) / (double)(src_width); | 
					
						
							|  |  |  |   double ratioy = (double)(dst_height) / (double)(src_height); | 
					
						
							|  |  |  |   uintptr_t x_src, dx_dst, x_dst; | 
					
						
							|  |  |  |   uintptr_t y_src, dy_dst, y_dst; | 
					
						
							|  |  |  |   intptr_t y_counter; | 
					
						
							|  |  |  |   unsigned char *dst_begin = dst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct scale_outpix_byte *dst_line1 = NULL; | 
					
						
							|  |  |  |   struct scale_outpix_byte *dst_line2 = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dst_line1 = (struct scale_outpix_byte *)MEM_callocN( | 
					
						
							|  |  |  |       (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 1"); | 
					
						
							|  |  |  |   dst_line2 = (struct scale_outpix_byte *)MEM_callocN( | 
					
						
							|  |  |  |       (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 2"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dx_dst = 65536.0 * ratiox; | 
					
						
							|  |  |  |   dy_dst = 65536.0 * ratioy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   y_dst = 0; | 
					
						
							|  |  |  |   y_counter = 65536; | 
					
						
							|  |  |  |   for (y_src = 0; y_src < src_height; y_src++) { | 
					
						
							|  |  |  |     unsigned char *line = src + y_src * 4 * src_width; | 
					
						
							|  |  |  |     uintptr_t weight1y = 65535 - (y_dst & 0xffff); | 
					
						
							|  |  |  |     uintptr_t weight2y = 65535 - weight1y; | 
					
						
							|  |  |  |     x_dst = 0; | 
					
						
							|  |  |  |     for (x_src = 0; x_src < src_width; x_src++) { | 
					
						
							|  |  |  |       uintptr_t weight1x = 65535 - (x_dst & 0xffff); | 
					
						
							|  |  |  |       uintptr_t weight2x = 65535 - weight1x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uintptr_t x = x_dst >> 16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uintptr_t w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = (weight1y * weight1x) >> 16; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 01:18:55 +10:00
										 |  |  |       /* Ensure correct rounding, without this you get ugly banding,
 | 
					
						
							|  |  |  |        * or too low color values (ton). */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       dst_line1[x].r += (line[0] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x].g += (line[1] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x].b += (line[2] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x].a += (line[3] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = (weight2y * weight1x) >> 16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line2[x].r += (line[0] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x].g += (line[1] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x].b += (line[2] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x].a += (line[3] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = (weight1y * weight2x) >> 16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line1[x + 1].r += (line[0] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x + 1].g += (line[1] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x + 1].b += (line[2] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x + 1].a += (line[3] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line1[x + 1].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = (weight2y * weight2x) >> 16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line2[x + 1].r += (line[0] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x + 1].g += (line[1] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x + 1].b += (line[2] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x + 1].a += (line[3] * w + 32767) >> 16; | 
					
						
							|  |  |  |       dst_line2[x + 1].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       x_dst += dx_dst; | 
					
						
							|  |  |  |       line += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     y_dst += dy_dst; | 
					
						
							|  |  |  |     y_counter -= dy_dst; | 
					
						
							|  |  |  |     if (y_counter < 0) { | 
					
						
							|  |  |  |       int val; | 
					
						
							|  |  |  |       uintptr_t x; | 
					
						
							|  |  |  |       struct scale_outpix_byte *temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       y_counter += 65536; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (x = 0; x < dst_width; x++) { | 
					
						
							|  |  |  |         uintptr_t f = 0x80000000UL / dst_line1[x].weight; | 
					
						
							|  |  |  |         *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |         *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |         *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |         *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_byte)); | 
					
						
							|  |  |  |       temp = dst_line1; | 
					
						
							|  |  |  |       dst_line1 = dst_line2; | 
					
						
							|  |  |  |       dst_line2 = temp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (dst - dst_begin < dst_width * dst_height * 4) { | 
					
						
							|  |  |  |     int val; | 
					
						
							|  |  |  |     uintptr_t x; | 
					
						
							|  |  |  |     for (x = 0; x < dst_width; x++) { | 
					
						
							|  |  |  |       uintptr_t f = 0x80000000UL / dst_line1[x].weight; | 
					
						
							|  |  |  |       *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |       *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |       *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |       *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   MEM_freeN(dst_line1); | 
					
						
							|  |  |  |   MEM_freeN(dst_line2); | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void q_scale_byte(unsigned char *in, | 
					
						
							|  |  |  |                          unsigned char *out, | 
					
						
							|  |  |  |                          int in_width, | 
					
						
							|  |  |  |                          int in_height, | 
					
						
							|  |  |  |                          int dst_width, | 
					
						
							|  |  |  |                          int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (dst_width > in_width && dst_height > in_height) { | 
					
						
							|  |  |  |     enlarge_picture_byte(in, out, in_width, in_height, dst_width, dst_height); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (dst_width < in_width && dst_height < in_height) { | 
					
						
							|  |  |  |     shrink_picture_byte(in, out, in_width, in_height, dst_width, dst_height); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void enlarge_picture_float( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001); | 
					
						
							|  |  |  |   double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001); | 
					
						
							|  |  |  |   uintptr_t x_dst; | 
					
						
							|  |  |  |   uintptr_t y_dst; | 
					
						
							|  |  |  |   double x_src, dx_src; | 
					
						
							|  |  |  |   double y_src, dy_src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dx_src = 1.0 / ratiox; | 
					
						
							|  |  |  |   dy_src = 1.0 / ratioy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   y_src = 0; | 
					
						
							|  |  |  |   for (y_dst = 0; y_dst < dst_height; y_dst++) { | 
					
						
							|  |  |  |     float *line1 = src + ((int)y_src) * 4 * src_width; | 
					
						
							|  |  |  |     const float *line2 = line1 + 4 * src_width; | 
					
						
							|  |  |  |     const float weight1y = (float)(1.0 - (y_src - (int)y_src)); | 
					
						
							|  |  |  |     const float weight2y = 1.0f - weight1y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((int)y_src == src_height - 1) { | 
					
						
							|  |  |  |       line2 = line1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     x_src = 0; | 
					
						
							|  |  |  |     for (x_dst = 0; x_dst < dst_width; x_dst++) { | 
					
						
							|  |  |  |       const float weight1x = (float)(1.0 - (x_src - (int)x_src)); | 
					
						
							|  |  |  |       const float weight2x = (float)(1.0f - weight1x); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const float w11 = weight1y * weight1x; | 
					
						
							|  |  |  |       const float w21 = weight2y * weight1x; | 
					
						
							|  |  |  |       const float w12 = weight1y * weight2x; | 
					
						
							|  |  |  |       const float w22 = weight2y * weight2x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uintptr_t x = ((int)x_src) * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = line1[x] * w11 + line2[x] * w21 + line1[4 + x] * w12 + line2[4 + x] * w22; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = line1[x + 1] * w11 + line2[x + 1] * w21 + line1[4 + x + 1] * w12 + | 
					
						
							|  |  |  |                line2[4 + x + 1] * w22; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = line1[x + 2] * w11 + line2[x + 2] * w21 + line1[4 + x + 2] * w12 + | 
					
						
							|  |  |  |                line2[4 + x + 2] * w22; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *dst++ = line1[x + 3] * w11 + line2[x + 3] * w21 + line1[4 + x + 3] * w12 + | 
					
						
							|  |  |  |                line2[4 + x + 3] * w22; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       x_src += dx_src; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     y_src += dy_src; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct scale_outpix_float { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float r; | 
					
						
							|  |  |  |   float g; | 
					
						
							|  |  |  |   float b; | 
					
						
							|  |  |  |   float a; | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float weight; | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void shrink_picture_float( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     const float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   double ratiox = (double)(dst_width) / (double)(src_width); | 
					
						
							|  |  |  |   double ratioy = (double)(dst_height) / (double)(src_height); | 
					
						
							|  |  |  |   uintptr_t x_src; | 
					
						
							|  |  |  |   uintptr_t y_src; | 
					
						
							|  |  |  |   float dx_dst, x_dst; | 
					
						
							|  |  |  |   float dy_dst, y_dst; | 
					
						
							|  |  |  |   float y_counter; | 
					
						
							|  |  |  |   const float *dst_begin = dst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct scale_outpix_float *dst_line1; | 
					
						
							|  |  |  |   struct scale_outpix_float *dst_line2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dst_line1 = (struct scale_outpix_float *)MEM_callocN( | 
					
						
							|  |  |  |       (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 1"); | 
					
						
							|  |  |  |   dst_line2 = (struct scale_outpix_float *)MEM_callocN( | 
					
						
							|  |  |  |       (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 2"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dx_dst = ratiox; | 
					
						
							|  |  |  |   dy_dst = ratioy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   y_dst = 0; | 
					
						
							|  |  |  |   y_counter = 1.0; | 
					
						
							|  |  |  |   for (y_src = 0; y_src < src_height; y_src++) { | 
					
						
							|  |  |  |     const float *line = src + y_src * 4 * src_width; | 
					
						
							|  |  |  |     uintptr_t weight1y = 1.0f - (y_dst - (int)y_dst); | 
					
						
							|  |  |  |     uintptr_t weight2y = 1.0f - weight1y; | 
					
						
							|  |  |  |     x_dst = 0; | 
					
						
							|  |  |  |     for (x_src = 0; x_src < src_width; x_src++) { | 
					
						
							|  |  |  |       uintptr_t weight1x = 1.0f - (x_dst - (int)x_dst); | 
					
						
							|  |  |  |       uintptr_t weight2x = 1.0f - weight1x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       uintptr_t x = (int)x_dst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       float w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = weight1y * weight1x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line1[x].r += line[0] * w; | 
					
						
							|  |  |  |       dst_line1[x].g += line[1] * w; | 
					
						
							|  |  |  |       dst_line1[x].b += line[2] * w; | 
					
						
							|  |  |  |       dst_line1[x].a += line[3] * w; | 
					
						
							|  |  |  |       dst_line1[x].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = weight2y * weight1x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line2[x].r += line[0] * w; | 
					
						
							|  |  |  |       dst_line2[x].g += line[1] * w; | 
					
						
							|  |  |  |       dst_line2[x].b += line[2] * w; | 
					
						
							|  |  |  |       dst_line2[x].a += line[3] * w; | 
					
						
							|  |  |  |       dst_line2[x].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = weight1y * weight2x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line1[x + 1].r += line[0] * w; | 
					
						
							|  |  |  |       dst_line1[x + 1].g += line[1] * w; | 
					
						
							|  |  |  |       dst_line1[x + 1].b += line[2] * w; | 
					
						
							|  |  |  |       dst_line1[x + 1].a += line[3] * w; | 
					
						
							|  |  |  |       dst_line1[x + 1].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       w = weight2y * weight2x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dst_line2[x + 1].r += line[0] * w; | 
					
						
							|  |  |  |       dst_line2[x + 1].g += line[1] * w; | 
					
						
							|  |  |  |       dst_line2[x + 1].b += line[2] * w; | 
					
						
							|  |  |  |       dst_line2[x + 1].a += line[3] * w; | 
					
						
							|  |  |  |       dst_line2[x + 1].weight += w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       x_dst += dx_dst; | 
					
						
							|  |  |  |       line += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     y_dst += dy_dst; | 
					
						
							|  |  |  |     y_counter -= dy_dst; | 
					
						
							|  |  |  |     if (y_counter < 0) { | 
					
						
							|  |  |  |       uintptr_t x; | 
					
						
							|  |  |  |       struct scale_outpix_float *temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       y_counter += 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (x = 0; x < dst_width; x++) { | 
					
						
							|  |  |  |         float f = 1.0f / dst_line1[x].weight; | 
					
						
							|  |  |  |         *dst++ = dst_line1[x].r * f; | 
					
						
							|  |  |  |         *dst++ = dst_line1[x].g * f; | 
					
						
							|  |  |  |         *dst++ = dst_line1[x].b * f; | 
					
						
							|  |  |  |         *dst++ = dst_line1[x].a * f; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_float)); | 
					
						
							|  |  |  |       temp = dst_line1; | 
					
						
							|  |  |  |       dst_line1 = dst_line2; | 
					
						
							|  |  |  |       dst_line2 = temp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (dst - dst_begin < dst_width * dst_height * 4) { | 
					
						
							|  |  |  |     uintptr_t x; | 
					
						
							|  |  |  |     for (x = 0; x < dst_width; x++) { | 
					
						
							|  |  |  |       float f = 1.0f / dst_line1[x].weight; | 
					
						
							|  |  |  |       *dst++ = dst_line1[x].r * f; | 
					
						
							|  |  |  |       *dst++ = dst_line1[x].g * f; | 
					
						
							|  |  |  |       *dst++ = dst_line1[x].b * f; | 
					
						
							|  |  |  |       *dst++ = dst_line1[x].a * f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   MEM_freeN(dst_line1); | 
					
						
							|  |  |  |   MEM_freeN(dst_line2); | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void q_scale_float( | 
					
						
							|  |  |  |     float *in, float *out, int in_width, int in_height, int dst_width, int dst_height) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (dst_width > in_width && dst_height > in_height) { | 
					
						
							|  |  |  |     enlarge_picture_float(in, out, in_width, in_height, dst_width, dst_height); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (dst_width < in_width && dst_height < in_height) { | 
					
						
							|  |  |  |     shrink_picture_float(in, out, in_width, in_height, dst_width, dst_height); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * q_scale_linear_interpolation (derived from ppmqscale, http://libdv.sf.net)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * q stands for quick _and_ quality :) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * only handles common cases when we either | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * scale  both, x and y or | 
					
						
							|  |  |  |  * shrink both, x and y | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * but that is pretty fast: | 
					
						
							|  |  |  |  * - does only blit once instead of two passes like the old code | 
					
						
							|  |  |  |  *   (fewer cache misses) | 
					
						
							|  |  |  |  * - uses fixed point integer arithmetic for byte buffers | 
					
						
							|  |  |  |  * - doesn't branch in tight loops | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Should be comparable in speed to the ImBuf ..._fast functions at least | 
					
						
							|  |  |  |  * for byte-buffers. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |  * NOTE: disabled, due to unacceptable inaccuracy and quality loss, see bug T18609 (ton) | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static bool q_scale_linear_interpolation(struct ImBuf *ibuf, int newx, int newy) | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if ((newx >= ibuf->x && newy <= ibuf->y) || (newx <= ibuf->x && newy >= ibuf->y)) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf->rect) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     unsigned char *newrect = MEM_mallocN(sizeof(int) * newx * newy, "q_scale rect"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y, newx, newy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     float *newrect = MEM_mallocN(sizeof(float[4]) * newx * newy, "q_scale rectfloat"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y, newx, newy); | 
					
						
							|  |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   ibuf->x = newx; | 
					
						
							|  |  |  |   ibuf->y = newy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2008-01-30 15:41:02 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | static ImBuf *scaledownx(struct ImBuf *ibuf, int newx) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int do_rect = (ibuf->rect != NULL); | 
					
						
							|  |  |  |   const int do_float = (ibuf->rect_float != NULL); | 
					
						
							|  |  |  |   const size_t rect_size = ibuf->x * ibuf->y * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uchar *rect, *_newrect, *newrect; | 
					
						
							|  |  |  |   float *rectf, *_newrectf, *newrectf; | 
					
						
							|  |  |  |   float sample, add, val[4], nval[4], valf[4], nvalf[4]; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rectf = _newrectf = newrectf = NULL; | 
					
						
							|  |  |  |   rect = _newrect = newrect = NULL; | 
					
						
							|  |  |  |   nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; | 
					
						
							|  |  |  |   nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (!do_rect && !do_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrect = MEM_mallocN(sizeof(uchar[4]) * newx * ibuf->y, "scaledownx"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (_newrect == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * ibuf->y, "scaledownxf"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (_newrectf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (_newrect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         MEM_freeN(_newrect); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   add = (ibuf->x - 0.01) / newx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     rect = (uchar *)ibuf->rect; | 
					
						
							|  |  |  |     newrect = _newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     rectf = ibuf->rect_float; | 
					
						
							|  |  |  |     newrectf = _newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = ibuf->y; y > 0; y--) { | 
					
						
							|  |  |  |     sample = 0.0f; | 
					
						
							|  |  |  |     val[0] = val[1] = val[2] = val[3] = 0.0f; | 
					
						
							|  |  |  |     valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (x = newx; x > 0; x--) { | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         nval[0] = -val[0] * sample; | 
					
						
							|  |  |  |         nval[1] = -val[1] * sample; | 
					
						
							|  |  |  |         nval[2] = -val[2] * sample; | 
					
						
							|  |  |  |         nval[3] = -val[3] * sample; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         nvalf[0] = -valf[0] * sample; | 
					
						
							|  |  |  |         nvalf[1] = -valf[1] * sample; | 
					
						
							|  |  |  |         nvalf[2] = -valf[2] * sample; | 
					
						
							|  |  |  |         nvalf[3] = -valf[3] * sample; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sample += add; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       while (sample >= 1.0f) { | 
					
						
							|  |  |  |         sample -= 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (do_rect) { | 
					
						
							|  |  |  |           nval[0] += rect[0]; | 
					
						
							|  |  |  |           nval[1] += rect[1]; | 
					
						
							|  |  |  |           nval[2] += rect[2]; | 
					
						
							|  |  |  |           nval[3] += rect[3]; | 
					
						
							|  |  |  |           rect += 4; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (do_float) { | 
					
						
							|  |  |  |           nvalf[0] += rectf[0]; | 
					
						
							|  |  |  |           nvalf[1] += rectf[1]; | 
					
						
							|  |  |  |           nvalf[2] += rectf[2]; | 
					
						
							|  |  |  |           nvalf[3] += rectf[3]; | 
					
						
							|  |  |  |           rectf += 4; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         val[0] = rect[0]; | 
					
						
							|  |  |  |         val[1] = rect[1]; | 
					
						
							|  |  |  |         val[2] = rect[2]; | 
					
						
							|  |  |  |         val[3] = rect[3]; | 
					
						
							|  |  |  |         rect += 4; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 16:23:00 +02:00
										 |  |  |         newrect[0] = roundf((nval[0] + sample * val[0]) / add); | 
					
						
							|  |  |  |         newrect[1] = roundf((nval[1] + sample * val[1]) / add); | 
					
						
							|  |  |  |         newrect[2] = roundf((nval[2] + sample * val[2]) / add); | 
					
						
							|  |  |  |         newrect[3] = roundf((nval[3] + sample * val[3]) / add); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         newrect += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         valf[0] = rectf[0]; | 
					
						
							|  |  |  |         valf[1] = rectf[1]; | 
					
						
							|  |  |  |         valf[2] = rectf[2]; | 
					
						
							|  |  |  |         valf[3] = rectf[3]; | 
					
						
							|  |  |  |         rectf += 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); | 
					
						
							|  |  |  |         newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); | 
					
						
							|  |  |  |         newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); | 
					
						
							|  |  |  |         newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newrectf += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sample -= 1.0f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size);
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |     BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)_newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size);
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |     BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = _newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   (void)rect_size; /* UNUSED in release builds */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf->x = newx; | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | static ImBuf *scaledowny(struct ImBuf *ibuf, int newy) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int do_rect = (ibuf->rect != NULL); | 
					
						
							|  |  |  |   const int do_float = (ibuf->rect_float != NULL); | 
					
						
							|  |  |  |   const size_t rect_size = ibuf->x * ibuf->y * 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   uchar *rect, *_newrect, *newrect; | 
					
						
							|  |  |  |   float *rectf, *_newrectf, *newrectf; | 
					
						
							|  |  |  |   float sample, add, val[4], nval[4], valf[4], nvalf[4]; | 
					
						
							|  |  |  |   int x, y, skipx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rectf = _newrectf = newrectf = NULL; | 
					
						
							|  |  |  |   rect = _newrect = newrect = NULL; | 
					
						
							|  |  |  |   nval[0] = nval[1] = nval[2] = nval[3] = 0.0f; | 
					
						
							|  |  |  |   nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (!do_rect && !do_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrect = MEM_mallocN(sizeof(uchar[4]) * newy * ibuf->x, "scaledowny"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (_newrect == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrectf = MEM_mallocN(sizeof(float[4]) * newy * ibuf->x, "scaledownyf"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (_newrectf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (_newrect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         MEM_freeN(_newrect); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   add = (ibuf->y - 0.01) / newy; | 
					
						
							|  |  |  |   skipx = 4 * ibuf->x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (x = skipx - 4; x >= 0; x -= 4) { | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       rect = ((uchar *)ibuf->rect) + x; | 
					
						
							|  |  |  |       newrect = _newrect + x; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       rectf = ibuf->rect_float + x; | 
					
						
							|  |  |  |       newrectf = _newrectf + x; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sample = 0.0f; | 
					
						
							|  |  |  |     val[0] = val[1] = val[2] = val[3] = 0.0f; | 
					
						
							|  |  |  |     valf[0] = valf[1] = valf[2] = valf[3] = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (y = newy; y > 0; y--) { | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         nval[0] = -val[0] * sample; | 
					
						
							|  |  |  |         nval[1] = -val[1] * sample; | 
					
						
							|  |  |  |         nval[2] = -val[2] * sample; | 
					
						
							|  |  |  |         nval[3] = -val[3] * sample; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         nvalf[0] = -valf[0] * sample; | 
					
						
							|  |  |  |         nvalf[1] = -valf[1] * sample; | 
					
						
							|  |  |  |         nvalf[2] = -valf[2] * sample; | 
					
						
							|  |  |  |         nvalf[3] = -valf[3] * sample; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sample += add; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       while (sample >= 1.0f) { | 
					
						
							|  |  |  |         sample -= 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (do_rect) { | 
					
						
							|  |  |  |           nval[0] += rect[0]; | 
					
						
							|  |  |  |           nval[1] += rect[1]; | 
					
						
							|  |  |  |           nval[2] += rect[2]; | 
					
						
							|  |  |  |           nval[3] += rect[3]; | 
					
						
							|  |  |  |           rect += skipx; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (do_float) { | 
					
						
							|  |  |  |           nvalf[0] += rectf[0]; | 
					
						
							|  |  |  |           nvalf[1] += rectf[1]; | 
					
						
							|  |  |  |           nvalf[2] += rectf[2]; | 
					
						
							|  |  |  |           nvalf[3] += rectf[3]; | 
					
						
							|  |  |  |           rectf += skipx; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         val[0] = rect[0]; | 
					
						
							|  |  |  |         val[1] = rect[1]; | 
					
						
							|  |  |  |         val[2] = rect[2]; | 
					
						
							|  |  |  |         val[3] = rect[3]; | 
					
						
							|  |  |  |         rect += skipx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 16:23:00 +02:00
										 |  |  |         newrect[0] = roundf((nval[0] + sample * val[0]) / add); | 
					
						
							|  |  |  |         newrect[1] = roundf((nval[1] + sample * val[1]) / add); | 
					
						
							|  |  |  |         newrect[2] = roundf((nval[2] + sample * val[2]) / add); | 
					
						
							|  |  |  |         newrect[3] = roundf((nval[3] + sample * val[3]) / add); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         newrect += skipx; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         valf[0] = rectf[0]; | 
					
						
							|  |  |  |         valf[1] = rectf[1]; | 
					
						
							|  |  |  |         valf[2] = rectf[2]; | 
					
						
							|  |  |  |         valf[3] = rectf[3]; | 
					
						
							|  |  |  |         rectf += skipx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newrectf[0] = ((nvalf[0] + sample * valf[0]) / add); | 
					
						
							|  |  |  |         newrectf[1] = ((nvalf[1] + sample * valf[1]) / add); | 
					
						
							|  |  |  |         newrectf[2] = ((nvalf[2] + sample * valf[2]) / add); | 
					
						
							|  |  |  |         newrectf[3] = ((nvalf[3] + sample * valf[3]) / add); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newrectf += skipx; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       sample -= 1.0f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size);
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |     BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)_newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size);
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |     BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = (float *)_newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   (void)rect_size; /* UNUSED in release builds */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf->y = newy; | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uchar *rect, *_newrect = NULL, *newrect; | 
					
						
							|  |  |  |   float *rectf, *_newrectf = NULL, *newrectf; | 
					
						
							|  |  |  |   float sample, add; | 
					
						
							|  |  |  |   float val_a, nval_a, diff_a; | 
					
						
							|  |  |  |   float val_b, nval_b, diff_b; | 
					
						
							|  |  |  |   float val_g, nval_g, diff_g; | 
					
						
							|  |  |  |   float val_r, nval_r, diff_r; | 
					
						
							|  |  |  |   float val_af, nval_af, diff_af; | 
					
						
							|  |  |  |   float val_bf, nval_bf, diff_bf; | 
					
						
							|  |  |  |   float val_gf, nval_gf, diff_gf; | 
					
						
							|  |  |  |   float val_rf, nval_rf, diff_rf; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   bool do_rect = false, do_float = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; | 
					
						
							|  |  |  |   val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; | 
					
						
							|  |  |  |   val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; | 
					
						
							|  |  |  |   val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect == NULL && ibuf->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf->rect) { | 
					
						
							|  |  |  |     do_rect = true; | 
					
						
							|  |  |  |     _newrect = MEM_mallocN(newx * ibuf->y * sizeof(int), "scaleupx"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (_newrect == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect_float) { | 
					
						
							|  |  |  |     do_float = true; | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * ibuf->y, "scaleupxf"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (_newrectf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (_newrect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         MEM_freeN(_newrect); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   add = (ibuf->x - 1.001) / (newx - 1.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rect = (uchar *)ibuf->rect; | 
					
						
							|  |  |  |   rectf = (float *)ibuf->rect_float; | 
					
						
							|  |  |  |   newrect = _newrect; | 
					
						
							|  |  |  |   newrectf = _newrectf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = ibuf->y; y > 0; y--) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sample = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       val_a = rect[0]; | 
					
						
							|  |  |  |       nval_a = rect[4]; | 
					
						
							|  |  |  |       diff_a = nval_a - val_a; | 
					
						
							|  |  |  |       val_a += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_b = rect[1]; | 
					
						
							|  |  |  |       nval_b = rect[5]; | 
					
						
							|  |  |  |       diff_b = nval_b - val_b; | 
					
						
							|  |  |  |       val_b += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_g = rect[2]; | 
					
						
							|  |  |  |       nval_g = rect[6]; | 
					
						
							|  |  |  |       diff_g = nval_g - val_g; | 
					
						
							|  |  |  |       val_g += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_r = rect[3]; | 
					
						
							|  |  |  |       nval_r = rect[7]; | 
					
						
							|  |  |  |       diff_r = nval_r - val_r; | 
					
						
							|  |  |  |       val_r += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rect += 8; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       val_af = rectf[0]; | 
					
						
							|  |  |  |       nval_af = rectf[4]; | 
					
						
							|  |  |  |       diff_af = nval_af - val_af; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_bf = rectf[1]; | 
					
						
							|  |  |  |       nval_bf = rectf[5]; | 
					
						
							|  |  |  |       diff_bf = nval_bf - val_bf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_gf = rectf[2]; | 
					
						
							|  |  |  |       nval_gf = rectf[6]; | 
					
						
							|  |  |  |       diff_gf = nval_gf - val_gf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_rf = rectf[3]; | 
					
						
							|  |  |  |       nval_rf = rectf[7]; | 
					
						
							|  |  |  |       diff_rf = nval_rf - val_rf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rectf += 8; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (x = newx; x > 0; x--) { | 
					
						
							|  |  |  |       if (sample >= 1.0f) { | 
					
						
							|  |  |  |         sample -= 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (do_rect) { | 
					
						
							|  |  |  |           val_a = nval_a; | 
					
						
							|  |  |  |           nval_a = rect[0]; | 
					
						
							|  |  |  |           diff_a = nval_a - val_a; | 
					
						
							|  |  |  |           val_a += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_b = nval_b; | 
					
						
							|  |  |  |           nval_b = rect[1]; | 
					
						
							|  |  |  |           diff_b = nval_b - val_b; | 
					
						
							|  |  |  |           val_b += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_g = nval_g; | 
					
						
							|  |  |  |           nval_g = rect[2]; | 
					
						
							|  |  |  |           diff_g = nval_g - val_g; | 
					
						
							|  |  |  |           val_g += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_r = nval_r; | 
					
						
							|  |  |  |           nval_r = rect[3]; | 
					
						
							|  |  |  |           diff_r = nval_r - val_r; | 
					
						
							|  |  |  |           val_r += 0.5f; | 
					
						
							|  |  |  |           rect += 4; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (do_float) { | 
					
						
							|  |  |  |           val_af = nval_af; | 
					
						
							|  |  |  |           nval_af = rectf[0]; | 
					
						
							|  |  |  |           diff_af = nval_af - val_af; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_bf = nval_bf; | 
					
						
							|  |  |  |           nval_bf = rectf[1]; | 
					
						
							|  |  |  |           diff_bf = nval_bf - val_bf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_gf = nval_gf; | 
					
						
							|  |  |  |           nval_gf = rectf[2]; | 
					
						
							|  |  |  |           diff_gf = nval_gf - val_gf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_rf = nval_rf; | 
					
						
							|  |  |  |           nval_rf = rectf[3]; | 
					
						
							|  |  |  |           diff_rf = nval_rf - val_rf; | 
					
						
							|  |  |  |           rectf += 4; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         newrect[0] = val_a + sample * diff_a; | 
					
						
							|  |  |  |         newrect[1] = val_b + sample * diff_b; | 
					
						
							|  |  |  |         newrect[2] = val_g + sample * diff_g; | 
					
						
							|  |  |  |         newrect[3] = val_r + sample * diff_r; | 
					
						
							|  |  |  |         newrect += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         newrectf[0] = val_af + sample * diff_af; | 
					
						
							|  |  |  |         newrectf[1] = val_bf + sample * diff_bf; | 
					
						
							|  |  |  |         newrectf[2] = val_gf + sample * diff_gf; | 
					
						
							|  |  |  |         newrectf[3] = val_rf + sample * diff_rf; | 
					
						
							|  |  |  |         newrectf += 4; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       sample += add; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)_newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = (float *)_newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf->x = newx; | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 23:21:11 +00:00
										 |  |  | static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   uchar *rect, *_newrect = NULL, *newrect; | 
					
						
							|  |  |  |   float *rectf, *_newrectf = NULL, *newrectf; | 
					
						
							|  |  |  |   float sample, add; | 
					
						
							|  |  |  |   float val_a, nval_a, diff_a; | 
					
						
							|  |  |  |   float val_b, nval_b, diff_b; | 
					
						
							|  |  |  |   float val_g, nval_g, diff_g; | 
					
						
							|  |  |  |   float val_r, nval_r, diff_r; | 
					
						
							|  |  |  |   float val_af, nval_af, diff_af; | 
					
						
							|  |  |  |   float val_bf, nval_bf, diff_bf; | 
					
						
							|  |  |  |   float val_gf, nval_gf, diff_gf; | 
					
						
							|  |  |  |   float val_rf, nval_rf, diff_rf; | 
					
						
							|  |  |  |   int x, y, skipx; | 
					
						
							|  |  |  |   bool do_rect = false, do_float = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0; | 
					
						
							|  |  |  |   val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0; | 
					
						
							|  |  |  |   val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0; | 
					
						
							|  |  |  |   val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect == NULL && ibuf->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |     return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf->rect) { | 
					
						
							|  |  |  |     do_rect = true; | 
					
						
							|  |  |  |     _newrect = MEM_mallocN(ibuf->x * newy * sizeof(int), "scaleupy"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (_newrect == NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect_float) { | 
					
						
							|  |  |  |     do_float = true; | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrectf = MEM_mallocN(sizeof(float[4]) * ibuf->x * newy, "scaleupyf"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (_newrectf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (_newrect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         MEM_freeN(_newrect); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |       return ibuf; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   add = (ibuf->y - 1.001) / (newy - 1.0); | 
					
						
							|  |  |  |   skipx = 4 * ibuf->x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rect = (uchar *)ibuf->rect; | 
					
						
							|  |  |  |   rectf = (float *)ibuf->rect_float; | 
					
						
							|  |  |  |   newrect = _newrect; | 
					
						
							|  |  |  |   newrectf = _newrectf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (x = ibuf->x; x > 0; x--) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sample = 0; | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       rect = ((uchar *)ibuf->rect) + 4 * (x - 1); | 
					
						
							|  |  |  |       newrect = _newrect + 4 * (x - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_a = rect[0]; | 
					
						
							|  |  |  |       nval_a = rect[skipx]; | 
					
						
							|  |  |  |       diff_a = nval_a - val_a; | 
					
						
							|  |  |  |       val_a += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_b = rect[1]; | 
					
						
							|  |  |  |       nval_b = rect[skipx + 1]; | 
					
						
							|  |  |  |       diff_b = nval_b - val_b; | 
					
						
							|  |  |  |       val_b += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_g = rect[2]; | 
					
						
							|  |  |  |       nval_g = rect[skipx + 2]; | 
					
						
							|  |  |  |       diff_g = nval_g - val_g; | 
					
						
							|  |  |  |       val_g += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_r = rect[3]; | 
					
						
							|  |  |  |       nval_r = rect[skipx + 3]; | 
					
						
							|  |  |  |       diff_r = nval_r - val_r; | 
					
						
							|  |  |  |       val_r += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rect += 2 * skipx; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       rectf = ibuf->rect_float + 4 * (x - 1); | 
					
						
							|  |  |  |       newrectf = _newrectf + 4 * (x - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_af = rectf[0]; | 
					
						
							|  |  |  |       nval_af = rectf[skipx]; | 
					
						
							|  |  |  |       diff_af = nval_af - val_af; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_bf = rectf[1]; | 
					
						
							|  |  |  |       nval_bf = rectf[skipx + 1]; | 
					
						
							|  |  |  |       diff_bf = nval_bf - val_bf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_gf = rectf[2]; | 
					
						
							|  |  |  |       nval_gf = rectf[skipx + 2]; | 
					
						
							|  |  |  |       diff_gf = nval_gf - val_gf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       val_rf = rectf[3]; | 
					
						
							|  |  |  |       nval_rf = rectf[skipx + 3]; | 
					
						
							|  |  |  |       diff_rf = nval_rf - val_rf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rectf += 2 * skipx; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (y = newy; y > 0; y--) { | 
					
						
							|  |  |  |       if (sample >= 1.0f) { | 
					
						
							|  |  |  |         sample -= 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (do_rect) { | 
					
						
							|  |  |  |           val_a = nval_a; | 
					
						
							|  |  |  |           nval_a = rect[0]; | 
					
						
							|  |  |  |           diff_a = nval_a - val_a; | 
					
						
							|  |  |  |           val_a += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_b = nval_b; | 
					
						
							|  |  |  |           nval_b = rect[1]; | 
					
						
							|  |  |  |           diff_b = nval_b - val_b; | 
					
						
							|  |  |  |           val_b += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_g = nval_g; | 
					
						
							|  |  |  |           nval_g = rect[2]; | 
					
						
							|  |  |  |           diff_g = nval_g - val_g; | 
					
						
							|  |  |  |           val_g += 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_r = nval_r; | 
					
						
							|  |  |  |           nval_r = rect[3]; | 
					
						
							|  |  |  |           diff_r = nval_r - val_r; | 
					
						
							|  |  |  |           val_r += 0.5f; | 
					
						
							|  |  |  |           rect += skipx; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (do_float) { | 
					
						
							|  |  |  |           val_af = nval_af; | 
					
						
							|  |  |  |           nval_af = rectf[0]; | 
					
						
							|  |  |  |           diff_af = nval_af - val_af; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_bf = nval_bf; | 
					
						
							|  |  |  |           nval_bf = rectf[1]; | 
					
						
							|  |  |  |           diff_bf = nval_bf - val_bf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_gf = nval_gf; | 
					
						
							|  |  |  |           nval_gf = rectf[2]; | 
					
						
							|  |  |  |           diff_gf = nval_gf - val_gf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           val_rf = nval_rf; | 
					
						
							|  |  |  |           nval_rf = rectf[3]; | 
					
						
							|  |  |  |           diff_rf = nval_rf - val_rf; | 
					
						
							|  |  |  |           rectf += skipx; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_rect) { | 
					
						
							|  |  |  |         newrect[0] = val_a + sample * diff_a; | 
					
						
							|  |  |  |         newrect[1] = val_b + sample * diff_b; | 
					
						
							|  |  |  |         newrect[2] = val_g + sample * diff_g; | 
					
						
							|  |  |  |         newrect[3] = val_r + sample * diff_r; | 
					
						
							|  |  |  |         newrect += skipx; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (do_float) { | 
					
						
							|  |  |  |         newrectf[0] = val_af + sample * diff_af; | 
					
						
							|  |  |  |         newrectf[1] = val_bf + sample * diff_bf; | 
					
						
							|  |  |  |         newrectf[2] = val_gf + sample * diff_gf; | 
					
						
							|  |  |  |         newrectf[3] = val_rf + sample * diff_rf; | 
					
						
							|  |  |  |         newrectf += skipx; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       sample += add; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)_newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = (float *)_newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf->y = newy; | 
					
						
							| 
									
										
										
										
											2020-08-08 11:02:11 +10:00
										 |  |  |   return ibuf; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-17 05:15:54 +00:00
										 |  |  | static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int *zbuf, *newzbuf, *_newzbuf = NULL; | 
					
						
							|  |  |  |   float *zbuf_float, *newzbuf_float, *_newzbuf_float = NULL; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   int ofsx, ofsy, stepx, stepy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf->zbuf) { | 
					
						
							|  |  |  |     _newzbuf = MEM_mallocN(newx * newy * sizeof(int), __func__); | 
					
						
							|  |  |  |     if (_newzbuf == NULL) { | 
					
						
							|  |  |  |       IMB_freezbufImBuf(ibuf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ibuf->zbuf_float) { | 
					
						
							|  |  |  |     _newzbuf_float = MEM_mallocN((size_t)newx * newy * sizeof(float), __func__); | 
					
						
							|  |  |  |     if (_newzbuf_float == NULL) { | 
					
						
							|  |  |  |       IMB_freezbuffloatImBuf(ibuf); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!_newzbuf && !_newzbuf_float) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 16:23:00 +02:00
										 |  |  |   stepx = round(65536.0 * (ibuf->x - 1.0) / (newx - 1.0)); | 
					
						
							|  |  |  |   stepy = round(65536.0 * (ibuf->y - 1.0) / (newy - 1.0)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ofsy = 32768; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   newzbuf = _newzbuf; | 
					
						
							|  |  |  |   newzbuf_float = _newzbuf_float; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = newy; y > 0; y--, ofsy += stepy) { | 
					
						
							|  |  |  |     if (newzbuf) { | 
					
						
							|  |  |  |       zbuf = ibuf->zbuf; | 
					
						
							|  |  |  |       zbuf += (ofsy >> 16) * ibuf->x; | 
					
						
							|  |  |  |       ofsx = 32768; | 
					
						
							|  |  |  |       for (x = newx; x > 0; x--, ofsx += stepx) { | 
					
						
							|  |  |  |         *newzbuf++ = zbuf[ofsx >> 16]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (newzbuf_float) { | 
					
						
							|  |  |  |       zbuf_float = ibuf->zbuf_float; | 
					
						
							|  |  |  |       zbuf_float += (ofsy >> 16) * ibuf->x; | 
					
						
							|  |  |  |       ofsx = 32768; | 
					
						
							|  |  |  |       for (x = newx; x > 0; x--, ofsx += stepx) { | 
					
						
							|  |  |  |         *newzbuf_float++ = zbuf_float[ofsx >> 16]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_newzbuf) { | 
					
						
							|  |  |  |     IMB_freezbufImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_zbuf; | 
					
						
							|  |  |  |     ibuf->zbuf = _newzbuf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_newzbuf_float) { | 
					
						
							|  |  |  |     IMB_freezbuffloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_zbuffloat; | 
					
						
							|  |  |  |     ibuf->zbuf_float = _newzbuf_float; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 17:30:35 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Return true if \a ibuf is modified. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect == NULL && ibuf->rect_float == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (newx == ibuf->x && newy == ibuf->y) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-17 00:54:22 +10:00
										 |  |  |   /* Scale-up / scale-down functions below change ibuf->x and ibuf->y
 | 
					
						
							|  |  |  |    * so we first scale the Z-buffer (if any). */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   scalefast_Z_ImBuf(ibuf, newx, newy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* try to scale common cases in a fast way */ | 
					
						
							| 
									
										
										
										
											2020-09-30 20:09:02 +10:00
										 |  |  |   /* disabled, quality loss is unacceptable, see report T18609  (ton) */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (newx && (newx < ibuf->x)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     scaledownx(ibuf, newx); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (newy && (newy < ibuf->y)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     scaledowny(ibuf, newy); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (newx && (newx > ibuf->x)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     scaleupx(ibuf, newx); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (newy && (newy > ibuf->y)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     scaleupy(ibuf, newy); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
  all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
  default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
  tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
  easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
  code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
  (pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
  rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
  with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
  done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
  window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
  system should be built from scratch. I can't really understand this code...
  I expect it is not much needed, especially with advanced layer/passes
  control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
  recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
  effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
  to check first the option to render to a Image window, so Blender can become
  a true single-window application. :)
  For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
											
										 
											2006-01-23 22:05:47 +00:00
										 |  |  | struct imbufRGBA { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float r, g, b, a; | 
					
						
							| 
									
										
											  
											
												Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
  all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
  default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
  tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
  easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
  code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
  (pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
  rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
  with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
  done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
  window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
  system should be built from scratch. I can't really understand this code...
  I expect it is not much needed, especially with advanced layer/passes
  control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
  recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
  effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
  to check first the option to render to a Image window, so Blender can become
  a true single-window application. :)
  For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
											
										 
											2006-01-23 22:05:47 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 17:30:35 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Return true if \a ibuf is modified. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned int *rect, *_newrect, *newrect; | 
					
						
							|  |  |  |   struct imbufRGBA *rectf, *_newrectf, *newrectf; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							|  |  |  |   bool do_float = false, do_rect = false; | 
					
						
							|  |  |  |   size_t ofsx, ofsy, stepx, stepy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rect = NULL; | 
					
						
							|  |  |  |   _newrect = NULL; | 
					
						
							|  |  |  |   newrect = NULL; | 
					
						
							|  |  |  |   rectf = NULL; | 
					
						
							|  |  |  |   _newrectf = NULL; | 
					
						
							|  |  |  |   newrectf = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     do_rect = true; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (ibuf->rect_float) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     do_float = true; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (do_rect == false && do_float == false) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (newx == ibuf->x && newy == ibuf->y) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     _newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     if (_newrect == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return false; | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     newrect = _newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							| 
									
										
										
										
											2020-08-08 13:29:21 +10:00
										 |  |  |     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * newy, "scalefastimbuf f"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (_newrectf == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       if (_newrect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         MEM_freeN(_newrect); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     newrectf = _newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-04 16:23:00 +02:00
										 |  |  |   stepx = round(65536.0 * (ibuf->x - 1.0) / (newx - 1.0)); | 
					
						
							|  |  |  |   stepy = round(65536.0 * (ibuf->y - 1.0) / (newy - 1.0)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ofsy = 32768; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (y = newy; y > 0; y--, ofsy += stepy) { | 
					
						
							|  |  |  |     if (do_rect) { | 
					
						
							|  |  |  |       rect = ibuf->rect; | 
					
						
							|  |  |  |       rect += (ofsy >> 16) * ibuf->x; | 
					
						
							|  |  |  |       ofsx = 32768; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (x = newx; x > 0; x--, ofsx += stepx) { | 
					
						
							|  |  |  |         *newrect++ = rect[ofsx >> 16]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (do_float) { | 
					
						
							|  |  |  |       rectf = (struct imbufRGBA *)ibuf->rect_float; | 
					
						
							|  |  |  |       rectf += (ofsy >> 16) * ibuf->x; | 
					
						
							|  |  |  |       ofsx = 32768; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (x = newx; x > 0; x--, ofsx += stepx) { | 
					
						
							|  |  |  |         *newrectf++ = rectf[ofsx >> 16]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_rect) { | 
					
						
							|  |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = _newrect; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_float) { | 
					
						
							|  |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = (float *)_newrectf; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   scalefast_Z_ImBuf(ibuf, newx, newy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ibuf->x = newx; | 
					
						
							|  |  |  |   ibuf->y = newy; | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | /* ******** threaded scaling ******** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct ScaleTreadInitData { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ImBuf *ibuf; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned int newx; | 
					
						
							|  |  |  |   unsigned int newy; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned char *byte_buffer; | 
					
						
							|  |  |  |   float *float_buffer; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | } ScaleTreadInitData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct ScaleThreadData { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ImBuf *ibuf; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned int newx; | 
					
						
							|  |  |  |   unsigned int newy; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int start_line; | 
					
						
							|  |  |  |   int tot_line; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unsigned char *byte_buffer; | 
					
						
							|  |  |  |   float *float_buffer; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | } ScaleThreadData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void scale_thread_init(void *data_v, int start_line, int tot_line, void *init_data_v) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ScaleThreadData *data = (ScaleThreadData *)data_v; | 
					
						
							|  |  |  |   ScaleTreadInitData *init_data = (ScaleTreadInitData *)init_data_v; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   data->ibuf = init_data->ibuf; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   data->newx = init_data->newx; | 
					
						
							|  |  |  |   data->newy = init_data->newy; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   data->start_line = start_line; | 
					
						
							|  |  |  |   data->tot_line = tot_line; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   data->byte_buffer = init_data->byte_buffer; | 
					
						
							|  |  |  |   data->float_buffer = init_data->float_buffer; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void *do_scale_thread(void *data_v) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ScaleThreadData *data = (ScaleThreadData *)data_v; | 
					
						
							|  |  |  |   ImBuf *ibuf = data->ibuf; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   float factor_x = (float)ibuf->x / data->newx; | 
					
						
							|  |  |  |   float factor_y = (float)ibuf->y / data->newy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < data->tot_line; i++) { | 
					
						
							|  |  |  |     int y = data->start_line + i; | 
					
						
							|  |  |  |     int x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (x = 0; x < data->newx; x++) { | 
					
						
							|  |  |  |       float u = (float)x * factor_x; | 
					
						
							|  |  |  |       float v = (float)y * factor_y; | 
					
						
							|  |  |  |       int offset = y * data->newx + x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (data->byte_buffer) { | 
					
						
							|  |  |  |         unsigned char *pixel = data->byte_buffer + 4 * offset; | 
					
						
							|  |  |  |         BLI_bilinear_interpolation_char( | 
					
						
							|  |  |  |             (unsigned char *)ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (data->float_buffer) { | 
					
						
							|  |  |  |         float *pixel = data->float_buffer + ibuf->channels * offset; | 
					
						
							|  |  |  |         BLI_bilinear_interpolation_fl( | 
					
						
							|  |  |  |             ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ScaleTreadInitData init_data = {NULL}; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* prepare initialization data */ | 
					
						
							|  |  |  |   init_data.ibuf = ibuf; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   init_data.newx = newx; | 
					
						
							|  |  |  |   init_data.newy = newy; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf->rect) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char), | 
					
						
							|  |  |  |                                         "threaded scale byte buffer"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   if (ibuf->rect_float) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float), | 
					
						
							|  |  |  |                                          "threaded scale float buffer"); | 
					
						
							| 
									
										
										
										
											2019-04-23 11:01:30 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* actual scaling threads */ | 
					
						
							|  |  |  |   IMB_processor_apply_threaded( | 
					
						
							|  |  |  |       newy, sizeof(ScaleThreadData), &init_data, scale_thread_init, do_scale_thread); | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* alter image buffer */ | 
					
						
							|  |  |  |   ibuf->x = newx; | 
					
						
							|  |  |  |   ibuf->y = newy; | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (ibuf->rect) { | 
					
						
							|  |  |  |     imb_freerectImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rect; | 
					
						
							|  |  |  |     ibuf->rect = (unsigned int *)init_data.byte_buffer; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (ibuf->rect_float) { | 
					
						
							|  |  |  |     imb_freerectfloatImBuf(ibuf); | 
					
						
							|  |  |  |     ibuf->mall |= IB_rectfloat; | 
					
						
							|  |  |  |     ibuf->rect_float = init_data.float_buffer; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-15 11:59:46 +00:00
										 |  |  | } |