1211{
1212
1213
1215
1216
1217
1218
1219
1220
1222 growFilter.process(pixelSelection,
rect);
1223
1224 const qint32 maskScanLineSize =
rect.width();
1226 const qint32 referencePixelSize = referenceColorSpace->
pixelSize();
1227 const qint32 referenceScanLineSize = maskScanLineSize * referencePixelSize;
1228
1232 quint8 *maskScanLines[2] = {maskBuffer.data(), maskBuffer.data() + maskScanLineSize};
1233 quint8 *referenceScanLines[2] = {referenceBuffer.data(), referenceBuffer.data() + referenceScanLineSize};
1234 quint8 *selectionScanLine = selectionBuffer.data();
1235
1236 auto testSelectPixel =
1237 [referenceColorSpace]
1238 (quint8 pixelOpacity, quint8 pixelIntensity,
1239 const quint8 *testMaskPixel, const quint8 *testReferencePixel) -> bool
1240 {
1241 if (*testMaskPixel) {
1242 const quint8 testOpacity = referenceColorSpace->
opacityU8(testReferencePixel);
1243 if (pixelOpacity >= testOpacity) {
1244
1245
1247 return true;
1248 }
1249
1250
1251 const quint8 testIntensity = referenceColorSpace->
intensity8(testReferencePixel);
1252 if (pixelIntensity <= testIntensity) {
1253 return true;
1254 }
1255 }
1256 }
1257 return false;
1258 };
1259
1260
1261
1262 {
1263 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.top(), maskScanLineSize, 1);
1265 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.top(), maskScanLineSize, 1);
1266 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1267 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1268 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1269 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1270
1271 ++currentMaskScanLineBegin;
1272 currentReferenceScanLineBegin += referencePixelSize;
1273 ++currentSelectionScanLineBegin;
1274
1275 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1277 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1278 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1279
1280 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1281 currentMaskScanLineBegin - 1,
1282 currentReferenceScanLineBegin - referencePixelSize);
1283 if (pixelIsSelected) {
1285 }
1286 }
1287 ++currentMaskScanLineBegin;
1288 currentReferenceScanLineBegin += referencePixelSize;
1289 ++currentSelectionScanLineBegin;
1290 }
1292 }
1293
1294 for (qint32 y =
rect.top() + 1;
y <=
rect.bottom(); ++
y) {
1297 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1299 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1300 quint8 *currentMaskScanLineBegin = maskScanLines[1];
1301 quint8 *currentMaskScanLineEnd = maskScanLines[1] + maskScanLineSize;
1302 quint8 *currentReferenceScanLineBegin = referenceScanLines[1];
1303 quint8 *topMaskScanLineBegin = maskScanLines[0];
1304 quint8 *topReferenceScanLineBegin = referenceScanLines[0];
1305 quint8 *currentSelectionScanLineBegin = selectionScanLine;
1306
1307 {
1309 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1310 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1311
1312 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1313 topMaskScanLineBegin,
1314 topReferenceScanLineBegin);
1315 if (!pixelIsSelected) {
1316 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1317 topMaskScanLineBegin + 1,
1318 topReferenceScanLineBegin + referencePixelSize);
1319 }
1320 if (pixelIsSelected) {
1322 }
1323 }
1324 ++currentMaskScanLineBegin;
1325 currentReferenceScanLineBegin += referencePixelSize;
1326 ++topMaskScanLineBegin;
1327 topReferenceScanLineBegin += referencePixelSize;
1328 ++currentSelectionScanLineBegin;
1329 }
1330
1331 while (currentMaskScanLineBegin != (currentMaskScanLineEnd - 1)) {
1333 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1334 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1335
1336 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1337 topMaskScanLineBegin - 1,
1338 topReferenceScanLineBegin - referencePixelSize);
1339 if (!pixelIsSelected) {
1340 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1341 topMaskScanLineBegin,
1342 topReferenceScanLineBegin);
1343 if (!pixelIsSelected) {
1344 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1345 topMaskScanLineBegin + 1,
1346 topReferenceScanLineBegin + referencePixelSize);
1347 if (!pixelIsSelected) {
1348 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1349 currentMaskScanLineBegin - 1,
1350 currentReferenceScanLineBegin - referencePixelSize);
1351 }
1352 }
1353 }
1354 if (pixelIsSelected) {
1356 }
1357 }
1358 ++currentMaskScanLineBegin;
1359 currentReferenceScanLineBegin += referencePixelSize;
1360 ++topMaskScanLineBegin;
1361 topReferenceScanLineBegin += referencePixelSize;
1362 ++currentSelectionScanLineBegin;
1363 }
1364
1365 {
1367 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1368 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1369
1370 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1371 topMaskScanLineBegin - 1,
1372 topReferenceScanLineBegin - referencePixelSize);
1373 if (!pixelIsSelected) {
1374 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1375 topMaskScanLineBegin,
1376 topReferenceScanLineBegin);
1377 if (!pixelIsSelected) {
1378 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1379 currentMaskScanLineBegin - 1,
1380 currentReferenceScanLineBegin - referencePixelSize);
1381 }
1382 }
1383 if (pixelIsSelected) {
1385 }
1386 }
1387 }
1388 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1389 }
1390
1391
1392
1393 {
1394 mask->
readBytes(maskScanLines[1],
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1396 pixelSelection->
readBytes(selectionScanLine,
rect.left(),
rect.bottom(), maskScanLineSize, 1);
1397 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1398 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1399 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1400 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1401
1402 --currentMaskScanLineBegin;
1403 currentReferenceScanLineBegin -= referencePixelSize;
1404 --currentSelectionScanLineBegin;
1405
1406 while (currentMaskScanLineBegin != currentMaskScanLineEnd) {
1408 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1409 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1410
1411 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1412 currentMaskScanLineBegin + 1,
1413 currentReferenceScanLineBegin + referencePixelSize);
1414 if (pixelIsSelected) {
1416 }
1417 }
1418 --currentMaskScanLineBegin;
1419 currentReferenceScanLineBegin -= referencePixelSize;
1420 --currentSelectionScanLineBegin;
1421 }
1423 }
1424
1425 for (qint32 y =
rect.bottom() - 1;
y >=
rect.top(); --
y) {
1428 mask->
readBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1430 pixelSelection->
readBytes(selectionScanLine,
rect.left(), y, maskScanLineSize, 1);
1431 quint8 *currentMaskScanLineBegin = maskScanLines[1] + maskScanLineSize - 1;
1432 quint8 *currentMaskScanLineEnd = maskScanLines[1] - 1;
1433 quint8 *currentReferenceScanLineBegin = referenceScanLines[1] + referenceScanLineSize - referencePixelSize;
1434 quint8 *bottomMaskScanLineBegin = maskScanLines[0] + maskScanLineSize - 1;
1435 quint8 *bottomReferenceScanLineBegin = referenceScanLines[0] + referenceScanLineSize - referencePixelSize;
1436 quint8 *currentSelectionScanLineBegin = selectionScanLine + maskScanLineSize - 1;
1437
1438 {
1440 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1441 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1442
1443 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1444 bottomMaskScanLineBegin,
1445 bottomReferenceScanLineBegin);
1446 if (!pixelIsSelected) {
1447 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1448 bottomMaskScanLineBegin - 1,
1449 bottomReferenceScanLineBegin - referencePixelSize);
1450 }
1451 if (pixelIsSelected) {
1453 }
1454 }
1455 --currentMaskScanLineBegin;
1456 currentReferenceScanLineBegin -= referencePixelSize;
1457 --bottomMaskScanLineBegin;
1458 bottomReferenceScanLineBegin -= referencePixelSize;
1459 --currentSelectionScanLineBegin;
1460 }
1461
1462 while (currentMaskScanLineBegin != (currentMaskScanLineEnd + 1)) {
1464 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1465 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1466
1467 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1468 bottomMaskScanLineBegin + 1,
1469 bottomReferenceScanLineBegin + referencePixelSize);
1470 if (!pixelIsSelected) {
1471 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1472 bottomMaskScanLineBegin,
1473 bottomReferenceScanLineBegin);
1474 if (!pixelIsSelected) {
1475 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1476 bottomMaskScanLineBegin - 1,
1477 bottomReferenceScanLineBegin - referencePixelSize);
1478 if (!pixelIsSelected) {
1479 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1480 currentMaskScanLineBegin + 1,
1481 currentReferenceScanLineBegin + referencePixelSize);
1482 }
1483 }
1484 }
1485 if (pixelIsSelected) {
1487 }
1488 }
1489 --currentMaskScanLineBegin;
1490 currentReferenceScanLineBegin -= referencePixelSize;
1491 --bottomMaskScanLineBegin;
1492 bottomReferenceScanLineBegin -= referencePixelSize;
1493 --currentSelectionScanLineBegin;
1494 }
1495
1496 {
1498 const quint8 currentOpacity = referenceColorSpace->
opacityU8(currentReferenceScanLineBegin);
1499 const quint8 currentIntensity = referenceColorSpace->
intensity8(currentReferenceScanLineBegin);
1500
1501 bool pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1502 bottomMaskScanLineBegin + 1,
1503 bottomReferenceScanLineBegin + referencePixelSize);
1504 if (!pixelIsSelected) {
1505 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1506 bottomMaskScanLineBegin,
1507 bottomReferenceScanLineBegin);
1508 if (!pixelIsSelected) {
1509 pixelIsSelected = testSelectPixel(currentOpacity, currentIntensity,
1510 currentMaskScanLineBegin + 1,
1511 currentReferenceScanLineBegin + referencePixelSize);
1512 }
1513 }
1514 if (pixelIsSelected) {
1516 }
1517 }
1518 }
1519 mask->
writeBytes(maskScanLines[1],
rect.left(), y, maskScanLineSize, 1);
1520 }
1521
1522
1523
1524
1525 {
1528 while (it1.nextPixel() && it2.nextPixel()) {
1529 *it2.rawData() *= (*it1.rawDataConst() !=
MIN_SELECTED);
1530 }
1531 }
1532}
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