From 93f541587931fae8a6b11b68270cd70433009be9 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Sun, 1 Nov 2015 05:10:05 +0200 Subject: [PATCH] generic: import kimio plugin for webp format from kde-workspace repo Signed-off-by: Ivailo Monev --- CMakeLists.txt | 9 ++ cmake/modules/CMakeLists.txt | 1 + cmake/modules/FindWebP.cmake | 40 ++++++ kimgio/CMakeLists.txt | 114 ++++++++++------ kimgio/webp.cpp | 246 +++++++++++++++++++++++++++++++++++ kimgio/webp.desktop | 7 + kimgio/webp.h | 49 +++++++ kimgio/webp.xml | 7 + mimetypes/CMakeLists.txt | 8 -- 9 files changed, 430 insertions(+), 51 deletions(-) create mode 100644 cmake/modules/FindWebP.cmake create mode 100644 kimgio/webp.cpp create mode 100644 kimgio/webp.desktop create mode 100644 kimgio/webp.h create mode 100644 kimgio/webp.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dda1bf6..926f5164 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,15 @@ set_package_properties(Strigi PROPERTIES PURPOSE "Required by some critical kioslaves" ) +# for KDE 4.7 we require at least version 0.60 +find_package(SharedMimeInfo 0.60) +set_package_properties(SharedMimeInfo PROPERTIES + DESCRIPTION "Shared Mime Info" + URL "http://freedesktop.org/wiki/Software/shared-mime-info" + TYPE REQUIRED + PURPOSE "Allows KDE applications to determine file types" +) + #optional features if(X11_FOUND) #X11_Xrender discovery is done by FindX11 diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt index 45863183..a50b9fc2 100644 --- a/cmake/modules/CMakeLists.txt +++ b/cmake/modules/CMakeLists.txt @@ -121,6 +121,7 @@ set(cmakeFiles FindXKB.cmake FindXine.cmake FindXmms.cmake + FindWebP.cmake HandleImportedTargetsInCMakeRequiredLibraries.cmake KDE4Defaults.cmake KDE4Macros.cmake diff --git a/cmake/modules/FindWebP.cmake b/cmake/modules/FindWebP.cmake new file mode 100644 index 00000000..d0373d65 --- /dev/null +++ b/cmake/modules/FindWebP.cmake @@ -0,0 +1,40 @@ +# - Try to find libwebp +# Once done this will define +# +# WEBP_FOUND - system has libwebp +# WEBP_INCLUDES - the libwebp include directory +# WEBP_LIBRARIES - The libraries needed to use libwebp +# +# Copyright (c) 2015, Ivailo Monev, +# +# Redistribution and use is allowed according to the terms of the BSD license. + +if(WEBP_INCLUDES AND WEBP_LIBRARIES) + set(WEBP_FIND_QUIETLY TRUE) +endif(WEBP_INCLUDES AND WEBP_LIBRARIES) + +find_path(WEBP_INCLUDES + NAMES + encode.h + decode.h + PATH_SUFFIXES webp + HINTS + $ENV{WEBPDIR}/include + /usr/include + /usr/local/include + ${INCLUDE_INSTALL_DIR} +) + +find_library(WEBP_LIBRARIES + webp + HINTS + $ENV{WEBPDIR}/lib + /usr/lib + /usr/local/lib + ${LIB_INSTALL_DIR} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WEBP DEFAULT_MSG WEBP_INCLUDES WEBP_LIBRARIES) + +mark_as_advanced(WEBP_INCLUDES WEBP_LIBRARIES) diff --git a/kimgio/CMakeLists.txt b/kimgio/CMakeLists.txt index bffe44ff..f5902d45 100644 --- a/kimgio/CMakeLists.txt +++ b/kimgio/CMakeLists.txt @@ -2,21 +2,31 @@ project(kimgio) macro_optional_find_package(Jasper) -set_package_properties(Jasper PROPERTIES DESCRIPTION "Support for JPEG-2000 images" - URL "http://www.ece.uvic.ca/~mdadams/jasper" - TYPE OPTIONAL - ) +set_package_properties(Jasper PROPERTIES + DESCRIPTION "Support for JPEG-2000 images" + URL "http://www.ece.uvic.ca/~mdadams/jasper" + TYPE OPTIONAL +) macro_optional_find_package(OpenEXR) -set_package_properties(OpenEXR PROPERTIES DESCRIPTION "Support for OpenEXR images" - URL "http://www.openexr.com" - TYPE OPTIONAL - ) +set_package_properties(OpenEXR PROPERTIES + DESCRIPTION "Support for OpenEXR images" + URL "http://www.openexr.com" + TYPE OPTIONAL +) + +macro_optional_find_package(WebP) +set_package_properties(WebP PROPERTIES + DESCRIPTION "A new image format for the Web" + URL "https://developers.google.com/speed/webp" + TYPE OPTIONAL +) include_directories( ${KDE4_KDEUI_INCLUDES} ) -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") +################################## if(JASPER_FOUND) @@ -97,7 +107,7 @@ target_link_libraries(kimg_psd ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) install(TARGETS kimg_psd DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageformats/ ) ################################## - + set(kimg_xview_LIB_SRCS xview.cpp) kde4_add_plugin(kimg_xview ${kimg_xview_LIB_SRCS}) target_link_libraries(kimg_xview ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) @@ -107,14 +117,14 @@ install(TARGETS kimg_xview DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageforma ################################## if(OPENEXR_FOUND) - include_directories( ${CMAKE_SOURCE_DIR}/kio ${OPENEXR_INCLUDE_DIR} ) + include_directories( ${CMAKE_SOURCE_DIR}/kio ${OPENEXR_INCLUDE_DIR}) add_definitions(${OPENEXR_DEFINITIONS}) set(kimg_exr_LIB_SRCS exr.cpp) kde4_add_plugin(kimg_exr ${kimg_exr_LIB_SRCS}) - target_link_libraries(kimg_exr ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${OPENEXR_LIBRARIES} ) + target_link_libraries(kimg_exr ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${OPENEXR_LIBRARIES}) -install(TARGETS kimg_exr DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageformats/ ) -install( FILES exr.desktop DESTINATION ${SERVICES_INSTALL_DIR}/qimageioplugins/ ) + install(TARGETS kimg_exr DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageformats/ ) + install( FILES exr.desktop DESTINATION ${SERVICES_INSTALL_DIR}/qimageioplugins/ ) endif(OPENEXR_FOUND) ################################## @@ -125,38 +135,56 @@ target_link_libraries(kimg_pic ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) install(TARGETS kimg_pic DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageformats/ ) +################################## + +if(WEBP_FOUND) + include_directories( ${WEBP_INCLUDES} ) + kde4_add_plugin(kimg_webp webp.cpp) + target_link_libraries(kimg_webp ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${WEBP_LIBRARIES}) + + install(TARGETS kimg_webp DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/imageformats/) + install(FILES webp.desktop DESTINATION ${SERVICES_INSTALL_DIR}/qimageioplugins/) + + install(FILES webp.xml DESTINATION ${XDG_MIME_INSTALL_DIR}) + update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR}) +endif() ########### install files ############### -install( FILES - png.desktop - xpm.desktop - bmp.desktop - pbm.desktop - pgm.desktop - pnm.desktop - ppm.desktop - xbm.desktop - jpeg.desktop - xv.desktop - eps.desktop - ico.desktop - gif.desktop - pcx.desktop - tga.desktop - ras.desktop - rgb.desktop - xcf.desktop - dds.desktop - mng.desktop - psd.desktop - hdr.desktop - tiff.desktop - pic.desktop - svg+xml.desktop - svg+xml-compressed.desktop - DESTINATION ${SERVICES_INSTALL_DIR}/qimageioplugins/ ) +install( + FILES + png.desktop + xpm.desktop + bmp.desktop + pbm.desktop + pgm.desktop + pnm.desktop + ppm.desktop + xbm.desktop + jpeg.desktop + xv.desktop + eps.desktop + ico.desktop + gif.desktop + pcx.desktop + tga.desktop + ras.desktop + rgb.desktop + xcf.desktop + dds.desktop + mng.desktop + psd.desktop + hdr.desktop + tiff.desktop + pic.desktop + svg+xml.desktop + svg+xml-compressed.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/qimageioplugins/ +) -install( FILES qimageio_plugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}/ ) +install( + FILES qimageio_plugin.desktop + DESTINATION ${SERVICETYPES_INSTALL_DIR}/ +) diff --git a/kimgio/webp.cpp b/kimgio/webp.cpp new file mode 100644 index 00000000..d51c1eac --- /dev/null +++ b/kimgio/webp.cpp @@ -0,0 +1,246 @@ +/* +QImageIO Routines to read/write WebP images. + +Copyright (c) 2012,2013 Martin Koller + +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) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 library. If not, see . +*/ + +#include + +#include "webp.h" +#include +#include + +#include +#include + +//--------------------------------------------------------------------- + +WebPHandler::WebPHandler() + : quality(75) +{ +} + +//--------------------------------------------------------------------- + +bool WebPHandler::canRead() const +{ + if (canRead(device())) { + setFormat("webp"); + return true; + } + return false; +} + +//--------------------------------------------------------------------- + +bool WebPHandler::read(QImage *retImage) +{ + QByteArray data = device()->readAll(); + + WebPBitstreamFeatures features; + VP8StatusCode ret = WebPGetFeatures(reinterpret_cast(data.constData()), data.size(), &features); + if ( ret != VP8_STATUS_OK ) { + return false; + } + + if ( features.has_alpha ) { + *retImage = QImage(features.width, features.height, QImage::Format_ARGB32); + } else { + *retImage = QImage(features.width, features.height, QImage::Format_RGB32); + } + + if ( retImage->isNull() ) { // out of memory + return false; + } + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if ( WebPDecodeARGBInto(reinterpret_cast(data.constData()), + data.size(), reinterpret_cast(retImage->bits()), + retImage->byteCount(), retImage->bytesPerLine()) == 0 ) { + return false; + } +#else + if ( WebPDecodeBGRAInto(reinterpret_cast(data.constData()), + data.size(), reinterpret_cast(retImage->bits()), + retImage->byteCount(), retImage->bytesPerLine()) == 0 ) { + return false; + } +#endif + + return true; +} + +//--------------------------------------------------------------------- + +bool WebPHandler::write(const QImage &image) +{ + // limitation in WebP + if ( (image.height() > 16383) || (image.height() == 0) || + (image.width() > 16383) || (image.width() == 0) ) + return false; + + uint8_t *imageData = new uint8_t[image.width() * image.height() * (3 + image.hasAlphaChannel())]; + + size_t idx = 0; + for (int y = 0; y < image.height(); y++) { + const QRgb *scanline = reinterpret_cast(image.constScanLine(y)); + for (int x = 0; x < image.width(); x++) { + imageData[idx++] = qRed(scanline[x]); + imageData[idx++] = qGreen(scanline[x]); + imageData[idx++] = qBlue(scanline[x]); + + if ( image.hasAlphaChannel() ) { + imageData[idx++] = qAlpha(scanline[x]); + } + } + } + + uint8_t *output = 0; + size_t size; + if ( image.hasAlphaChannel() ) { + size = WebPEncodeRGBA(imageData, image.width(), image.height(), image.width() * 4, quality, &output); + } else { + size = WebPEncodeRGB(imageData, image.width(), image.height(), image.width() * 4, quality, &output); + } + delete [] imageData; + + if ( size == 0 ) { + free(output); + return false; + } + + device()->write(reinterpret_cast(output), size); + free(output); + + return true; +} + +//--------------------------------------------------------------------- + +QByteArray WebPHandler::format() const +{ + return "webp"; +} + +//--------------------------------------------------------------------- + +bool WebPHandler::supportsOption(ImageOption option) const +{ + return (option == Quality) || (option == Size); +} + +//--------------------------------------------------------------------- + +QVariant WebPHandler::option(ImageOption option) const +{ + switch ( option ) + { + case Quality: + return quality; + + case Size: { + QByteArray data = device()->peek(26); + + int width = 0, height = 0; + + if ( WebPGetInfo(reinterpret_cast(data.constData()), + data.size(), &width, &height) == 0 ) + return QSize(); // header error + + return QSize(width, height); + } + + default: return QVariant(); + } +} + +//--------------------------------------------------------------------- + +void WebPHandler::setOption(ImageOption option, const QVariant &value) +{ + if (option == Quality) + quality = qBound(0, value.toInt(), 100); +} + +//--------------------------------------------------------------------- + +bool WebPHandler::canRead(QIODevice *device) +{ + if (!device) { + qWarning("WebPHandler::canRead() called with no device"); + return false; + } + + // WebP file header: 4 bytes "RIFF", 4 bytes length, 4 bytes "WEBP" + QByteArray header = device->peek(12); + + return (header.size() == 12) && header.startsWith("RIFF") && header.endsWith("WEBP"); +} + +//--------------------------------------------------------------------- +//--------------------------------------------------------------------- + +class WebPPlugin : public QImageIOPlugin +{ +public: + QStringList keys() const; + Capabilities capabilities(QIODevice *device, const QByteArray &format) const; + QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const; +}; + +//--------------------------------------------------------------------- + +QStringList WebPPlugin::keys() const +{ + return QStringList() << "webp"; +} + +//--------------------------------------------------------------------- + +QImageIOPlugin::Capabilities WebPPlugin::capabilities(QIODevice *device, const QByteArray &format) const +{ + if (format == "webp") + return Capabilities(CanRead | CanWrite); + if (!format.isEmpty()) + return 0; + if (!device->isOpen()) + return 0; + + Capabilities cap; + if (device->isReadable() && WebPHandler::canRead(device)) + cap |= CanRead; + if (device->isWritable()) + cap |= CanWrite; + return cap; +} + +//--------------------------------------------------------------------- + +QImageIOHandler *WebPPlugin::create(QIODevice *device, const QByteArray &format) const +{ + QImageIOHandler *handler = new WebPHandler; + handler->setDevice(device); + handler->setFormat(format); + return handler; +} + +//--------------------------------------------------------------------- + +Q_EXPORT_STATIC_PLUGIN(WebPPlugin) +Q_EXPORT_PLUGIN2(webp, WebPPlugin) diff --git a/kimgio/webp.desktop b/kimgio/webp.desktop new file mode 100644 index 00000000..3526be5f --- /dev/null +++ b/kimgio/webp.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=QImageIOPlugins +X-KDE-ImageFormat=webp +X-KDE-MimeType=image/x-webp +X-KDE-Read=true +X-KDE-Write=true diff --git a/kimgio/webp.h b/kimgio/webp.h new file mode 100644 index 00000000..a58d1f16 --- /dev/null +++ b/kimgio/webp.h @@ -0,0 +1,49 @@ +/* +QImageIO Routines to read/write WebP images. + +Copyright (c) 2012,2013 Martin Koller + +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) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +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 library. If not, see . +*/ + +#ifndef WEBP_H +#define WEBP_H + +#include + +class WebPHandler : public QImageIOHandler +{ +public: + WebPHandler(); + + virtual bool canRead() const; + virtual bool read(QImage *image); + virtual bool write(const QImage &image); + + virtual QByteArray format() const; + + virtual bool supportsOption(ImageOption option) const; + virtual QVariant option(ImageOption option) const; + virtual void setOption(ImageOption option, const QVariant &value); + + static bool canRead(QIODevice *device); + +private: + int quality; +}; + +#endif diff --git a/kimgio/webp.xml b/kimgio/webp.xml new file mode 100644 index 00000000..4246f760 --- /dev/null +++ b/kimgio/webp.xml @@ -0,0 +1,7 @@ + + + + WebP image + + + diff --git a/mimetypes/CMakeLists.txt b/mimetypes/CMakeLists.txt index e7459309..ab1ad6ac 100644 --- a/mimetypes/CMakeLists.txt +++ b/mimetypes/CMakeLists.txt @@ -1,11 +1,3 @@ -# for KDE 4.7 we require at least version 0.60 -find_package(SharedMimeInfo 0.60) -set_package_properties(SharedMimeInfo PROPERTIES DESCRIPTION "Shared Mime Info" - URL "http://freedesktop.org/wiki/Software/shared-mime-info" - TYPE REQUIRED - PURPOSE "Allows KDE applications to determine file types" - ) - ########### install files ############### install(FILES kde.xml DESTINATION ${XDG_MIME_INSTALL_DIR}) update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})