1206{
1207
1208
1210
1211
1212
1213
1214
1215
1217 growFilter.process(pixelSelection,
rect);
1218
1219 const qint32 maskScanLineSize =
rect.width();
1221 const qint32 referencePixelSize = referenceColorSpace->
pixelSize();
1222 const qint32 referenceScanLineSize = maskScanLineSize * referencePixelSize;
1223
1227 quint8 *maskScanLines[2] = {maskBuffer.data(), maskBuffer.data() + maskScanLineSize};
1228 quint8 *referenceScanLines[2] = {referenceBuffer.data(), referenceBuffer.data() + referenceScanLineSize};
1229 quint8 *selectionScanLine = selectionBuffer.data();
1230
1231 auto testSelectPixel =
1232 [referenceColorSpace]
1233 (quint8 pixelOpacity, quint8 pixelIntensity,
1234 const quint8 *testMaskPixel, const quint8 *testReferencePixel) -> bool
1235 {
1236 if (*testMaskPixel) {
1237 const quint8 testOpacity = referenceColorSpace->
opacityU8(testReferencePixel);
1238 if (pixelOpacity >= testOpacity) {
1239
1240
1242 return true;
1243 }
1244
1245
1246 const quint8 testIntensity = referenceColorSpace->
intensity8(testReferencePixel);
1247 if (pixelIntensity <= testIntensity) {
1248 return true;
1249 }
1250 }
1251 }
1252 return false;
1253 };
1254
1255
1256
1257 {
1258 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.top(), maskScanLineSize, 1);
1260 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.top(), maskScanLineSize, 1);
1261 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1262 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1263 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1264 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1265
1266 ++currentMaskScanLineBegin;
1267 currentReferenceScanLineBegin += referencePixelSize;
1268 ++currentSelectionScanLineBegin;
1269
1270 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1272 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1273 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1274
1275 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1276 currentMaskScanLineBegin - 1,
1277 currentReferenceScanLineBegin - referencePixelSize);
1278 if (pixelIsSelected) {
1280 }
1281 }
1282 ++currentMaskScanLineBegin;
1283 currentReferenceScanLineBegin += referencePixelSize;
1284 ++currentSelectionScanLineBegin;
1285 }
1287 }
1288
1289 for (qint32 y =
rect.top() + 1;
y <=
rect.bottom(); ++
y) {
1292 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1294 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1295 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1296 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1297 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1298 quint8 *topMaskScanLineBegin = maskScanLines[0];
1299 quint8 *topReferenceScanLineBegin = referenceScanLines[0];
1300 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1301
1302 {
1304 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1305 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1306
1307 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1308 topMaskScanLineBegin,
1309 topReferenceScanLineBegin);
1310 if (!pixelIsSelected) {
1311 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1312 topMaskScanLineBegin + 1,
1313 topReferenceScanLineBegin + referencePixelSize);
1314 }
1315 if (pixelIsSelected) {
1317 }
1318 }
1319 ++currentMaskScanLineBegin;
1320 currentReferenceScanLineBegin += referencePixelSize;
1321 ++topMaskScanLineBegin;
1322 topReferenceScanLineBegin += referencePixelSize;
1323 ++currentSelectionScanLineBegin;
1324 }
1325
1326 while (currentMaskScanLineBegin != (currentMaskScanLineEnd - 1)) {
1328 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1329 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1330
1331 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1332 topMaskScanLineBegin - 1,
1333 topReferenceScanLineBegin - referencePixelSize);
1334 if (!pixelIsSelected) {
1335 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1336 topMaskScanLineBegin,
1337 topReferenceScanLineBegin);
1338 if (!pixelIsSelected) {
1339 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1340 topMaskScanLineBegin + 1,
1341 topReferenceScanLineBegin + referencePixelSize);
1342 if (!pixelIsSelected) {
1343 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1344 currentMaskScanLineBegin - 1,
1345 currentReferenceScanLineBegin - referencePixelSize);
1346 }
1347 }
1348 }
1349 if (pixelIsSelected) {
1351 }
1352 }
1353 ++currentMaskScanLineBegin;
1354 currentReferenceScanLineBegin += referencePixelSize;
1355 ++topMaskScanLineBegin;
1356 topReferenceScanLineBegin += referencePixelSize;
1357 ++currentSelectionScanLineBegin;
1358 }
1359
1360 {
1362 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1363 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1364
1365 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1366 topMaskScanLineBegin - 1,
1367 topReferenceScanLineBegin - referencePixelSize);
1368 if (!pixelIsSelected) {
1369 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1370 topMaskScanLineBegin,
1371 topReferenceScanLineBegin);
1372 if (!pixelIsSelected) {
1373 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1374 currentMaskScanLineBegin - 1,
1375 currentReferenceScanLineBegin - referencePixelSize);
1376 }
1377 }
1378 if (pixelIsSelected) {
1380 }
1381 }
1382 }
1383 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1384 }
1385
1386
1387
1388 {
1389 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1391 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1392 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1393 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1394 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1395 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1396
1397 --currentMaskScanLineBegin;
1398 currentReferenceScanLineBegin -= referencePixelSize;
1399 --currentSelectionScanLineBegin;
1400
1401 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1403 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1404 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1405
1406 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1407 currentMaskScanLineBegin + 1,
1408 currentReferenceScanLineBegin + referencePixelSize);
1409 if (pixelIsSelected) {
1411 }
1412 }
1413 --currentMaskScanLineBegin;
1414 currentReferenceScanLineBegin -= referencePixelSize;
1415 --currentSelectionScanLineBegin;
1416 }
1418 }
1419
1420 for (qint32 y =
rect.bottom() - 1;
y >=
rect.top(); --
y) {
1423 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1425 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1426 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1427 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1428 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1429 quint8 *bottomMaskScanLineBegin = maskScanLines[0] + maskScanLineSize - 1;
1430 quint8 *bottomReferenceScanLineBegin = referenceScanLines[0] + referenceScanLineSize - referencePixelSize;
1431 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1432
1433 {
1435 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1436 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1437
1438 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1439 bottomMaskScanLineBegin,
1440 bottomReferenceScanLineBegin);
1441 if (!pixelIsSelected) {
1442 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1443 bottomMaskScanLineBegin - 1,
1444 bottomReferenceScanLineBegin - referencePixelSize);
1445 }
1446 if (pixelIsSelected) {
1448 }
1449 }
1450 --currentMaskScanLineBegin;
1451 currentReferenceScanLineBegin -= referencePixelSize;
1452 --bottomMaskScanLineBegin;
1453 bottomReferenceScanLineBegin -= referencePixelSize;
1454 --currentSelectionScanLineBegin;
1455 }
1456
1457 while (currentMaskScanLineBegin != (currentMaskScanLineEnd + 1)) {
1459 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1460 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1461
1462 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1463 bottomMaskScanLineBegin + 1,
1464 bottomReferenceScanLineBegin + referencePixelSize);
1465 if (!pixelIsSelected) {
1466 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1467 bottomMaskScanLineBegin,
1468 bottomReferenceScanLineBegin);
1469 if (!pixelIsSelected) {
1470 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1471 bottomMaskScanLineBegin - 1,
1472 bottomReferenceScanLineBegin - referencePixelSize);
1473 if (!pixelIsSelected) {
1474 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1475 currentMaskScanLineBegin + 1,
1476 currentReferenceScanLineBegin + referencePixelSize);
1477 }
1478 }
1479 }
1480 if (pixelIsSelected) {
1482 }
1483 }
1484 --currentMaskScanLineBegin;
1485 currentReferenceScanLineBegin -= referencePixelSize;
1486 --bottomMaskScanLineBegin;
1487 bottomReferenceScanLineBegin -= referencePixelSize;
1488 --currentSelectionScanLineBegin;
1489 }
1490
1491 {
1493 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1494 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1495
1496 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1497 bottomMaskScanLineBegin + 1,
1498 bottomReferenceScanLineBegin + referencePixelSize);
1499 if (!pixelIsSelected) {
1500 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1501 bottomMaskScanLineBegin,
1502 bottomReferenceScanLineBegin);
1503 if (!pixelIsSelected) {
1504 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1505 currentMaskScanLineBegin + 1,
1506 currentReferenceScanLineBegin + referencePixelSize);
1507 }
1508 }
1509 if (pixelIsSelected) {
1511 }
1512 }
1513 }
1514 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1515 }
1516
1517
1518
1519
1520 {
1523 while (it1.nextPixel() && it2.nextPixel()) {
1524 *it2.rawData() *= (*it1.rawDataConst() !=
MIN_SELECTED);
1525 }
1526 }
1527}
const KoColorSpace * colorSpace() const
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
void writeBytes(const quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h)
void rotatePointers(quint8 **p, quint32 n)
virtual quint8 intensity8(const quint8 *src) const =0
virtual quint32 pixelSize() const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
const quint8 MAX_SELECTED
const quint8 MIN_SELECTED