Krita Source Code Documentation
Loading...
Searching...
No Matches
KisShrinkSelectionFilter Class Reference

#include <kis_selection_filters.h>

+ Inheritance diagram for KisShrinkSelectionFilter:

Public Member Functions

QRect changeRect (const QRect &rect, KisDefaultBoundsBaseSP defaultBounds) override
 
 KisShrinkSelectionFilter (qint32 xRadius, qint32 yRadius, bool edgeLock)
 
KUndo2MagicString name () override
 
void process (KisPixelSelectionSP pixelSelection, const QRect &rect) override
 
- Public Member Functions inherited from KisSelectionFilter
virtual ~KisSelectionFilter ()
 

Private Attributes

qint32 m_edgeLock
 
qint32 m_xRadius
 
qint32 m_yRadius
 

Additional Inherited Members

- Protected Member Functions inherited from KisSelectionFilter
void computeBorder (qint32 *circ, qint32 xradius, qint32 yradius)
 
void computeTransition (quint8 *transition, quint8 **buf, qint32 width)
 
void rotatePointers (quint8 **p, quint32 n)
 

Detailed Description

Definition at line 107 of file kis_selection_filters.h.

Constructor & Destructor Documentation

◆ KisShrinkSelectionFilter()

KisShrinkSelectionFilter::KisShrinkSelectionFilter ( qint32 xRadius,
qint32 yRadius,
bool edgeLock )

Definition at line 670 of file kis_selection_filters.cpp.

671 : m_xRadius(xRadius)
672 , m_yRadius(yRadius)
673 , m_edgeLock(edgeLock)
674{
675}

Member Function Documentation

◆ changeRect()

QRect KisShrinkSelectionFilter::changeRect ( const QRect & rect,
KisDefaultBoundsBaseSP defaultBounds )
overridevirtual

Reimplemented from KisSelectionFilter.

Definition at line 682 of file kis_selection_filters.cpp.

683{
684 return m_edgeLock ? defaultBounds->imageBorderRect() : rect;
685}
virtual QRect imageBorderRect() const

References KisDefaultBoundsBase::imageBorderRect(), and m_edgeLock.

◆ name()

KUndo2MagicString KisShrinkSelectionFilter::name ( )
overridevirtual

Reimplemented from KisSelectionFilter.

Definition at line 677 of file kis_selection_filters.cpp.

678{
679 return kundo2_i18n("Shrink Selection");
680}
KUndo2MagicString kundo2_i18n(const char *text)

References kundo2_i18n().

◆ process()

void KisShrinkSelectionFilter::process ( KisPixelSelectionSP pixelSelection,
const QRect & rect )
overridevirtual

Implements KisSelectionFilter.

Definition at line 687 of file kis_selection_filters.cpp.

