File indexing completed on 2025-01-26 04:10:56
0001 /* 0002 * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_jpeg_export.h" 0008 0009 #include <QCheckBox> 0010 #include <QSlider> 0011 #include <QColor> 0012 #include <QString> 0013 #include <QStringList> 0014 #include <QApplication> 0015 #include <QFileInfo> 0016 #include <QScopedPointer> 0017 0018 #include <kpluginfactory.h> 0019 0020 #include <KoColorSpace.h> 0021 #include <KoColorProfile.h> 0022 #include <KoColorSpaceConstants.h> 0023 #include <KoColorSpaceRegistry.h> 0024 0025 #include <KisImportExportManager.h> 0026 #include <kis_slider_spin_box.h> 0027 #include <KisDocument.h> 0028 #include <KoDocumentInfo.h> 0029 #include <kis_image.h> 0030 #include <kis_group_layer.h> 0031 #include <kis_paint_layer.h> 0032 #include <kis_paint_device.h> 0033 #include <kis_properties_configuration.h> 0034 #include <kis_config.h> 0035 #include <kis_meta_data_store.h> 0036 #include <kis_meta_data_entry.h> 0037 #include <kis_meta_data_value.h> 0038 #include <kis_meta_data_schema.h> 0039 #include <kis_meta_data_schema_registry.h> 0040 #include <kis_meta_data_filter_registry_model.h> 0041 #include <kis_exif_info_visitor.h> 0042 #include <generator/kis_generator_layer.h> 0043 #include <KisExportCheckRegistry.h> 0044 #include <KisSpinBoxI18nHelper.h> 0045 #include "kis_jpeg_converter.h" 0046 0047 class KisExternalLayer; 0048 0049 K_PLUGIN_FACTORY_WITH_JSON(KisJPEGExportFactory, "krita_jpeg_export.json", registerPlugin<KisJPEGExport>();) 0050 0051 KisJPEGExport::KisJPEGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) 0052 { 0053 } 0054 0055 KisJPEGExport::~KisJPEGExport() 0056 { 0057 } 0058 0059 KisImportExportErrorCode KisJPEGExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) 0060 { 0061 KisImageSP image = document->savingImage(); 0062 Q_CHECK_PTR(image); 0063 0064 // An extra option to pass to the config widget to set the state correctly, this isn't saved 0065 const KoColorSpace* cs = image->projection()->colorSpace(); 0066 bool sRGB = cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive); 0067 configuration->setProperty("is_sRGB", sRGB); 0068 0069 KisJPEGOptions options; 0070 options.progressive = configuration->getBool("progressive", false); 0071 options.quality = configuration->getInt("quality", 80); 0072 options.forceSRGB = configuration->getBool("forceSRGB", false); 0073 options.saveProfile = configuration->getBool("saveProfile", true); 0074 options.optimize = configuration->getBool("optimize", true); 0075 options.smooth = configuration->getInt("smoothing", 0); 0076 options.baseLineJPEG = configuration->getBool("baseline", true); 0077 options.subsampling = configuration->getInt("subsampling", 0); 0078 options.exif = configuration->getBool("exif", true); 0079 options.iptc = configuration->getBool("iptc", true); 0080 options.xmp = configuration->getBool("xmp", true); 0081 KoColor c(KoColorSpaceRegistry::instance()->rgb8()); 0082 c.fromQColor(Qt::white); 0083 options.transparencyFillColor = configuration->getColor("transparencyFillcolor", c).toQColor(); 0084 KisMetaData::FilterRegistryModel m; 0085 m.setEnabledFilters(configuration->getString("filters").split(",")); 0086 options.filters = m.enabledFilters(); 0087 options.storeAuthor = configuration->getBool("storeAuthor", false); 0088 options.storeDocumentMetaData = configuration->getBool("storeMetaData", false); 0089 0090 KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); 0091 0092 KisJPEGConverter kpc(document, batchMode()); 0093 KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); 0094 0095 KisExifInfoVisitor exivInfoVisitor; 0096 exivInfoVisitor.visit(image->rootLayer().data()); 0097 0098 QScopedPointer<KisMetaData::Store> metaDataStore; 0099 if (exivInfoVisitor.metaDataCount() == 1) { 0100 metaDataStore.reset(new KisMetaData::Store(*exivInfoVisitor.exifInfo())); 0101 } 0102 else { 0103 metaDataStore.reset(new KisMetaData::Store()); 0104 } 0105 0106 //add extra meta-data here 0107 const KisMetaData::Schema* dcSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::DublinCoreSchemaUri); 0108 Q_ASSERT(dcSchema); 0109 if (options.storeDocumentMetaData) { 0110 QString title = document->documentInfo()->aboutInfo("title"); 0111 if (!title.isEmpty()) { 0112 if (metaDataStore->containsEntry("title")) { 0113 metaDataStore->removeEntry("title"); 0114 } 0115 metaDataStore->addEntry(KisMetaData::Entry(dcSchema, "title", KisMetaData::Value(QVariant(title)))); 0116 } 0117 QString description = document->documentInfo()->aboutInfo("subject"); 0118 if (description.isEmpty()) { 0119 description = document->documentInfo()->aboutInfo("abstract"); 0120 } 0121 if (!description.isEmpty()) { 0122 QString keywords = document->documentInfo()->aboutInfo("keyword"); 0123 if (!keywords.isEmpty()) { 0124 description = description + " keywords: " + keywords; 0125 } 0126 if (metaDataStore->containsEntry("description")) { 0127 metaDataStore->removeEntry("description"); 0128 } 0129 metaDataStore->addEntry(KisMetaData::Entry(dcSchema, "description", KisMetaData::Value(QVariant(description)))); 0130 } 0131 QString license = document->documentInfo()->aboutInfo("license"); 0132 if (!license.isEmpty()) { 0133 if (metaDataStore->containsEntry("rights")) { 0134 metaDataStore->removeEntry("rights"); 0135 } 0136 metaDataStore->addEntry(KisMetaData::Entry(dcSchema, "rights", KisMetaData::Value(QVariant(license)))); 0137 } 0138 QString date = document->documentInfo()->aboutInfo("date"); 0139 if (!date.isEmpty() && !metaDataStore->containsEntry("rights")) { 0140 metaDataStore->addEntry(KisMetaData::Entry(dcSchema, "date", KisMetaData::Value(QVariant(date)))); 0141 } 0142 } 0143 if (options.storeAuthor) { 0144 QString author = document->documentInfo()->authorInfo("creator"); 0145 if (!author.isEmpty()) { 0146 if (!document->documentInfo()->authorContactInfo().isEmpty()) { 0147 QString contact = document->documentInfo()->authorContactInfo().at(0); 0148 if (!contact.isEmpty()) { 0149 author = author+"("+contact+")"; 0150 } 0151 } 0152 if (metaDataStore->containsEntry("creator")) { 0153 metaDataStore->removeEntry("creator"); 0154 } 0155 metaDataStore->addEntry(KisMetaData::Entry(dcSchema, "creator", KisMetaData::Value(QVariant(author)))); 0156 } 0157 } 0158 0159 KisImportExportErrorCode res = kpc.buildFile(io, l, options, metaDataStore.data()); 0160 return res; 0161 } 0162 0163 KisPropertiesConfigurationSP KisJPEGExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const 0164 { 0165 KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); 0166 cfg->setProperty("progressive", false); 0167 cfg->setProperty("quality", 80); 0168 cfg->setProperty("forceSRGB", false); 0169 cfg->setProperty("saveProfile", true); 0170 cfg->setProperty("optimize", true); 0171 cfg->setProperty("smoothing", 0); 0172 cfg->setProperty("baseline", true); 0173 cfg->setProperty("subsampling", 0); 0174 cfg->setProperty("exif", true); 0175 cfg->setProperty("iptc", true); 0176 cfg->setProperty("xmp", true); 0177 cfg->setProperty("storeAuthor", false); 0178 cfg->setProperty("storeMetaData", false); 0179 0180 KoColor fill_color(KoColorSpaceRegistry::instance()->rgb8()); 0181 fill_color = KoColor(); 0182 fill_color.fromQColor(Qt::white); 0183 QVariant v; 0184 v.setValue(fill_color); 0185 0186 cfg->setProperty("transparencyFillcolor", v); 0187 cfg->setProperty("filters", ""); 0188 0189 return cfg; 0190 } 0191 0192 KisConfigWidget *KisJPEGExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &/*to*/) const 0193 { 0194 return new KisWdgOptionsJPEG(parent); 0195 } 0196 0197 void KisJPEGExport::initializeCapabilities() 0198 { 0199 addCapability(KisExportCheckRegistry::instance()->get("sRGBProfileCheck")->create(KisExportCheckBase::SUPPORTED)); 0200 addCapability(KisExportCheckRegistry::instance()->get("ExifCheck")->create(KisExportCheckBase::SUPPORTED)); 0201 0202 QList<QPair<KoID, KoID> > supportedColorModels; 0203 supportedColorModels << QPair<KoID, KoID>() 0204 << QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID) 0205 << QPair<KoID, KoID>(GrayAColorModelID, Integer8BitsColorDepthID) 0206 << QPair<KoID, KoID>(CMYKAColorModelID, Integer8BitsColorDepthID); 0207 addSupportedColorModels(supportedColorModels, "JPEG"); 0208 } 0209 0210 0211 KisWdgOptionsJPEG::KisWdgOptionsJPEG(QWidget *parent) 0212 : KisConfigWidget(parent) 0213 { 0214 setupUi(this); 0215 0216 metaDataFilters->setModel(&m_filterRegistryModel); 0217 qualityLevel->setRange(0, 100, 0); 0218 KisSpinBoxI18nHelper::setText(qualityLevel, i18nc("{n} is the number value, % is the percent sign", "{n}%")); 0219 smoothLevel->setRange(0, 100, 0); 0220 KisSpinBoxI18nHelper::setText(smoothLevel, i18nc("{n} is the number value, % is the percent sign", "{n}%")); 0221 } 0222 0223 0224 void KisWdgOptionsJPEG::setConfiguration(const KisPropertiesConfigurationSP cfg) 0225 { 0226 progressive->setChecked(cfg->getBool("progressive", false)); 0227 qualityLevel->setValue(cfg->getInt("quality", 80)); 0228 optimize->setChecked(cfg->getBool("optimize", true)); 0229 smoothLevel->setValue(cfg->getInt("smoothing", 0)); 0230 baseLineJPEG->setChecked(cfg->getBool("baseline", true)); 0231 subsampling->setCurrentIndex(cfg->getInt("subsampling", 0)); 0232 exif->setChecked(cfg->getBool("exif", true)); 0233 iptc->setChecked(cfg->getBool("iptc", true)); 0234 xmp->setChecked(cfg->getBool("xmp", true)); 0235 chkForceSRGB->setVisible(cfg->getBool("is_sRGB")); 0236 chkForceSRGB->setChecked(cfg->getBool("forceSRGB", false)); 0237 chkSaveProfile->setChecked(cfg->getBool("saveProfile", true)); 0238 KoColor background(KoColorSpaceRegistry::instance()->rgb8()); 0239 background.fromQColor(Qt::white); 0240 bnTransparencyFillColor->setDefaultColor(background); 0241 bnTransparencyFillColor->setColor(cfg->getColor("transparencyFillcolor", background)); 0242 chkAuthor->setChecked(cfg->getBool("storeAuthor", false)); 0243 chkMetaData->setChecked(cfg->getBool("storeMetaData", false)); 0244 0245 m_filterRegistryModel.setEnabledFilters(cfg->getString("filters").split(',')); 0246 0247 } 0248 0249 KisPropertiesConfigurationSP KisWdgOptionsJPEG::configuration() const 0250 { 0251 KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); 0252 0253 QVariant transparencyFillcolor; 0254 transparencyFillcolor.setValue(bnTransparencyFillColor->color()); 0255 0256 cfg->setProperty("progressive", progressive->isChecked()); 0257 cfg->setProperty("quality", (int)qualityLevel->value()); 0258 cfg->setProperty("forceSRGB", chkForceSRGB->isChecked()); 0259 cfg->setProperty("saveProfile", chkSaveProfile->isChecked()); 0260 cfg->setProperty("optimize", optimize->isChecked()); 0261 cfg->setProperty("smoothing", (int)smoothLevel->value()); 0262 cfg->setProperty("baseline", baseLineJPEG->isChecked()); 0263 cfg->setProperty("subsampling", subsampling->currentIndex()); 0264 cfg->setProperty("exif", exif->isChecked()); 0265 cfg->setProperty("iptc", iptc->isChecked()); 0266 cfg->setProperty("xmp", xmp->isChecked()); 0267 cfg->setProperty("transparencyFillcolor", transparencyFillcolor); 0268 cfg->setProperty("storeAuthor", chkAuthor->isChecked()); 0269 cfg->setProperty("storeMetaData", chkMetaData->isChecked()); 0270 0271 QString enabledFilters; 0272 Q_FOREACH (const KisMetaData::Filter* filter, m_filterRegistryModel.enabledFilters()) { 0273 enabledFilters = enabledFilters + filter->id() + ','; 0274 } 0275 cfg->setProperty("filters", enabledFilters); 0276 0277 return cfg; 0278 } 0279 #include <kis_jpeg_export.moc>