Krita Source Code Documentation
Loading...
Searching...
No Matches
KisPropagateColorsFilter.cpp File Reference

Go to the source code of this file.

Classes

struct  GenericExpansionStrategy< DiagonalDistance, BoundedExpansion, ExpandAlpha >
 
struct  ScaledProgress
 

Functions

template<typename ExpansionStrategy >
void expand (ExpansionStrategy &expansionStrategy, KoUpdater *progressUpdater)
 
template<quint32 DiagonalDistance>
void selectStrategyAndExpand1 (KisPaintDeviceSP device, const QRect &applyRect, const KisPropagateColorsFilterConfiguration *filterConfig, KoUpdater *progressUpdater)
 
template<quint32 DiagonalDistance, bool BoundedExpansion>
void selectStrategyAndExpand2 (KisPaintDeviceSP device, const QRect &applyRect, const KisPropagateColorsFilterConfiguration *filterConfig, KoUpdater *progressUpdater)
 
static void swapRowPointers (quint8 **distanceMapRow1, quint8 **distanceMapRow2, quint8 **deviceRow1, quint8 **deviceRow2)
 

Function Documentation

◆ expand()

template<typename ExpansionStrategy >
void expand ( ExpansionStrategy & expansionStrategy,
KoUpdater * progressUpdater )

Definition at line 226 of file KisPropagateColorsFilter.cpp.