688{
689 if (m_xRadius <= 0 || m_yRadius <= 0) return;
690
691 /*
692 pretty much the same as fatten_region only different
693 blame all bugs in this function on jaycox@gimp.org
694 */
695 /* If edge_lock is true we assume that pixels outside the region
696 we are passed are identical to the edge pixels.
697 If edge_lock is false, we assume that pixels outside the region are 0
698 */
699 quint8 **buf; // caches the region's pixels
700 quint8 **max; // caches the smallest values for each column
701 qint32 last_max, last_index;
702
703 max = new quint8* [rect.width() + 2 * m_xRadius];
704 buf = new quint8* [m_yRadius + 1];
705 for (qint32 i = 0; i < m_yRadius + 1; i++) {
706 buf[i] = new quint8[rect.width()];
707 }
708
709 qint32 buffer_size = (rect.width() + 2 * m_xRadius + 1) * (m_yRadius + 1);
710 quint8* buffer = new quint8[buffer_size];
711
712 if (m_edgeLock)
713 memset(buffer, 255, buffer_size);
714 else
715 memset(buffer, 0, buffer_size);
716
717 for (qint32 i = 0; i < rect.width() + 2 * m_xRadius; i++) {
718 if (i < m_xRadius)
719 if (m_edgeLock)
720 max[i] = buffer;
721 else
722 max[i] = &buffer[(m_yRadius + 1) * (rect.width() + m_xRadius)];
723 else if (i < rect.width() + m_xRadius)
724 max[i] = &buffer[(m_yRadius + 1) * (i - m_xRadius)];
725 else if (m_edgeLock)
726 max[i] = &buffer[(m_yRadius + 1) * (rect.width() + m_xRadius - 1)];
727 else
728 max[i] = &buffer[(m_yRadius + 1) * (rect.width() + m_xRadius)];
729 }
730 if (!m_edgeLock)
731 for (qint32 j = 0 ; j < m_xRadius + 1; j++) max[0][j] = 0;
732
733 // offset the max pointer by m_xRadius so the range of the array is [-m_xRadius] to [region->w + m_xRadius]
734 max += m_xRadius;
735
736 quint8* out = new quint8[rect.width()]; // holds the new scan line we are computing
737
738 qint32* circ = new qint32[2 * m_xRadius + 1]; // holds the y coords of the filter's mask
739
741
742 // offset the circ pointer by m_xRadius so the range of the array is [-m_xRadius] to [m_xRadius]
743 circ += m_xRadius;
744
745 for (qint32 i = 0; i < m_yRadius && i < rect.height(); i++) // load top of image
746 pixelSelection->readBytes(buf[i + 1], rect.x(), rect.y() + i, rect.width(), 1);
747
748 if (m_edgeLock)
749 memcpy(buf[0], buf[1], rect.width());
750 else
751 memset(buf[0], 0, rect.width());
752
753
754 for (qint32 x = 0; x < rect.width(); x++) { // set up max for top of image
755 max[x][0] = buf[0][x];
756 for (qint32 j = 1; j < m_yRadius + 1; j++)
757 max[x][j] = MIN(buf[j][x], max[x][j-1]);
758 }
759
760 for (qint32 y = 0; y < rect.height(); y++) {
761 rotatePointers(buf, m_yRadius + 1);
762 if (y < rect.height() - m_yRadius)
763 pixelSelection->readBytes(buf[m_yRadius], rect.x(), rect.y() + y + m_yRadius, rect.width(), 1);
764 else if (m_edgeLock)
765 memcpy(buf[m_yRadius], buf[m_yRadius - 1], rect.width());
766 else
767 memset(buf[m_yRadius], 0, rect.width());
768
769 for (qint32 x = 0 ; x < rect.width(); x++) { // update max array
770 for (qint32 i = m_yRadius; i > 0; i--) {
771 max[x][i] = MIN(MIN(max[x][i - 1], buf[i - 1][x]), buf[i][x]);
772 }
773 max[x][0] = buf[0][x];
774 }
775 last_max = max[0][circ[-1]];
776 last_index = 0;
777
778 for (qint32 x = 0 ; x < rect.width(); x++) { // render scan line
779 last_index--;
780 if (last_index >= 0) {
781 if (last_max == 0)
782 out[x] = 0;
783 else {
784 last_max = 255;
785 for (qint32 i = m_xRadius; i >= 0; i--)
786 if (last_max > max[x + i][circ[i]]) {
787 last_max = max[x + i][circ[i]];
788 last_index = i;
789 }
790 out[x] = last_max;
791 }
792 } else {
793 last_index = m_xRadius;
794 last_max = max[x + m_xRadius][circ[m_xRadius]];
795 for (qint32 i = m_xRadius - 1; i >= -m_xRadius; i--)
796 if (last_max > max[x + i][circ[i]]) {
797 last_max = max[x + i][circ[i]];
798 last_index = i;
799 }
800 out[x] = last_max;
801 }
802 }
803 pixelSelection->writeBytes(out, rect.x(), rect.y() + y, rect.width(), 1);
804 }
805
806 // undo the offsets to the pointers so we can free the malloced memory
807 circ -= m_xRadius;
808 max -= m_xRadius;
809
810 delete[] circ;
811 delete[] buffer;
812 delete[] max;
813 for (qint32 i = 0; i < m_yRadius + 1; i++)
814 delete[] buf[i];
815 delete[] buf;
816 delete[] out;
817}
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)
void computeBorder(qint32 *circ, qint32 xradius, qint32 yradius)
#define MIN(a, b)
constexpr std::enable_if< sizeof...(values)==0, size_t >::type max()

References KisSelectionFilter::computeBorder(), m_edgeLock, m_xRadius, m_yRadius, MIN, KisPaintDevice::readBytes(), KisSelectionFilter::rotatePointers(), and KisPaintDevice::writeBytes().

Member Data Documentation

◆ m_edgeLock

qint32 KisShrinkSelectionFilter::m_edgeLock
private

Definition at line 121 of file kis_selection_filters.h.

◆ m_xRadius

qint32 KisShrinkSelectionFilter::m_xRadius
private

Definition at line 119 of file kis_selection_filters.h.

◆ m_yRadius

qint32 KisShrinkSelectionFilter::m_yRadius
private

Definition at line 120 of file kis_selection_filters.h.


The documentation for this class was generated from the following files: