File indexing completed on 2024-05-12 15:56:11
0001 /* 0002 * SPDX-FileCopyrightText: 2010 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_png_brush.h" 0008 0009 #include <QDomElement> 0010 #include <QFileInfo> 0011 #include <QImageReader> 0012 #include <QByteArray> 0013 #include <QBuffer> 0014 #include <QPainter> 0015 0016 #include <kis_dom_utils.h> 0017 0018 KisPngBrush::KisPngBrush(const QString& filename) 0019 : KisColorfulBrush(filename) 0020 { 0021 setBrushType(INVALID); 0022 setSpacing(0.25); 0023 } 0024 0025 KisPngBrush::KisPngBrush(const KisPngBrush &rhs) 0026 : KisColorfulBrush(rhs) 0027 { 0028 } 0029 0030 KoResourceSP KisPngBrush::clone() const 0031 { 0032 return KoResourceSP(new KisPngBrush(*this)); 0033 } 0034 0035 bool KisPngBrush::loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) 0036 { 0037 Q_UNUSED(resourcesInterface); 0038 0039 // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice 0040 // fails with "libpng error: IDAT: CRC error" 0041 QByteArray data = dev->readAll(); 0042 QBuffer buf(&data); 0043 buf.open(QIODevice::ReadOnly); 0044 QImageReader reader(&buf, "PNG"); 0045 0046 if (!reader.canRead()) { 0047 dbgKrita << "Could not read brush" << filename() << ". Error:" << reader.errorString(); 0048 setValid(false); 0049 return false; 0050 } 0051 0052 if (reader.textKeys().contains("brush_spacing")) { 0053 setSpacing(KisDomUtils::toDouble(reader.text("brush_spacing"))); 0054 } 0055 0056 if (reader.textKeys().contains("brush_name")) { 0057 setName(reader.text("brush_name")); 0058 } 0059 else { 0060 QFileInfo info(filename()); 0061 setName(info.completeBaseName()); 0062 } 0063 0064 QImage image = reader.read(); 0065 0066 if (image.isNull()) { 0067 dbgKrita << "Could not create image for" << filename() << ". Error:" << reader.errorString(); 0068 setValid(false); 0069 return false; 0070 } 0071 0072 setValid(true); 0073 0074 bool hasAlpha = false; 0075 for (int y = 0; y < image.height(); y++) { 0076 for (int x = 0; x < image.width(); x++) { 0077 if (qAlpha(image.pixel(x, y)) != 255) { 0078 hasAlpha = true; 0079 break; 0080 } 0081 } 0082 } 0083 0084 const bool isAllGray = image.allGray(); 0085 0086 if (isAllGray && !hasAlpha) { 0087 // Make sure brush tips all have a white background 0088 // NOTE: drawing it over white background can probably be skipped now... 0089 // Any images with an Alpha channel should be loaded as RGBA so 0090 // they can have the lightness and gradient options available 0091 QImage base(image.size(), image.format()); 0092 if ((int)base.format() < (int)QImage::Format_RGB32) { 0093 base = base.convertToFormat(QImage::Format_ARGB32); 0094 } 0095 QPainter gc(&base); 0096 gc.fillRect(base.rect(), Qt::white); 0097 gc.drawImage(0, 0, image); 0098 gc.end(); 0099 QImage converted = base.convertToFormat(QImage::Format_Grayscale8); 0100 setBrushTipImage(converted); 0101 setBrushType(MASK); 0102 setBrushApplication(ALPHAMASK); 0103 setHasColorAndTransparency(false); 0104 } 0105 else { 0106 if ((int)image.format() < (int)QImage::Format_RGB32) { 0107 image = image.convertToFormat(QImage::Format_ARGB32); 0108 } 0109 0110 setBrushTipImage(image); 0111 setBrushType(IMAGE); 0112 setBrushApplication(isAllGray ? ALPHAMASK : LIGHTNESSMAP); 0113 setHasColorAndTransparency(!isAllGray); 0114 } 0115 0116 setWidth(brushTipImage().width()); 0117 setHeight(brushTipImage().height()); 0118 0119 return valid(); 0120 } 0121 0122 bool KisPngBrush::saveToDevice(QIODevice *dev) const 0123 { 0124 return brushTipImage().save(dev, "PNG"); 0125 } 0126 0127 QString KisPngBrush::defaultFileExtension() const 0128 { 0129 return QString(".png"); 0130 } 0131 0132 void KisPngBrush::toXML(QDomDocument& d, QDomElement& e) const 0133 { 0134 predefinedBrushToXML("png_brush", e); 0135 KisColorfulBrush::toXML(d, e); 0136 }