227{
228 ScaledProgress progress(expansionStrategy.rect.height() * 2, progressUpdater);
229
230 QVector<quint8> distanceMapRows(expansionStrategy.rect.width() * 4 * 2);
231 QVector<quint8> deviceRows(expansionStrategy.rect.width() * expansionStrategy.sourceDevicePixelSize * 2);
232 quint8 *distanceMapRow1, *distanceMapRow2;
233 quint8 *deviceRow1, *deviceRow2;
234
235 // Forwards pass
236 distanceMapRow1 = distanceMapRows.data();
237 distanceMapRow2 = distanceMapRows.data() + expansionStrategy.rect.width() * 4;
238 deviceRow1 = deviceRows.data();
239 deviceRow2 = deviceRows.data() + expansionStrategy.rect.width() * expansionStrategy.sourceDevicePixelSize;
240 // Top row
241 expansionStrategy.distanceMap->readBytes(distanceMapRow1, expansionStrategy.rect.left(),
242 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
243 expansionStrategy.sourceDevice->readBytes(deviceRow1, expansionStrategy.rect.left(),
244 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
245 // Left pixel
246 expansionStrategy.initializePixel(reinterpret_cast<quint32*>(distanceMapRow1), deviceRow1);
247 // Middle pixels
248 {
249 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow1) + 1;
250 quint8 *devicePixel = deviceRow1 + expansionStrategy.sourceDevicePixelSize;
251 for (qint32 x = 1; x < expansionStrategy.rect.width();
252 ++x, ++distancePixel, devicePixel += expansionStrategy.sourceDevicePixelSize) {
253
254 expansionStrategy.initializePixel(distancePixel, devicePixel);
255 if (*distancePixel == 0) {
256 continue;
257 }
258 expansionStrategy.updatePixel(
259 distancePixel, devicePixel,
260 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
261 expansionStrategy.orthogonalDistance
262 );
263 }
264 }
265 expansionStrategy.distanceMap->writeBytes(distanceMapRow1, expansionStrategy.rect.left(),
266 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
267 expansionStrategy.sourceDevice->writeBytes(deviceRow1, expansionStrategy.rect.left(),
268 expansionStrategy.rect.top(), expansionStrategy.rect.width(), 1);
269 progress.stepUp();
270 // Rest of rows
271 for (qint32 y = expansionStrategy.rect.top() + 1; y <= expansionStrategy.rect.bottom(); ++y) {
272 expansionStrategy.distanceMap->readBytes(distanceMapRow2, expansionStrategy.rect.left(),
273 y, expansionStrategy.rect.width(), 1);
274 expansionStrategy.sourceDevice->readBytes(deviceRow2, expansionStrategy.rect.left(), y,
275 expansionStrategy.rect.width(), 1);
276
277 quint32 *topDistancePixel = reinterpret_cast<quint32*>(distanceMapRow1);
278 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow2);
279 quint8 *topDevicePixel = deviceRow1;
280 quint8 *devicePixel = deviceRow2;
281 // Left pixel
282 {
283 expansionStrategy.initializePixel(distancePixel, devicePixel);
284 if (*distancePixel != 0) {
285 if (expansionStrategy.rect.width() > 1) {
286 expansionStrategy.updatePixel(
287 distancePixel, devicePixel,
288 topDistancePixel, topDevicePixel,
289 topDistancePixel + 1, topDevicePixel + expansionStrategy.sourceDevicePixelSize,
290 expansionStrategy.orthogonalDistance, expansionStrategy.diagonalDistance
291 );
292 } else {
293 expansionStrategy.updatePixel(
294 distancePixel, devicePixel,
295 topDistancePixel, topDevicePixel,
296 expansionStrategy.orthogonalDistance
297 );
298 }
299 }
300 ++topDistancePixel;
301 ++distancePixel;
302 topDevicePixel += expansionStrategy.sourceDevicePixelSize;
303 devicePixel += expansionStrategy.sourceDevicePixelSize;
304 }
305 // Middle pixels
306 for (qint32 x = 1; x < expansionStrategy.rect.width() - 1;
307 ++x, ++topDistancePixel, ++distancePixel,
308 topDevicePixel += expansionStrategy.sourceDevicePixelSize,
309 devicePixel += expansionStrategy.sourceDevicePixelSize) {
310
311 expansionStrategy.initializePixel(distancePixel, devicePixel);
312 if (*distancePixel == 0) {
313 continue;
314 }
315 expansionStrategy.updatePixel(
316 distancePixel, devicePixel,
317 topDistancePixel - 1,topDevicePixel - expansionStrategy.sourceDevicePixelSize,
318 topDistancePixel, topDevicePixel,
319 topDistancePixel + 1, topDevicePixel + expansionStrategy.sourceDevicePixelSize,
320 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
321 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
322 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance
323 );
324 }
325 // Right pixel
326 expansionStrategy.initializePixel(distancePixel, devicePixel);
327 if (expansionStrategy.rect.width() > 1 && *distancePixel != 0) {
328 expansionStrategy.updatePixel(
329 distancePixel, devicePixel,
330 topDistancePixel - 1, topDevicePixel - expansionStrategy.sourceDevicePixelSize,
331 distancePixel - 1, devicePixel - expansionStrategy.sourceDevicePixelSize,
332 topDistancePixel, topDevicePixel,
333 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
334 expansionStrategy.orthogonalDistance
335 );
336 }
337 // Write new pixels
338 expansionStrategy.distanceMap->writeBytes(distanceMapRow2, expansionStrategy.rect.left(),
339 y, expansionStrategy.rect.width(), 1);
340 expansionStrategy.sourceDevice->writeBytes(deviceRow2, expansionStrategy.rect.left(),
341 y, expansionStrategy.rect.width(), 1);
342 // Swap pointers
343 swapRowPointers(&distanceMapRow1, &distanceMapRow2, &deviceRow1, &deviceRow2);
344
345 progress.stepUp();
346 }
347
348 // Backwards pass
349 // Bottom row
350 // Right pixel (no op)
351 // Middle pixels
352 {
353 quint32 *distancePixel = reinterpret_cast<quint32*>(distanceMapRow1) + expansionStrategy.rect.width() - 2;
354 quint8 *devicePixel =
355 deviceRow1 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 2);
356 for (qint32 x = 1; x < expansionStrategy.rect.width();
357 ++x, --distancePixel, devicePixel -= expansionStrategy.sourceDevicePixelSize) {
358
359 if (*distancePixel == 0) {
360 continue;
361 }
362 expansionStrategy.updatePixel(
363 distancePixel, devicePixel,
364 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
365 expansionStrategy.orthogonalDistance
366 );
367 }
368 }
369 expansionStrategy.distanceMap->writeBytes(distanceMapRow1, expansionStrategy.rect.left(),
370 expansionStrategy.rect.bottom(), expansionStrategy.rect.width(), 1);
371 expansionStrategy.sourceDevice->writeBytes(deviceRow1, expansionStrategy.rect.left(),
372 expansionStrategy.rect.bottom(), expansionStrategy.rect.width(), 1);
373 progress.stepUp();
374 // Rest of rows
375 for (qint32 y = expansionStrategy.rect.bottom() - 1; y >= expansionStrategy.rect.top(); --y) {
376 expansionStrategy.distanceMap->readBytes(distanceMapRow2, expansionStrategy.rect.left(),
377 y, expansionStrategy.rect.width(), 1);
378 expansionStrategy.sourceDevice->readBytes(deviceRow2, expansionStrategy.rect.left(),
379 y, expansionStrategy.rect.width(), 1);
380
381 quint32 *bottomDistancePixel =
382 reinterpret_cast<quint32*>(distanceMapRow1) + expansionStrategy.rect.width() - 1;
383 quint32 *distancePixel =
384 reinterpret_cast<quint32*>(distanceMapRow2) + expansionStrategy.rect.width() - 1;
385 quint8 *bottomDevicePixel =
386 deviceRow1 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 1);
387 quint8 *devicePixel =
388 deviceRow2 + expansionStrategy.sourceDevicePixelSize * (expansionStrategy.rect.width() - 1);
389 // Right pixel
390 {
391 if (*distancePixel != 0) {
392 if (expansionStrategy.rect.width() > 1) {
393 expansionStrategy.updatePixel(
394 distancePixel, devicePixel,
395 bottomDistancePixel, bottomDevicePixel,
396 bottomDistancePixel - 1, bottomDevicePixel - expansionStrategy.sourceDevicePixelSize,
397 expansionStrategy.orthogonalDistance, expansionStrategy.diagonalDistance
398 );
399 } else {
400 expansionStrategy.updatePixel(
401 distancePixel, devicePixel,
402 bottomDistancePixel, bottomDevicePixel,
403 expansionStrategy.orthogonalDistance
404 );
405 }
406 }
407 --bottomDistancePixel;
408 --distancePixel;
409 bottomDevicePixel -= expansionStrategy.sourceDevicePixelSize;
410 devicePixel -= expansionStrategy.sourceDevicePixelSize;
411 }
412 // Middle pixels
413 for (qint32 x = 1; x < expansionStrategy.rect.width() - 1;
414 ++x, --bottomDistancePixel, --distancePixel,
415 bottomDevicePixel -= expansionStrategy.sourceDevicePixelSize,
416 devicePixel -= expansionStrategy.sourceDevicePixelSize) {
417
418 if (*distancePixel == 0) {
419 continue;
420 }
421 expansionStrategy.updatePixel(
422 distancePixel, devicePixel,
423 bottomDistancePixel + 1, bottomDevicePixel + expansionStrategy.sourceDevicePixelSize,
424 bottomDistancePixel, bottomDevicePixel,
425 bottomDistancePixel - 1, bottomDevicePixel - expansionStrategy.sourceDevicePixelSize,
426 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
427 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
428 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance
429 );
430 }
431 // Left pixel
432 if (expansionStrategy.rect.width() > 1 && *distancePixel != 0) {
433 expansionStrategy.updatePixel(
434 distancePixel, devicePixel,
435 bottomDistancePixel + 1, bottomDevicePixel + expansionStrategy.sourceDevicePixelSize,
436 bottomDistancePixel, bottomDevicePixel,
437 distancePixel + 1, devicePixel + expansionStrategy.sourceDevicePixelSize,
438 expansionStrategy.diagonalDistance, expansionStrategy.orthogonalDistance,
439 expansionStrategy.orthogonalDistance
440 );
441 }
442 // Write new pixels
443 expansionStrategy.distanceMap->writeBytes(distanceMapRow2, expansionStrategy.rect.left(),
444 y, expansionStrategy.rect.width(), 1);
445 expansionStrategy.sourceDevice->writeBytes(deviceRow2, expansionStrategy.rect.left(), y,
446 expansionStrategy.rect.width(), 1);
447 // Swap pointers
448 swapRowPointers(&distanceMapRow1, &distanceMapRow2, &deviceRow1, &deviceRow2);
449
450 progress.stepUp();
451 }
452
453 progress.complete();
454}
static void swapRowPointers(quint8 **distanceMapRow1, quint8 **distanceMapRow2, quint8 **deviceRow1, quint8 **deviceRow2)

