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