14#define FRAC(f, from, to) ((((f) - (from)) / (double)((to) - (from))))
15#define LERP(f, mi, ma) ((mi) + (f) * ((ma) - (mi)))
16#define CLAMP(v, mi, ma) (((v) < (mi)) ? (mi) : ((v) > (ma)) ? (ma) : (v))
17#define SIGN(x) ((x) >= 0 ? 1.0 : -1.0)
19#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wcast-align"
23ScanRender::ScanRender(
void)
29void ScanRender::setBilinearInterpolationEnabled(
bool enable)
36bool ScanRender::isBilinearInterpolationEnabled()
43void ScanRender::resetScanPoly(
int sx,
int sy)
49 if (sy >= MAX_BK_SCANLINES)
51 qDebug(
"ScanRender::resetScanPoly fail!");
60void ScanRender::scanLine(
int x1,
int y1,
int x2,
int y2)
86 float dy = (float)(y2 - y1);
93 float dx = (float)(x2 - x1) / dy;
104 float m = (float) -y1;
110 int minY = qMin(y1, y2);
111 int maxY = qMax(y1, y2);
124 int fx = (int)(x * (
float)(1 << FP));
125 int fdx = (int)(dx * (
float)(1 << FP));
127 for (y = y1; y <= y2; y++)
129 scLR[y].scan[side] = fx >> FP;
135 for (y = y1; y <= y2; y++)
139 scLR[y].scan[0] = float2int(x);
143 scLR[y].scan[1] = float2int(x);
153void ScanRender::scanLine(
int x1,
int y1,
int x2,
int y2,
float u1,
float v1,
float u2,
float v2)
176 float dy = (float)(y2 - y1);
181 float dx = (float)(x2 - x1) / dy;
189 float uv[2] = {u1, v1};
191 duv[0] = (u2 - u1) / dy;
192 duv[1] = (v2 - v1) / dy;
196 float m = (float) -y1;
205 int minY = qMin(y1, y2);
206 int maxY = qMax(y1, y2);
213 for (y = y1; y <= y2; y++)
215 scLR[y].scan[side] = (int)x;
216 scLR[y].uv[side][0] = uv[0];
217 scLR[y].uv[side][1] = uv[1];
231 quint32 c = col.
rgb();
232 quint32 *bits = (quint32 *)dst->
bits();
233 int dw = dst->
width();
234 bkScan_t *
scan = scLR;
236 for (
int y = plMinY; y <= plMaxY; y++)
238 int px1 =
scan[y].scan[0];
239 int px2 =
scan[y].scan[1];
264 quint32 *pDst = bits + (y * dw) + px1;
265 for (
int x = px1; x < px2; x++)
275void ScanRender::renderPolygonAlpha(
QColor col,
QImage *dst)
278 quint32 c = col.
rgba();
279 quint32 *bits = (quint32 *)dst->
bits();
280 int dw = dst->
width();
281 bkScan_t *
scan = scLR;
282 float a = qAlpha(c) / 256.0f;
287 for (
int y = plMinY; y <= plMaxY; y++)
289 int px1 =
scan[y].scan[0];
290 int px2 =
scan[y].scan[1];
307 quint32 *pDst = bits + (y * dw) + px1;
308 for (
int x = px1; x < px2; x++)
312 *pDst = qRgb(LERP(a, qRed(rgbd), rc),
313 LERP(a, qGreen(rgbd), gc),
314 LERP(a, qBlue(rgbd), bc)
321void ScanRender::setOpacity(
float opacity)
331 renderPolygonBI(dst, src);
333 renderPolygonNI(dst, src);
343 if (interpolation < 2)
346 scanLine(pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y(), 1, 1, 1, 0);
347 scanLine(pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), 1, 0, 0, 0);
348 scanLine(pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y(), 0, 0, 0, 1);
349 scanLine(pts[3].x(), pts[3].y(), pts[0].x(), pts[0].y(), 0, 1, 1, 1);
350 renderPolygon(pDest, pSrc);
361 for (
int i = 0; i < interpolation; i++)
363 QPointF P1 = A + i * (D - A) / interpolation;
364 QPointF P1uv = Auv + i * (Duv - Auv) / interpolation;
366 QPointF P2 = B + i * (C - B) / interpolation;
367 QPointF P2uv = Buv + i * (Cuv - Buv) / interpolation;
369 QPointF Q1 = A + (i + 1) * (D - A) / interpolation;
370 QPointF Q1uv = Auv + (i + 1) * (Duv - Auv) / interpolation;
372 QPointF Q2 = B + (i + 1) * (C - B) / interpolation;
373 QPointF Q2uv = Buv + (i + 1) * (Cuv - Buv) / interpolation;
375 for (
int j = 0; j < interpolation; j++)
377 QPointF A1 = P1 + j * (P2 - P1) / interpolation;
378 QPointF A1uv = P1uv + j * (P2uv - P1uv) / interpolation;
380 QPointF B1 = P1 + (j + 1) * (P2 - P1) / interpolation;
381 QPointF B1uv = P1uv + (j + 1) * (P2uv - P1uv) / interpolation;
383 QPointF C1 = Q1 + (j + 1) * (Q2 - Q1) / interpolation;
384 QPointF C1uv = Q1uv + (j + 1) * (Q2uv - Q1uv) / interpolation;
386 QPointF D1 = Q1 + j * (Q2 - Q1) / interpolation;
387 QPointF D1uv = Q1uv + j * (Q2uv - Q1uv) / interpolation;
390 scanLine(A1.
x(), A1.
y(), B1.x(), B1.y(), A1uv.x(), A1uv.y(), B1uv.
x(), B1uv.
y());
391 scanLine(B1.x(), B1.y(), C1.
x(), C1.
y(), B1uv.
x(), B1uv.
y(), C1uv.
x(), C1uv.
y());
392 scanLine(C1.
x(), C1.
y(), D1.
x(), D1.
y(), C1uv.
x(), C1uv.
y(), D1uv.x(), D1uv.y());
393 scanLine(D1.
x(), D1.
y(), A1.
x(), A1.
y(), D1uv.x(), D1uv.y(), A1uv.x(), A1uv.y());
394 renderPolygon(pDest, pSrc);
405void ScanRender::renderPolygonNI(
QImage *dst,
QImage *src)
408 int w = dst->
width();
409 int sw = src->
width();
411 float tsx = src->
width() - 1;
412 float tsy = src->
height() - 1;
413 const quint32 *bitsSrc = (quint32 *)src->
constBits();
414 quint32 *bitsDst = (quint32 *)dst->
bits();
415 bkScan_t *
scan = scLR;
419 for (
int y = plMinY; y <= plMaxY; y++)
421 if (scan[y].scan[0] > scan[y].scan[1])
423 qSwap(scan[y].scan[0], scan[y].scan[1]);
424 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
425 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
428 int px1 =
scan[y].scan[0];
429 int px2 =
scan[y].scan[1];
431 float dx = px2 - px1;
438 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
439 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
441 uv[0] =
scan[y].uv[0][0];
442 uv[1] =
scan[y].uv[0][1];
446 float m = (float)-px1;
462 quint32 *pDst = bitsDst + (y * w) + px1;
467 fuv[0] = uv[0] * 65536;
468 fuv[1] = uv[1] * 65536;
470 fduv[0] = duv[0] * 65536;
471 fduv[1] = duv[1] * 65536;
473 fuv[0] = CLAMP(fuv[0], 0, (sw - 1) * 65536.);
474 fuv[1] = CLAMP(fuv[1], 0, (sh - 1) * 65536.);
478 for (
int x = px1; x < px2; x++)
480 const uchar *pSrc = (uchar *)bitsSrc + (fuv[0] >> 16) + ((fuv[1] >> 16) * sw);
481 *pDst = qRgb(*pSrc, *pSrc, *pSrc);
490 for (
int x = px1; x < px2; x++)
492 int offset = (fuv[0] >> 16) + ((fuv[1] >> 16) * sw);
494 const quint32 *pSrc = bitsSrc + offset;
495 *pDst = (*pSrc) | (0xFF << 24);
508void ScanRender::renderPolygonBI(
QImage *dst,
QImage *src)
511 int w = dst->
width();
512 int sw = src->
width();
514 float tsx = src->
width() - 1;
515 float tsy = src->
height() - 1;
516 const quint32 *bitsSrc = (quint32 *)src->
constBits();
517 const uchar *bitsSrc8 = (uchar *)src->
constBits();
518 quint32 *bitsDst = (quint32 *)dst->
bits();
519 bkScan_t *
scan = scLR;
523 #pragma omp parallel for
525 for (
int y = plMinY; y <= plMaxY; y++)
527 if (scan[y].scan[0] > scan[y].scan[1])
529 qSwap(scan[y].scan[0], scan[y].scan[1]);
530 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
531 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
534 int px1 =
scan[y].scan[0];
535 int px2 =
scan[y].scan[1];
537 float dx = px2 - px1;
544 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
545 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
547 uv[0] =
scan[y].uv[0][0];
548 uv[1] =
scan[y].uv[0][1];
552 float m = (float)-px1;
570 quint32 *pDst = bitsDst + (y * w) + px1;
573 for (
int x = px1; x < px2; x++)
575 float x_diff = uv[0] -
static_cast<int>(uv[0]);
576 float y_diff = uv[1] -
static_cast<int>(uv[1]);
577 float x_1diff = 1 - x_diff;
578 float y_1diff = 1 - y_diff;
580 int index = ((int)uv[0] + ((int)uv[1] * sw));
582 uchar a = bitsSrc8[index];
583 uchar b = bitsSrc8[(index + 1) % size];
584 uchar c = bitsSrc8[(index + sw) % size];
585 uchar d = bitsSrc8[(index + sw + 1) % size];
587 int val = (a&0xff)*(x_1diff)*(y_1diff) + (b&0xff)*(x_diff)*(y_1diff) +
588 (c&0xff)*(y_diff)*(x_1diff) + (d&0xff)*(x_diff*y_diff);
591 ((((int)val)<<16)&0xff0000) |
592 ((((
int)val)<<8)&0xff00) |
602 for (
int x = px1; x < px2; x++)
604 float x_diff = uv[0] -
static_cast<int>(uv[0]);
605 float y_diff = uv[1] -
static_cast<int>(uv[1]);
606 float x_1diff = 1 - x_diff;
607 float y_1diff = 1 - y_diff;
609 int index = ((int)uv[0] + ((int)uv[1] * sw));
611 quint32 a = bitsSrc[index];
612 quint32 b = bitsSrc[(index + 1) % size];
613 quint32 c = bitsSrc[(index + sw) % size];
614 quint32 d = bitsSrc[(index + sw + 1) % size];
616 int qxy1 = (x_1diff * y_1diff) * 65536;
617 int qxy2 =(x_diff * y_1diff) * 65536;
618 int qxy = (x_diff * y_diff) * 65536;
619 int qyx1 = (y_diff * x_1diff) * 65536;
622 int blue = ((a&0xff)*(qxy1) + (b&0xff)*(qxy2) + (c&0xff)*(qyx1) + (d&0xff)*(qxy)) >> 16;
625 int green = (((a>>8)&0xff)*(qxy1) + ((b>>8)&0xff)*(qxy2) + ((c>>8)&0xff)*(qyx1) + ((d>>8)&0xff)*(qxy)) >> 16;
628 int red = (((a>>16)&0xff)*(qxy1) + ((b>>16)&0xff)*(qxy2) +((c>>16)&0xff)*(qyx1) + ((d>>16)&0xff)*(qxy)) >> 16;
630 *pDst = 0xff000000 | (((
red)<<16)&0xff0000) | (((green)<<8)&0xff00) | (
blue);
641void ScanRender::renderPolygonAlpha(
QImage *dst,
QImage *src)
644 renderPolygonAlphaBI(dst, src);
646 renderPolygonAlphaNI(dst, src);
650void ScanRender::renderPolygonAlphaBI(
QImage *dst,
QImage *src)
652 int w = dst->
width();
653 int sw = src->
width();
655 float tsx = src->
width() - 1;
656 float tsy = src->
height() - 1;
657 const quint32 *bitsSrc = (quint32 *)src->
constBits();
658 quint32 *bitsDst = (quint32 *)dst->
bits();
659 bkScan_t *
scan = scLR;
661 float opacity = (m_opacity / 65536.) * 0.00390625f;
664 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw)
666 for (
int y = plMinY; y <= plMaxY; y++)
668 if (scan[y].scan[0] > scan[y].scan[1])
670 qSwap(scan[y].scan[0], scan[y].scan[1]);
671 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
672 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
675 int px1 =
scan[y].scan[0];
676 int px2 =
scan[y].scan[1];
678 float dx = px2 - px1;
685 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
686 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
688 uv[0] =
scan[y].uv[0][0];
689 uv[1] =
scan[y].uv[0][1];
693 float m = (float)-px1;
711 quint32 *pDst = bitsDst + (y * w) + px1;
746 for (
int x = px1; x < px2; x++)
748 float x_diff = uv[0] -
static_cast<int>(uv[0]);
749 float y_diff = uv[1] -
static_cast<int>(uv[1]);
750 float x_1diff = 1 - x_diff;
751 float y_1diff = 1 - y_diff;
753 int index = ((int)uv[0] + ((int)uv[1] * sw));
755 quint32 a = bitsSrc[index];
756 quint32 b = bitsSrc[(index + 1) % size];
757 quint32 c = bitsSrc[(index + sw) % size];
758 quint32 d = bitsSrc[(index + sw + 1) % size];
760 int x1y1 = (x_1diff * y_1diff) * 65536;
761 int xy = (x_diff * y_diff) * 65536;
762 int x1y = (y_diff * x_1diff) * 65536;
763 int xy1 = (x_diff *y_1diff) * 65536;
765 float alpha = ((((a>>24)&0xff)*(x1y1) + ((b>>24)&0xff)*(xy1) +
766 ((c>>24)&0xff)*(x1y) + ((d>>24)&0xff)*(xy)) * opacity);
768 if (alpha > 0.00390625f)
771 int blue = ((a&0xff)*(x1y1) + (b&0xff)* (xy1) +
772 (c&0xff)*(x1y) + (d&0xff)*(xy)) >> 16;
775 int green = (((a>>8)&0xff)*(x1y1) + ((b>>8)&0xff)*(xy1) +
776 ((c>>8)&0xff)*(x1y) + ((d>>8)&0xff)*(xy)) >> 16;
779 int red = (((a>>16)&0xff)*(x1y1) + ((b>>16)&0xff)*(xy1) +
780 ((c>>16)&0xff)*(x1y) + ((d>>16)&0xff)*(xy)) >> 16;
782 int rd = qRed(*pDst);
783 int gd = qGreen(*pDst);
784 int bd = qBlue(*pDst);
786 *pDst = qRgb(LERP(alpha, rd, red), LERP(alpha, gd, green), LERP(alpha, bd, blue));
800void ScanRender::renderPolygonAlphaNI(
QImage *dst,
QImage *src)
803 int w = dst->
width();
804 int sw = src->
width();
805 float tsx = src->
width() - 1;
806 float tsy = src->
height() - 1;
807 const quint32 *bitsSrc = (quint32 *)src->
constBits();
808 quint32 *bitsDst = (quint32 *)dst->
bits();
809 bkScan_t *
scan = scLR;
810 float opacity = 0.00390625f * m_opacity;
813 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw)
815 for (
int y = plMinY; y <= plMaxY; y++)
817 if (scan[y].scan[0] > scan[y].scan[1])
819 qSwap(scan[y].scan[0], scan[y].scan[1]);
820 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]);
821 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]);
824 int px1 =
scan[y].scan[0];
825 int px2 =
scan[y].scan[1];
827 float dx = px2 - px1;
834 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx;
835 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx;
837 uv[0] =
scan[y].uv[0][0];
838 uv[1] =
scan[y].uv[0][1];
842 float m = (float)-px1;
852 quint32 *pDst = bitsDst + (y * w) + px1;
860 for (
int x = px1; x < px2; x++)
862 const quint32 *pSrc = bitsSrc + ((int)(uv[0])) + ((
int)(uv[1]) * sw);
865 float a = qAlpha(*pSrc) * opacity;
869 *pDst = qRgb(LERP(a, qRed(rgbd), qRed(rgbs)),
870 LERP(a, qGreen(rgbd), qGreen(rgbs)),
871 LERP(a, qBlue(rgbd), qBlue(rgbs))
882#pragma GCC diagnostic pop
PRISONSCANNER_EXPORT ScanResult scan(const QImage &image, Format::BarcodeFormats formats={})
const uchar * constBits() const const