References ScaledProgress::complete(), ScaledProgress::stepUp(), and swapRowPointers().

◆ selectStrategyAndExpand1()

template<quint32 DiagonalDistance>
void selectStrategyAndExpand1 ( KisPaintDeviceSP device,
const QRect & applyRect,
const KisPropagateColorsFilterConfiguration * filterConfig,
KoUpdater * progressUpdater )

Definition at line 478 of file KisPropagateColorsFilter.cpp.

482{
483 const KisPropagateColorsFilterConfiguration::ExpansionMode expansionMode = filterConfig->expansionMode();
484
486 selectStrategyAndExpand2<DiagonalDistance, true>(device, applyRect, filterConfig, progressUpdater);
487 } else {
488 selectStrategyAndExpand2<DiagonalDistance, false>(device, applyRect, filterConfig, progressUpdater);
489 }
490}

References KisPropagateColorsFilterConfiguration::expansionMode(), and KisPropagateColorsFilterConfiguration::ExpansionMode_Bounded.

◆ selectStrategyAndExpand2()

template<quint32 DiagonalDistance, bool BoundedExpansion>
void selectStrategyAndExpand2 ( KisPaintDeviceSP device,
const QRect & applyRect,
const KisPropagateColorsFilterConfiguration * filterConfig,
KoUpdater * progressUpdater )

Definition at line 457 of file KisPropagateColorsFilter.cpp.

461{
462 const KisPropagateColorsFilterConfiguration::AlphaChannelMode alphaChannelMode = filterConfig->alphaChannelMode();
463
466 device, applyRect, filterConfig->expansionAmount()
467 );
468 expand(expansionStrategy, progressUpdater);
469 } else {
471 device, applyRect, filterConfig->expansionAmount()
472 );
473 expand(expansionStrategy, progressUpdater);
474 }
475}
void expand(ExpansionStrategy &expansionStrategy, KoUpdater *progressUpdater)

References KisPropagateColorsFilterConfiguration::alphaChannelMode(), KisPropagateColorsFilterConfiguration::AlphaChannelMode_Preserve, expand(), and KisPropagateColorsFilterConfiguration::expansionAmount().

◆ swapRowPointers()

static void swapRowPointers ( quint8 ** distanceMapRow1,
quint8 ** distanceMapRow2,
quint8 ** deviceRow1,
quint8 ** deviceRow2 )
static

Definition at line 185 of file KisPropagateColorsFilter.cpp.

189{
190 quint8 *temp = *distanceMapRow1;
191 *distanceMapRow1 = *distanceMapRow2;
192 *distanceMapRow2 = temp;
193 temp = *deviceRow1;
194 *deviceRow1 = *deviceRow2;
195 *deviceRow2 = temp;
196}