kimgio: new RAW-specialized plugin

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-10-11 19:38:58 +03:00
parent 73532012e0
commit 7a137a6a9f
7 changed files with 312 additions and 35 deletions

View file

@ -163,6 +163,7 @@ set_package_properties(LibLZMA PROPERTIES
kde4_optional_find_package(ImageMagick COMPONENTS Magick++)
set_package_properties(ImageMagick PROPERTIES
DESCRIPTION "Software suite to create, edit, and compose bitmap images"
URL "https://imagemagick.org/"
PURPOSE "Support for various image formats"
TYPE OPTIONAL
@ -172,6 +173,15 @@ kde4_optional_find_package(WebP)
set_package_properties(WebP PROPERTIES
DESCRIPTION "A new image format for the Web"
URL "https://developers.google.com/speed/webp"
PURPOSE "Support for WebP image format"
TYPE OPTIONAL
)
kde4_optional_find_package(LibRaw)
set_package_properties(LibRaw PROPERTIES
DESCRIPTION "Simple and unified interface for extracting out of RAW files"
URL "https://www.libraw.org/"
PURPOSE "Support for RAW image format"
TYPE OPTIONAL
)

View file

@ -25,6 +25,7 @@
*
* Currently supported formats include:
* @li WEBP \<read\> \<write\>
* @li RAW \<read\>
* @li PGM \<read\>
* @li XBM \<read\>
* @li BMP \<read\>
@ -32,7 +33,6 @@
* @li JPEG \<read\>
* @li JP2 \<read\>
* @li GIF \<read\>
* @li RAW \<read\>
*
* @todo move to kdeui
*/

View file

@ -42,3 +42,24 @@ if(WEBP_FOUND)
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/plugins/imageformats
)
endif(WEBP_FOUND)
##################################
if(LIBRAW_FOUND)
include_directories(${LIBRAW_INCLUDE_DIR})
kde4_add_plugin(kimg_raw raw.cpp)
target_link_libraries(kimg_raw
${KDE4_KDECORE_LIBS}
${QT_QTGUI_LIBRARY}
${LIBRAW_LIBRARIES}
)
set_target_properties(kimg_raw PROPERTIES
COMPILE_FLAGS "${KDE4_ENABLE_EXCEPTIONS}"
OUTPUT_NAME raw
)
install(
TARGETS kimg_raw
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/plugins/imageformats
)
endif(LIBRAW_FOUND)

View file

@ -4,6 +4,7 @@ writing a new handler.
Current formats include:
WEBP <read> <write>
RAW <read>
along with whatever ImageMagick supports but it is assumed that it supports
reading atleast the following formats (even if they cannot be loaded because
@ -16,7 +17,6 @@ ICO <read>
JPEG <read>
JP2 <read>
GIF <read>
RAW <read>
If you want to contribute plugin for image format and there is no solid
C/C++ library for it (like there is for WebP) then it is unlikely it will be

View file

@ -59,24 +59,15 @@ static const struct HeadersTblData {
};
static const qint16 HeadersTblSize = sizeof(HeadersTbl) / sizeof(HeadersTblData);
static QList<std::string> s_blacklist = QList<std::string>()
// borked coders
<< std::string("PDF")
<< std::string("EPDF")
<< std::string("PS")
<< std::string("HTML")
<< std::string("SHTML")
<< std::string("TXT")
<< std::string("VIDEO")
<< std::string("TTF")
// kdelibs provides these
<< std::string("WEBP")
// Katie provides these, SVG coders are very borked
<< std::string("SVG")
<< std::string("SVGZ")
<< std::string("XPM")
<< std::string("PBM")
<< std::string("PPM");
static QList<std::string> s_whitelist = QList<std::string>()
<< std::string("PGM")
<< std::string("XBM")
<< std::string("BMP")
<< std::string("ICO")
<< std::string("JPEG")
<< std::string("JP2")
<< std::string("GIF")
<< std::string("PNG");
int initMagick()
{
@ -97,19 +88,18 @@ int initMagick()
kWarning() << "Exception raised";
}
foreach (const Magick::CoderInfo &magickcoder, magickcoderlist) {
foreach (const std::string &blacklist, s_blacklist) {
if (magickcoder.name() == blacklist) {
kDebug() << "Blacklisting coder" << blacklist.c_str();
try {
magickcoder.unregister();
} catch(Magick::Exception &err) {
kWarning() << err.what();
} catch(std::exception &err) {
kWarning() << err.what();
} catch (...) {
kWarning() << "Exception raised";
}
}
if (s_whitelist.contains(magickcoder.name())) {
continue;
}
try {
kDebug() << "Blacklisting coder" << magickcoder.name().c_str();
magickcoder.unregister();
} catch(Magick::Exception &err) {
kWarning() << err.what();
} catch(std::exception &err) {
kWarning() << err.what();
} catch (...) {
kWarning() << "Exception raised";
}
}
return 0;
@ -267,7 +257,11 @@ bool MagickHandler::canRead(QIODevice *device, QByteArray *actualformat)
);
if (isvalid) {
kDebug() << "Magick format detected" << magickformat;
actualformat->append(magickformat);
if (s_whitelist.contains(std::string(magickformat, qstrlen(magickformat)))) {
actualformat->append(magickformat);
} else {
isvalid = false;
}
}
} catch(Magick::Exception &err) {
kWarning() << err.what();
@ -343,7 +337,6 @@ QList<QByteArray> MagickPlugin::mimeTypes() const
<< "image/x-portable-bitmap"
<< "image/x-portable-graymap"
<< "image/x-portable-pixmap"
<< "image/x-dcraw"
<< "image/x-xbitmap";
return list;
}

203
kimgio/raw.cpp Normal file
View file

@ -0,0 +1,203 @@
/* This file is part of the KDE libraries
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
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 "raw.h"
#include <QImage>
#include <kdebug.h>
#include <libraw/libraw.h>
static const char* const s_rawpluginformat = "raw";
RAWHandler::RAWHandler()
{
}
RAWHandler::~RAWHandler()
{
}
bool RAWHandler::canRead() const
{
if (RAWHandler::canRead(device())) {
setFormat(s_rawpluginformat);
return true;
}
return false;
}
bool RAWHandler::read(QImage *image)
{
const qint64 devicepos = device()->pos();
QByteArray data = device()->readAll();
device()->seek(devicepos);
if (Q_UNLIKELY(data.isEmpty())) {
return false;
}
try {
LibRaw raw;
raw.imgdata.params.output_color = LIBRAW_COLORSPACE_sRGB;
int rawresult = raw.open_buffer(data.data(), data.size());
if (rawresult != LIBRAW_SUCCESS) {
kWarning() << libraw_strerror(rawresult);
raw.recycle();
return false;
}
rawresult = raw.unpack();
if (rawresult != LIBRAW_SUCCESS) {
kWarning() << libraw_strerror(rawresult);
raw.recycle();
return false;
}
rawresult = raw.dcraw_process();
if (rawresult != LIBRAW_SUCCESS) {
kWarning() << libraw_strerror(rawresult);
raw.recycle();
return false;
}
libraw_processed_image_t* rawimg = raw.dcraw_make_mem_image(&rawresult);
if (!rawimg || rawresult != LIBRAW_SUCCESS) {
kWarning() << libraw_strerror(rawresult);
raw.recycle();
return false;
}
if (rawimg->colors != 3) {
kWarning() << "Color components count not supported" << rawimg->colors;
raw.dcraw_clear_mem(rawimg);
raw.recycle();
return false;
}
*image = QImage(rawimg->width, rawimg->height, QImage::Format_ARGB32);
if (image->isNull()) {
kWarning() << "Could not create QImage";
raw.dcraw_clear_mem(rawimg);
raw.recycle();
return false;
}
QRgb* imagebits = reinterpret_cast<QRgb*>(image->bits());
for (uint i = 0 ; i < rawimg->data_size; i += 3) {
*imagebits = qRgba(rawimg->data[i], rawimg->data[i + 1], rawimg->data[i + 2], 0xff);
imagebits++;
}
raw.dcraw_clear_mem(rawimg);
raw.recycle();
} catch (...) {
kWarning() << "Exception raised";
return false;
}
return true;
}
bool RAWHandler::write(const QImage &image)
{
// this plugin is a read-only kind of plugin
return false;
}
QByteArray RAWHandler::name() const
{
return s_rawpluginformat;
}
bool RAWHandler::canRead(QIODevice *device)
{
if (Q_UNLIKELY(!device)) {
kWarning() << "Called with no device";
return false;
}
const qint64 devicepos = device->pos();
QByteArray data = device->readAll();
device->seek(devicepos);
if (Q_UNLIKELY(data.isEmpty())) {
return false;
}
try {
LibRaw raw;
raw.imgdata.params.output_color = LIBRAW_COLORSPACE_sRGB;
const int rawresult = raw.open_buffer(data.data(), data.size());
if (rawresult == LIBRAW_FILE_UNSUPPORTED) {
kDebug() << libraw_strerror(rawresult);
raw.recycle();
return false;
} else if (rawresult != LIBRAW_SUCCESS) {
kWarning() << libraw_strerror(rawresult);
raw.recycle();
return false;
}
raw.recycle();
} catch (...) {
kWarning() << "Exception raised";
return false;
}
return true;
}
QStringList RAWPlugin::keys() const
{
return QStringList() << s_rawpluginformat;
}
QList<QByteArray> RAWPlugin::mimeTypes() const
{
static const QList<QByteArray> list = QList<QByteArray>()
<< "image/x-dcraw";
return list;
}
QImageIOPlugin::Capabilities RAWPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == s_rawpluginformat)
return QImageIOPlugin::Capabilities(QImageIOPlugin::CanRead);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
QImageIOPlugin::Capabilities cap;
if (device->isReadable() && RAWHandler::canRead(device))
cap |= QImageIOPlugin::CanRead;
return cap;
}
QImageIOHandler *RAWPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new RAWHandler();
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(raw, RAWPlugin)

50
kimgio/raw.h Normal file
View file

@ -0,0 +1,50 @@
/* This file is part of the KDE libraries
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
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 KIMG_RAW_H
#define KIMG_RAW_H
#include <QtCore/qstringlist.h>
#include <QtGui/qimageiohandler.h>
class RAWHandler : public QImageIOHandler
{
public:
RAWHandler();
~RAWHandler();
bool canRead() const final;
bool read(QImage *image) final;
bool write(const QImage &image) final;
QByteArray name() const final;
static bool canRead(QIODevice *device);
};
class RAWPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
QList<QByteArray> mimeTypes() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const final;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const final;
};
#endif // KIMG_RAW_H