mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
kimgio: new JPEG-specialized plugin
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
cdd26390b0
commit
7995231b45
9 changed files with 323 additions and 12 deletions
|
@ -185,6 +185,14 @@ set_package_properties(LibRaw PROPERTIES
|
|||
TYPE OPTIONAL
|
||||
)
|
||||
|
||||
kde4_optional_find_package(LibJPEG)
|
||||
set_package_properties(LibJPEG PROPERTIES
|
||||
DESCRIPTION "JPEG image codec that uses SIMD instructions"
|
||||
URL "https://libjpeg-turbo.org/"
|
||||
PURPOSE "Support for JPEG image format"
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
|
||||
# v143+ required for udev_monitor_filter_add_match_subsystem_devtype()
|
||||
kde4_optional_find_package(UDev 143)
|
||||
set_package_properties(UDev PROPERTIES
|
||||
|
|
39
cmake/modules/FindLibJPEG.cmake
Normal file
39
cmake/modules/FindLibJPEG.cmake
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Try to find libjpeg-turbo library, once done this will define:
|
||||
#
|
||||
# LIBJPEG_FOUND - system has libjpeg-turbo
|
||||
# LIBJPEG_INCLUDE_DIR - the libjpeg-turbo include directory
|
||||
# LIBJPEG_LIBRARIES - the libraries needed to use libjpeg-turbo
|
||||
# LIBJPEG_DEFINITIONS - compiler switches required for using libjpeg-turbo
|
||||
#
|
||||
# Copyright (c) 2022 Ivailo Monev <xakepa10@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(PC_LIBJPEG QUIET libturbojpeg)
|
||||
|
||||
set(LIBJPEG_INCLUDE_DIR ${PC_LIBJPEG_INCLUDE_DIRS})
|
||||
set(LIBJPEG_LIBRARIES ${PC_LIBJPEG_LIBRARIES})
|
||||
set(LIBJPEG_VERSION ${PC_LIBJPEG_VERSION})
|
||||
set(LIBJPEG_DEFINITIONS ${PC_LIBJPEG_CFLAGS_OTHER})
|
||||
|
||||
if(NOT LIBJPEG_INCLUDE_DIR OR NOT LIBJPEG_LIBRARIES)
|
||||
find_path(LIBJPEG_INCLUDE_DIR
|
||||
NAMES turbojpeg.h
|
||||
HINTS $ENV{LIBJPEGDIR}/include
|
||||
)
|
||||
|
||||
find_library(LIBJPEG_LIBRARIES
|
||||
NAMES turbojpeg
|
||||
HINTS $ENV{LIBJPEGDIR}/lib
|
||||
)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibJPEG
|
||||
VERSION_VAR LIBJPEG_VERSION
|
||||
REQUIRED_VARS LIBJPEG_LIBRARIES LIBJPEG_INCLUDE_DIR
|
||||
)
|
||||
|
||||
mark_as_advanced(LIBJPEG_INCLUDE_DIR LIBJPEG_LIBRARIES)
|
|
@ -5,7 +5,7 @@
|
|||
# LIBRAW_LIBRARIES - the libraries needed to use LibRaw
|
||||
# LIBRAW_DEFINITIONS - compiler switches required for using LibRaw
|
||||
#
|
||||
# Copyright (c) 2020 Ivailo Monev <xakepa10@gmail.com>
|
||||
# Copyright (c) 2022 Ivailo Monev <xakepa10@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
|
|
@ -26,15 +26,13 @@
|
|||
* Currently supported formats include:
|
||||
* @li WEBP \<read\> \<write\>
|
||||
* @li RAW \<read\>
|
||||
* @li JPEG \<read\>
|
||||
* @li PGM \<read\>
|
||||
* @li XBM \<read\>
|
||||
* @li BMP \<read\>
|
||||
* @li ICO \<read\>
|
||||
* @li JPEG \<read\>
|
||||
* @li JP2 \<read\>
|
||||
* @li GIF \<read\>
|
||||
*
|
||||
* @todo move to kdeui
|
||||
*/
|
||||
namespace KImageIO
|
||||
{
|
||||
|
|
|
@ -63,3 +63,23 @@ if(LIBRAW_FOUND)
|
|||
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/plugins/imageformats
|
||||
)
|
||||
endif(LIBRAW_FOUND)
|
||||
|
||||
##################################
|
||||
|
||||
if(LIBJPEG_FOUND)
|
||||
include_directories(${LIBJPEG_INCLUDE_DIR})
|
||||
kde4_add_plugin(kimg_jpeg jpeg.cpp)
|
||||
target_link_libraries(kimg_jpeg
|
||||
${KDE4_KDECORE_LIBS}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${LIBJPEG_LIBRARIES}
|
||||
)
|
||||
set_target_properties(kimg_jpeg PROPERTIES
|
||||
OUTPUT_NAME jpeg
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS kimg_jpeg
|
||||
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/plugins/imageformats
|
||||
)
|
||||
endif(LIBJPEG_FOUND)
|
||||
|
|
|
@ -5,6 +5,7 @@ Current formats include:
|
|||
|
||||
WEBP <read> <write>
|
||||
RAW <read>
|
||||
JPEG <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
|
||||
|
@ -14,7 +15,6 @@ PGM <read>
|
|||
XBM <read>
|
||||
BMP <read>
|
||||
ICO <read>
|
||||
JPEG <read>
|
||||
JP2 <read>
|
||||
GIF <read>
|
||||
|
||||
|
|
203
kimgio/jpeg.cpp
Normal file
203
kimgio/jpeg.cpp
Normal 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 "jpeg.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <kdebug.h>
|
||||
|
||||
#include <turbojpeg.h>
|
||||
|
||||
static const char* const s_jpegpluginformat = "jpg";
|
||||
|
||||
static const ushort s_peekbuffsize = 32;
|
||||
// for reference:
|
||||
// https://en.wikipedia.org/wiki/List_of_file_signatures
|
||||
static const uchar s_jpgjfifheader[] = { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01 };
|
||||
static const uchar s_jpgheader[] = { 0xFF, 0xD8, 0xFF, 0xE0 };
|
||||
static const uchar s_jpg2header[] = { 0xFF, 0xD8, 0xFF, 0xEE };
|
||||
static const uchar s_jpegexifheader[] = { 0xFF, 0xD8, 0xFF, 0xE1 };
|
||||
|
||||
static const struct HeadersTblData {
|
||||
const uchar *header;
|
||||
const int headersize;
|
||||
const char *format;
|
||||
} HeadersTbl[] = {
|
||||
{ s_jpgjfifheader, 12, "jpg" },
|
||||
{ s_jpgheader, 4, "jpg" },
|
||||
{ s_jpg2header, 4, "jpg" },
|
||||
{ s_jpegexifheader, 4, "jpg" }
|
||||
};
|
||||
static const qint16 HeadersTblSize = sizeof(HeadersTbl) / sizeof(HeadersTblData);
|
||||
|
||||
JPEGHandler::JPEGHandler()
|
||||
{
|
||||
}
|
||||
|
||||
JPEGHandler::~JPEGHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool JPEGHandler::canRead() const
|
||||
{
|
||||
if (canRead(device())) {
|
||||
setFormat(s_jpegpluginformat);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JPEGHandler::read(QImage *image)
|
||||
{
|
||||
QByteArray data = device()->readAll();
|
||||
|
||||
tjhandle jpegdecomp = tjInitDecompress();
|
||||
if (!jpegdecomp) {
|
||||
kWarning() << "Could not initialize decompressor" << tjGetErrorStr();
|
||||
return false;
|
||||
}
|
||||
|
||||
int jpegwidth = 0;
|
||||
int jpegheight = 0;
|
||||
int jpegsubsamp = 0;
|
||||
int jpegcolorspace = 0;
|
||||
int jpegstatus = tjDecompressHeader3(
|
||||
jpegdecomp,
|
||||
reinterpret_cast<const uchar*>(data.constData()), data.size(),
|
||||
&jpegwidth, &jpegheight,
|
||||
&jpegsubsamp, &jpegcolorspace
|
||||
);
|
||||
if (jpegstatus != 0) {
|
||||
kWarning() << "Could not decompress header" << tjGetErrorStr2(jpegdecomp);
|
||||
(void)tjDestroy(jpegdecomp);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int s_jpegpixelFormat = TJPF_ARGB;
|
||||
int jpegbuffersize = (jpegwidth * jpegheight * tjPixelSize[s_jpegpixelFormat]);
|
||||
unsigned char *jpegbuffer = tjAlloc(jpegbuffersize);
|
||||
if (!jpegbuffer) {
|
||||
kWarning() << "Could not allocate buffer" << tjGetErrorStr2(jpegdecomp);
|
||||
(void)tjDestroy(jpegdecomp);
|
||||
return false;
|
||||
}
|
||||
|
||||
jpegstatus = tjDecompress2(
|
||||
jpegdecomp,
|
||||
reinterpret_cast<const uchar*>(data.constData()), data.size(),
|
||||
jpegbuffer,
|
||||
jpegwidth, 0 , jpegheight,
|
||||
s_jpegpixelFormat,
|
||||
TJFLAG_FASTDCT
|
||||
);
|
||||
if (jpegstatus != 0) {
|
||||
kWarning() << "Could not decompress" << tjGetErrorStr2(jpegdecomp);
|
||||
tjFree(jpegbuffer);
|
||||
(void)tjDestroy(jpegdecomp);
|
||||
return false;
|
||||
}
|
||||
|
||||
*image = QImage(jpegwidth, jpegheight, QImage::Format_ARGB32);
|
||||
if (image->isNull()) {
|
||||
tjFree(jpegbuffer);
|
||||
(void)tjDestroy(jpegdecomp);
|
||||
return false;
|
||||
}
|
||||
|
||||
QRgb* imagebits = reinterpret_cast<QRgb*>(image->bits());
|
||||
for (uint i = 0; i < jpegbuffersize; i += 4) {
|
||||
*imagebits = qRgba(jpegbuffer[i + 1], jpegbuffer[i + 2], jpegbuffer[i + 3], jpegbuffer[i]);
|
||||
imagebits++;
|
||||
}
|
||||
|
||||
tjFree(jpegbuffer);
|
||||
(void)tjDestroy(jpegdecomp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JPEGHandler::write(const QImage &image)
|
||||
{
|
||||
// this plugin is a read-only kind of plugin
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray JPEGHandler::name() const
|
||||
{
|
||||
return s_jpegpluginformat;
|
||||
}
|
||||
|
||||
bool JPEGHandler::canRead(QIODevice *device)
|
||||
{
|
||||
if (Q_UNLIKELY(!device)) {
|
||||
kWarning() << "Called with no device";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QByteArray data = device->peek(s_peekbuffsize);
|
||||
|
||||
if (Q_UNLIKELY(data.isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < HeadersTblSize; i++) {
|
||||
if (qstrncmp(data.constData(), reinterpret_cast<const char*>(HeadersTbl[i].header), HeadersTbl[i].headersize) == 0) {
|
||||
kDebug() << "Header detected" << HeadersTbl[i].format;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList JPEGPlugin::keys() const
|
||||
{
|
||||
return QStringList() << s_jpegpluginformat;
|
||||
}
|
||||
|
||||
QList<QByteArray> JPEGPlugin::mimeTypes() const
|
||||
{
|
||||
static const QList<QByteArray> list = QList<QByteArray>()
|
||||
<< "image/jpeg";
|
||||
return list;
|
||||
}
|
||||
|
||||
QImageIOPlugin::Capabilities JPEGPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
if (format == s_jpegpluginformat)
|
||||
return QImageIOPlugin::Capabilities(QImageIOPlugin::CanRead);
|
||||
if (!format.isEmpty())
|
||||
return 0;
|
||||
if (!device->isOpen())
|
||||
return 0;
|
||||
|
||||
QImageIOPlugin::Capabilities cap;
|
||||
if (device->isReadable() && JPEGHandler::canRead(device))
|
||||
cap |= QImageIOPlugin::CanRead;
|
||||
return cap;
|
||||
}
|
||||
|
||||
QImageIOHandler *JPEGPlugin::create(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
QImageIOHandler *handler = new JPEGHandler();
|
||||
handler->setDevice(device);
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN2(jpeg, JPEGPlugin)
|
50
kimgio/jpeg.h
Normal file
50
kimgio/jpeg.h
Normal 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_JPEG_H
|
||||
#define KIMG_JPEG_H
|
||||
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <QtGui/qimageiohandler.h>
|
||||
|
||||
class JPEGHandler : public QImageIOHandler
|
||||
{
|
||||
public:
|
||||
JPEGHandler();
|
||||
~JPEGHandler();
|
||||
|
||||
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 JPEGPlugin : 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_JPEG_H
|
||||
|
|
@ -35,12 +35,9 @@ static const ushort s_peekbuffsize = 32;
|
|||
// for reference:
|
||||
// https://en.wikipedia.org/wiki/List_of_file_signatures
|
||||
static const uchar s_jp2header[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
|
||||
static const uchar s_jpgjfifheader[] = { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01 };
|
||||
static const uchar s_gif87aheader[] = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 };
|
||||
static const uchar s_gif89aheader[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
|
||||
static const uchar s_icoheader[] = { 0x0, 0x0, 0x1, 0x0, 0x0 };
|
||||
static const uchar s_jpgheader[] = { 0xFF, 0xD8, 0xFF, 0xE0 };
|
||||
static const uchar s_jpg2header[] = { 0xFF, 0xD8, 0xFF, 0xEE };
|
||||
static const uchar s_bmpheader[] = { 0x42, 0x4D };
|
||||
|
||||
static const struct HeadersTblData {
|
||||
|
@ -49,12 +46,9 @@ static const struct HeadersTblData {
|
|||
const char *format;
|
||||
} HeadersTbl[] = {
|
||||
{ s_jp2header, 12, "jp2" },
|
||||
{ s_jpgjfifheader, 12, "jpg" },
|
||||
{ s_gif87aheader, 6, "gif" },
|
||||
{ s_gif89aheader, 6, "gif" },
|
||||
{ s_icoheader, 5, "ico" },
|
||||
{ s_jpgheader, 4, "jpg" },
|
||||
{ s_jpg2header, 4, "jpg" },
|
||||
{ s_bmpheader , 2, "bmp" }
|
||||
};
|
||||
static const qint16 HeadersTblSize = sizeof(HeadersTbl) / sizeof(HeadersTblData);
|
||||
|
@ -64,7 +58,6 @@ static QList<std::string> s_whitelist = QList<std::string>()
|
|||
<< std::string("XBM")
|
||||
<< std::string("BMP")
|
||||
<< std::string("ICO")
|
||||
<< std::string("JPEG")
|
||||
<< std::string("JP2")
|
||||
<< std::string("GIF")
|
||||
<< std::string("PNG");
|
||||
|
|
Loading…
Add table
Reference in a new issue