File indexing completed on 2024-06-09 04:21:59

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_LAZY_FILL_CAPACITY_MAP_H
0008 #define __KIS_LAZY_FILL_CAPACITY_MAP_H
0009 
0010 #include <KoColorSpace.h>
0011 
0012 #include "kis_lazy_fill_graph.h"
0013 #include "kis_paint_device.h"
0014 #include "kis_types.h"
0015 #include "kis_painter.h"
0016 #include "kis_random_accessor_ng.h"
0017 #include "kis_global.h"
0018 #include <KisRegion.h>
0019 
0020 
0021 class KisLazyFillCapacityMap
0022 {
0023     typedef KisLazyFillCapacityMap type;
0024     typedef typename boost::graph_traits<KisLazyFillGraph>::vertex_descriptor VertexDescriptor;
0025     typedef typename boost::graph_traits<KisLazyFillGraph>::edge_descriptor EdgeDescriptor;
0026 
0027 public:
0028     typedef EdgeDescriptor key_type;
0029     typedef int value_type;
0030     typedef const int& reference;
0031     typedef boost::readable_property_map_tag category;
0032 
0033     KisLazyFillCapacityMap(KisPaintDeviceSP mainImage,
0034                            KisPaintDeviceSP aLabelImage,
0035                            KisPaintDeviceSP bLabelImage,
0036                            KisPaintDeviceSP maskImage,
0037                            const QRect &boundingRect)
0038         : m_mainImage(mainImage),
0039           m_aLabelImage(aLabelImage),
0040           m_bLabelImage(bLabelImage),
0041           m_maskImage(maskImage),
0042           m_mainRect(boundingRect),
0043           m_aLabelRect(m_aLabelImage->exactBounds() & boundingRect),
0044           m_bLabelRect(m_bLabelImage->exactBounds() & boundingRect),
0045           m_colorSpace(mainImage->colorSpace()),
0046           m_pixelSize(m_colorSpace->pixelSize()),
0047           m_graph(m_mainRect,
0048                   m_aLabelImage->regionExact() & boundingRect,
0049                   m_bLabelImage->regionExact() & boundingRect)
0050     {
0051         KIS_ASSERT_RECOVER_NOOP(m_mainImage->colorSpace()->pixelSize() == 1);
0052         KIS_ASSERT_RECOVER_NOOP(m_aLabelImage->colorSpace()->pixelSize() == 1);
0053         KIS_ASSERT_RECOVER_NOOP(m_bLabelImage->colorSpace()->pixelSize() == 1);
0054 
0055         m_mainAccessor = m_mainImage->createRandomConstAccessorNG();
0056         m_aAccessor = m_aLabelImage->createRandomConstAccessorNG();
0057         m_bAccessor = m_bLabelImage->createRandomConstAccessorNG();
0058         m_maskAccessor = m_maskImage->createRandomConstAccessorNG();
0059         m_srcPixelBuf.resize(m_pixelSize);
0060     }
0061 
0062     int maxCapacity() const {
0063         const int k  = 2 * (m_mainRect.width() + m_mainRect.height());
0064         return k + 1;
0065     }
0066 
0067     friend value_type get(type &map,
0068                           const key_type &key)
0069         {
0070             VertexDescriptor src = source(key, map.m_graph);
0071             VertexDescriptor dst = target(key, map.m_graph);
0072 
0073             if (src.type == VertexDescriptor::NORMAL) {
0074                 map.m_maskAccessor->moveTo(src.x, src.y);
0075                 if (*map.m_maskAccessor->rawDataConst()) {
0076                     return 0;
0077                 }
0078             }
0079 
0080             if (dst.type == VertexDescriptor::NORMAL) {
0081                 map.m_maskAccessor->moveTo(dst.x, dst.y);
0082                 if (*map.m_maskAccessor->rawDataConst()) {
0083                     return 0;
0084                 }
0085             }
0086 
0087             bool srcLabelA = src.type == VertexDescriptor::LABEL_A;
0088             bool srcLabelB = src.type == VertexDescriptor::LABEL_B;
0089             bool dstLabelA = dst.type == VertexDescriptor::LABEL_A;
0090             bool dstLabelB = dst.type == VertexDescriptor::LABEL_B;
0091 
0092             if (srcLabelA || srcLabelB) {
0093                 std::swap(src, dst);
0094                 std::swap(srcLabelA, dstLabelA);
0095                 std::swap(srcLabelB, dstLabelB);
0096             }
0097 
0098             Q_ASSERT(!srcLabelA && !srcLabelB);
0099 
0100 
0101             // TODO: precalculate!
0102             const int k  = 2 * (map.m_mainRect.width() + map.m_mainRect.height());
0103 
0104             static const int unitValue = 256;
0105 
0106             qreal value = 0.0;
0107 
0108             if (dstLabelA) {
0109                 map.m_aAccessor->moveTo(src.x, src.y);
0110                 const int i0 = *((quint8*)map.m_aAccessor->rawDataConst());
0111                 value = i0 / 255.0 * k;
0112 
0113             } else if (dstLabelB) {
0114                 map.m_bAccessor->moveTo(src.x, src.y);
0115                 const int i0 = *((quint8*)map.m_bAccessor->rawDataConst());
0116                 value = i0 / 255.0 * k;
0117 
0118             } else {
0119                 map.m_mainAccessor->moveTo(src.x, src.y);
0120                 memcpy(map.m_srcPixelBuf.data(), map.m_mainAccessor->rawDataConst(), map.m_pixelSize);
0121                 map.m_mainAccessor->moveTo(dst.x, dst.y);
0122 
0123                 //const quint8 diff = map.m_colorSpace->differenceA((quint8*)map.m_srcPixelBuf.data(), map.m_mainAccessor->rawDataConst());
0124                 //const quint8 i0 = map.m_colorSpace->intensity8((quint8*)map.m_srcPixelBuf.data());
0125                 //const quint8 i1 = map.m_colorSpace->intensity8(map.m_mainAccessor->rawDataConst());
0126 
0127                 const quint8 i0 = *((quint8*)map.m_srcPixelBuf.data());
0128                 const quint8 i1 = *map.m_mainAccessor->rawDataConst();
0129 
0130                 const quint8 diff = qAbs(i1 - i0);
0131 
0132                 const qreal diffPenalty = qBound(0.0, qreal(diff) / 10.0, 1.0);
0133                 const qreal intensityPenalty = 1.0 - i1 / 255.0;
0134 
0135                 const qreal totalPenalty = qMax(0.0 * diffPenalty, intensityPenalty);
0136 
0137                 value = 1.0 + k * (1.0 - pow2(totalPenalty));
0138             }
0139 
0140             return value * unitValue;
0141         }
0142 
0143     KisLazyFillGraph& graph() {
0144         return m_graph;
0145     }
0146 
0147 private:
0148     KisPaintDeviceSP m_mainImage;
0149     KisPaintDeviceSP m_aLabelImage;
0150     KisPaintDeviceSP m_bLabelImage;
0151     KisPaintDeviceSP m_maskImage;
0152 
0153     QRect m_mainRect;
0154     QRect m_aLabelRect;
0155     QRect m_bLabelRect;
0156 
0157     const KoColorSpace *m_colorSpace;
0158     int m_pixelSize;
0159     KisRandomConstAccessorSP m_mainAccessor;
0160     KisRandomConstAccessorSP m_aAccessor;
0161     KisRandomConstAccessorSP m_bAccessor;
0162     KisRandomConstAccessorSP m_maskAccessor;
0163     QByteArray m_srcPixelBuf;
0164 
0165     KisLazyFillGraph m_graph;
0166 };
0167 
0168 #endif /* __KIS_LAZY_FILL_CAPACITY_MAP_H */