Commit 59a2e1f3 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Replace our own ppm filter with the qimageio filter

BUG:409714

This means we no longer load 16 bit ppm files, but that should
be fixed in a next commit, since QImage supports 16 bit these
days.
parent 4f769aa4
......@@ -349,7 +349,6 @@ set(kritaui_LIB_SRCS
KisCloneDocumentStroke.cpp
kis_node_view_color_scheme.cpp
KisImportExportFilter.cpp
KisFilterEntry.cpp
KisImportExportManager.cpp
KisImportExportUtils.cpp
kis_async_action_feedback.cpp
......
/* This file is part of the KDE project
Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
Copyright 2007 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "KisFilterEntry.h"
#include "KisDocument.h"
#include "KisImportExportFilter.h"
#include <kis_debug.h>
#include <KoJsonTrader.h>
#include <kpluginfactory.h>
#include <QFile>
#include <limits.h> // UINT_MAX
KisFilterEntry::KisFilterEntry(QPluginLoader *loader)
: KisShared()
, m_loader(loader)
{
import = loader->metaData().value("MetaData").toObject().value("X-KDE-Import").toString().split(',');
export_ = loader->metaData().value("MetaData").toObject().value("X-KDE-Export").toString().split(',');
int w = loader->metaData().value("MetaData").toObject().value("X-KDE-Weight").toString().toInt();
weight = w < 0 ? UINT_MAX : static_cast<unsigned int>(w);
available = loader->metaData().value("MetaData").toObject().value("X-KDE-Available").toString();
}
KisFilterEntry::~KisFilterEntry()
{
delete m_loader;
}
QList<KisFilterEntrySP> KisFilterEntry::query()
{
QList<KisFilterEntrySP> lst;
QList<QPluginLoader *> offers = KoJsonTrader::instance()->query("Krita/FileFilter", QString());
unsigned int max = offers.count();
dbgFile <<"Query returned" << max <<" offers";
Q_FOREACH(QPluginLoader *pluginLoader, offers) {
//dbgFile <<" desktopEntryPath=" << (*it)->entryPath()
// << " library=" << (*it)->library() << endl;
// Append converted offer
lst.append(KisFilterEntrySP(new KisFilterEntry(pluginLoader)));
}
return lst;
}
KisImportExportFilter* KisFilterEntry::createFilter()
{
KLibFactory *factory = qobject_cast<KLibFactory *>(m_loader->instance());
if (!factory) {
warnUI << m_loader->errorString();
return 0;
}
QObject *obj = factory->create<KisImportExportFilter>(0);
if (!obj || !obj->inherits("KisImportExportFilter")) {
delete obj;
return 0;
}
KisImportExportFilter* filter = static_cast<KisImportExportFilter*>(obj);
return filter;
}
/* This file is part of the KDE project
Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
Copyright 2007 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KIS_FILTER_ENTRY_H
#define KIS_FILTER_ENTRY_H
#include <QList>
#include <QStringList>
#include "kis_types.h"
#include "kis_shared.h"
#include "kis_shared_ptr.h"
#include "kritaui_export.h"
class QObject;
class QPluginLoader;
class KisImportExportFilter;
class KisFilterEntry;
typedef KisSharedPtr<KisFilterEntry> KisFilterEntrySP;
/**
* Represents an available filter.
*/
class KRITAUI_EXPORT KisFilterEntry : public KisShared
{
public:
//KisFilterEntry() : weight( 0 ) { m_service = 0; } // for QList
explicit KisFilterEntry(QPluginLoader *loader);
~KisFilterEntry();
KisImportExportFilter *createFilter();
/**
* The imported mimetype(s).
*/
QStringList import;
/**
* The exported mimetype(s).
*/
QStringList export_;
/**
* The "weight" of this filter path. Has to be > 0 to be valid.
*/
unsigned int weight;
/**
* Do we have to check during runtime?
*/
QString available;
/**
* @return TRUE if the filter can import the requested mimetype.
*/
bool imports(const QString& _mimetype) const {
return (import.contains(_mimetype));
}
/**
* @return TRUE if the filter can export the requested mimetype.
*/
bool exports(const QString& _m) const {
return (export_.contains(_m));
}
/**
* This function will query KDED to find all available filters.
*/
static QList<KisFilterEntrySP> query();
QPluginLoader *loader() const {
return m_loader;
}
private:
QPluginLoader *m_loader;
};
#endif
......@@ -34,7 +34,6 @@ endif()
add_subdirectory(svg)
add_subdirectory(qimageio)
add_subdirectory(ora)
add_subdirectory(ppm)
add_subdirectory(xcf)
add_subdirectory(psd)
add_subdirectory(qml)
......
add_subdirectory(tests)
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
set(kritappmimport_SOURCES
kis_ppm_import.cpp
)
add_library(kritappmimport MODULE ${kritappmimport_SOURCES})
target_link_libraries(kritappmimport kritaui )
install(TARGETS kritappmimport DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
set(kritappmexport_SOURCES
kis_ppm_export.cpp
)
ki18n_wrap_ui(kritappmexport_SOURCES kis_wdg_options_ppm.ui )
add_library(kritappmexport MODULE ${kritappmexport_SOURCES})
target_link_libraries(kritappmexport kritaui kritaimpex)
install(TARGETS kritappmexport DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
install( PROGRAMS krita_ppm.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
/*
* Copyright (c) 2009 Cyrille Berger <cberger@cberger.net>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kis_ppm_export.h"
#include <kpluginfactory.h>
#include <KoColorSpace.h>
#include <KoColorSpaceConstants.h>
#include <KisImportExportManager.h>
#include <KisExportCheckRegistry.h>
#include <kis_debug.h>
#include <KisDocument.h>
#include <kis_image.h>
#include <kis_paint_device.h>
#include <kis_properties_configuration.h>
#include <kis_config.h>
#include <qendian.h>
#include <KoColorSpaceTraits.h>
#include <KoColorSpaceRegistry.h>
#include <KoColorModelStandardIds.h>
#include "kis_iterator_ng.h"
#include <QApplication>
K_PLUGIN_FACTORY_WITH_JSON(KisPPMExportFactory, "krita_ppm_export.json", registerPlugin<KisPPMExport>();)
KisPPMExport::KisPPMExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
{
}
KisPPMExport::~KisPPMExport()
{
}
class KisPPMFlow
{
public:
KisPPMFlow() {
}
virtual ~KisPPMFlow() {
}
virtual void writeBool(quint8 v) = 0;
virtual void writeBool(quint16 v) = 0;
virtual void writeNumber(quint8 v) = 0;
virtual void writeNumber(quint16 v) = 0;
virtual void flush() = 0;
private:
};
class KisPPMAsciiFlow : public KisPPMFlow
{
public:
KisPPMAsciiFlow(QIODevice* device) : m_device(device) {
}
~KisPPMAsciiFlow() override {
}
void writeBool(quint8 v) override {
if (v > 127) {
m_device->write("1 ");
} else {
m_device->write("0 ");
}
}
void writeBool(quint16 v) override {
writeBool(quint8(v >> 8));
}
void writeNumber(quint8 v) override {
m_device->write(QByteArray::number(v));
m_device->write(" ");
}
void writeNumber(quint16 v) override {
m_device->write(QByteArray::number(v));
m_device->write(" ");
}
void flush() override {
}
private:
QIODevice* m_device;
};
class KisPPMBinaryFlow : public KisPPMFlow
{
public:
KisPPMBinaryFlow(QIODevice* device) : m_device(device), m_pos(0), m_current(0) {
}
~KisPPMBinaryFlow() override {
}
void writeBool(quint8 v) override {
m_current = m_current << 1;
m_current |= (v > 127);
++m_pos;
if (m_pos >= 8) {
m_current = 0;
m_pos = 0;
flush();
}
}
void writeBool(quint16 v) override {
writeBool(quint8(v >> 8));
}
void writeNumber(quint8 v) override {
m_device->write((char*)&v, 1);
}
void writeNumber(quint16 v) override {
quint16 vo = qToBigEndian(v);
m_device->write((char*)&vo, 2);
}
void flush() override {
m_device->write((char*)&m_current, 1);
}
private:
QIODevice* m_device;
int m_pos;
quint8 m_current;
};
KisImportExportErrorCode KisPPMExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration)
{
bool rgb = (mimeType() == "image/x-portable-pixmap");
bool binary = (configuration->getInt("type") == 0);
bool bitmap = (mimeType() == "image/x-portable-bitmap");
KisImageSP image = document->savingImage();
KisPaintDeviceSP pd = new KisPaintDevice(*image->projection());
// Test color space
if (((rgb && (pd->colorSpace()->id() != "RGBA" && pd->colorSpace()->id() != "RGBA16"))
|| (!rgb && (pd->colorSpace()->id() != "GRAYA" && pd->colorSpace()->id() != "GRAYA16" && pd->colorSpace()->id() != "GRAYAU16")))) {
if (rgb) {
pd->convertTo(KoColorSpaceRegistry::instance()->rgb8(0), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
}
else {
pd->convertTo(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), 0), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
}
}
bool is16bit = pd->colorSpace()->id() == "RGBA16" || pd->colorSpace()->id() == "GRAYAU16";
// Write the magic
QString toWrite = "";
int written = 0;
if (rgb) {
if (binary) {
toWrite = "P6";
}
else {
toWrite = "P3";
}
} else if (bitmap) {
if (binary) {
toWrite = "P4";
}
else {
toWrite = "P1";
}
} else {
if (binary) {
toWrite = "P5";
}
else {
toWrite = "P2";
}
}
written = io->write(toWrite.toUtf8());
if (written != toWrite.toUtf8().length()) {
return ImportExportCodes::ErrorWhileWriting;
}
written = io->write("\n");
// Write the header
QByteArray width = QByteArray::number(image->width());
QByteArray height = QByteArray::number(image->height());
written += io->write(width);
written += io->write(" ");
written += io->write(height);
if (written != QString(" ").length() + QString("\n").length() + width.length() + height.length()) {
return ImportExportCodes::ErrorWhileWriting;
}
if (!bitmap) {
if (is16bit) {
toWrite = " 65535\n";
}
else {
toWrite = " 255\n";
}
} else {
toWrite = "\n";
}
written = io->write(toWrite.toUtf8());
if (written != toWrite.toUtf8().length()) {
return ImportExportCodes::ErrorWhileWriting;
}
// Write the data
KisPPMFlow* flow = 0;
if (binary) flow = new KisPPMBinaryFlow(io);
else flow = new KisPPMAsciiFlow(io);
for (int y = 0; y < image->height(); ++y) {
KisHLineIteratorSP it = pd->createHLineIteratorNG(0, y, image->width());
if (is16bit) {
if (rgb) {
do {
flow->writeNumber(KoBgrU16Traits::red(it->rawData()));
flow->writeNumber(KoBgrU16Traits::green(it->rawData()));
flow->writeNumber(KoBgrU16Traits::blue(it->rawData()));
} while (it->nextPixel());
} else if (bitmap) {
do {
flow->writeBool(*reinterpret_cast<quint16*>(it->rawData()));
} while (it->nextPixel());
} else {
do {
flow->writeNumber(*reinterpret_cast<quint16*>(it->rawData()));
} while (it->nextPixel());
}
} else {
if (rgb) {
do {
flow->writeNumber(KoBgrTraits<quint8>::red(it->rawData()));
flow->writeNumber(KoBgrTraits<quint8>::green(it->rawData()));
flow->writeNumber(KoBgrTraits<quint8>::blue(it->rawData()));
} while (it->nextPixel());
} else if (bitmap) {
do {
flow->writeBool(*reinterpret_cast<quint8*>(it->rawData()));
} while (it->nextPixel());
} else {
do {
flow->writeNumber(*reinterpret_cast<quint8*>(it->rawData()));
} while (it->nextPixel());
}
}
}
if (bitmap) {
flow->flush();
}
delete flow;
return ImportExportCodes::OK;
}
KisPropertiesConfigurationSP KisPPMExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const
{
KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration();
cfg->setProperty("type", 0);
return cfg;
}
KisConfigWidget *KisPPMExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &/*to*/) const
{
return new KisWdgOptionsPPM(parent);
}
void KisWdgOptionsPPM::setConfiguration(const KisPropertiesConfigurationSP cfg)
{
cmbType->setCurrentIndex(cfg->getInt("type", 0));
}
KisPropertiesConfigurationSP KisWdgOptionsPPM::configuration() const
{
KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration();
cfg->setProperty("type", cmbType->currentIndex());
return cfg;
}
void KisPPMExport::initializeCapabilities()
{
addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + RGBAColorModelID.id() + "/" + Integer8BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED));
addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + RGBAColorModelID.id() + "/" + Integer16BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED));
addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + GrayAColorModelID.id() + "/" + Integer8BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED));
addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + GrayAColorModelID.id() + "/" + Integer16BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED));
QList<QPair<KoID, KoID> > supportedColorModels;
supportedColorModels << QPair<KoID, KoID>()
<< QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID)
<< QPair<KoID, KoID>(RGBAColorModelID, Integer16BitsColorDepthID)
<< QPair<KoID, KoID>(GrayAColorModelID, Integer8BitsColorDepthID)
<< QPair<KoID, KoID>(GrayAColorModelID, Integer16BitsColorDepthID);
addSupportedColorModels(supportedColorModels, "PPM");
}
#include "kis_ppm_export.moc"
/*
* Copyright (c) 2009 Cyrille Berger <cberger@cberger.net>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _KIS_PPM_EXPORT_H_
#define _KIS_PPM_EXPORT_H_
#include <QVariant>
#include <KisImportExportFilter.h>
#include <kis_config_widget.h>
#include "ui_kis_wdg_options_ppm.h"
class KisWdgOptionsPPM : public KisConfigWidget, public Ui::WdgOptionsPPM
{
Q_OBJECT
public:
KisWdgOptionsPPM(QWidget *parent)
: KisConfigWidget(parent)
{
setupUi(this);
}
void setConfiguration(const KisPropertiesConfigurationSP cfg) override;
KisPropertiesConfigurationSP configuration() const override;
};
class KisPPMExport : public KisImportExportFilter
{
Q_OBJECT
public:
KisPPMExport(QObject *parent, const QVariantList &);
~KisPPMExport() override;
public:
KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override;
KisPropertiesConfigurationSP defaultConfiguration(const QByteArray& from = "", const QByteArray& to = "") const override;
KisConfigWidget *createConfigurationWidget(QWidget *parent, const QByteArray& from = "", const QByteArray& to = "") const override;
void initializeCapabilities() override;
};
#endif
/*
* Copyright (c) 2009 Cyrille Berger <cberger@cberger.net>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kis_ppm_import.h"
#include <ctype.h>
#include <QApplication>
#include <QFile>
#include <kpluginfactory.h>
#include <QFileInfo>
#include <KoColorSpaceRegistry.h>
#include <kis_debug.h>
#include <KisDocument.h>
#include <kis_group_layer.h>
#include <kis_image.h>
#include <kis_paint_layer.h>
#include <KoColorSpaceTraits.h>
#include <kis_paint_device.h>
#include <kis_transaction.h>
#include <KoColorSpace.h>
#include <qendian.h>
#include <KoColorModelStandardIds.h>
#include "kis_iterator_ng.h"
K_PLUGIN_FACTORY_WITH_JSON(PPMImportFactory, "krita_ppm_import.json", registerPlugin<KisPPMImport>();)
KisPPMImport::KisPPMImport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
{
}
KisPPMImport::~KisPPMImport()
{
}
int readNumber(QIODevice* device)
{
char c;
int val = 0;
while (true) {
if (!device->getChar(&c)) break; // End of the file
if (isdigit(c)) {
val = 10 * val + c - '0';
} else if (c == '#') {
device->readLine();
break;
} else if (isspace((uchar) c)) {
break;
}
}
return val;
}
class KisPpmFlow
{
public:
KisPpmFlow() {
}
virtual ~KisPpmFlow() {
}
virtual void nextRow() = 0;
virtual bool valid() = 0;
virtual bool nextUint1() = 0;
virtual quint8 nextUint8() = 0;
virtual quint16 nextUint16() = 0;
};
class KisAsciiPpmFlow : public KisPpmFlow
{
public:
KisAsciiPpmFlow(QIODevice* device) : m_device(device) {
}
~KisAsciiPpmFlow() override {