Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_png_brush.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_png_brush.h"
8
9#include <QDomElement>
10#include <QFileInfo>
11#include <QImageReader>
12#include <QByteArray>
13#include <QBuffer>
14#include <QPainter>
15
16#include <kis_dom_utils.h>
17
18KisPngBrush::KisPngBrush(const QString& filename)
19 : KisColorfulBrush(filename)
20{
22 setSpacing(0.25);
23}
24
29
31{
32 return KoResourceSP(new KisPngBrush(*this));
33}
34
35bool KisPngBrush::loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface)
36{
37 Q_UNUSED(resourcesInterface);
38
39 // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice
40 // fails with "libpng error: IDAT: CRC error"
41 QByteArray data = dev->readAll();
42 QBuffer buf(&data);
43 buf.open(QIODevice::ReadOnly);
44 QImageReader reader(&buf, "PNG");
45
46 if (!reader.canRead()) {
47 dbgKrita << "Could not read brush" << filename() << ". Error:" << reader.errorString();
48 setValid(false);
49 return false;
50 }
51
52 if (reader.textKeys().contains("brush_spacing")) {
53 setSpacing(KisDomUtils::toDouble(reader.text("brush_spacing")));
54 }
55
56 if (reader.textKeys().contains("brush_name")) {
57 setName(reader.text("brush_name"));
58 }
59 else {
60 QFileInfo info(filename());
61 setName(info.completeBaseName());
62 }
63
64 QImage image = reader.read();
65
66 if (image.isNull()) {
67 dbgKrita << "Could not create image for" << filename() << ". Error:" << reader.errorString();
68 setValid(false);
69 return false;
70 }
71
72 setValid(true);
73
74 bool hasAlpha = false;
75 for (int y = 0; y < image.height(); y++) {
76 for (int x = 0; x < image.width(); x++) {
77 if (qAlpha(image.pixel(x, y)) != 255) {
78 hasAlpha = true;
79 break;
80 }
81 }
82 }
83
84 const bool isAllGray = image.allGray();
85
86 if (isAllGray && !hasAlpha) {
87 // Make sure brush tips all have a white background
88 // NOTE: drawing it over white background can probably be skipped now...
89 // Any images with an Alpha channel should be loaded as RGBA so
90 // they can have the lightness and gradient options available
91 QImage base(image.size(), image.format());
92 if ((int)base.format() < (int)QImage::Format_RGB32) {
93 base.convertTo(QImage::Format_ARGB32);
94 }
95 QPainter gc(&base);
96 gc.fillRect(base.rect(), Qt::white);
97 gc.drawImage(0, 0, image);
98 gc.end();
99 QImage converted = base.convertToFormat(QImage::Format_Grayscale8);
100 setBrushTipImage(converted);
104 }
105 else {
106 // see bug https://bugs.kde.org/show_bug.cgi?id=484115 if you want to edit this condition
107 // keep it in sync with KisColorfulBrush code
108 if ((int)image.format() != (int)QImage::Format_ARGB32) {
109 image.convertTo(QImage::Format_ARGB32);
110 }
111
115 setHasColorAndTransparency(!isAllGray);
116 }
117
118
121
122 return valid();
123}
124
125bool KisPngBrush::saveToDevice(QIODevice *dev) const
126{
127 return brushTipImage().save(dev, "PNG");
128}
129
131{
132 return QString(".png");
133}
134
135void KisPngBrush::toXML(QDomDocument& d, QDomElement& e) const
136{
137 predefinedBrushToXML("png_brush", e);
139}
virtual void setSpacing(double spacing)
qint32 width() const
virtual void setBrushType(enumBrushType type)
void predefinedBrushToXML(const QString &type, QDomElement &e) const
Private *const d
Definition kis_brush.h:387
virtual void setBrushTipImage(const QImage &image)
void setWidth(qint32 width)
qint32 height() const
void setHeight(qint32 height)
virtual void setBrushApplication(enumBrushApplication brushApplication)
QImage brushTipImage() const override
brushImage the image the brush tip can paint with. Not all brush types have a single image.
void setHasColorAndTransparency(bool value)
void toXML(QDomDocument &d, QDomElement &e) const override
bool loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) override
QString defaultFileExtension() const override
void toXML(QDomDocument &d, QDomElement &e) const override
bool saveToDevice(QIODevice *dev) const override
KoResourceSP clone() const override
KisPngBrush(const QString &filename)
Construct brush to load filename later as brush.
@ IMAGE
Definition kis_brush.h:33
@ MASK
Definition kis_brush.h:32
@ INVALID
Definition kis_brush.h:31
@ ALPHAMASK
Definition kis_brush.h:39
@ LIGHTNESSMAP
Definition kis_brush.h:41
#define dbgKrita
Definition kis_debug.h:45
QSharedPointer< KoResource > KoResourceSP
double toDouble(const QString &str, bool *ok=nullptr)
void setValid(bool valid)
void setName(const QString &name)
QImage image
QString filename