4#include <private/qimagescale_p.h>
5#include <private/qdrawhelper_p.h>
6#include <private/qimage_p.h>
13#if QT_CONFIG(qtgui_threadpool)
14#include <private/qlatch_p.h>
15#include <qthreadpool.h>
16#include <private/qguiapplication_p.h>
17#include <private/qthreadpool_p.h>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
72 static const unsigned int**
qimageCalcYPoints(
const unsigned int *src,
int sw,
int sh,
int dh);
86 int sw,
int sh,
int dh)
88 const unsigned int **p;
96 p =
new const unsigned int* [dh+1];
98 int up = qAbs(dh) >= sh;
99 val = up ? 0x8000 * sh / dh - 0x8000 : 0;
100 inc = (((qint64)sh) << 16) / dh;
101 for (
int i = 0; i < dh; i++) {
102 p[j++] = src + qMax(0LL, val >> 16) * sw;
106 for (
int i = dh / 2; --i >= 0; ) {
107 const unsigned int *tmp = p[i];
108 p[i] = p[dh - i - 1];
117 int *p, j = 0, rv = 0;
126 int up = qAbs(dw) >= sw;
127 val = up ? 0x8000 * sw / dw - 0x8000 : 0;
128 inc = (((qint64)sw) << 16) / dw;
129 for (
int i = 0; i < dw; i++) {
130 p[j++] = qMax(0LL, val >> 16);
135 for (
int i = dw / 2; --i >= 0; ) {
137 p[i] = p[dw - i - 1];
146 int *p, j = 0, rv = 0;
156 qint64 val = 0x8000 * s / d - 0x8000;
157 qint64 inc = (((qint64)s) << 16) / d;
158 for (
int i = 0; i < d; i++) {
162 else if (pos >= (s - 1))
165 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
171 qint64 inc = (((qint64)s) << 16) / d;
172 int Cp = (((d << 14) + s - 1) / s);
173 for (
int i = 0; i < d; i++) {
174 int ap = ((0x10000 - (val & 0xffff)) * Cp) >> 16;
175 p[j] = ap | (Cp << 16);
182 for (
int i = d / 2; --i >= 0; ) {
194 delete[] isi->xpoints;
195 delete[] isi->ypoints;
196 delete[] isi->xapoints;
197 delete[] isi->yapoints;
205 int dw,
int dh,
char aa)
207 QImageScaleInfo *isi;
210 scw = dw * qlonglong(img.width()) / sw;
211 sch = dh * qlonglong(img.height()) / sh;
213 isi =
new QImageScaleInfo;
219 isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
221 isi->xpoints = qimageCalcXPoints(img.width(), scw);
223 return qimageFreeScaleInfo(isi);
224 isi->ypoints = qimageCalcYPoints((
const unsigned int *)img.scanLine(0),
225 img.bytesPerLine() / 4, img.height(), sch);
227 return qimageFreeScaleInfo(isi);
229 isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
231 return qimageFreeScaleInfo(isi);
232 isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
234 return qimageFreeScaleInfo(isi);
241 int dw,
int dh,
int dow,
int sow);
244 int dw,
int dh,
int dow,
int sow);
247 int dw,
int dh,
int dow,
int sow);
249#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
251void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi,
unsigned int *dest,
252 int dw,
int dh,
int dow,
int sow);
254void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi,
unsigned int *dest,
255 int dw,
int dh,
int dow,
int sow);
257void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi,
unsigned int *dest,
258 int dw,
int dh,
int dow,
int sow);
261#if defined(QT_COMPILER_SUPPORTS_LSX)
263void qt_qimageScaleAARGBA_up_x_down_y_lsx(QImageScaleInfo *isi,
unsigned int *dest,
264 int dw,
int dh,
int dow,
int sow);
266void qt_qimageScaleAARGBA_down_x_up_y_lsx(QImageScaleInfo *isi,
unsigned int *dest,
267 int dw,
int dh,
int dow,
int sow);
269void qt_qimageScaleAARGBA_down_xy_lsx(QImageScaleInfo *isi,
unsigned int *dest,
270 int dw,
int dh,
int dow,
int sow);
273#if defined(__ARM_NEON__)
275void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi,
unsigned int *dest,
276 int dw,
int dh,
int dow,
int sow);
278void qt_qimageScaleAARGBA_down_x_up_y_neon(QImageScaleInfo *isi,
unsigned int *dest,
279 int dw,
int dh,
int dow,
int sow);
281void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi,
unsigned int *dest,
282 int dw,
int dh,
int dow,
int sow);
288#if QT_CONFIG(qtgui_threadpool)
289 int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
290 segments = std::min(segments, dh);
291 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
292 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
293 QLatch latch(segments);
295 for (
int i = 0; i < segments; ++i) {
296 int yn = (dh - y) / (segments - i);
297 threadPool->start([&, y, yn]() {
298 scaleSection(y, y + yn);
313 int dw,
int dh,
int dow,
int sow)
315 const unsigned int **ypoints = isi->ypoints;
316 int *xpoints = isi->xpoints;
317 int *xapoints = isi->xapoints;
318 int *yapoints = isi->yapoints;
321 auto scaleSection = [&] (
int yStart,
int yEnd) {
322 for (
int y = yStart; y < yEnd; ++y) {
324 const unsigned int *sptr = ypoints[y];
325 unsigned int *dptr = dest + (y * dow);
326 const int yap = yapoints[y];
328 for (
int x = 0; x < dw; x++) {
329 const unsigned int *pix = sptr + xpoints[x];
330 const int xap = xapoints[x];
332 *dptr = interpolate_4_pixels(pix, pix + sow, xap, yap);
334 *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap);
338 for (
int x = 0; x < dw; x++) {
339 const unsigned int *pix = sptr + xpoints[x];
340 const int xap = xapoints[x];
342 *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
350 multithread_pixels_function(isi, dh, scaleSection);
355 int dw,
int dh,
int dow,
int sow)
358 if (isi->xup_yup == 3) {
359 qt_qimageScaleAARGBA_up_xy(isi, dest, dw, dh, dow, sow);
362 else if (isi->xup_yup == 1) {
363#ifdef QT_COMPILER_SUPPORTS_SSE4_1
364 if (qCpuHasFeature(SSE4_1))
365 qt_qimageScaleAARGBA_up_x_down_y_sse4<
false>(isi, dest, dw, dh, dow, sow);
367#elif defined(QT_COMPILER_SUPPORTS_LSX)
368 if (qCpuHasFeature(LSX))
369 qt_qimageScaleAARGBA_up_x_down_y_lsx<
false>(isi, dest, dw, dh, dow, sow);
371#elif defined(__ARM_NEON__)
372 if (qCpuHasFeature(NEON))
373 qt_qimageScaleAARGBA_up_x_down_y_neon<
false>(isi, dest, dw, dh, dow, sow);
376 qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dw, dh, dow, sow);
379 else if (isi->xup_yup == 2) {
380#ifdef QT_COMPILER_SUPPORTS_SSE4_1
381 if (qCpuHasFeature(SSE4_1))
382 qt_qimageScaleAARGBA_down_x_up_y_sse4<
false>(isi, dest, dw, dh, dow, sow);
384#elif defined(QT_COMPILER_SUPPORTS_LSX)
385 if (qCpuHasFeature(LSX))
386 qt_qimageScaleAARGBA_down_x_up_y_lsx<
false>(isi, dest, dw, dh, dow, sow);
388#elif defined(__ARM_NEON__)
389 if (qCpuHasFeature(NEON))
390 qt_qimageScaleAARGBA_down_x_up_y_neon<
false>(isi, dest, dw, dh, dow, sow);
393 qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dw, dh, dow, sow);
397#ifdef QT_COMPILER_SUPPORTS_SSE4_1
398 if (qCpuHasFeature(SSE4_1))
399 qt_qimageScaleAARGBA_down_xy_sse4<
false>(isi, dest, dw, dh, dow, sow);
401#elif defined(QT_COMPILER_SUPPORTS_LSX)
402 if (qCpuHasFeature(LSX))
403 qt_qimageScaleAARGBA_down_xy_lsx<
false>(isi, dest, dw, dh, dow, sow);
405#elif defined(__ARM_NEON__)
406 if (qCpuHasFeature(NEON))
407 qt_qimageScaleAARGBA_down_xy_neon<
false>(isi, dest, dw, dh, dow, sow);
410 qt_qimageScaleAARGBA_down_xy(isi, dest, dw, dh, dow, sow);
416 r = qRed(*pix) * xyap;
417 g = qGreen(*pix) * xyap;
418 b = qBlue(*pix) * xyap;
419 a = qAlpha(*pix) * xyap;
421 for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
423 r += qRed(*pix) * Cxy;
424 g += qGreen(*pix) * Cxy;
425 b += qBlue(*pix) * Cxy;
426 a += qAlpha(*pix) * Cxy;
430 g += qGreen(*pix) * j;
431 b += qBlue(*pix) * j;
432 a += qAlpha(*pix) * j;
436 int dw,
int dh,
int dow,
int sow)
438 const unsigned int **ypoints = isi->ypoints;
439 int *xpoints = isi->xpoints;
440 int *xapoints = isi->xapoints;
441 int *yapoints = isi->yapoints;
444 auto scaleSection = [&] (
int yStart,
int yEnd) {
445 for (
int y = yStart; y < yEnd; ++y) {
446 int Cy = yapoints[y] >> 16;
447 int yap = yapoints[y] & 0xffff;
449 unsigned int *dptr = dest + (y * dow);
450 for (
int x = 0; x < dw; x++) {
451 const unsigned int *sptr = ypoints[y] + xpoints[x];
455 int xap = xapoints[x];
464 r = (r + (rr * xap)) >> 8;
465 g = (g + (gg * xap)) >> 8;
466 b = (b + (bb * xap)) >> 8;
467 a = (a + (aa * xap)) >> 8;
469 *dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
473 multithread_pixels_function(isi, dh, scaleSection);
477 int dw,
int dh,
int dow,
int sow)
479 const unsigned int **ypoints = isi->ypoints;
480 int *xpoints = isi->xpoints;
481 int *xapoints = isi->xapoints;
482 int *yapoints = isi->yapoints;
485 auto scaleSection = [&] (
int yStart,
int yEnd) {
486 for (
int y = yStart; y < yEnd; ++y) {
487 unsigned int *dptr = dest + (y * dow);
488 for (
int x = 0; x < dw; x++) {
489 int Cx = xapoints[x] >> 16;
490 int xap = xapoints[x] & 0xffff;
492 const unsigned int *sptr = ypoints[y] + xpoints[x];
496 int yap = yapoints[y];
505 r = (r + (rr * yap)) >> 8;
506 g = (g + (gg * yap)) >> 8;
507 b = (b + (bb * yap)) >> 8;
508 a = (a + (aa * yap)) >> 8;
510 *dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
515 multithread_pixels_function(isi, dh, scaleSection);
519 int dw,
int dh,
int dow,
int sow)
521 const unsigned int **ypoints = isi->ypoints;
522 int *xpoints = isi->xpoints;
523 int *xapoints = isi->xapoints;
524 int *yapoints = isi->yapoints;
526 auto scaleSection = [&] (
int yStart,
int yEnd) {
527 for (
int y = yStart; y < yEnd; ++y) {
528 int Cy = (yapoints[y]) >> 16;
529 int yap = (yapoints[y]) & 0xffff;
531 unsigned int *dptr = dest + (y * dow);
532 for (
int x = 0; x < dw; x++) {
533 int Cx = xapoints[x] >> 16;
534 int xap = xapoints[x] & 0xffff;
536 const unsigned int *sptr = ypoints[y] + xpoints[x];
540 int r = ((rx>>4) * yap);
541 int g = ((gx>>4) * yap);
542 int b = ((bx>>4) * yap);
543 int a = ((ax>>4) * yap);
546 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
562 *dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
567 multithread_pixels_function(isi, dh, scaleSection);
570#if QT_CONFIG(raster_64bit)
571static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
572 int dw,
int dh,
int dow,
int sow);
574static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
575 int dw,
int dh,
int dow,
int sow);
577static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
578 int dw,
int dh,
int dow,
int sow);
580static void qt_qimageScaleRgba64_up_xy(QImageScaleInfo *isi, QRgba64 *dest,
581 int dw,
int dh,
int dow,
int sow)
583 const QRgba64 **ypoints = (
const QRgba64 **)isi->ypoints;
584 int *xpoints = isi->xpoints;
585 int *xapoints = isi->xapoints;
586 int *yapoints = isi->yapoints;
588 auto scaleSection = [&] (
int yStart,
int yEnd) {
589 for (
int y = yStart; y < yEnd; ++y) {
590 const QRgba64 *sptr = ypoints[y];
591 QRgba64 *dptr = dest + (y * dow);
592 const int yap = yapoints[y];
594 for (
int x = 0; x < dw; x++) {
595 const QRgba64 *pix = sptr + xpoints[x];
596 const int xap = xapoints[x];
598 *dptr = interpolate_4_pixels_rgb64(pix, pix + sow, xap * 256, yap * 256);
600 *dptr = interpolate256(pix[0], 256 - yap, pix[sow], yap);
604 for (
int x = 0; x < dw; x++) {
605 const QRgba64 *pix = sptr + xpoints[x];
606 const int xap = xapoints[x];
608 *dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
616 multithread_pixels_function(isi, dh, scaleSection);
619void qt_qimageScaleRgba64(QImageScaleInfo *isi, QRgba64 *dest,
620 int dw,
int dh,
int dow,
int sow)
622 if (isi->xup_yup == 3)
623 qt_qimageScaleRgba64_up_xy(isi, dest, dw, dh, dow, sow);
624 else if (isi->xup_yup == 1)
625 qt_qimageScaleRgba64_up_x_down_y(isi, dest, dw, dh, dow, sow);
626 else if (isi->xup_yup == 2)
627 qt_qimageScaleRgba64_down_x_up_y(isi, dest, dw, dh, dow, sow);
629 qt_qimageScaleRgba64_down_xy(isi, dest, dw, dh, dow, sow);
632inline static void qt_qimageScaleRgba64_helper(
const QRgba64 *pix,
int xyap,
int Cxy,
int step, qint64 &r, qint64 &g, qint64 &b, qint64 &a)
634 r = pix->red() * xyap;
635 g = pix->green() * xyap;
636 b = pix->blue() * xyap;
637 a = pix->alpha() * xyap;
639 for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
641 r += pix->red() * Cxy;
642 g += pix->green() * Cxy;
643 b += pix->blue() * Cxy;
644 a += pix->alpha() * Cxy;
648 g += pix->green() * j;
649 b += pix->blue() * j;
650 a += pix->alpha() * j;
653static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
654 int dw,
int dh,
int dow,
int sow)
656 const QRgba64 **ypoints = (
const QRgba64 **)isi->ypoints;
657 int *xpoints = isi->xpoints;
658 int *xapoints = isi->xapoints;
659 int *yapoints = isi->yapoints;
661 auto scaleSection = [&] (
int yStart,
int yEnd) {
662 for (
int y = yStart; y < yEnd; ++y) {
663 int Cy = (yapoints[y]) >> 16;
664 int yap = (yapoints[y]) & 0xffff;
666 QRgba64 *dptr = dest + (y * dow);
667 for (
int x = 0; x < dw; x++) {
668 const QRgba64 *sptr = ypoints[y] + xpoints[x];
670 qt_qimageScaleRgba64_helper(sptr, yap, Cy, sow, r, g, b, a);
672 int xap = xapoints[x];
674 qint64 rr, gg, bb, aa;
675 qt_qimageScaleRgba64_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
681 r = (r + (rr * xap)) >> 8;
682 g = (g + (gg * xap)) >> 8;
683 b = (b + (bb * xap)) >> 8;
684 a = (a + (aa * xap)) >> 8;
686 *dptr++ = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
690 multithread_pixels_function(isi, dh, scaleSection);
693static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
694 int dw,
int dh,
int dow,
int sow)
696 const QRgba64 **ypoints = (
const QRgba64 **)isi->ypoints;
697 int *xpoints = isi->xpoints;
698 int *xapoints = isi->xapoints;
699 int *yapoints = isi->yapoints;
701 auto scaleSection = [&] (
int yStart,
int yEnd) {
702 for (
int y = yStart; y < yEnd; ++y) {
703 QRgba64 *dptr = dest + (y * dow);
704 for (
int x = 0; x < dw; x++) {
705 int Cx = xapoints[x] >> 16;
706 int xap = xapoints[x] & 0xffff;
708 const QRgba64 *sptr = ypoints[y] + xpoints[x];
710 qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, r, g, b, a);
712 int yap = yapoints[y];
714 qint64 rr, gg, bb, aa;
715 qt_qimageScaleRgba64_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
721 r = (r + (rr * yap)) >> 8;
722 g = (g + (gg * yap)) >> 8;
723 b = (b + (bb * yap)) >> 8;
724 a = (a + (aa * yap)) >> 8;
726 *dptr = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
731 multithread_pixels_function(isi, dh, scaleSection);
734static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
735 int dw,
int dh,
int dow,
int sow)
737 const QRgba64 **ypoints = (
const QRgba64 **)isi->ypoints;
738 int *xpoints = isi->xpoints;
739 int *xapoints = isi->xapoints;
740 int *yapoints = isi->yapoints;
742 auto scaleSection = [&] (
int yStart,
int yEnd) {
743 for (
int y = yStart; y < yEnd; ++y) {
744 int Cy = (yapoints[y]) >> 16;
745 int yap = (yapoints[y]) & 0xffff;
747 QRgba64 *dptr = dest + (y * dow);
748 for (
int x = 0; x < dw; x++) {
749 int Cx = xapoints[x] >> 16;
750 int xap = xapoints[x] & 0xffff;
752 const QRgba64 *sptr = ypoints[y] + xpoints[x];
753 qint64 rx, gx, bx, ax;
754 qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
761 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
763 qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
770 qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
776 *dptr = qRgba64(r >> 28, g >> 28, b >> 28, a >> 28);
781 multithread_pixels_function(isi, dh, scaleSection);
785#if QT_CONFIG(raster_fp)
786static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgbaFloat32 *dest,
787 int dw,
int dh,
int dow,
int sow);
789static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgbaFloat32 *dest,
790 int dw,
int dh,
int dow,
int sow);
792static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgbaFloat32 *dest,
793 int dw,
int dh,
int dow,
int sow);
795static void qt_qimageScaleRgbaFP_up_xy(QImageScaleInfo *isi, QRgbaFloat32 *dest,
796 int dw,
int dh,
int dow,
int sow)
798 const QRgbaFloat32 **ypoints = (
const QRgbaFloat32 **)isi->ypoints;
799 int *xpoints = isi->xpoints;
800 int *xapoints = isi->xapoints;
801 int *yapoints = isi->yapoints;
803 auto scaleSection = [&] (
int yStart,
int yEnd) {
804 for (
int y = yStart; y < yEnd; ++y) {
805 const QRgbaFloat32 *sptr = ypoints[y];
806 QRgbaFloat32 *dptr = dest + (y * dow);
807 const int yap = yapoints[y];
809 for (
int x = 0; x < dw; x++) {
810 const QRgbaFloat32 *pix = sptr + xpoints[x];
811 const int xap = xapoints[x];
813 *dptr = interpolate_4_pixels_rgba32f(pix, pix + sow, xap * 256, yap * 256);
815 *dptr = interpolate_rgba32f(pix[0], 256 - yap, pix[sow], yap);
819 for (
int x = 0; x < dw; x++) {
820 const QRgbaFloat32 *pix = sptr + xpoints[x];
821 const int xap = xapoints[x];
823 *dptr = interpolate_rgba32f(pix[0], 256 - xap, pix[1], xap);
831 multithread_pixels_function(isi, dh, scaleSection);
834void qt_qimageScaleRgbaFP(QImageScaleInfo *isi, QRgbaFloat32 *dest,
835 int dw,
int dh,
int dow,
int sow)
837 if (isi->xup_yup == 3)
838 qt_qimageScaleRgbaFP_up_xy(isi, dest, dw, dh, dow, sow);
839 else if (isi->xup_yup == 1)
840 qt_qimageScaleRgbaFP_up_x_down_y(isi, dest, dw, dh, dow, sow);
841 else if (isi->xup_yup == 2)
842 qt_qimageScaleRgbaFP_down_x_up_y(isi, dest, dw, dh, dow, sow);
844 qt_qimageScaleRgbaFP_down_xy(isi, dest, dw, dh, dow, sow);
847inline static void qt_qimageScaleRgbaFP_helper(
const QRgbaFloat32 *pix,
int xyap,
int Cxy,
int step,
float &r,
float &g,
float &b,
float &a)
849 constexpr float f = (1.0f /
float(1<<14));
850 const float xyapf = xyap * f;
851 const float Cxyf = Cxy * f;
852 r = pix->red() * xyapf;
853 g = pix->green() * xyapf;
854 b = pix->blue() * xyapf;
855 a = pix->alpha() * xyapf;
857 for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
859 r += pix->red() * Cxyf;
860 g += pix->green() * Cxyf;
861 b += pix->blue() * Cxyf;
862 a += pix->alpha() * Cxyf;
865 const float jf = j * f;
866 r += pix->red() * jf;
867 g += pix->green() * jf;
868 b += pix->blue() * jf;
869 a += pix->alpha() * jf;
872static void qt_qimageScaleRgbaFP_up_x_down_y(QImageScaleInfo *isi, QRgbaFloat32 *dest,
873 int dw,
int dh,
int dow,
int sow)
875 const QRgbaFloat32 **ypoints = (
const QRgbaFloat32 **)isi->ypoints;
876 int *xpoints = isi->xpoints;
877 int *xapoints = isi->xapoints;
878 int *yapoints = isi->yapoints;
880 auto scaleSection = [&] (
int yStart,
int yEnd) {
881 for (
int y = yStart; y < yEnd; ++y) {
882 int Cy = (yapoints[y]) >> 16;
883 int yap = (yapoints[y]) & 0xffff;
885 QRgbaFloat32 *dptr = dest + (y * dow);
886 for (
int x = 0; x < dw; x++) {
887 const QRgbaFloat32 *sptr = ypoints[y] + xpoints[x];
889 qt_qimageScaleRgbaFP_helper(sptr, yap, Cy, sow, r, g, b, a);
891 int xap = xapoints[x];
892 float xapf = xap * (1.f / 256.f);
894 float rr, gg, bb, aa;
895 qt_qimageScaleRgbaFP_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
897 r = (r * (1.0f - xapf) + (rr * xapf));
898 g = (g * (1.0f - xapf) + (gg * xapf));
899 b = (b * (1.0f - xapf) + (bb * xapf));
900 a = (a * (1.0f - xapf) + (aa * xapf));
902 *dptr++ = QRgbaFloat32{r, g, b, a};
906 multithread_pixels_function(isi, dh, scaleSection);
909static void qt_qimageScaleRgbaFP_down_x_up_y(QImageScaleInfo *isi, QRgbaFloat32 *dest,
910 int dw,
int dh,
int dow,
int sow)
912 const QRgbaFloat32 **ypoints = (
const QRgbaFloat32 **)isi->ypoints;
913 int *xpoints = isi->xpoints;
914 int *xapoints = isi->xapoints;
915 int *yapoints = isi->yapoints;
917 auto scaleSection = [&] (
int yStart,
int yEnd) {
918 for (
int y = yStart; y < yEnd; ++y) {
919 QRgbaFloat32 *dptr = dest + (y * dow);
920 for (
int x = 0; x < dw; x++) {
921 int Cx = xapoints[x] >> 16;
922 int xap = xapoints[x] & 0xffff;
924 const QRgbaFloat32 *sptr = ypoints[y] + xpoints[x];
926 qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, r, g, b, a);
928 int yap = yapoints[y];
929 float yapf = yap * (1.f / 256.f);
931 float rr, gg, bb, aa;
932 qt_qimageScaleRgbaFP_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
934 r = (r * (1.0f - yapf) + (rr * yapf));
935 g = (g * (1.0f - yapf) + (gg * yapf));
936 b = (b * (1.0f - yapf) + (bb * yapf));
937 a = (a * (1.0f - yapf) + (aa * yapf));
939 *dptr++ = QRgbaFloat32{r, g, b, a};
943 multithread_pixels_function(isi, dh, scaleSection);
946static void qt_qimageScaleRgbaFP_down_xy(QImageScaleInfo *isi, QRgbaFloat32 *dest,
947 int dw,
int dh,
int dow,
int sow)
949 const QRgbaFloat32 **ypoints = (
const QRgbaFloat32 **)isi->ypoints;
950 int *xpoints = isi->xpoints;
951 int *xapoints = isi->xapoints;
952 int *yapoints = isi->yapoints;
954 auto scaleSection = [&] (
int yStart,
int yEnd) {
955 constexpr float f = 1.f /
float(1 << 14);
956 for (
int y = yStart; y < yEnd; ++y) {
957 int Cy = (yapoints[y]) >> 16;
958 int yap = (yapoints[y]) & 0xffff;
960 QRgbaFloat32 *dptr = dest + (y * dow);
961 for (
int x = 0; x < dw; x++) {
962 int Cx = xapoints[x] >> 16;
963 int xap = xapoints[x] & 0xffff;
965 const QRgbaFloat32 *sptr = ypoints[y] + xpoints[x];
966 float rx, gx, bx, ax;
967 qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
969 const float yapf = yap * f;
970 const float Cyf = Cy * f;
976 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
978 qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
985 qt_qimageScaleRgbaFP_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
986 const float jf = j * f;
992 *dptr++ = QRgbaFloat32{r, g, b, a};
996 multithread_pixels_function(isi, dh, scaleSection);
1001 int dw,
int dh,
int dow,
int sow);
1004 int dw,
int dh,
int dow,
int sow);
1007 int dw,
int dh,
int dow,
int sow);
1011 int dw,
int dh,
int dow,
int sow)
1014 if (isi->xup_yup == 3) {
1015 qt_qimageScaleAARGBA_up_xy(isi, dest, dw, dh, dow, sow);
1018 else if (isi->xup_yup == 1) {
1019#ifdef QT_COMPILER_SUPPORTS_SSE4_1
1020 if (qCpuHasFeature(SSE4_1))
1021 qt_qimageScaleAARGBA_up_x_down_y_sse4<
true>(isi, dest, dw, dh, dow, sow);
1023#elif defined QT_COMPILER_SUPPORTS_LSX
1024 if (qCpuHasFeature(LSX))
1025 qt_qimageScaleAARGBA_up_x_down_y_lsx<
true>(isi, dest, dw, dh, dow, sow);
1027#elif defined(__ARM_NEON__)
1028 if (qCpuHasFeature(NEON))
1029 qt_qimageScaleAARGBA_up_x_down_y_neon<
true>(isi, dest, dw, dh, dow, sow);
1032 qt_qimageScaleAARGB_up_x_down_y(isi, dest, dw, dh, dow, sow);
1035 else if (isi->xup_yup == 2) {
1036#ifdef QT_COMPILER_SUPPORTS_SSE4_1
1037 if (qCpuHasFeature(SSE4_1))
1038 qt_qimageScaleAARGBA_down_x_up_y_sse4<
true>(isi, dest, dw, dh, dow, sow);
1040#elif defined QT_COMPILER_SUPPORTS_LSX
1041 if (qCpuHasFeature(LSX))
1042 qt_qimageScaleAARGBA_down_x_up_y_lsx<
true>(isi, dest, dw, dh, dow, sow);
1044#elif defined(__ARM_NEON__)
1045 if (qCpuHasFeature(NEON))
1046 qt_qimageScaleAARGBA_down_x_up_y_neon<
true>(isi, dest, dw, dh, dow, sow);
1049 qt_qimageScaleAARGB_down_x_up_y(isi, dest, dw, dh, dow, sow);
1053#ifdef QT_COMPILER_SUPPORTS_SSE4_1
1054 if (qCpuHasFeature(SSE4_1))
1055 qt_qimageScaleAARGBA_down_xy_sse4<
true>(isi, dest, dw, dh, dow, sow);
1057#elif defined QT_COMPILER_SUPPORTS_LSX
1058 if (qCpuHasFeature(LSX))
1059 qt_qimageScaleAARGBA_down_xy_lsx<
true>(isi, dest, dw, dh, dow, sow);
1061#elif defined(__ARM_NEON__)
1062 if (qCpuHasFeature(NEON))
1063 qt_qimageScaleAARGBA_down_xy_neon<
true>(isi, dest, dw, dh, dow, sow);
1066 qt_qimageScaleAARGB_down_xy(isi, dest, dw, dh, dow, sow);
1073 r = qRed(*pix) * xyap;
1074 g = qGreen(*pix) * xyap;
1075 b = qBlue(*pix) * xyap;
1077 for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
1079 r += qRed(*pix) * Cxy;
1080 g += qGreen(*pix) * Cxy;
1081 b += qBlue(*pix) * Cxy;
1084 r += qRed(*pix) * j;
1085 g += qGreen(*pix) * j;
1086 b += qBlue(*pix) * j;
1090 int dw,
int dh,
int dow,
int sow)
1092 const unsigned int **ypoints = isi->ypoints;
1093 int *xpoints = isi->xpoints;
1094 int *xapoints = isi->xapoints;
1095 int *yapoints = isi->yapoints;
1098 auto scaleSection = [&] (
int yStart,
int yEnd) {
1099 for (
int y = yStart; y < yEnd; ++y) {
1100 int Cy = yapoints[y] >> 16;
1101 int yap = yapoints[y] & 0xffff;
1103 unsigned int *dptr = dest + (y * dow);
1104 for (
int x = 0; x < dw; x++) {
1105 const unsigned int *sptr = ypoints[y] + xpoints[x];
1109 int xap = xapoints[x];
1114 r = r * (256 - xap);
1115 g = g * (256 - xap);
1116 b = b * (256 - xap);
1117 r = (r + (rr * xap)) >> 8;
1118 g = (g + (gg * xap)) >> 8;
1119 b = (b + (bb * xap)) >> 8;
1121 *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
1125 multithread_pixels_function(isi, dh, scaleSection);
1129 int dw,
int dh,
int dow,
int sow)
1131 const unsigned int **ypoints = isi->ypoints;
1132 int *xpoints = isi->xpoints;
1133 int *xapoints = isi->xapoints;
1134 int *yapoints = isi->yapoints;
1137 auto scaleSection = [&] (
int yStart,
int yEnd) {
1138 for (
int y = yStart; y < yEnd; ++y) {
1139 unsigned int *dptr = dest + (y * dow);
1140 for (
int x = 0; x < dw; x++) {
1141 int Cx = xapoints[x] >> 16;
1142 int xap = xapoints[x] & 0xffff;
1144 const unsigned int *sptr = ypoints[y] + xpoints[x];
1148 int yap = yapoints[y];
1153 r = r * (256 - yap);
1154 g = g * (256 - yap);
1155 b = b * (256 - yap);
1156 r = (r + (rr * yap)) >> 8;
1157 g = (g + (gg * yap)) >> 8;
1158 b = (b + (bb * yap)) >> 8;
1160 *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
1164 multithread_pixels_function(isi, dh, scaleSection);
1168 int dw,
int dh,
int dow,
int sow)
1170 const unsigned int **ypoints = isi->ypoints;
1171 int *xpoints = isi->xpoints;
1172 int *xapoints = isi->xapoints;
1173 int *yapoints = isi->yapoints;
1175 auto scaleSection = [&] (
int yStart,
int yEnd) {
1176 for (
int y = yStart; y < yEnd; ++y) {
1177 int Cy = yapoints[y] >> 16;
1178 int yap = yapoints[y] & 0xffff;
1180 unsigned int *dptr = dest + (y * dow);
1181 for (
int x = 0; x < dw; x++) {
1182 int Cx = xapoints[x] >> 16;
1183 int xap = xapoints[x] & 0xffff;
1185 const unsigned int *sptr = ypoints[y] + xpoints[x];
1189 int r = (rx >> 4) * yap;
1190 int g = (gx >> 4) * yap;
1191 int b = (bx >> 4) * yap;
1194 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
1198 r += (rx >> 4) * Cy;
1199 g += (gx >> 4) * Cy;
1200 b += (bx >> 4) * Cy;
1209 *dptr = qRgb(r >> 24, g >> 24, b >> 24);
1214 multithread_pixels_function(isi, dh, scaleSection);
1220 if (src.isNull() || dw <= 0 || dh <= 0)
1223 int w = src.width();
1224 int h = src.height();
1225 QImageScaleInfo *scaleinfo =
1226 qimageCalcScaleInfo(src, w, h, dw, dh,
true);
1230 buffer = QImage(dw, dh, src.format());
1231 if (buffer.isNull()) {
1232 qWarning(
"QImage: out of memory, returning null");
1233 qimageFreeScaleInfo(scaleinfo);
1237#if QT_CONFIG(raster_fp)
1238 if (qt_fpColorPrecision(src.format()))
1239 qt_qimageScaleRgbaFP(scaleinfo, (QRgbaFloat32 *)buffer.scanLine(0),
1240 dw, dh, dw, src.bytesPerLine() / 16);
1243#if QT_CONFIG(raster_64bit)
1244 if (src.depth() > 32)
1245 qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
1246 dw, dh, dw, src.bytesPerLine() / 8);
1249 if (src.hasAlphaChannel() || src.format() == QImage::Format_CMYK8888)
1250 qt_qimageScaleAARGBA(scaleinfo, (
unsigned int *)buffer.scanLine(0),
1251 dw, dh, dw, src.bytesPerLine() / 4);
1253 qt_qimageScaleAARGB(scaleinfo, (
unsigned int *)buffer.scanLine(0),
1254 dw, dh, dw, src.bytesPerLine() / 4);
1256 qimageFreeScaleInfo(scaleinfo);
static QImageScaleInfo * qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa)
static int * qimageCalcXPoints(int sw, int dw)
static QImageScaleInfo * qimageFreeScaleInfo(QImageScaleInfo *isi)
static int * qimageCalcApoints(int s, int d, int up)
static const unsigned int ** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh)
static void multithread_pixels_function(QImageScaleInfo *isi, int dh, const T &scaleSection)
static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b, int &a)
static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGB_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b)
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)
static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow)