File indexing completed on 2024-04-28 11:24:33
0001 /* 0002 SPDX-FileCopyrightText: 2015-2017 Pavel Mraz 0003 0004 SPDX-FileCopyrightText: 2017 Jasem Mutlaq 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "scanrender.h" 0010 0011 //#include <omp.h> 0012 //#define PARALLEL_OMP 0013 0014 #define FRAC(f, from, to) ((((f) - (from)) / (double)((to) - (from)))) 0015 #define LERP(f, mi, ma) ((mi) + (f) * ((ma) - (mi))) 0016 #define CLAMP(v, mi, ma) (((v) < (mi)) ? (mi) : ((v) > (ma)) ? (ma) : (v)) 0017 #define SIGN(x) ((x) >= 0 ? 1.0 : -1.0) 0018 0019 #pragma GCC diagnostic push 0020 #pragma GCC diagnostic ignored "-Wcast-align" 0021 0022 ////////////////////////////// 0023 ScanRender::ScanRender(void) 0024 ////////////////////////////// 0025 { 0026 } 0027 0028 ///////////////////////////////////////////////// 0029 void ScanRender::setBilinearInterpolationEnabled(bool enable) 0030 ///////////////////////////////////////////////// 0031 { 0032 bBilinear = enable; 0033 } 0034 0035 ////////////////////////////////// 0036 bool ScanRender::isBilinearInterpolationEnabled() 0037 ////////////////////////////////// 0038 { 0039 return(bBilinear); 0040 } 0041 0042 /////////////////////////////////////////////// 0043 void ScanRender::resetScanPoly(int sx, int sy) 0044 /////////////////////////////////////////////// 0045 { 0046 plMinY = 999999; 0047 plMaxY = -999999; 0048 0049 if (sy >= MAX_BK_SCANLINES) 0050 { 0051 qDebug("ScanRender::resetScanPoly fail!"); 0052 return; 0053 } 0054 0055 m_sx = sx; 0056 m_sy = sy; 0057 } 0058 0059 ////////////////////////////////////////////////////////// 0060 void ScanRender::scanLine(int x1, int y1, int x2, int y2) 0061 ////////////////////////////////////////////////////////// 0062 { 0063 int side; 0064 0065 if (y1 > y2) 0066 { 0067 qSwap(x1, x2); 0068 qSwap(y1, y2); 0069 side = 0; 0070 } 0071 else 0072 { 0073 side = 1; 0074 } 0075 0076 if (y2 < 0) 0077 { 0078 return; // offscreen 0079 } 0080 0081 if (y1 >= m_sy) 0082 { 0083 return; // offscreen 0084 } 0085 0086 float dy = (float)(y2 - y1); 0087 0088 if (dy == 0) // hor. line 0089 { 0090 return; 0091 } 0092 0093 float dx = (float)(x2 - x1) / dy; 0094 float x = x1; 0095 int y; 0096 0097 if (y2 >= m_sy) 0098 { 0099 y2 = m_sy - 1; 0100 } 0101 0102 if (y1 < 0) 0103 { // partially off screen 0104 float m = (float) -y1; 0105 0106 x += dx * m; 0107 y1 = 0; 0108 } 0109 0110 int minY = qMin(y1, y2); 0111 int maxY = qMax(y1, y2); 0112 0113 if (minY < plMinY) 0114 plMinY = minY; 0115 if (maxY > plMaxY) 0116 plMaxY = maxY; 0117 0118 #define SCAN_FIX_PT 1 0119 0120 #if SCAN_FIX_PT 0121 0122 #define FP 16 0123 0124 int fx = (int)(x * (float)(1 << FP)); 0125 int fdx = (int)(dx * (float)(1 << FP)); 0126 0127 for (y = y1; y <= y2; y++) 0128 { 0129 scLR[y].scan[side] = fx >> FP; 0130 fx += fdx; 0131 } 0132 0133 #else 0134 0135 for (y = y1; y <= y2; y++) 0136 { 0137 if (side == 1) 0138 { // side left 0139 scLR[y].scan[0] = float2int(x); 0140 } 0141 else 0142 { // side right 0143 scLR[y].scan[1] = float2int(x); 0144 } 0145 x += dx; 0146 } 0147 0148 #endif 0149 } 0150 0151 0152 ////////////////////////////////////////////////////////////////////////////////////////////////// 0153 void ScanRender::scanLine(int x1, int y1, int x2, int y2, float u1, float v1, float u2, float v2) 0154 ////////////////////////////////////////////////////////////////////////////////////////////////// 0155 { 0156 int side; 0157 0158 if (y1 > y2) 0159 { 0160 qSwap(x1, x2); 0161 qSwap(y1, y2); 0162 qSwap(u1, u2); 0163 qSwap(v1, v2); 0164 side = 0; 0165 } 0166 else 0167 { 0168 side = 1; 0169 } 0170 0171 if (y2 < 0) 0172 return; // offscreen 0173 if (y1 >= m_sy) 0174 return; // offscreen 0175 0176 float dy = (float)(y2 - y1); 0177 0178 if (dy == 0) // hor. line 0179 return; 0180 0181 float dx = (float)(x2 - x1) / dy; 0182 float x = x1; 0183 int y; 0184 0185 if (y2 >= m_sy) 0186 y2 = m_sy - 1; 0187 0188 float duv[2]; 0189 float uv[2] = {u1, v1}; 0190 0191 duv[0] = (u2 - u1) / dy; 0192 duv[1] = (v2 - v1) / dy; 0193 0194 if (y1 < 0) 0195 { // partially off screen 0196 float m = (float) -y1; 0197 0198 uv[0] += duv[0] * m; 0199 uv[1] += duv[1] * m; 0200 0201 x += dx * m; 0202 y1 = 0; 0203 } 0204 0205 int minY = qMin(y1, y2); 0206 int maxY = qMax(y1, y2); 0207 0208 if (minY < plMinY) 0209 plMinY = minY; 0210 if (maxY > plMaxY) 0211 plMaxY = maxY; 0212 0213 for (y = y1; y <= y2; y++) 0214 { 0215 scLR[y].scan[side] = (int)x; 0216 scLR[y].uv[side][0] = uv[0]; 0217 scLR[y].uv[side][1] = uv[1]; 0218 0219 x += dx; 0220 0221 uv[0] += duv[0]; 0222 uv[1] += duv[1]; 0223 } 0224 } 0225 0226 0227 //////////////////////////////////////////////////////// 0228 void ScanRender::renderPolygon(QColor col, QImage *dst) 0229 //////////////////////////////////////////////////////// 0230 { 0231 quint32 c = col.rgb(); 0232 quint32 *bits = (quint32 *)dst->bits(); 0233 int dw = dst->width(); 0234 bkScan_t *scan = scLR; 0235 0236 for (int y = plMinY; y <= plMaxY; y++) 0237 { 0238 int px1 = scan[y].scan[0]; 0239 int px2 = scan[y].scan[1]; 0240 0241 if (px1 > px2) 0242 { 0243 qSwap(px1, px2); 0244 } 0245 0246 if (px1 < 0) 0247 { 0248 px1 = 0; 0249 if (px2 < 0) 0250 { 0251 continue; 0252 } 0253 } 0254 0255 if (px2 >= m_sx) 0256 { 0257 if (px1 >= m_sx) 0258 { 0259 continue; 0260 } 0261 px2 = m_sx - 1; 0262 } 0263 0264 quint32 *pDst = bits + (y * dw) + px1; 0265 for (int x = px1; x < px2; x++) 0266 { 0267 *pDst = c; 0268 pDst++; 0269 } 0270 } 0271 } 0272 0273 0274 ///////////////////////////////////////////////////////////// 0275 void ScanRender::renderPolygonAlpha(QColor col, QImage *dst) 0276 ///////////////////////////////////////////////////////////// 0277 { 0278 quint32 c = col.rgba(); 0279 quint32 *bits = (quint32 *)dst->bits(); 0280 int dw = dst->width(); 0281 bkScan_t *scan = scLR; 0282 float a = qAlpha(c) / 256.0f; 0283 int rc = qRed(c); 0284 int gc = qGreen(c); 0285 int bc = qBlue(c); 0286 0287 for (int y = plMinY; y <= plMaxY; y++) 0288 { 0289 int px1 = scan[y].scan[0]; 0290 int px2 = scan[y].scan[1]; 0291 0292 if (px1 > px2) 0293 { 0294 qSwap(px1, px2); 0295 } 0296 0297 if (px1 < 0) 0298 { 0299 px1 = 0; 0300 } 0301 0302 if (px2 >= m_sx) 0303 { 0304 px2 = m_sx - 1; 0305 } 0306 0307 quint32 *pDst = bits + (y * dw) + px1; 0308 for (int x = px1; x < px2; x++) 0309 { 0310 QRgb rgbd = *pDst; 0311 0312 *pDst = qRgb(LERP(a, qRed(rgbd), rc), 0313 LERP(a, qGreen(rgbd), gc), 0314 LERP(a, qBlue(rgbd), bc) 0315 ); 0316 pDst++; 0317 } 0318 } 0319 } 0320 0321 void ScanRender::setOpacity(float opacity) 0322 { 0323 m_opacity = opacity; 0324 } 0325 0326 ///////////////////////////////////////////////////////// 0327 void ScanRender::renderPolygon(QImage *dst, QImage *src) 0328 ///////////////////////////////////////////////////////// 0329 { 0330 if (bBilinear) 0331 renderPolygonBI(dst, src); 0332 else 0333 renderPolygonNI(dst, src); 0334 } 0335 0336 void ScanRender::renderPolygon(int interpolation, QPointF *pts, QImage *pDest, QImage *pSrc, QPointF *uv) 0337 { 0338 QPointF Auv = uv[0]; 0339 QPointF Buv = uv[1]; 0340 QPointF Cuv = uv[2]; 0341 QPointF Duv = uv[3]; 0342 0343 if (interpolation < 2) 0344 { 0345 resetScanPoly(pDest->width(), pDest->height()); 0346 scanLine(pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y(), 1, 1, 1, 0); 0347 scanLine(pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), 1, 0, 0, 0); 0348 scanLine(pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y(), 0, 0, 0, 1); 0349 scanLine(pts[3].x(), pts[3].y(), pts[0].x(), pts[0].y(), 0, 1, 1, 1); 0350 renderPolygon(pDest, pSrc); 0351 return; 0352 } 0353 0354 QPointF A = pts[0]; 0355 QPointF B = pts[1]; 0356 QPointF C = pts[2]; 0357 QPointF D = pts[3]; 0358 0359 //p->setPen(Qt::green); 0360 0361 for (int i = 0; i < interpolation; i++) 0362 { 0363 QPointF P1 = A + i * (D - A) / interpolation; 0364 QPointF P1uv = Auv + i * (Duv - Auv) / interpolation; 0365 0366 QPointF P2 = B + i * (C - B) / interpolation; 0367 QPointF P2uv = Buv + i * (Cuv - Buv) / interpolation; 0368 0369 QPointF Q1 = A + (i + 1) * (D - A) / interpolation; 0370 QPointF Q1uv = Auv + (i + 1) * (Duv - Auv) / interpolation; 0371 0372 QPointF Q2 = B + (i + 1) * (C - B) / interpolation; 0373 QPointF Q2uv = Buv + (i + 1) * (Cuv - Buv) / interpolation; 0374 0375 for (int j = 0; j < interpolation; j++) 0376 { 0377 QPointF A1 = P1 + j * (P2 - P1) / interpolation; 0378 QPointF A1uv = P1uv + j * (P2uv - P1uv) / interpolation; 0379 0380 QPointF B1 = P1 + (j + 1) * (P2 - P1) / interpolation; 0381 QPointF B1uv = P1uv + (j + 1) * (P2uv - P1uv) / interpolation; 0382 0383 QPointF C1 = Q1 + (j + 1) * (Q2 - Q1) / interpolation; 0384 QPointF C1uv = Q1uv + (j + 1) * (Q2uv - Q1uv) / interpolation; 0385 0386 QPointF D1 = Q1 + j * (Q2 - Q1) / interpolation; 0387 QPointF D1uv = Q1uv + j * (Q2uv - Q1uv) / interpolation; 0388 0389 resetScanPoly(pDest->width(), pDest->height()); 0390 scanLine(A1.x(), A1.y(), B1.x(), B1.y(), A1uv.x(), A1uv.y(), B1uv.x(), B1uv.y()); 0391 scanLine(B1.x(), B1.y(), C1.x(), C1.y(), B1uv.x(), B1uv.y(), C1uv.x(), C1uv.y()); 0392 scanLine(C1.x(), C1.y(), D1.x(), D1.y(), C1uv.x(), C1uv.y(), D1uv.x(), D1uv.y()); 0393 scanLine(D1.x(), D1.y(), A1.x(), A1.y(), D1uv.x(), D1uv.y(), A1uv.x(), A1uv.y()); 0394 renderPolygon(pDest, pSrc); 0395 0396 //p->drawLine(A1, B1); 0397 //p->drawLine(B1, C1); 0398 //p->drawLine(C1, D1); 0399 //p->drawLine(D1, A1); 0400 } 0401 } 0402 } 0403 0404 /////////////////////////////////////////////////////////// 0405 void ScanRender::renderPolygonNI(QImage *dst, QImage *src) 0406 /////////////////////////////////////////////////////////// 0407 { 0408 int w = dst->width(); 0409 int sw = src->width(); 0410 int sh = src->height(); 0411 float tsx = src->width() - 1; 0412 float tsy = src->height() - 1; 0413 const quint32 *bitsSrc = (quint32 *)src->constBits(); 0414 quint32 *bitsDst = (quint32 *)dst->bits(); 0415 bkScan_t *scan = scLR; 0416 bool bw = src->format() == QImage::Format_Indexed8 || src->format() == QImage::Format_Grayscale8; 0417 0418 //#pragma omp parallel for 0419 for (int y = plMinY; y <= plMaxY; y++) 0420 { 0421 if (scan[y].scan[0] > scan[y].scan[1]) 0422 { 0423 qSwap(scan[y].scan[0], scan[y].scan[1]); 0424 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]); 0425 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]); 0426 } 0427 0428 int px1 = scan[y].scan[0]; 0429 int px2 = scan[y].scan[1]; 0430 0431 float dx = px2 - px1; 0432 if (dx == 0) 0433 continue; 0434 0435 float duv[2]; 0436 float uv[2]; 0437 0438 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx; 0439 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx; 0440 0441 uv[0] = scan[y].uv[0][0]; 0442 uv[1] = scan[y].uv[0][1]; 0443 0444 if (px1 < 0) 0445 { 0446 float m = (float)-px1; 0447 0448 px1 = 0; 0449 uv[0] += duv[0] * m; 0450 uv[1] += duv[1] * m; 0451 } 0452 0453 if (px2 >= w) 0454 px2 = w - 1; 0455 0456 uv[0] *= tsx; 0457 uv[1] *= tsy; 0458 0459 duv[0] *= tsx; 0460 duv[1] *= tsy; 0461 0462 quint32 *pDst = bitsDst + (y * w) + px1; 0463 0464 int fuv[2]; 0465 int fduv[2]; 0466 0467 fuv[0] = uv[0] * 65536; 0468 fuv[1] = uv[1] * 65536; 0469 0470 fduv[0] = duv[0] * 65536; 0471 fduv[1] = duv[1] * 65536; 0472 0473 fuv[0] = CLAMP(fuv[0], 0, (sw - 1) * 65536.); 0474 fuv[1] = CLAMP(fuv[1], 0, (sh - 1) * 65536.); 0475 0476 if (bw) 0477 { 0478 for (int x = px1; x < px2; x++) 0479 { 0480 const uchar *pSrc = (uchar *)bitsSrc + (fuv[0] >> 16) + ((fuv[1] >> 16) * sw); 0481 *pDst = qRgb(*pSrc, *pSrc, *pSrc); 0482 pDst++; 0483 0484 fuv[0] += fduv[0]; 0485 fuv[1] += fduv[1]; 0486 } 0487 } 0488 else 0489 { 0490 for (int x = px1; x < px2; x++) 0491 { 0492 int offset = (fuv[0] >> 16) + ((fuv[1] >> 16) * sw); 0493 0494 const quint32 *pSrc = bitsSrc + offset; 0495 *pDst = (*pSrc) | (0xFF << 24); 0496 0497 pDst++; 0498 0499 fuv[0] += fduv[0]; 0500 fuv[1] += fduv[1]; 0501 } 0502 } 0503 } 0504 } 0505 0506 0507 /////////////////////////////////////////////////////////// 0508 void ScanRender::renderPolygonBI(QImage *dst, QImage *src) 0509 /////////////////////////////////////////////////////////// 0510 { 0511 int w = dst->width(); 0512 int sw = src->width(); 0513 int sh = src->height(); 0514 float tsx = src->width() - 1; 0515 float tsy = src->height() - 1; 0516 const quint32 *bitsSrc = (quint32 *)src->constBits(); 0517 const uchar *bitsSrc8 = (uchar *)src->constBits(); 0518 quint32 *bitsDst = (quint32 *)dst->bits(); 0519 bkScan_t *scan = scLR; 0520 bool bw = src->format() == QImage::Format_Indexed8 || src->format() == QImage::Format_Grayscale8; 0521 0522 #ifdef PARALLEL_OMP 0523 #pragma omp parallel for 0524 #endif 0525 for (int y = plMinY; y <= plMaxY; y++) 0526 { 0527 if (scan[y].scan[0] > scan[y].scan[1]) 0528 { 0529 qSwap(scan[y].scan[0], scan[y].scan[1]); 0530 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]); 0531 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]); 0532 } 0533 0534 int px1 = scan[y].scan[0]; 0535 int px2 = scan[y].scan[1]; 0536 0537 float dx = px2 - px1; 0538 if (dx == 0) 0539 continue; 0540 0541 float duv[2]; 0542 float uv[2]; 0543 0544 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx; 0545 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx; 0546 0547 uv[0] = scan[y].uv[0][0]; 0548 uv[1] = scan[y].uv[0][1]; 0549 0550 if (px1 < 0) 0551 { 0552 float m = (float)-px1; 0553 0554 px1 = 0; 0555 uv[0] += duv[0] * m; 0556 uv[1] += duv[1] * m; 0557 } 0558 0559 if (px2 >= w) 0560 px2 = w - 1; 0561 0562 uv[0] *= tsx; 0563 uv[1] *= tsy; 0564 0565 duv[0] *= tsx; 0566 duv[1] *= tsy; 0567 0568 int size = sw * sh; 0569 0570 quint32 *pDst = bitsDst + (y * w) + px1; 0571 if (bw) 0572 { 0573 for (int x = px1; x < px2; x++) 0574 { 0575 float x_diff = uv[0] - static_cast<int>(uv[0]); 0576 float y_diff = uv[1] - static_cast<int>(uv[1]); 0577 float x_1diff = 1 - x_diff; 0578 float y_1diff = 1 - y_diff; 0579 0580 int index = ((int)uv[0] + ((int)uv[1] * sw)); 0581 0582 uchar a = bitsSrc8[index]; 0583 uchar b = bitsSrc8[(index + 1) % size]; 0584 uchar c = bitsSrc8[(index + sw) % size]; 0585 uchar d = bitsSrc8[(index + sw + 1) % size]; 0586 0587 int val = (a&0xff)*(x_1diff)*(y_1diff) + (b&0xff)*(x_diff)*(y_1diff) + 0588 (c&0xff)*(y_diff)*(x_1diff) + (d&0xff)*(x_diff*y_diff); 0589 0590 *pDst = 0xff000000 | 0591 ((((int)val)<<16)&0xff0000) | 0592 ((((int)val)<<8)&0xff00) | 0593 ((int)val) ; 0594 pDst++; 0595 0596 uv[0] += duv[0]; 0597 uv[1] += duv[1]; 0598 } 0599 } 0600 else 0601 { 0602 for (int x = px1; x < px2; x++) 0603 { 0604 float x_diff = uv[0] - static_cast<int>(uv[0]); 0605 float y_diff = uv[1] - static_cast<int>(uv[1]); 0606 float x_1diff = 1 - x_diff; 0607 float y_1diff = 1 - y_diff; 0608 0609 int index = ((int)uv[0] + ((int)uv[1] * sw)); 0610 0611 quint32 a = bitsSrc[index]; 0612 quint32 b = bitsSrc[(index + 1) % size]; 0613 quint32 c = bitsSrc[(index + sw) % size]; 0614 quint32 d = bitsSrc[(index + sw + 1) % size]; 0615 0616 int qxy1 = (x_1diff * y_1diff) * 65536; 0617 int qxy2 =(x_diff * y_1diff) * 65536; 0618 int qxy = (x_diff * y_diff) * 65536; 0619 int qyx1 = (y_diff * x_1diff) * 65536; 0620 0621 // blue element 0622 int blue = ((a&0xff)*(qxy1) + (b&0xff)*(qxy2) + (c&0xff)*(qyx1) + (d&0xff)*(qxy)) >> 16; 0623 0624 // green element 0625 int green = (((a>>8)&0xff)*(qxy1) + ((b>>8)&0xff)*(qxy2) + ((c>>8)&0xff)*(qyx1) + ((d>>8)&0xff)*(qxy)) >> 16; 0626 0627 // red element 0628 int red = (((a>>16)&0xff)*(qxy1) + ((b>>16)&0xff)*(qxy2) +((c>>16)&0xff)*(qyx1) + ((d>>16)&0xff)*(qxy)) >> 16; 0629 0630 *pDst = 0xff000000 | (((red)<<16)&0xff0000) | (((green)<<8)&0xff00) | (blue); 0631 0632 pDst++; 0633 0634 uv[0] += duv[0]; 0635 uv[1] += duv[1]; 0636 } 0637 } 0638 } 0639 } 0640 0641 void ScanRender::renderPolygonAlpha(QImage *dst, QImage *src) 0642 { 0643 if (bBilinear) 0644 renderPolygonAlphaBI(dst, src); 0645 else 0646 renderPolygonAlphaNI(dst, src); 0647 } 0648 0649 0650 void ScanRender::renderPolygonAlphaBI(QImage *dst, QImage *src) 0651 { 0652 int w = dst->width(); 0653 int sw = src->width(); 0654 int sh = src->height(); 0655 float tsx = src->width() - 1; 0656 float tsy = src->height() - 1; 0657 const quint32 *bitsSrc = (quint32 *)src->constBits(); 0658 quint32 *bitsDst = (quint32 *)dst->bits(); 0659 bkScan_t *scan = scLR; 0660 bool bw = src->format() == QImage::Format_Indexed8; 0661 float opacity = (m_opacity / 65536.) * 0.00390625f; 0662 0663 #ifdef PARALLEL_OMP 0664 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw) 0665 #endif 0666 for (int y = plMinY; y <= plMaxY; y++) 0667 { 0668 if (scan[y].scan[0] > scan[y].scan[1]) 0669 { 0670 qSwap(scan[y].scan[0], scan[y].scan[1]); 0671 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]); 0672 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]); 0673 } 0674 0675 int px1 = scan[y].scan[0]; 0676 int px2 = scan[y].scan[1]; 0677 0678 float dx = px2 - px1; 0679 if (dx == 0) 0680 continue; 0681 0682 float duv[2]; 0683 float uv[2]; 0684 0685 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx; 0686 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx; 0687 0688 uv[0] = scan[y].uv[0][0]; 0689 uv[1] = scan[y].uv[0][1]; 0690 0691 if (px1 < 0) 0692 { 0693 float m = (float)-px1; 0694 0695 px1 = 0; 0696 uv[0] += duv[0] * m; 0697 uv[1] += duv[1] * m; 0698 } 0699 0700 if (px2 >= w) 0701 px2 = w - 1; 0702 0703 uv[0] *= tsx; 0704 uv[1] *= tsy; 0705 0706 duv[0] *= tsx; 0707 duv[1] *= tsy; 0708 0709 int size = sw * sh; 0710 0711 quint32 *pDst = bitsDst + (y * w) + px1; 0712 if (bw) 0713 { 0714 /* 0715 for (int x = px1; x < px2; x++) 0716 { 0717 float x_diff = uv[0] - static_cast<int>(uv[0]); 0718 float y_diff = uv[1] - static_cast<int>(uv[1]); 0719 float x_1diff = 1 - x_diff; 0720 float y_1diff = 1 - y_diff; 0721 0722 int index = ((int)uv[0] + ((int)uv[1] * sw)); 0723 0724 uchar a = bitsSrc8[index]; 0725 uchar b = bitsSrc8[(index + 1) % size]; 0726 uchar c = bitsSrc8[(index + sw) % size]; 0727 uchar d = bitsSrc8[(index + sw + 1) % size]; 0728 0729 int val = (a&0xff)*(x_1diff)*(y_1diff) + (b&0xff)*(x_diff)*(y_1diff) + 0730 (c&0xff)*(y_diff)*(x_1diff) + (d&0xff)*(x_diff*y_diff); 0731 0732 0733 *pDst = 0xff000000 | 0734 ((((int)val)<<16)&0xff0000) | 0735 ((((int)val)<<8)&0xff00) | 0736 ((int)val) ; 0737 pDst++; 0738 0739 uv[0] += duv[0]; 0740 uv[1] += duv[1]; 0741 } 0742 */ 0743 } 0744 else 0745 { 0746 for (int x = px1; x < px2; x++) 0747 { 0748 float x_diff = uv[0] - static_cast<int>(uv[0]); 0749 float y_diff = uv[1] - static_cast<int>(uv[1]); 0750 float x_1diff = 1 - x_diff; 0751 float y_1diff = 1 - y_diff; 0752 0753 int index = ((int)uv[0] + ((int)uv[1] * sw)); 0754 0755 quint32 a = bitsSrc[index]; 0756 quint32 b = bitsSrc[(index + 1) % size]; 0757 quint32 c = bitsSrc[(index + sw) % size]; 0758 quint32 d = bitsSrc[(index + sw + 1) % size]; 0759 0760 int x1y1 = (x_1diff * y_1diff) * 65536; 0761 int xy = (x_diff * y_diff) * 65536; 0762 int x1y = (y_diff * x_1diff) * 65536; 0763 int xy1 = (x_diff *y_1diff) * 65536; 0764 0765 float alpha = ((((a>>24)&0xff)*(x1y1) + ((b>>24)&0xff)*(xy1) + 0766 ((c>>24)&0xff)*(x1y) + ((d>>24)&0xff)*(xy)) * opacity); 0767 0768 if (alpha > 0.00390625f) // > 1 / 256. 0769 { 0770 // blue element 0771 int blue = ((a&0xff)*(x1y1) + (b&0xff)* (xy1) + 0772 (c&0xff)*(x1y) + (d&0xff)*(xy)) >> 16; 0773 0774 // green element 0775 int green = (((a>>8)&0xff)*(x1y1) + ((b>>8)&0xff)*(xy1) + 0776 ((c>>8)&0xff)*(x1y) + ((d>>8)&0xff)*(xy)) >> 16; 0777 0778 // red element 0779 int red = (((a>>16)&0xff)*(x1y1) + ((b>>16)&0xff)*(xy1) + 0780 ((c>>16)&0xff)*(x1y) + ((d>>16)&0xff)*(xy)) >> 16; 0781 0782 int rd = qRed(*pDst); 0783 int gd = qGreen(*pDst); 0784 int bd = qBlue(*pDst); 0785 0786 *pDst = qRgb(LERP(alpha, rd, red), LERP(alpha, gd, green), LERP(alpha, bd, blue)); 0787 } 0788 0789 pDst++; 0790 0791 uv[0] += duv[0]; 0792 uv[1] += duv[1]; 0793 } 0794 } 0795 } 0796 } 0797 0798 0799 //////////////////////////////////////////////////////////////// 0800 void ScanRender::renderPolygonAlphaNI(QImage *dst, QImage *src) 0801 //////////////////////////////////////////////////////////////// 0802 { 0803 int w = dst->width(); 0804 int sw = src->width(); 0805 float tsx = src->width() - 1; 0806 float tsy = src->height() - 1; 0807 const quint32 *bitsSrc = (quint32 *)src->constBits(); 0808 quint32 *bitsDst = (quint32 *)dst->bits(); 0809 bkScan_t *scan = scLR; 0810 float opacity = 0.00390625f * m_opacity; 0811 0812 #ifdef PARALLEL_OMP 0813 #pragma omp parallel for shared(bitsDst, bitsSrc, scan, tsx, tsy, w, sw) 0814 #endif 0815 for (int y = plMinY; y <= plMaxY; y++) 0816 { 0817 if (scan[y].scan[0] > scan[y].scan[1]) 0818 { 0819 qSwap(scan[y].scan[0], scan[y].scan[1]); 0820 qSwap(scan[y].uv[0][0], scan[y].uv[1][0]); 0821 qSwap(scan[y].uv[0][1], scan[y].uv[1][1]); 0822 } 0823 0824 int px1 = scan[y].scan[0]; 0825 int px2 = scan[y].scan[1]; 0826 0827 float dx = px2 - px1; 0828 if (dx == 0) 0829 continue; 0830 0831 float duv[2]; 0832 float uv[2]; 0833 0834 duv[0] = (float)(scan[y].uv[1][0] - scan[y].uv[0][0]) / dx; 0835 duv[1] = (float)(scan[y].uv[1][1] - scan[y].uv[0][1]) / dx; 0836 0837 uv[0] = scan[y].uv[0][0]; 0838 uv[1] = scan[y].uv[0][1]; 0839 0840 if (px1 < 0) 0841 { 0842 float m = (float)-px1; 0843 0844 px1 = 0; 0845 uv[0] += duv[0] * m; 0846 uv[1] += duv[1] * m; 0847 } 0848 0849 if (px2 >= w) 0850 px2 = w - 1; 0851 0852 quint32 *pDst = bitsDst + (y * w) + px1; 0853 0854 uv[0] *= tsx; 0855 uv[1] *= tsy; 0856 0857 duv[0] *= tsx; 0858 duv[1] *= tsy; 0859 0860 for (int x = px1; x < px2; x++) 0861 { 0862 const quint32 *pSrc = bitsSrc + ((int)(uv[0])) + ((int)(uv[1]) * sw); 0863 QRgb rgbs = *pSrc; 0864 QRgb rgbd = *pDst; 0865 float a = qAlpha(*pSrc) * opacity; 0866 0867 if (a > 0.00390625f) 0868 { 0869 *pDst = qRgb(LERP(a, qRed(rgbd), qRed(rgbs)), 0870 LERP(a, qGreen(rgbd), qGreen(rgbs)), 0871 LERP(a, qBlue(rgbd), qBlue(rgbs)) 0872 ); 0873 } 0874 pDst++; 0875 0876 uv[0] += duv[0]; 0877 uv[1] += duv[1]; 0878 } 0879 } 0880 } 0881 0882 #pragma GCC diagnostic pop