1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * allocimbuf.c
19  */
20 
21 /** \file
22  * \ingroup imbuf
23  */
24 
25 #include <math.h>
26 
27 #include "BLI_math_color.h"
28 #include "BLI_math_interp.h"
29 #include "BLI_utildefines.h"
30 #include "MEM_guardedalloc.h"
31 
32 #include "IMB_imbuf.h"
33 #include "IMB_imbuf_types.h"
34 #include "imbuf.h"
35 
36 #include "IMB_filter.h"
37 
38 #include "BLI_sys_types.h" /* for intptr_t support */
39 
imb_half_x_no_alloc(struct ImBuf * ibuf2,struct ImBuf * ibuf1)40 static void imb_half_x_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
41 {
42   uchar *p1, *_p1, *dest;
43   short a, r, g, b;
44   int x, y;
45   float af, rf, gf, bf, *p1f, *_p1f, *destf;
46   bool do_rect, do_float;
47 
48   do_rect = (ibuf1->rect != NULL);
49   do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL);
50 
51   _p1 = (uchar *)ibuf1->rect;
52   dest = (uchar *)ibuf2->rect;
53 
54   _p1f = ibuf1->rect_float;
55   destf = ibuf2->rect_float;
56 
57   for (y = ibuf2->y; y > 0; y--) {
58     p1 = _p1;
59     p1f = _p1f;
60     for (x = ibuf2->x; x > 0; x--) {
61       if (do_rect) {
62         a = *(p1++);
63         b = *(p1++);
64         g = *(p1++);
65         r = *(p1++);
66         a += *(p1++);
67         b += *(p1++);
68         g += *(p1++);
69         r += *(p1++);
70         *(dest++) = a >> 1;
71         *(dest++) = b >> 1;
72         *(dest++) = g >> 1;
73         *(dest++) = r >> 1;
74       }
75       if (do_float) {
76         af = *(p1f++);
77         bf = *(p1f++);
78         gf = *(p1f++);
79         rf = *(p1f++);
80         af += *(p1f++);
81         bf += *(p1f++);
82         gf += *(p1f++);
83         rf += *(p1f++);
84         *(destf++) = 0.5f * af;
85         *(destf++) = 0.5f * bf;
86         *(destf++) = 0.5f * gf;
87         *(destf++) = 0.5f * rf;
88       }
89     }
90     if (do_rect) {
91       _p1 += (ibuf1->x << 2);
92     }
93     if (do_float) {
94       _p1f += (ibuf1->x << 2);
95     }
96   }
97 }
98 
IMB_half_x(struct ImBuf * ibuf1)99 struct ImBuf *IMB_half_x(struct ImBuf *ibuf1)
100 {
101   struct ImBuf *ibuf2;
102 
103   if (ibuf1 == NULL) {
104     return NULL;
105   }
106   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
107     return NULL;
108   }
109 
110   if (ibuf1->x <= 1) {
111     return (IMB_dupImBuf(ibuf1));
112   }
113 
114   ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags);
115   if (ibuf2 == NULL) {
116     return NULL;
117   }
118 
119   imb_half_x_no_alloc(ibuf2, ibuf1);
120 
121   return ibuf2;
122 }
123 
IMB_double_fast_x(struct ImBuf * ibuf1)124 struct ImBuf *IMB_double_fast_x(struct ImBuf *ibuf1)
125 {
126   struct ImBuf *ibuf2;
127   int *p1, *dest, i, col, do_rect, do_float;
128   float *p1f, *destf;
129 
130   if (ibuf1 == NULL) {
131     return NULL;
132   }
133   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
134     return NULL;
135   }
136 
137   do_rect = (ibuf1->rect != NULL);
138   do_float = (ibuf1->rect_float != NULL);
139 
140   ibuf2 = IMB_allocImBuf(2 * ibuf1->x, ibuf1->y, ibuf1->planes, ibuf1->flags);
141   if (ibuf2 == NULL) {
142     return NULL;
143   }
144 
145   p1 = (int *)ibuf1->rect;
146   dest = (int *)ibuf2->rect;
147   p1f = (float *)ibuf1->rect_float;
148   destf = (float *)ibuf2->rect_float;
149 
150   for (i = ibuf1->y * ibuf1->x; i > 0; i--) {
151     if (do_rect) {
152       col = *p1++;
153       *dest++ = col;
154       *dest++ = col;
155     }
156     if (do_float) {
157       destf[0] = destf[4] = p1f[0];
158       destf[1] = destf[5] = p1f[1];
159       destf[2] = destf[6] = p1f[2];
160       destf[3] = destf[7] = p1f[3];
161       destf += 8;
162       p1f += 4;
163     }
164   }
165 
166   return ibuf2;
167 }
168 
IMB_double_x(struct ImBuf * ibuf1)169 struct ImBuf *IMB_double_x(struct ImBuf *ibuf1)
170 {
171   struct ImBuf *ibuf2;
172 
173   if (ibuf1 == NULL) {
174     return NULL;
175   }
176   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
177     return NULL;
178   }
179 
180   ibuf2 = IMB_double_fast_x(ibuf1);
181 
182   imb_filterx(ibuf2);
183   return ibuf2;
184 }
185 
imb_half_y_no_alloc(struct ImBuf * ibuf2,struct ImBuf * ibuf1)186 static void imb_half_y_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
187 {
188   uchar *p1, *p2, *_p1, *dest;
189   short a, r, g, b;
190   int x, y;
191   int do_rect, do_float;
192   float af, rf, gf, bf, *p1f, *p2f, *_p1f, *destf;
193 
194   p1 = p2 = NULL;
195   p1f = p2f = NULL;
196 
197   do_rect = (ibuf1->rect != NULL);
198   do_float = (ibuf1->rect_float != NULL && ibuf2->rect_float != NULL);
199 
200   _p1 = (uchar *)ibuf1->rect;
201   dest = (uchar *)ibuf2->rect;
202   _p1f = (float *)ibuf1->rect_float;
203   destf = (float *)ibuf2->rect_float;
204 
205   for (y = ibuf2->y; y > 0; y--) {
206     if (do_rect) {
207       p1 = _p1;
208       p2 = _p1 + (ibuf1->x << 2);
209     }
210     if (do_float) {
211       p1f = _p1f;
212       p2f = _p1f + (ibuf1->x << 2);
213     }
214     for (x = ibuf2->x; x > 0; x--) {
215       if (do_rect) {
216         a = *(p1++);
217         b = *(p1++);
218         g = *(p1++);
219         r = *(p1++);
220         a += *(p2++);
221         b += *(p2++);
222         g += *(p2++);
223         r += *(p2++);
224         *(dest++) = a >> 1;
225         *(dest++) = b >> 1;
226         *(dest++) = g >> 1;
227         *(dest++) = r >> 1;
228       }
229       if (do_float) {
230         af = *(p1f++);
231         bf = *(p1f++);
232         gf = *(p1f++);
233         rf = *(p1f++);
234         af += *(p2f++);
235         bf += *(p2f++);
236         gf += *(p2f++);
237         rf += *(p2f++);
238         *(destf++) = 0.5f * af;
239         *(destf++) = 0.5f * bf;
240         *(destf++) = 0.5f * gf;
241         *(destf++) = 0.5f * rf;
242       }
243     }
244     if (do_rect) {
245       _p1 += (ibuf1->x << 3);
246     }
247     if (do_float) {
248       _p1f += (ibuf1->x << 3);
249     }
250   }
251 }
252 
IMB_half_y(struct ImBuf * ibuf1)253 struct ImBuf *IMB_half_y(struct ImBuf *ibuf1)
254 {
255   struct ImBuf *ibuf2;
256 
257   if (ibuf1 == NULL) {
258     return NULL;
259   }
260   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
261     return NULL;
262   }
263 
264   if (ibuf1->y <= 1) {
265     return (IMB_dupImBuf(ibuf1));
266   }
267 
268   ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
269   if (ibuf2 == NULL) {
270     return NULL;
271   }
272 
273   imb_half_y_no_alloc(ibuf2, ibuf1);
274 
275   return ibuf2;
276 }
277 
IMB_double_fast_y(struct ImBuf * ibuf1)278 struct ImBuf *IMB_double_fast_y(struct ImBuf *ibuf1)
279 {
280   struct ImBuf *ibuf2;
281   int *p1, *dest1, *dest2;
282   float *p1f, *dest1f, *dest2f;
283   int x, y;
284   int do_rect, do_float;
285 
286   if (ibuf1 == NULL) {
287     return NULL;
288   }
289   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
290     return NULL;
291   }
292 
293   do_rect = (ibuf1->rect != NULL);
294   do_float = (ibuf1->rect_float != NULL);
295 
296   ibuf2 = IMB_allocImBuf(ibuf1->x, 2 * ibuf1->y, ibuf1->planes, ibuf1->flags);
297   if (ibuf2 == NULL) {
298     return NULL;
299   }
300 
301   p1 = (int *)ibuf1->rect;
302   dest1 = (int *)ibuf2->rect;
303   p1f = (float *)ibuf1->rect_float;
304   dest1f = (float *)ibuf2->rect_float;
305 
306   for (y = ibuf1->y; y > 0; y--) {
307     if (do_rect) {
308       dest2 = dest1 + ibuf2->x;
309       for (x = ibuf2->x; x > 0; x--) {
310         *dest1++ = *dest2++ = *p1++;
311       }
312       dest1 = dest2;
313     }
314     if (do_float) {
315       dest2f = dest1f + (4 * ibuf2->x);
316       for (x = ibuf2->x * 4; x > 0; x--) {
317         *dest1f++ = *dest2f++ = *p1f++;
318       }
319       dest1f = dest2f;
320     }
321   }
322 
323   return ibuf2;
324 }
325 
IMB_double_y(struct ImBuf * ibuf1)326 struct ImBuf *IMB_double_y(struct ImBuf *ibuf1)
327 {
328   struct ImBuf *ibuf2;
329 
330   if (ibuf1 == NULL) {
331     return NULL;
332   }
333   if (ibuf1->rect == NULL) {
334     return NULL;
335   }
336 
337   ibuf2 = IMB_double_fast_y(ibuf1);
338 
339   IMB_filtery(ibuf2);
340   return ibuf2;
341 }
342 
343 /* pretty much specific functions which converts uchar <-> ushort but assumes
344  * ushort range of 255*255 which is more convenient here
345  */
straight_uchar_to_premul_ushort(unsigned short result[4],const unsigned char color[4])346 MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4],
347                                              const unsigned char color[4])
348 {
349   unsigned short alpha = color[3];
350 
351   result[0] = color[0] * alpha;
352   result[1] = color[1] * alpha;
353   result[2] = color[2] * alpha;
354   result[3] = alpha * 256;
355 }
356 
premul_ushort_to_straight_uchar(unsigned char * result,const unsigned short color[4])357 MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4])
358 {
359   if (color[3] <= 255) {
360     result[0] = unit_ushort_to_uchar(color[0]);
361     result[1] = unit_ushort_to_uchar(color[1]);
362     result[2] = unit_ushort_to_uchar(color[2]);
363     result[3] = unit_ushort_to_uchar(color[3]);
364   }
365   else {
366     unsigned short alpha = color[3] / 256;
367 
368     result[0] = unit_ushort_to_uchar((ushort)(color[0] / alpha * 256));
369     result[1] = unit_ushort_to_uchar((ushort)(color[1] / alpha * 256));
370     result[2] = unit_ushort_to_uchar((ushort)(color[2] / alpha * 256));
371     result[3] = unit_ushort_to_uchar(color[3]);
372   }
373 }
374 
375 /* result in ibuf2, scaling should be done correctly */
imb_onehalf_no_alloc(struct ImBuf * ibuf2,struct ImBuf * ibuf1)376 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
377 {
378   int x, y;
379   const short do_rect = (ibuf1->rect != NULL);
380   const short do_float = (ibuf1->rect_float != NULL) && (ibuf2->rect_float != NULL);
381 
382   if (do_rect && (ibuf2->rect == NULL)) {
383     imb_addrectImBuf(ibuf2);
384   }
385 
386   if (ibuf1->x <= 1) {
387     imb_half_y_no_alloc(ibuf2, ibuf1);
388     return;
389   }
390   if (ibuf1->y <= 1) {
391     imb_half_x_no_alloc(ibuf2, ibuf1);
392     return;
393   }
394 
395   if (do_rect) {
396     unsigned char *cp1, *cp2, *dest;
397 
398     cp1 = (unsigned char *)ibuf1->rect;
399     dest = (unsigned char *)ibuf2->rect;
400 
401     for (y = ibuf2->y; y > 0; y--) {
402       cp2 = cp1 + (ibuf1->x << 2);
403       for (x = ibuf2->x; x > 0; x--) {
404         unsigned short p1i[8], p2i[8], desti[4];
405 
406         straight_uchar_to_premul_ushort(p1i, cp1);
407         straight_uchar_to_premul_ushort(p2i, cp2);
408         straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4);
409         straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4);
410 
411         desti[0] = ((unsigned int)p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
412         desti[1] = ((unsigned int)p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
413         desti[2] = ((unsigned int)p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
414         desti[3] = ((unsigned int)p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
415 
416         premul_ushort_to_straight_uchar(dest, desti);
417 
418         cp1 += 8;
419         cp2 += 8;
420         dest += 4;
421       }
422       cp1 = cp2;
423       if (ibuf1->x & 1) {
424         cp1 += 4;
425       }
426     }
427   }
428 
429   if (do_float) {
430     float *p1f, *p2f, *destf;
431 
432     p1f = ibuf1->rect_float;
433     destf = ibuf2->rect_float;
434     for (y = ibuf2->y; y > 0; y--) {
435       p2f = p1f + (ibuf1->x << 2);
436       for (x = ibuf2->x; x > 0; x--) {
437         destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
438         destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
439         destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
440         destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
441         p1f += 8;
442         p2f += 8;
443         destf += 4;
444       }
445       p1f = p2f;
446       if (ibuf1->x & 1) {
447         p1f += 4;
448       }
449     }
450   }
451 }
452 
IMB_onehalf(struct ImBuf * ibuf1)453 ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
454 {
455   struct ImBuf *ibuf2;
456 
457   if (ibuf1 == NULL) {
458     return NULL;
459   }
460   if (ibuf1->rect == NULL && ibuf1->rect_float == NULL) {
461     return NULL;
462   }
463 
464   if (ibuf1->x <= 1) {
465     return (IMB_half_y(ibuf1));
466   }
467   if (ibuf1->y <= 1) {
468     return (IMB_half_x(ibuf1));
469   }
470 
471   ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
472   if (ibuf2 == NULL) {
473     return NULL;
474   }
475 
476   imb_onehalf_no_alloc(ibuf2, ibuf1);
477 
478   return ibuf2;
479 }
480 
481 /* q_scale_linear_interpolation helper functions */
482 
enlarge_picture_byte(unsigned char * src,unsigned char * dst,int src_width,int src_height,int dst_width,int dst_height)483 static void enlarge_picture_byte(unsigned char *src,
484                                  unsigned char *dst,
485                                  int src_width,
486                                  int src_height,
487                                  int dst_width,
488                                  int dst_height)
489 {
490   double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001);
491   double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001);
492   uintptr_t x_src, dx_src, x_dst;
493   uintptr_t y_src, dy_src, y_dst;
494 
495   dx_src = 65536.0 / ratiox;
496   dy_src = 65536.0 / ratioy;
497 
498   y_src = 0;
499   for (y_dst = 0; y_dst < dst_height; y_dst++) {
500     unsigned char *line1 = src + (y_src >> 16) * 4 * src_width;
501     unsigned char *line2 = line1 + 4 * src_width;
502     uintptr_t weight1y = 65536 - (y_src & 0xffff);
503     uintptr_t weight2y = 65536 - weight1y;
504 
505     if ((y_src >> 16) == src_height - 1) {
506       line2 = line1;
507     }
508 
509     x_src = 0;
510     for (x_dst = 0; x_dst < dst_width; x_dst++) {
511       uintptr_t weight1x = 65536 - (x_src & 0xffff);
512       uintptr_t weight2x = 65536 - weight1x;
513 
514       unsigned long x = (x_src >> 16) * 4;
515 
516       *dst++ = ((((line1[x] * weight1y) >> 16) * weight1x) >> 16) +
517                ((((line2[x] * weight2y) >> 16) * weight1x) >> 16) +
518                ((((line1[4 + x] * weight1y) >> 16) * weight2x) >> 16) +
519                ((((line2[4 + x] * weight2y) >> 16) * weight2x) >> 16);
520 
521       *dst++ = ((((line1[x + 1] * weight1y) >> 16) * weight1x) >> 16) +
522                ((((line2[x + 1] * weight2y) >> 16) * weight1x) >> 16) +
523                ((((line1[4 + x + 1] * weight1y) >> 16) * weight2x) >> 16) +
524                ((((line2[4 + x + 1] * weight2y) >> 16) * weight2x) >> 16);
525 
526       *dst++ = ((((line1[x + 2] * weight1y) >> 16) * weight1x) >> 16) +
527                ((((line2[x + 2] * weight2y) >> 16) * weight1x) >> 16) +
528                ((((line1[4 + x + 2] * weight1y) >> 16) * weight2x) >> 16) +
529                ((((line2[4 + x + 2] * weight2y) >> 16) * weight2x) >> 16);
530 
531       *dst++ = ((((line1[x + 3] * weight1y) >> 16) * weight1x) >> 16) +
532                ((((line2[x + 3] * weight2y) >> 16) * weight1x) >> 16) +
533                ((((line1[4 + x + 3] * weight1y) >> 16) * weight2x) >> 16) +
534                ((((line2[4 + x + 3] * weight2y) >> 16) * weight2x) >> 16);
535 
536       x_src += dx_src;
537     }
538     y_src += dy_src;
539   }
540 }
541 
542 struct scale_outpix_byte {
543   uintptr_t r;
544   uintptr_t g;
545   uintptr_t b;
546   uintptr_t a;
547 
548   uintptr_t weight;
549 };
550 
shrink_picture_byte(unsigned char * src,unsigned char * dst,int src_width,int src_height,int dst_width,int dst_height)551 static void shrink_picture_byte(unsigned char *src,
552                                 unsigned char *dst,
553                                 int src_width,
554                                 int src_height,
555                                 int dst_width,
556                                 int dst_height)
557 {
558   double ratiox = (double)(dst_width) / (double)(src_width);
559   double ratioy = (double)(dst_height) / (double)(src_height);
560   uintptr_t x_src, dx_dst, x_dst;
561   uintptr_t y_src, dy_dst, y_dst;
562   intptr_t y_counter;
563   unsigned char *dst_begin = dst;
564 
565   struct scale_outpix_byte *dst_line1 = NULL;
566   struct scale_outpix_byte *dst_line2 = NULL;
567 
568   dst_line1 = (struct scale_outpix_byte *)MEM_callocN(
569       (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 1");
570   dst_line2 = (struct scale_outpix_byte *)MEM_callocN(
571       (dst_width + 1) * sizeof(struct scale_outpix_byte), "shrink_picture_byte 2");
572 
573   dx_dst = 65536.0 * ratiox;
574   dy_dst = 65536.0 * ratioy;
575 
576   y_dst = 0;
577   y_counter = 65536;
578   for (y_src = 0; y_src < src_height; y_src++) {
579     unsigned char *line = src + y_src * 4 * src_width;
580     uintptr_t weight1y = 65535 - (y_dst & 0xffff);
581     uintptr_t weight2y = 65535 - weight1y;
582     x_dst = 0;
583     for (x_src = 0; x_src < src_width; x_src++) {
584       uintptr_t weight1x = 65535 - (x_dst & 0xffff);
585       uintptr_t weight2x = 65535 - weight1x;
586 
587       uintptr_t x = x_dst >> 16;
588 
589       uintptr_t w;
590 
591       w = (weight1y * weight1x) >> 16;
592 
593       /* Ensure correct rounding, without this you get ugly banding,
594        * or too low color values (ton). */
595       dst_line1[x].r += (line[0] * w + 32767) >> 16;
596       dst_line1[x].g += (line[1] * w + 32767) >> 16;
597       dst_line1[x].b += (line[2] * w + 32767) >> 16;
598       dst_line1[x].a += (line[3] * w + 32767) >> 16;
599       dst_line1[x].weight += w;
600 
601       w = (weight2y * weight1x) >> 16;
602 
603       dst_line2[x].r += (line[0] * w + 32767) >> 16;
604       dst_line2[x].g += (line[1] * w + 32767) >> 16;
605       dst_line2[x].b += (line[2] * w + 32767) >> 16;
606       dst_line2[x].a += (line[3] * w + 32767) >> 16;
607       dst_line2[x].weight += w;
608 
609       w = (weight1y * weight2x) >> 16;
610 
611       dst_line1[x + 1].r += (line[0] * w + 32767) >> 16;
612       dst_line1[x + 1].g += (line[1] * w + 32767) >> 16;
613       dst_line1[x + 1].b += (line[2] * w + 32767) >> 16;
614       dst_line1[x + 1].a += (line[3] * w + 32767) >> 16;
615       dst_line1[x + 1].weight += w;
616 
617       w = (weight2y * weight2x) >> 16;
618 
619       dst_line2[x + 1].r += (line[0] * w + 32767) >> 16;
620       dst_line2[x + 1].g += (line[1] * w + 32767) >> 16;
621       dst_line2[x + 1].b += (line[2] * w + 32767) >> 16;
622       dst_line2[x + 1].a += (line[3] * w + 32767) >> 16;
623       dst_line2[x + 1].weight += w;
624 
625       x_dst += dx_dst;
626       line += 4;
627     }
628 
629     y_dst += dy_dst;
630     y_counter -= dy_dst;
631     if (y_counter < 0) {
632       int val;
633       uintptr_t x;
634       struct scale_outpix_byte *temp;
635 
636       y_counter += 65536;
637 
638       for (x = 0; x < dst_width; x++) {
639         uintptr_t f = 0x80000000UL / dst_line1[x].weight;
640         *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val;
641         *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val;
642         *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val;
643         *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val;
644       }
645       memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_byte));
646       temp = dst_line1;
647       dst_line1 = dst_line2;
648       dst_line2 = temp;
649     }
650   }
651   if (dst - dst_begin < dst_width * dst_height * 4) {
652     int val;
653     uintptr_t x;
654     for (x = 0; x < dst_width; x++) {
655       uintptr_t f = 0x80000000UL / dst_line1[x].weight;
656       *dst++ = (val = (dst_line1[x].r * f) >> 15) > 255 ? 255 : val;
657       *dst++ = (val = (dst_line1[x].g * f) >> 15) > 255 ? 255 : val;
658       *dst++ = (val = (dst_line1[x].b * f) >> 15) > 255 ? 255 : val;
659       *dst++ = (val = (dst_line1[x].a * f) >> 15) > 255 ? 255 : val;
660     }
661   }
662   MEM_freeN(dst_line1);
663   MEM_freeN(dst_line2);
664 }
665 
q_scale_byte(unsigned char * in,unsigned char * out,int in_width,int in_height,int dst_width,int dst_height)666 static void q_scale_byte(unsigned char *in,
667                          unsigned char *out,
668                          int in_width,
669                          int in_height,
670                          int dst_width,
671                          int dst_height)
672 {
673   if (dst_width > in_width && dst_height > in_height) {
674     enlarge_picture_byte(in, out, in_width, in_height, dst_width, dst_height);
675   }
676   else if (dst_width < in_width && dst_height < in_height) {
677     shrink_picture_byte(in, out, in_width, in_height, dst_width, dst_height);
678   }
679 }
680 
enlarge_picture_float(float * src,float * dst,int src_width,int src_height,int dst_width,int dst_height)681 static void enlarge_picture_float(
682     float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height)
683 {
684   double ratiox = (double)(dst_width - 1.0) / (double)(src_width - 1.001);
685   double ratioy = (double)(dst_height - 1.0) / (double)(src_height - 1.001);
686   uintptr_t x_dst;
687   uintptr_t y_dst;
688   double x_src, dx_src;
689   double y_src, dy_src;
690 
691   dx_src = 1.0 / ratiox;
692   dy_src = 1.0 / ratioy;
693 
694   y_src = 0;
695   for (y_dst = 0; y_dst < dst_height; y_dst++) {
696     float *line1 = src + ((int)y_src) * 4 * src_width;
697     const float *line2 = line1 + 4 * src_width;
698     const float weight1y = (float)(1.0 - (y_src - (int)y_src));
699     const float weight2y = 1.0f - weight1y;
700 
701     if ((int)y_src == src_height - 1) {
702       line2 = line1;
703     }
704 
705     x_src = 0;
706     for (x_dst = 0; x_dst < dst_width; x_dst++) {
707       const float weight1x = (float)(1.0 - (x_src - (int)x_src));
708       const float weight2x = (float)(1.0f - weight1x);
709 
710       const float w11 = weight1y * weight1x;
711       const float w21 = weight2y * weight1x;
712       const float w12 = weight1y * weight2x;
713       const float w22 = weight2y * weight2x;
714 
715       uintptr_t x = ((int)x_src) * 4;
716 
717       *dst++ = line1[x] * w11 + line2[x] * w21 + line1[4 + x] * w12 + line2[4 + x] * w22;
718 
719       *dst++ = line1[x + 1] * w11 + line2[x + 1] * w21 + line1[4 + x + 1] * w12 +
720                line2[4 + x + 1] * w22;
721 
722       *dst++ = line1[x + 2] * w11 + line2[x + 2] * w21 + line1[4 + x + 2] * w12 +
723                line2[4 + x + 2] * w22;
724 
725       *dst++ = line1[x + 3] * w11 + line2[x + 3] * w21 + line1[4 + x + 3] * w12 +
726                line2[4 + x + 3] * w22;
727 
728       x_src += dx_src;
729     }
730     y_src += dy_src;
731   }
732 }
733 
734 struct scale_outpix_float {
735   float r;
736   float g;
737   float b;
738   float a;
739 
740   float weight;
741 };
742 
shrink_picture_float(const float * src,float * dst,int src_width,int src_height,int dst_width,int dst_height)743 static void shrink_picture_float(
744     const float *src, float *dst, int src_width, int src_height, int dst_width, int dst_height)
745 {
746   double ratiox = (double)(dst_width) / (double)(src_width);
747   double ratioy = (double)(dst_height) / (double)(src_height);
748   uintptr_t x_src;
749   uintptr_t y_src;
750   float dx_dst, x_dst;
751   float dy_dst, y_dst;
752   float y_counter;
753   const float *dst_begin = dst;
754 
755   struct scale_outpix_float *dst_line1;
756   struct scale_outpix_float *dst_line2;
757 
758   dst_line1 = (struct scale_outpix_float *)MEM_callocN(
759       (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 1");
760   dst_line2 = (struct scale_outpix_float *)MEM_callocN(
761       (dst_width + 1) * sizeof(struct scale_outpix_float), "shrink_picture_float 2");
762 
763   dx_dst = ratiox;
764   dy_dst = ratioy;
765 
766   y_dst = 0;
767   y_counter = 1.0;
768   for (y_src = 0; y_src < src_height; y_src++) {
769     const float *line = src + y_src * 4 * src_width;
770     uintptr_t weight1y = 1.0f - (y_dst - (int)y_dst);
771     uintptr_t weight2y = 1.0f - weight1y;
772     x_dst = 0;
773     for (x_src = 0; x_src < src_width; x_src++) {
774       uintptr_t weight1x = 1.0f - (x_dst - (int)x_dst);
775       uintptr_t weight2x = 1.0f - weight1x;
776 
777       uintptr_t x = (int)x_dst;
778 
779       float w;
780 
781       w = weight1y * weight1x;
782 
783       dst_line1[x].r += line[0] * w;
784       dst_line1[x].g += line[1] * w;
785       dst_line1[x].b += line[2] * w;
786       dst_line1[x].a += line[3] * w;
787       dst_line1[x].weight += w;
788 
789       w = weight2y * weight1x;
790 
791       dst_line2[x].r += line[0] * w;
792       dst_line2[x].g += line[1] * w;
793       dst_line2[x].b += line[2] * w;
794       dst_line2[x].a += line[3] * w;
795       dst_line2[x].weight += w;
796 
797       w = weight1y * weight2x;
798 
799       dst_line1[x + 1].r += line[0] * w;
800       dst_line1[x + 1].g += line[1] * w;
801       dst_line1[x + 1].b += line[2] * w;
802       dst_line1[x + 1].a += line[3] * w;
803       dst_line1[x + 1].weight += w;
804 
805       w = weight2y * weight2x;
806 
807       dst_line2[x + 1].r += line[0] * w;
808       dst_line2[x + 1].g += line[1] * w;
809       dst_line2[x + 1].b += line[2] * w;
810       dst_line2[x + 1].a += line[3] * w;
811       dst_line2[x + 1].weight += w;
812 
813       x_dst += dx_dst;
814       line += 4;
815     }
816 
817     y_dst += dy_dst;
818     y_counter -= dy_dst;
819     if (y_counter < 0) {
820       uintptr_t x;
821       struct scale_outpix_float *temp;
822 
823       y_counter += 1.0f;
824 
825       for (x = 0; x < dst_width; x++) {
826         float f = 1.0f / dst_line1[x].weight;
827         *dst++ = dst_line1[x].r * f;
828         *dst++ = dst_line1[x].g * f;
829         *dst++ = dst_line1[x].b * f;
830         *dst++ = dst_line1[x].a * f;
831       }
832       memset(dst_line1, 0, dst_width * sizeof(struct scale_outpix_float));
833       temp = dst_line1;
834       dst_line1 = dst_line2;
835       dst_line2 = temp;
836     }
837   }
838   if (dst - dst_begin < dst_width * dst_height * 4) {
839     uintptr_t x;
840     for (x = 0; x < dst_width; x++) {
841       float f = 1.0f / dst_line1[x].weight;
842       *dst++ = dst_line1[x].r * f;
843       *dst++ = dst_line1[x].g * f;
844       *dst++ = dst_line1[x].b * f;
845       *dst++ = dst_line1[x].a * f;
846     }
847   }
848   MEM_freeN(dst_line1);
849   MEM_freeN(dst_line2);
850 }
851 
q_scale_float(float * in,float * out,int in_width,int in_height,int dst_width,int dst_height)852 static void q_scale_float(
853     float *in, float *out, int in_width, int in_height, int dst_width, int dst_height)
854 {
855   if (dst_width > in_width && dst_height > in_height) {
856     enlarge_picture_float(in, out, in_width, in_height, dst_width, dst_height);
857   }
858   else if (dst_width < in_width && dst_height < in_height) {
859     shrink_picture_float(in, out, in_width, in_height, dst_width, dst_height);
860   }
861 }
862 
863 /**
864  * q_scale_linear_interpolation (derived from ppmqscale, http://libdv.sf.net)
865  *
866  * q stands for quick _and_ quality :)
867  *
868  * only handles common cases when we either
869  *
870  * scale  both, x and y or
871  * shrink both, x and y
872  *
873  * but that is pretty fast:
874  * - does only blit once instead of two passes like the old code
875  *   (fewer cache misses)
876  * - uses fixed point integer arithmetic for byte buffers
877  * - doesn't branch in tight loops
878  *
879  * Should be comparable in speed to the ImBuf ..._fast functions at least
880  * for byte-buffers.
881  *
882  * NOTE: disabled, due to unacceptable inaccuracy and quality loss, see bug T18609 (ton)
883  */
q_scale_linear_interpolation(struct ImBuf * ibuf,int newx,int newy)884 static bool q_scale_linear_interpolation(struct ImBuf *ibuf, int newx, int newy)
885 {
886   if ((newx >= ibuf->x && newy <= ibuf->y) || (newx <= ibuf->x && newy >= ibuf->y)) {
887     return false;
888   }
889 
890   if (ibuf->rect) {
891     unsigned char *newrect = MEM_mallocN(sizeof(int) * newx * newy, "q_scale rect");
892     q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y, newx, newy);
893 
894     imb_freerectImBuf(ibuf);
895     ibuf->mall |= IB_rect;
896     ibuf->rect = (unsigned int *)newrect;
897   }
898   if (ibuf->rect_float) {
899     float *newrect = MEM_mallocN(sizeof(float[4]) * newx * newy, "q_scale rectfloat");
900     q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y, newx, newy);
901     imb_freerectfloatImBuf(ibuf);
902     ibuf->mall |= IB_rectfloat;
903     ibuf->rect_float = newrect;
904   }
905   ibuf->x = newx;
906   ibuf->y = newy;
907 
908   return true;
909 }
910 
scaledownx(struct ImBuf * ibuf,int newx)911 static ImBuf *scaledownx(struct ImBuf *ibuf, int newx)
912 {
913   const int do_rect = (ibuf->rect != NULL);
914   const int do_float = (ibuf->rect_float != NULL);
915   const size_t rect_size = ibuf->x * ibuf->y * 4;
916 
917   uchar *rect, *_newrect, *newrect;
918   float *rectf, *_newrectf, *newrectf;
919   float sample, add, val[4], nval[4], valf[4], nvalf[4];
920   int x, y;
921 
922   rectf = _newrectf = newrectf = NULL;
923   rect = _newrect = newrect = NULL;
924   nval[0] = nval[1] = nval[2] = nval[3] = 0.0f;
925   nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f;
926 
927   if (!do_rect && !do_float) {
928     return ibuf;
929   }
930 
931   if (do_rect) {
932     _newrect = MEM_mallocN(sizeof(uchar[4]) * newx * ibuf->y, "scaledownx");
933     if (_newrect == NULL) {
934       return ibuf;
935     }
936   }
937   if (do_float) {
938     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * ibuf->y, "scaledownxf");
939     if (_newrectf == NULL) {
940       if (_newrect) {
941         MEM_freeN(_newrect);
942       }
943       return ibuf;
944     }
945   }
946 
947   add = (ibuf->x - 0.01) / newx;
948 
949   if (do_rect) {
950     rect = (uchar *)ibuf->rect;
951     newrect = _newrect;
952   }
953   if (do_float) {
954     rectf = ibuf->rect_float;
955     newrectf = _newrectf;
956   }
957 
958   for (y = ibuf->y; y > 0; y--) {
959     sample = 0.0f;
960     val[0] = val[1] = val[2] = val[3] = 0.0f;
961     valf[0] = valf[1] = valf[2] = valf[3] = 0.0f;
962 
963     for (x = newx; x > 0; x--) {
964       if (do_rect) {
965         nval[0] = -val[0] * sample;
966         nval[1] = -val[1] * sample;
967         nval[2] = -val[2] * sample;
968         nval[3] = -val[3] * sample;
969       }
970       if (do_float) {
971         nvalf[0] = -valf[0] * sample;
972         nvalf[1] = -valf[1] * sample;
973         nvalf[2] = -valf[2] * sample;
974         nvalf[3] = -valf[3] * sample;
975       }
976 
977       sample += add;
978 
979       while (sample >= 1.0f) {
980         sample -= 1.0f;
981 
982         if (do_rect) {
983           nval[0] += rect[0];
984           nval[1] += rect[1];
985           nval[2] += rect[2];
986           nval[3] += rect[3];
987           rect += 4;
988         }
989         if (do_float) {
990           nvalf[0] += rectf[0];
991           nvalf[1] += rectf[1];
992           nvalf[2] += rectf[2];
993           nvalf[3] += rectf[3];
994           rectf += 4;
995         }
996       }
997 
998       if (do_rect) {
999         val[0] = rect[0];
1000         val[1] = rect[1];
1001         val[2] = rect[2];
1002         val[3] = rect[3];
1003         rect += 4;
1004 
1005         newrect[0] = roundf((nval[0] + sample * val[0]) / add);
1006         newrect[1] = roundf((nval[1] + sample * val[1]) / add);
1007         newrect[2] = roundf((nval[2] + sample * val[2]) / add);
1008         newrect[3] = roundf((nval[3] + sample * val[3]) / add);
1009 
1010         newrect += 4;
1011       }
1012       if (do_float) {
1013 
1014         valf[0] = rectf[0];
1015         valf[1] = rectf[1];
1016         valf[2] = rectf[2];
1017         valf[3] = rectf[3];
1018         rectf += 4;
1019 
1020         newrectf[0] = ((nvalf[0] + sample * valf[0]) / add);
1021         newrectf[1] = ((nvalf[1] + sample * valf[1]) / add);
1022         newrectf[2] = ((nvalf[2] + sample * valf[2]) / add);
1023         newrectf[3] = ((nvalf[3] + sample * valf[3]) / add);
1024 
1025         newrectf += 4;
1026       }
1027 
1028       sample -= 1.0f;
1029     }
1030   }
1031 
1032   if (do_rect) {
1033     // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size);
1034     BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */
1035     imb_freerectImBuf(ibuf);
1036     ibuf->mall |= IB_rect;
1037     ibuf->rect = (unsigned int *)_newrect;
1038   }
1039   if (do_float) {
1040     // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size);
1041     BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */
1042     imb_freerectfloatImBuf(ibuf);
1043     ibuf->mall |= IB_rectfloat;
1044     ibuf->rect_float = _newrectf;
1045   }
1046   (void)rect_size; /* UNUSED in release builds */
1047 
1048   ibuf->x = newx;
1049   return ibuf;
1050 }
1051 
scaledowny(struct ImBuf * ibuf,int newy)1052 static ImBuf *scaledowny(struct ImBuf *ibuf, int newy)
1053 {
1054   const int do_rect = (ibuf->rect != NULL);
1055   const int do_float = (ibuf->rect_float != NULL);
1056   const size_t rect_size = ibuf->x * ibuf->y * 4;
1057 
1058   uchar *rect, *_newrect, *newrect;
1059   float *rectf, *_newrectf, *newrectf;
1060   float sample, add, val[4], nval[4], valf[4], nvalf[4];
1061   int x, y, skipx;
1062 
1063   rectf = _newrectf = newrectf = NULL;
1064   rect = _newrect = newrect = NULL;
1065   nval[0] = nval[1] = nval[2] = nval[3] = 0.0f;
1066   nvalf[0] = nvalf[1] = nvalf[2] = nvalf[3] = 0.0f;
1067 
1068   if (!do_rect && !do_float) {
1069     return ibuf;
1070   }
1071 
1072   if (do_rect) {
1073     _newrect = MEM_mallocN(sizeof(uchar[4]) * newy * ibuf->x, "scaledowny");
1074     if (_newrect == NULL) {
1075       return ibuf;
1076     }
1077   }
1078   if (do_float) {
1079     _newrectf = MEM_mallocN(sizeof(float[4]) * newy * ibuf->x, "scaledownyf");
1080     if (_newrectf == NULL) {
1081       if (_newrect) {
1082         MEM_freeN(_newrect);
1083       }
1084       return ibuf;
1085     }
1086   }
1087 
1088   add = (ibuf->y - 0.01) / newy;
1089   skipx = 4 * ibuf->x;
1090 
1091   for (x = skipx - 4; x >= 0; x -= 4) {
1092     if (do_rect) {
1093       rect = ((uchar *)ibuf->rect) + x;
1094       newrect = _newrect + x;
1095     }
1096     if (do_float) {
1097       rectf = ibuf->rect_float + x;
1098       newrectf = _newrectf + x;
1099     }
1100 
1101     sample = 0.0f;
1102     val[0] = val[1] = val[2] = val[3] = 0.0f;
1103     valf[0] = valf[1] = valf[2] = valf[3] = 0.0f;
1104 
1105     for (y = newy; y > 0; y--) {
1106       if (do_rect) {
1107         nval[0] = -val[0] * sample;
1108         nval[1] = -val[1] * sample;
1109         nval[2] = -val[2] * sample;
1110         nval[3] = -val[3] * sample;
1111       }
1112       if (do_float) {
1113         nvalf[0] = -valf[0] * sample;
1114         nvalf[1] = -valf[1] * sample;
1115         nvalf[2] = -valf[2] * sample;
1116         nvalf[3] = -valf[3] * sample;
1117       }
1118 
1119       sample += add;
1120 
1121       while (sample >= 1.0f) {
1122         sample -= 1.0f;
1123 
1124         if (do_rect) {
1125           nval[0] += rect[0];
1126           nval[1] += rect[1];
1127           nval[2] += rect[2];
1128           nval[3] += rect[3];
1129           rect += skipx;
1130         }
1131         if (do_float) {
1132           nvalf[0] += rectf[0];
1133           nvalf[1] += rectf[1];
1134           nvalf[2] += rectf[2];
1135           nvalf[3] += rectf[3];
1136           rectf += skipx;
1137         }
1138       }
1139 
1140       if (do_rect) {
1141         val[0] = rect[0];
1142         val[1] = rect[1];
1143         val[2] = rect[2];
1144         val[3] = rect[3];
1145         rect += skipx;
1146 
1147         newrect[0] = roundf((nval[0] + sample * val[0]) / add);
1148         newrect[1] = roundf((nval[1] + sample * val[1]) / add);
1149         newrect[2] = roundf((nval[2] + sample * val[2]) / add);
1150         newrect[3] = roundf((nval[3] + sample * val[3]) / add);
1151 
1152         newrect += skipx;
1153       }
1154       if (do_float) {
1155 
1156         valf[0] = rectf[0];
1157         valf[1] = rectf[1];
1158         valf[2] = rectf[2];
1159         valf[3] = rectf[3];
1160         rectf += skipx;
1161 
1162         newrectf[0] = ((nvalf[0] + sample * valf[0]) / add);
1163         newrectf[1] = ((nvalf[1] + sample * valf[1]) / add);
1164         newrectf[2] = ((nvalf[2] + sample * valf[2]) / add);
1165         newrectf[3] = ((nvalf[3] + sample * valf[3]) / add);
1166 
1167         newrectf += skipx;
1168       }
1169 
1170       sample -= 1.0f;
1171     }
1172   }
1173 
1174   if (do_rect) {
1175     // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size);
1176     BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */
1177     imb_freerectImBuf(ibuf);
1178     ibuf->mall |= IB_rect;
1179     ibuf->rect = (unsigned int *)_newrect;
1180   }
1181   if (do_float) {
1182     // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size);
1183     BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */
1184     imb_freerectfloatImBuf(ibuf);
1185     ibuf->mall |= IB_rectfloat;
1186     ibuf->rect_float = (float *)_newrectf;
1187   }
1188   (void)rect_size; /* UNUSED in release builds */
1189 
1190   ibuf->y = newy;
1191   return ibuf;
1192 }
1193 
scaleupx(struct ImBuf * ibuf,int newx)1194 static ImBuf *scaleupx(struct ImBuf *ibuf, int newx)
1195 {
1196   uchar *rect, *_newrect = NULL, *newrect;
1197   float *rectf, *_newrectf = NULL, *newrectf;
1198   float sample, add;
1199   float val_a, nval_a, diff_a;
1200   float val_b, nval_b, diff_b;
1201   float val_g, nval_g, diff_g;
1202   float val_r, nval_r, diff_r;
1203   float val_af, nval_af, diff_af;
1204   float val_bf, nval_bf, diff_bf;
1205   float val_gf, nval_gf, diff_gf;
1206   float val_rf, nval_rf, diff_rf;
1207   int x, y;
1208   bool do_rect = false, do_float = false;
1209 
1210   val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
1211   val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
1212   val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
1213   val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
1214   if (ibuf == NULL) {
1215     return NULL;
1216   }
1217   if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
1218     return ibuf;
1219   }
1220 
1221   if (ibuf->rect) {
1222     do_rect = true;
1223     _newrect = MEM_mallocN(newx * ibuf->y * sizeof(int), "scaleupx");
1224     if (_newrect == NULL) {
1225       return ibuf;
1226     }
1227   }
1228   if (ibuf->rect_float) {
1229     do_float = true;
1230     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * ibuf->y, "scaleupxf");
1231     if (_newrectf == NULL) {
1232       if (_newrect) {
1233         MEM_freeN(_newrect);
1234       }
1235       return ibuf;
1236     }
1237   }
1238 
1239   add = (ibuf->x - 1.001) / (newx - 1.0);
1240 
1241   rect = (uchar *)ibuf->rect;
1242   rectf = (float *)ibuf->rect_float;
1243   newrect = _newrect;
1244   newrectf = _newrectf;
1245 
1246   for (y = ibuf->y; y > 0; y--) {
1247 
1248     sample = 0;
1249 
1250     if (do_rect) {
1251       val_a = rect[0];
1252       nval_a = rect[4];
1253       diff_a = nval_a - val_a;
1254       val_a += 0.5f;
1255 
1256       val_b = rect[1];
1257       nval_b = rect[5];
1258       diff_b = nval_b - val_b;
1259       val_b += 0.5f;
1260 
1261       val_g = rect[2];
1262       nval_g = rect[6];
1263       diff_g = nval_g - val_g;
1264       val_g += 0.5f;
1265 
1266       val_r = rect[3];
1267       nval_r = rect[7];
1268       diff_r = nval_r - val_r;
1269       val_r += 0.5f;
1270 
1271       rect += 8;
1272     }
1273     if (do_float) {
1274       val_af = rectf[0];
1275       nval_af = rectf[4];
1276       diff_af = nval_af - val_af;
1277 
1278       val_bf = rectf[1];
1279       nval_bf = rectf[5];
1280       diff_bf = nval_bf - val_bf;
1281 
1282       val_gf = rectf[2];
1283       nval_gf = rectf[6];
1284       diff_gf = nval_gf - val_gf;
1285 
1286       val_rf = rectf[3];
1287       nval_rf = rectf[7];
1288       diff_rf = nval_rf - val_rf;
1289 
1290       rectf += 8;
1291     }
1292     for (x = newx; x > 0; x--) {
1293       if (sample >= 1.0f) {
1294         sample -= 1.0f;
1295 
1296         if (do_rect) {
1297           val_a = nval_a;
1298           nval_a = rect[0];
1299           diff_a = nval_a - val_a;
1300           val_a += 0.5f;
1301 
1302           val_b = nval_b;
1303           nval_b = rect[1];
1304           diff_b = nval_b - val_b;
1305           val_b += 0.5f;
1306 
1307           val_g = nval_g;
1308           nval_g = rect[2];
1309           diff_g = nval_g - val_g;
1310           val_g += 0.5f;
1311 
1312           val_r = nval_r;
1313           nval_r = rect[3];
1314           diff_r = nval_r - val_r;
1315           val_r += 0.5f;
1316           rect += 4;
1317         }
1318         if (do_float) {
1319           val_af = nval_af;
1320           nval_af = rectf[0];
1321           diff_af = nval_af - val_af;
1322 
1323           val_bf = nval_bf;
1324           nval_bf = rectf[1];
1325           diff_bf = nval_bf - val_bf;
1326 
1327           val_gf = nval_gf;
1328           nval_gf = rectf[2];
1329           diff_gf = nval_gf - val_gf;
1330 
1331           val_rf = nval_rf;
1332           nval_rf = rectf[3];
1333           diff_rf = nval_rf - val_rf;
1334           rectf += 4;
1335         }
1336       }
1337       if (do_rect) {
1338         newrect[0] = val_a + sample * diff_a;
1339         newrect[1] = val_b + sample * diff_b;
1340         newrect[2] = val_g + sample * diff_g;
1341         newrect[3] = val_r + sample * diff_r;
1342         newrect += 4;
1343       }
1344       if (do_float) {
1345         newrectf[0] = val_af + sample * diff_af;
1346         newrectf[1] = val_bf + sample * diff_bf;
1347         newrectf[2] = val_gf + sample * diff_gf;
1348         newrectf[3] = val_rf + sample * diff_rf;
1349         newrectf += 4;
1350       }
1351       sample += add;
1352     }
1353   }
1354 
1355   if (do_rect) {
1356     imb_freerectImBuf(ibuf);
1357     ibuf->mall |= IB_rect;
1358     ibuf->rect = (unsigned int *)_newrect;
1359   }
1360   if (do_float) {
1361     imb_freerectfloatImBuf(ibuf);
1362     ibuf->mall |= IB_rectfloat;
1363     ibuf->rect_float = (float *)_newrectf;
1364   }
1365 
1366   ibuf->x = newx;
1367   return ibuf;
1368 }
1369 
scaleupy(struct ImBuf * ibuf,int newy)1370 static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
1371 {
1372   uchar *rect, *_newrect = NULL, *newrect;
1373   float *rectf, *_newrectf = NULL, *newrectf;
1374   float sample, add;
1375   float val_a, nval_a, diff_a;
1376   float val_b, nval_b, diff_b;
1377   float val_g, nval_g, diff_g;
1378   float val_r, nval_r, diff_r;
1379   float val_af, nval_af, diff_af;
1380   float val_bf, nval_bf, diff_bf;
1381   float val_gf, nval_gf, diff_gf;
1382   float val_rf, nval_rf, diff_rf;
1383   int x, y, skipx;
1384   bool do_rect = false, do_float = false;
1385 
1386   val_a = nval_a = diff_a = val_b = nval_b = diff_b = 0;
1387   val_g = nval_g = diff_g = val_r = nval_r = diff_r = 0;
1388   val_af = nval_af = diff_af = val_bf = nval_bf = diff_bf = 0;
1389   val_gf = nval_gf = diff_gf = val_rf = nval_rf = diff_rf = 0;
1390   if (ibuf == NULL) {
1391     return NULL;
1392   }
1393   if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
1394     return ibuf;
1395   }
1396 
1397   if (ibuf->rect) {
1398     do_rect = true;
1399     _newrect = MEM_mallocN(ibuf->x * newy * sizeof(int), "scaleupy");
1400     if (_newrect == NULL) {
1401       return ibuf;
1402     }
1403   }
1404   if (ibuf->rect_float) {
1405     do_float = true;
1406     _newrectf = MEM_mallocN(sizeof(float[4]) * ibuf->x * newy, "scaleupyf");
1407     if (_newrectf == NULL) {
1408       if (_newrect) {
1409         MEM_freeN(_newrect);
1410       }
1411       return ibuf;
1412     }
1413   }
1414 
1415   add = (ibuf->y - 1.001) / (newy - 1.0);
1416   skipx = 4 * ibuf->x;
1417 
1418   rect = (uchar *)ibuf->rect;
1419   rectf = (float *)ibuf->rect_float;
1420   newrect = _newrect;
1421   newrectf = _newrectf;
1422 
1423   for (x = ibuf->x; x > 0; x--) {
1424 
1425     sample = 0;
1426     if (do_rect) {
1427       rect = ((uchar *)ibuf->rect) + 4 * (x - 1);
1428       newrect = _newrect + 4 * (x - 1);
1429 
1430       val_a = rect[0];
1431       nval_a = rect[skipx];
1432       diff_a = nval_a - val_a;
1433       val_a += 0.5f;
1434 
1435       val_b = rect[1];
1436       nval_b = rect[skipx + 1];
1437       diff_b = nval_b - val_b;
1438       val_b += 0.5f;
1439 
1440       val_g = rect[2];
1441       nval_g = rect[skipx + 2];
1442       diff_g = nval_g - val_g;
1443       val_g += 0.5f;
1444 
1445       val_r = rect[3];
1446       nval_r = rect[skipx + 3];
1447       diff_r = nval_r - val_r;
1448       val_r += 0.5f;
1449 
1450       rect += 2 * skipx;
1451     }
1452     if (do_float) {
1453       rectf = ibuf->rect_float + 4 * (x - 1);
1454       newrectf = _newrectf + 4 * (x - 1);
1455 
1456       val_af = rectf[0];
1457       nval_af = rectf[skipx];
1458       diff_af = nval_af - val_af;
1459 
1460       val_bf = rectf[1];
1461       nval_bf = rectf[skipx + 1];
1462       diff_bf = nval_bf - val_bf;
1463 
1464       val_gf = rectf[2];
1465       nval_gf = rectf[skipx + 2];
1466       diff_gf = nval_gf - val_gf;
1467 
1468       val_rf = rectf[3];
1469       nval_rf = rectf[skipx + 3];
1470       diff_rf = nval_rf - val_rf;
1471 
1472       rectf += 2 * skipx;
1473     }
1474 
1475     for (y = newy; y > 0; y--) {
1476       if (sample >= 1.0f) {
1477         sample -= 1.0f;
1478 
1479         if (do_rect) {
1480           val_a = nval_a;
1481           nval_a = rect[0];
1482           diff_a = nval_a - val_a;
1483           val_a += 0.5f;
1484 
1485           val_b = nval_b;
1486           nval_b = rect[1];
1487           diff_b = nval_b - val_b;
1488           val_b += 0.5f;
1489 
1490           val_g = nval_g;
1491           nval_g = rect[2];
1492           diff_g = nval_g - val_g;
1493           val_g += 0.5f;
1494 
1495           val_r = nval_r;
1496           nval_r = rect[3];
1497           diff_r = nval_r - val_r;
1498           val_r += 0.5f;
1499           rect += skipx;
1500         }
1501         if (do_float) {
1502           val_af = nval_af;
1503           nval_af = rectf[0];
1504           diff_af = nval_af - val_af;
1505 
1506           val_bf = nval_bf;
1507           nval_bf = rectf[1];
1508           diff_bf = nval_bf - val_bf;
1509 
1510           val_gf = nval_gf;
1511           nval_gf = rectf[2];
1512           diff_gf = nval_gf - val_gf;
1513 
1514           val_rf = nval_rf;
1515           nval_rf = rectf[3];
1516           diff_rf = nval_rf - val_rf;
1517           rectf += skipx;
1518         }
1519       }
1520       if (do_rect) {
1521         newrect[0] = val_a + sample * diff_a;
1522         newrect[1] = val_b + sample * diff_b;
1523         newrect[2] = val_g + sample * diff_g;
1524         newrect[3] = val_r + sample * diff_r;
1525         newrect += skipx;
1526       }
1527       if (do_float) {
1528         newrectf[0] = val_af + sample * diff_af;
1529         newrectf[1] = val_bf + sample * diff_bf;
1530         newrectf[2] = val_gf + sample * diff_gf;
1531         newrectf[3] = val_rf + sample * diff_rf;
1532         newrectf += skipx;
1533       }
1534       sample += add;
1535     }
1536   }
1537 
1538   if (do_rect) {
1539     imb_freerectImBuf(ibuf);
1540     ibuf->mall |= IB_rect;
1541     ibuf->rect = (unsigned int *)_newrect;
1542   }
1543   if (do_float) {
1544     imb_freerectfloatImBuf(ibuf);
1545     ibuf->mall |= IB_rectfloat;
1546     ibuf->rect_float = (float *)_newrectf;
1547   }
1548 
1549   ibuf->y = newy;
1550   return ibuf;
1551 }
1552 
scalefast_Z_ImBuf(ImBuf * ibuf,int newx,int newy)1553 static void scalefast_Z_ImBuf(ImBuf *ibuf, int newx, int newy)
1554 {
1555   int *zbuf, *newzbuf, *_newzbuf = NULL;
1556   float *zbuf_float, *newzbuf_float, *_newzbuf_float = NULL;
1557   int x, y;
1558   int ofsx, ofsy, stepx, stepy;
1559 
1560   if (ibuf->zbuf) {
1561     _newzbuf = MEM_mallocN(newx * newy * sizeof(int), __func__);
1562     if (_newzbuf == NULL) {
1563       IMB_freezbufImBuf(ibuf);
1564     }
1565   }
1566 
1567   if (ibuf->zbuf_float) {
1568     _newzbuf_float = MEM_mallocN((size_t)newx * newy * sizeof(float), __func__);
1569     if (_newzbuf_float == NULL) {
1570       IMB_freezbuffloatImBuf(ibuf);
1571     }
1572   }
1573 
1574   if (!_newzbuf && !_newzbuf_float) {
1575     return;
1576   }
1577 
1578   stepx = round(65536.0 * (ibuf->x - 1.0) / (newx - 1.0));
1579   stepy = round(65536.0 * (ibuf->y - 1.0) / (newy - 1.0));
1580   ofsy = 32768;
1581 
1582   newzbuf = _newzbuf;
1583   newzbuf_float = _newzbuf_float;
1584 
1585   for (y = newy; y > 0; y--, ofsy += stepy) {
1586     if (newzbuf) {
1587       zbuf = ibuf->zbuf;
1588       zbuf += (ofsy >> 16) * ibuf->x;
1589       ofsx = 32768;
1590       for (x = newx; x > 0; x--, ofsx += stepx) {
1591         *newzbuf++ = zbuf[ofsx >> 16];
1592       }
1593     }
1594 
1595     if (newzbuf_float) {
1596       zbuf_float = ibuf->zbuf_float;
1597       zbuf_float += (ofsy >> 16) * ibuf->x;
1598       ofsx = 32768;
1599       for (x = newx; x > 0; x--, ofsx += stepx) {
1600         *newzbuf_float++ = zbuf_float[ofsx >> 16];
1601       }
1602     }
1603   }
1604 
1605   if (_newzbuf) {
1606     IMB_freezbufImBuf(ibuf);
1607     ibuf->mall |= IB_zbuf;
1608     ibuf->zbuf = _newzbuf;
1609   }
1610 
1611   if (_newzbuf_float) {
1612     IMB_freezbuffloatImBuf(ibuf);
1613     ibuf->mall |= IB_zbuffloat;
1614     ibuf->zbuf_float = _newzbuf_float;
1615   }
1616 }
1617 
1618 /**
1619  * Return true if \a ibuf is modified.
1620  */
IMB_scaleImBuf(struct ImBuf * ibuf,unsigned int newx,unsigned int newy)1621 bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
1622 {
1623   if (ibuf == NULL) {
1624     return false;
1625   }
1626   if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
1627     return false;
1628   }
1629 
1630   if (newx == ibuf->x && newy == ibuf->y) {
1631     return false;
1632   }
1633 
1634   /* Scale-up / scale-down functions below change ibuf->x and ibuf->y
1635    * so we first scale the Z-buffer (if any). */
1636   scalefast_Z_ImBuf(ibuf, newx, newy);
1637 
1638   /* try to scale common cases in a fast way */
1639   /* disabled, quality loss is unacceptable, see report T18609  (ton) */
1640   if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) {
1641     return true;
1642   }
1643 
1644   if (newx && (newx < ibuf->x)) {
1645     scaledownx(ibuf, newx);
1646   }
1647   if (newy && (newy < ibuf->y)) {
1648     scaledowny(ibuf, newy);
1649   }
1650   if (newx && (newx > ibuf->x)) {
1651     scaleupx(ibuf, newx);
1652   }
1653   if (newy && (newy > ibuf->y)) {
1654     scaleupy(ibuf, newy);
1655   }
1656 
1657   return true;
1658 }
1659 
1660 struct imbufRGBA {
1661   float r, g, b, a;
1662 };
1663 
1664 /**
1665  * Return true if \a ibuf is modified.
1666  */
IMB_scalefastImBuf(struct ImBuf * ibuf,unsigned int newx,unsigned int newy)1667 bool IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
1668 {
1669   unsigned int *rect, *_newrect, *newrect;
1670   struct imbufRGBA *rectf, *_newrectf, *newrectf;
1671   int x, y;
1672   bool do_float = false, do_rect = false;
1673   size_t ofsx, ofsy, stepx, stepy;
1674 
1675   rect = NULL;
1676   _newrect = NULL;
1677   newrect = NULL;
1678   rectf = NULL;
1679   _newrectf = NULL;
1680   newrectf = NULL;
1681 
1682   if (ibuf == NULL) {
1683     return false;
1684   }
1685   if (ibuf->rect) {
1686     do_rect = true;
1687   }
1688   if (ibuf->rect_float) {
1689     do_float = true;
1690   }
1691   if (do_rect == false && do_float == false) {
1692     return false;
1693   }
1694 
1695   if (newx == ibuf->x && newy == ibuf->y) {
1696     return false;
1697   }
1698 
1699   if (do_rect) {
1700     _newrect = MEM_mallocN(newx * newy * sizeof(int), "scalefastimbuf");
1701     if (_newrect == NULL) {
1702       return false;
1703     }
1704     newrect = _newrect;
1705   }
1706 
1707   if (do_float) {
1708     _newrectf = MEM_mallocN(sizeof(float[4]) * newx * newy, "scalefastimbuf f");
1709     if (_newrectf == NULL) {
1710       if (_newrect) {
1711         MEM_freeN(_newrect);
1712       }
1713       return false;
1714     }
1715     newrectf = _newrectf;
1716   }
1717 
1718   stepx = round(65536.0 * (ibuf->x - 1.0) / (newx - 1.0));
1719   stepy = round(65536.0 * (ibuf->y - 1.0) / (newy - 1.0));
1720   ofsy = 32768;
1721 
1722   for (y = newy; y > 0; y--, ofsy += stepy) {
1723     if (do_rect) {
1724       rect = ibuf->rect;
1725       rect += (ofsy >> 16) * ibuf->x;
1726       ofsx = 32768;
1727 
1728       for (x = newx; x > 0; x--, ofsx += stepx) {
1729         *newrect++ = rect[ofsx >> 16];
1730       }
1731     }
1732 
1733     if (do_float) {
1734       rectf = (struct imbufRGBA *)ibuf->rect_float;
1735       rectf += (ofsy >> 16) * ibuf->x;
1736       ofsx = 32768;
1737 
1738       for (x = newx; x > 0; x--, ofsx += stepx) {
1739         *newrectf++ = rectf[ofsx >> 16];
1740       }
1741     }
1742   }
1743 
1744   if (do_rect) {
1745     imb_freerectImBuf(ibuf);
1746     ibuf->mall |= IB_rect;
1747     ibuf->rect = _newrect;
1748   }
1749 
1750   if (do_float) {
1751     imb_freerectfloatImBuf(ibuf);
1752     ibuf->mall |= IB_rectfloat;
1753     ibuf->rect_float = (float *)_newrectf;
1754   }
1755 
1756   scalefast_Z_ImBuf(ibuf, newx, newy);
1757 
1758   ibuf->x = newx;
1759   ibuf->y = newy;
1760   return true;
1761 }
1762 
1763 /* ******** threaded scaling ******** */
1764 
1765 typedef struct ScaleTreadInitData {
1766   ImBuf *ibuf;
1767 
1768   unsigned int newx;
1769   unsigned int newy;
1770 
1771   unsigned char *byte_buffer;
1772   float *float_buffer;
1773 } ScaleTreadInitData;
1774 
1775 typedef struct ScaleThreadData {
1776   ImBuf *ibuf;
1777 
1778   unsigned int newx;
1779   unsigned int newy;
1780 
1781   int start_line;
1782   int tot_line;
1783 
1784   unsigned char *byte_buffer;
1785   float *float_buffer;
1786 } ScaleThreadData;
1787 
scale_thread_init(void * data_v,int start_line,int tot_line,void * init_data_v)1788 static void scale_thread_init(void *data_v, int start_line, int tot_line, void *init_data_v)
1789 {
1790   ScaleThreadData *data = (ScaleThreadData *)data_v;
1791   ScaleTreadInitData *init_data = (ScaleTreadInitData *)init_data_v;
1792 
1793   data->ibuf = init_data->ibuf;
1794 
1795   data->newx = init_data->newx;
1796   data->newy = init_data->newy;
1797 
1798   data->start_line = start_line;
1799   data->tot_line = tot_line;
1800 
1801   data->byte_buffer = init_data->byte_buffer;
1802   data->float_buffer = init_data->float_buffer;
1803 }
1804 
do_scale_thread(void * data_v)1805 static void *do_scale_thread(void *data_v)
1806 {
1807   ScaleThreadData *data = (ScaleThreadData *)data_v;
1808   ImBuf *ibuf = data->ibuf;
1809   int i;
1810   float factor_x = (float)ibuf->x / data->newx;
1811   float factor_y = (float)ibuf->y / data->newy;
1812 
1813   for (i = 0; i < data->tot_line; i++) {
1814     int y = data->start_line + i;
1815     int x;
1816 
1817     for (x = 0; x < data->newx; x++) {
1818       float u = (float)x * factor_x;
1819       float v = (float)y * factor_y;
1820       int offset = y * data->newx + x;
1821 
1822       if (data->byte_buffer) {
1823         unsigned char *pixel = data->byte_buffer + 4 * offset;
1824         BLI_bilinear_interpolation_char(
1825             (unsigned char *)ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v);
1826       }
1827 
1828       if (data->float_buffer) {
1829         float *pixel = data->float_buffer + ibuf->channels * offset;
1830         BLI_bilinear_interpolation_fl(
1831             ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v);
1832       }
1833     }
1834   }
1835 
1836   return NULL;
1837 }
1838 
IMB_scaleImBuf_threaded(ImBuf * ibuf,unsigned int newx,unsigned int newy)1839 void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy)
1840 {
1841   ScaleTreadInitData init_data = {NULL};
1842 
1843   /* prepare initialization data */
1844   init_data.ibuf = ibuf;
1845 
1846   init_data.newx = newx;
1847   init_data.newy = newy;
1848 
1849   if (ibuf->rect) {
1850     init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char),
1851                                         "threaded scale byte buffer");
1852   }
1853 
1854   if (ibuf->rect_float) {
1855     init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float),
1856                                          "threaded scale float buffer");
1857   }
1858 
1859   /* actual scaling threads */
1860   IMB_processor_apply_threaded(
1861       newy, sizeof(ScaleThreadData), &init_data, scale_thread_init, do_scale_thread);
1862 
1863   /* alter image buffer */
1864   ibuf->x = newx;
1865   ibuf->y = newy;
1866 
1867   if (ibuf->rect) {
1868     imb_freerectImBuf(ibuf);
1869     ibuf->mall |= IB_rect;
1870     ibuf->rect = (unsigned int *)init_data.byte_buffer;
1871   }
1872 
1873   if (ibuf->rect_float) {
1874     imb_freerectfloatImBuf(ibuf);
1875     ibuf->mall |= IB_rectfloat;
1876     ibuf->rect_float = init_data.float_buffer;
1877   }
1878 }
1879