Merge branch 'master' of https://github.com/fluxer/kdelibs into devinfo

This commit is contained in:
Ivailo Monev 2021-07-27 21:02:52 +03:00
commit 704c37c902
68 changed files with 348 additions and 9351 deletions

View file

@ -186,17 +186,10 @@ set_package_properties(LibLZMA PROPERTIES
TYPE OPTIONAL TYPE OPTIONAL
) )
macro_optional_find_package(Jasper 2.0.20) macro_optional_find_package(ImageMagick COMPONENTS Magick++)
set_package_properties(Jasper PROPERTIES set_package_properties(ImageMagick PROPERTIES
URL "http://www.ece.uvic.ca/~mdadams/jasper" URL "https://imagemagick.org/"
PURPOSE "Support for JPEG-2000 images" PURPOSE "Support for various image formats"
TYPE OPTIONAL
)
macro_optional_find_package(OpenEXR)
set_package_properties(OpenEXR PROPERTIES
URL "http://www.openexr.com"
PURPOSE "Support for OpenEXR images"
TYPE OPTIONAL TYPE OPTIONAL
) )

View file

@ -19,7 +19,7 @@ build_script:
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -qq cmake katie-dev libenchant-dev \ sudo apt-get install -qq cmake katie-dev libenchant-dev \
libopenexr-dev libmpv-dev libraw-dev xorg-dev mesa-common-dev \ libmagick++-dev libmpv-dev libraw-dev xorg-dev mesa-common-dev \
libavahi-common-dev krb5-multidev libwebp-dev \ libavahi-common-dev krb5-multidev libwebp-dev \
libudev-dev liblzma-dev libexiv2-dev libilmbase-dev libjpeg-dev \ libudev-dev liblzma-dev libexiv2-dev libilmbase-dev libjpeg-dev \
libbz2-dev libattr1-dev libacl1-dev libxcb-render-util0-dev \ libbz2-dev libattr1-dev libacl1-dev libxcb-render-util0-dev \

View file

@ -280,7 +280,7 @@ struct KDebugPrivate
file.close(); file.close();
} }
inline int level(QtMsgType type) inline int level(QtMsgType type) const
{ return int(type) - int(QtDebugMsg); } { return int(type) - int(QtDebugMsg); }
QString groupNameForArea(unsigned int area) const QString groupNameForArea(unsigned int area) const
@ -466,12 +466,6 @@ struct KDebugPrivate
QDebug setupQtWriter(QtMsgType type) QDebug setupQtWriter(QtMsgType type)
{ {
if (type != QtDebugMsg) { if (type != QtDebugMsg) {
if (type == QtWarningMsg) {
// KDE warnings are not the same thing as Qt warnings
// in Qt, warnings indicate bad code, which must be corrected before the release
// in KDE, it's just something that everyone sees (including users)
type = QtDebugMsg;
}
return QDebug(type); return QDebug(type);
} }
return QDebug(&lineendstrippingwriter); return QDebug(&lineendstrippingwriter);

View file

@ -94,7 +94,7 @@ public:
* The keys used in the query (Type, ServiceType, Exec) are all * The keys used in the query (Type, ServiceType, Exec) are all
* fields found in the .desktop files. * fields found in the .desktop files.
* *
* @param servicetype A service type like 'KMyApp/Plugin' or 'KFilePlugin'. * @param servicetype A service type like 'KMyApp/Plugin'.
* @param constraint A constraint to limit the choices returned, QString() to * @param constraint A constraint to limit the choices returned, QString() to
* get all services of the given @p servicetype * get all services of the given @p servicetype
* *

View file

@ -43,7 +43,7 @@ KLocaleTest::initTestCase()
void KLocaleTest::languages() void KLocaleTest::languages()
{ {
QVERIFY(KGlobal::locale()->installedLanguages().contains("gb")); QVERIFY(KGlobal::locale()->installedLanguages().contains("en_GB"));
} }
void void

View file

@ -259,10 +259,14 @@ void KMimeTypeTest::testFindByPathUsingFileName_data()
} }
QString exePath = KStandardDirs::findExe( "kioexec" ); QString exePath = KStandardDirs::findExe( "kioexec" );
if ( exePath.isEmpty() ) if ( exePath.isEmpty() ) {
kWarning() << "kioexec not found"; kWarning() << "kioexec not found";
else { } else {
const QString executableType = QString::fromLatin1( "application/x-executable" ); QString executableType = QString::fromLatin1( "application/x-executable" );
// https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11
if (KMimeType::sharedMimeInfoVersion() <= KDE_MAKE_VERSION(2, 0, 0)) {
executableType = QString::fromLatin1( "application/x-sharedlib" );
}
QTest::newRow("executable") << exePath << executableType; QTest::newRow("executable") << exePath << executableType;
} }
} }
@ -841,25 +845,25 @@ void KMimeTypeTest::testParseMagicFile_data()
QTest::newRow("Second rule, two-level match") << "AB[C]" << "application/x-desktop"; QTest::newRow("Second rule, two-level match") << "AB[C]" << "application/x-desktop";
QTest::newRow("Second rule, failure at first level (mask)") << "AB[B]" << QString(); QTest::newRow("Second rule, failure at first level (mask)") << "AB[B]" << QString();
QTest::newRow("Second rule, failure at second level") << "AB[CN" << QString(); QTest::newRow("Second rule, failure at second level") << "AB[CN" << QString();
QTest::newRow("Tnef magic, should pass") << "\x78\x9f\x3e\x22" << "application/vnd.ms-tnef"; QTest::newRow("Tnef magic, should pass") << QString::fromLatin1("\x78\x9f\x3e\x22") << "application/vnd.ms-tnef";
QTest::newRow("Tnef magic, should fail") << "\x22\x3e\x9f\x78" << QString(); QTest::newRow("Tnef magic, should fail") << QString::fromLatin1("\x22\x3e\x9f\x78") << QString();
QTest::newRow("Powerpoint rule, for endianness check, should pass") << "\xd0\xcf\x11\xe0" << "application/vnd.ms-powerpoint"; QTest::newRow("Powerpoint rule, for endianness check, should pass") << QString::fromLatin1("\xd0\xcf\x11\xe0") << "application/vnd.ms-powerpoint";
QTest::newRow("Powerpoint rule, no swapping, should fail") << "\x11\xe0\xd0\xcf" << QString(); QTest::newRow("Powerpoint rule, no swapping, should fail") << QString::fromLatin1("\x11\xe0\xd0\xcf") << QString();
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
QTest::newRow("Test mime, host16, wrong endianness") << "\x12\x34" << QString(); QTest::newRow("Test mime, host16, wrong endianness") << QString::fromLatin1("\x12\x34") << QString();
QTest::newRow("Test mime, host16, little endian, ok") << "\x34\x12" << "text/x-test-mime-host16"; QTest::newRow("Test mime, host16, little endian, ok") << QString::fromLatin1("\x34\x12") << "text/x-test-mime-host16";
QTest::newRow("Test mime, host32, wrong endianness") << "\x12\x34\x56\x78" << QString(); QTest::newRow("Test mime, host32, wrong endianness") << QString::fromLatin1("\x12\x34\x56\x78") << QString();
QTest::newRow("Test mime, host32, little endian, ok") << "\x78\x56\x34\x12" << "text/x-test-mime-host32"; QTest::newRow("Test mime, host32, little endian, ok") << QString::fromLatin1("\x78\x56\x34\x12") << "text/x-test-mime-host32";
#else #else
QTest::newRow("Test mime, host16, big endian, ok") << "\x12\x34" << "text/x-test-mime-host16"; QTest::newRow("Test mime, host16, big endian, ok") << QString::fromLatin1("\x12\x34") << "text/x-test-mime-host16";
QTest::newRow("Test mime, host16, wrong endianness") << "\x34\x12" << QString(); QTest::newRow("Test mime, host16, wrong endianness") << QString::fromLatin1("\x34\x12") << QString();
QTest::newRow("Test mime, host32, big endian, ok") << "\x12\x34\x56\x78" << "text/x-test-mime-host32"; QTest::newRow("Test mime, host32, big endian, ok") << QString::fromLatin1("\x12\x34\x56\x78") << "text/x-test-mime-host32";
QTest::newRow("Test mime, host32, wrong endianness") << "\x78\x56\x34\x12" << QString(); QTest::newRow("Test mime, host32, wrong endianness") << QString::fromLatin1("\x78\x56\x34\x12") << QString();
#endif #endif
QTest::newRow("Test mime, little16, little endian, ok") << "\x78\x55" << "text/x-test-mime-little16"; QTest::newRow("Test mime, little16, little endian, ok") << QString::fromLatin1("\x78\x55") << "text/x-test-mime-little16";
QTest::newRow("Test mime, little16, wrong endianness") << "\x55\x78" << QString(); QTest::newRow("Test mime, little16, wrong endianness") << QString::fromLatin1("\x55\x78") << QString();
QTest::newRow("Test mime, big16, little endian, ok") << "\x12\x78" << "text/x-test-mime-big16"; QTest::newRow("Test mime, big16, little endian, ok") << QString::fromLatin1("\x12\x78") << "text/x-test-mime-big16";
QTest::newRow("Test mime, big16, wrong endianness") << "\x78\x12" << QString(); QTest::newRow("Test mime, big16, wrong endianness") << QString::fromLatin1("\x78\x12") << QString();
QByteArray magicData; QByteArray magicData;
magicData.resize(sizeof(s_magicData) - 1 /*trailing nul*/); magicData.resize(sizeof(s_magicData) - 1 /*trailing nul*/);

View file

@ -115,7 +115,7 @@ void KStandarddirsTest::testFindAllResources()
const QStringList cmakeModulesFiles = KGlobal::dirs()->findAllResources( "data", "cmake/modules/" ); const QStringList cmakeModulesFiles = KGlobal::dirs()->findAllResources( "data", "cmake/modules/" );
QVERIFY( !cmakeModulesFiles.isEmpty() ); QVERIFY( !cmakeModulesFiles.isEmpty() );
QVERIFY( cmakeModulesFiles.count() > 80 ); // I have 150 here, installed by kdelibs. QVERIFY( cmakeModulesFiles.count() > 40 ); // I have 79 here, installed by kdelibs.
// Create a local config file, the file will be used as expected result // Create a local config file, the file will be used as expected result
const QString localConfigFile = m_kdehome + "/share/config/foorc"; const QString localConfigFile = m_kdehome + "/share/config/foorc";

View file

@ -59,7 +59,7 @@ KTemperaturePrivate::KTemperaturePrivate(const double number, const QString &uni
|| unit == QLatin1String("kelvins")) { || unit == QLatin1String("kelvins")) {
m_unitenum = KTemperature::Kelvin; m_unitenum = KTemperature::Kelvin;
} else { } else {
kDebug() << "invalid temperature unit" << unit; kDebug(930) << "invalid temperature unit" << unit;
} }
} }
@ -196,7 +196,7 @@ KVelocityPrivate::KVelocityPrivate(const double number, const QString &unit)
|| unit == QLatin1String("mph")) { || unit == QLatin1String("mph")) {
m_unitenum = KVelocity::MilePerHour; m_unitenum = KVelocity::MilePerHour;
} else { } else {
kDebug() << "invalid velocity unit" << unit; kDebug(930) << "invalid velocity unit" << unit;
} }
} }
@ -355,7 +355,7 @@ KPressurePrivate::KPressurePrivate(const double number, const QString &unit)
|| unit == QLatin1String("mbar") || unit == QLatin1String("mb")) { || unit == QLatin1String("mbar") || unit == QLatin1String("mb")) {
m_unitenum = KPressure::Millibar; m_unitenum = KPressure::Millibar;
} else { } else {
kDebug() << "invalid pressure unit" << unit; kDebug(930) << "invalid pressure unit" << unit;
} }
} }
@ -493,7 +493,7 @@ KLengthPrivate::KLengthPrivate(const double number, const QString &unit)
|| unit == QLatin1String("mi")) { || unit == QLatin1String("mi")) {
m_unitenum = KLength::Mile; m_unitenum = KLength::Mile;
} else { } else {
kDebug() << "invalid length unit" << unit; kDebug(930) << "invalid length unit" << unit;
} }
} }

View file

@ -29,6 +29,33 @@ class KLengthPrivate;
/*! /*!
Base class for all other conversion classes Base class for all other conversion classes
Converting from one unit to other with any of the conversion classes is pretty simple:
@code
KTemperature temp(12.3, "°C");
qDebug() << temp.convertTo(KTemperature::Fahrenheit);
@endcode
Unlike the original KUnitConversion classes, @p KTemperature, @p KVelocity, @p KPressure and
@p KLength are thread-safe and much faster, albeit do not provide as many unit conversion
options (that may change). Being unable to copy the classes is design choice - storing the
unit (string or enum representation) however is absolutely possible and you can in fact
optimize it for use case if you have to store both the number and the unit by using struct:
@code
struct TempUnit {
double number;
KTemperature::KTempUnit unit;
};
@endcode
vs:
@code
struct TempUnit {
double number;
QString unit;
};
@endcode
@since 4.20 @since 4.20
@see KTemperature, KVelocity, KPressure, KLength @see KTemperature, KVelocity, KPressure, KLength
*/ */

View file

@ -295,6 +295,7 @@ KApplication::KApplication()
d->read_app_startup_id(); d->read_app_startup_id();
setApplicationName(d->componentData.componentName()); setApplicationName(d->componentData.componentName());
setOrganizationDomain(d->componentData.aboutData()->organizationDomain()); setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
setApplicationVersion(d->componentData.aboutData()->version());
installSigpipeHandler(); installSigpipeHandler();
d->init(); d->init();
} }
@ -307,6 +308,7 @@ KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
d->read_app_startup_id(); d->read_app_startup_id();
setApplicationName(d->componentData.componentName()); setApplicationName(d->componentData.componentName());
setOrganizationDomain(d->componentData.aboutData()->organizationDomain()); setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
setApplicationVersion(d->componentData.aboutData()->version());
installSigpipeHandler(); installSigpipeHandler();
d->init(); d->init();
} }
@ -318,6 +320,7 @@ KApplication::KApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
d->read_app_startup_id(); d->read_app_startup_id();
setApplicationName(d->componentData.componentName()); setApplicationName(d->componentData.componentName());
setOrganizationDomain(d->componentData.aboutData()->organizationDomain()); setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
setApplicationVersion(d->componentData.aboutData()->version());
installSigpipeHandler(); installSigpipeHandler();
d->init(); d->init();
} }
@ -334,6 +337,7 @@ KApplication::KApplication(const KComponentData &cData)
d->read_app_startup_id(); d->read_app_startup_id();
setApplicationName(d->componentData.componentName()); setApplicationName(d->componentData.componentName());
setOrganizationDomain(d->componentData.aboutData()->organizationDomain()); setOrganizationDomain(d->componentData.aboutData()->organizationDomain());
setApplicationVersion(d->componentData.aboutData()->version());
installSigpipeHandler(); installSigpipeHandler();
d->init(); d->init();
} }

View file

@ -1,11 +1,3 @@
Sirtaj Singh Kang <taj@kde.org> -- kimgio and krl readers Sirtaj Singh Kang <taj@kde.org> -- kimgio and krl readers
Dirk Schoenberger <> -- eps, netpbm readers
Antonio Larossa <larossa@kde.org> -- initial version of KRL reader Antonio Larossa <larossa@kde.org> -- initial version of KRL reader
Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot) Ivailo Monev <xakepa10@gmail.com> -- magick plugin
Nadeem Hasan <nhasan@kde.org> -- PCX format read/write support
Melchior Franz <mfranz@kde.org> -- SGI format read/write support, port of XCF qimgio
Allen Barnett <allen@lignumcomputing.com> -- XCF format read support (qimgio)
Ignacio Castaño <castano@ludicon.com> -- DDS and PDS format reader.
Christoph Hormann <chris_hormann@gmx.de> -- HDR format read support.
Michael Ritzert <kde@ritzert.de> -- JPEG 2000 format read/write support
Troy Unrau <troy@kde.org> -- Sun RASter read support

View file

@ -4,49 +4,34 @@ include_directories(${KDE4_KDEUI_INCLUDES})
################################## ##################################
if(JASPER_FOUND) if(IMAGEMAGICK_FOUND)
include_directories(${JASPER_INCLUDE_DIR}) include_directories(${ImageMagick_INCLUDE_DIRS})
kde4_add_plugin(kimg_jp2 jp2.cpp) kde4_add_plugin(kimg_magick magick.cpp)
target_link_libraries(kimg_jp2 target_link_libraries(kimg_magick
${KDE4_KDECORE_LIBS} ${KDE4_KDECORE_LIBS}
${QT_QTGUI_LIBRARY} ${QT_QTGUI_LIBRARY}
${JASPER_LIBRARIES} ${ImageMagick_LIBRARIES}
)
set_target_properties(kimg_magick PROPERTIES
COMPILE_FLAGS "${KDE4_ENABLE_EXCEPTIONS}"
) )
install( install(
TARGETS kimg_jp2 TARGETS kimg_magick
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/kde4/plugins/imageformats DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/kde4/plugins/imageformats
) )
install( install(
FILES FILES
dds.desktop
eps.desktop
exr.desktop
jp2.desktop jp2.desktop
pcx.desktop
psd.desktop
xcf.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/qimageioplugins DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/qimageioplugins
) )
endif(JASPER_FOUND) endif(IMAGEMAGICK_FOUND)
##################################
if(OPENEXR_FOUND)
include_directories(${CMAKE_SOURCE_DIR}/kio ${OPENEXR_INCLUDE_DIR})
add_definitions(${OPENEXR_DEFINITIONS})
set_source_files_properties(exr.cpp PROPERTIES COMPILE_FLAGS "${KDE4_ENABLE_EXCEPTIONS}")
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}
)
install(
TARGETS kimg_exr
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/kde4/plugins/imageformats
)
install(
FILES exr.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/qimageioplugins
)
endif(OPENEXR_FOUND)
################################## ##################################
@ -71,66 +56,8 @@ if(WEBP_FOUND)
) )
endif(WEBP_FOUND) endif(WEBP_FOUND)
##################################
set(imgioplugins
eps
pcx
ras
rgb
xcf
dds
psd
)
foreach(plugin ${imgioplugins})
kde4_add_plugin(kimg_${plugin} ${plugin}.cpp)
target_link_libraries(kimg_${plugin}
${KDE4_KDECORE_LIBS}
${QT_QTGUI_LIBRARY}
)
install(
TARGETS kimg_${plugin}
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/kde4/plugins/imageformats
)
endforeach()
##################################
set(kimg_pic_LIB_SRCS
pic_read.cpp
pic_write.cpp
pic_io_plugin.cpp
pic_io_handler.cpp
)
kde4_add_plugin(kimg_pic ${kimg_pic_LIB_SRCS})
target_link_libraries(kimg_pic
${KDE4_KDECORE_LIBS}
${QT_QTGUI_LIBRARY}
)
install(
TARGETS kimg_pic
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}/kde4/plugins/imageformats
)
########### install files ############### ########### install files ###############
install(
FILES
eps.desktop
pcx.desktop
ras.desktop
rgb.desktop
xcf.desktop
dds.desktop
psd.desktop
hdr.desktop
pic.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}/qimageioplugins
)
install( install(
FILES qimageio_plugin.desktop FILES qimageio_plugin.desktop
DESTINATION ${KDE4_SERVICETYPES_INSTALL_DIR} DESTINATION ${KDE4_SERVICETYPES_INSTALL_DIR}

View file

@ -1,18 +1,18 @@
This directory contains Qt imageformat plugins. See Qt docs for This directory contains Katie imageformat plugins. See Katie docs for
writing a new handler. writing a new handler.
Current formats include: Current formats include:
DDS <read>
EPS <read> <write>
EXR <read>
HDR <read>
JP2 <read> <write>
PCX <read> <write>
PIC <read> <write>
PNM <read>
PSD <read>
RAS <read>
RGB <read> <write>
WEBP <read> <write> WEBP <read> <write>
along with whatever ImageMagick supports but it is assumed that it supports
reading atleast the following formats (even if they cannot be loaded) for
compatibility:
DDS <read>
EPS <read>
EXR <read>
JP2 <read>
PCX <read>
PSD <read>
XCF <read> XCF <read>

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=dds X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-dds X-KDE-MimeType=image/x-dds
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=false X-KDE-Write=false

View file

@ -1,30 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003 Ignacio Castaño <castano@ludicon.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef KIMG_DDS_H
#define KIMG_DDS_H
#include <QtGui/qimageiohandler.h>
class DDSHandler : public QImageIOHandler
{
public:
DDSHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
#endif

View file

@ -1,357 +0,0 @@
/**
* QImageIO Routines to read/write EPS images.
* copyright (c) 1998 Dirk Schoenberger <dirk.schoenberger@freenet.de>
*
* This library is distributed under the conditions of the GNU LGPL.
*/
#include "eps.h"
#include <unistd.h>
#include <stdio.h>
#include <QtGui/QImage>
#include <QtCore/QFile>
#include <QtGui/QPainter>
#include <QtGui/QPrinter>
#include <QtCore/QTextStream>
#include <QtCore/QTemporaryFile>
#include <kapplication.h>
#include <kdebug.h>
#include <kdeversion.h>
#define BUFLEN 200
#define BBOX "%%BoundingBox:"
#define BBOX_LEN strlen(BBOX)
static bool seekToCodeStart( QIODevice * io, quint32 & ps_offset, quint32 & ps_size )
{
char buf[4]; // We at most need to read 4 bytes at a time
ps_offset=0L;
ps_size=0L;
if ( io->read(buf, 2)!=2 ) // Read first two bytes
{
kError(399) << "kimgio EPS: EPS file has less than 2 bytes." << endl;
return false;
}
if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
{
kDebug(399) << "kimgio EPS: normal EPS file";
}
else if ( buf[0]==char(0xc5) && buf[1]==char(0xd0) ) // Check start of MS-DOS EPS magic
{ // May be a MS-DOS EPS file
if ( io->read(buf+2, 2)!=2 ) // Read further bytes of MS-DOS EPS magic
{
kError(399) << "kimgio EPS: potential MS-DOS EPS file has less than 4 bytes." << endl;
return false;
}
if ( buf[2]==char(0xd3) && buf[3]==char(0xc6) ) // Check last bytes of MS-DOS EPS magic
{
if (io->read(buf, 4)!=4) // Get offset of PostScript code in the MS-DOS EPS file.
{
kError(399) << "kimgio EPS: cannot read offset of MS-DOS EPS file" << endl;
return false;
}
ps_offset // Offset is in little endian
= ((unsigned char) buf[0])
+ ((unsigned char) buf[1] << 8)
+ ((unsigned char) buf[2] << 16)
+ ((unsigned char) buf[3] << 24);
if (io->read(buf, 4)!=4) // Get size of PostScript code in the MS-DOS EPS file.
{
kError(399) << "kimgio EPS: cannot read size of MS-DOS EPS file" << endl;
return false;
}
ps_size // Size is in little endian
= ((unsigned char) buf[0])
+ ((unsigned char) buf[1] << 8)
+ ((unsigned char) buf[2] << 16)
+ ((unsigned char) buf[3] << 24);
kDebug(399) << "kimgio EPS: Offset: " << ps_offset <<" Size: " << ps_size;
if ( !io->seek(ps_offset) ) // Get offset of PostScript code in the MS-DOS EPS file.
{
kError(399) << "kimgio EPS: cannot seek in MS-DOS EPS file" << endl;
return false;
}
if ( io->read(buf, 2)!=2 ) // Read first two bytes of what should be the Postscript code
{
kError(399) << "kimgio EPS: PostScript code has less than 2 bytes." << endl;
return false;
}
if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
{
kDebug(399) << "kimgio EPS: MS-DOS EPS file";
}
else
{
kError(399) << "kimgio EPS: supposed Postscript code of a MS-DOS EPS file doe not start with %!." << endl;
return false;
}
}
else
{
kError(399) << "kimgio EPS: wrong magic for potential MS-DOS EPS file!" << endl;
return false;
}
}
else
{
kError(399) << "kimgio EPS: not an EPS file!" << endl;
return false;
}
return true;
}
static bool bbox ( QIODevice *io, int *x1, int *y1, int *x2, int *y2)
{
char buf[BUFLEN+1];
bool ret = false;
while (io->readLine(buf, BUFLEN) > 0)
{
if (strncmp (buf, BBOX, BBOX_LEN) == 0)
{
// Some EPS files have non-integer values for the bbox
// We don't support that currently, but at least we parse it
float _x1, _y1, _x2, _y2;
if ( sscanf (buf, "%*s %f %f %f %f",
&_x1, &_y1, &_x2, &_y2) == 4) {
kDebug(399) << "kimgio EPS BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2;
*x1=(int)_x1; *y1=(int)_y1; *x2=(int)_x2; *y2=(int)_y2;
ret = true;
break;
}
}
}
return ret;
}
EPSHandler::EPSHandler()
{
}
bool EPSHandler::canRead() const
{
if (canRead(device())) {
setFormat("eps");
return true;
}
return false;
}
bool EPSHandler::read(QImage *image)
{
kDebug(399) << "kimgio EPS: starting...";
FILE * ghostfd;
int x1, y1, x2, y2;
//QTime dt;
//dt.start();
QString cmdBuf;
QString tmp;
QIODevice* io = device();
quint32 ps_offset, ps_size;
// find start of PostScript code
if ( !seekToCodeStart(io, ps_offset, ps_size) )
return false;
// find bounding box
if ( !bbox (io, &x1, &y1, &x2, &y2)) {
kError(399) << "kimgio EPS: no bounding box found!" << endl;
return false;
}
QTemporaryFile tmpFile;
if( !tmpFile.open() ) {
kError(399) << "kimgio EPS: no temp file!" << endl;
return false;
}
// x1, y1 -> translation
// x2, y2 -> new size
x2 -= x1;
y2 -= y1;
//kDebug(399) << "origin point: " << x1 << "," << y1 << " size:" << x2 << "," << y2;
double xScale = 1.0;
double yScale = 1.0;
int wantedWidth = x2;
int wantedHeight = y2;
// create GS command line
cmdBuf = "gs -sOutputFile=";
cmdBuf += tmpFile.fileName();
cmdBuf += " -q -g";
tmp.setNum( wantedWidth );
cmdBuf += tmp;
tmp.setNum( wantedHeight );
cmdBuf += 'x';
cmdBuf += tmp;
cmdBuf += " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
"0 0 moveto "
"1000 0 lineto "
"1000 1000 lineto "
"0 1000 lineto "
"1 1 254 255 div setrgbcolor fill "
"0 0 0 setrgbcolor - -c showpage quit";
// run ghostview
ghostfd = popen (QFile::encodeName(cmdBuf), "w");
if ( ghostfd == 0 ) {
kError(399) << "kimgio EPS: no GhostScript?" << endl;
return false;
}
fprintf (ghostfd, "\n%d %d translate\n", -qRound(x1*xScale), -qRound(y1*yScale));
// write image to gs
io->reset(); // Go back to start of file to give all the file to GhostScript
if (ps_offset>0L) // We have an offset
io->seek(ps_offset);
QByteArray buffer ( io->readAll() );
// If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
if (ps_size<=0 || ps_size>(unsigned int)buffer.size())
ps_size=buffer.size();
fwrite(buffer.data(), sizeof(char), ps_size, ghostfd);
buffer.resize(0);
pclose ( ghostfd );
// load image
if( image->load (tmpFile.fileName()) ) {
kDebug(399) << "kimgio EPS: success!";
//kDebug(399) << "Loading EPS took " << (float)(dt.elapsed()) / 1000 << " seconds";
return true;
}
kError(399) << "kimgio EPS: no image!" << endl;
return false;
}
// Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot)
bool EPSHandler::write(const QImage &image)
{
QPrinter psOut(QPrinter::PrinterResolution);
QPainter p;
// making some definitions (papersize, output to file, filename):
psOut.setCreator( "KDE " KDE_VERSION_STRING );
if ( psOut.outputFileName().isEmpty() )
psOut.setOutputFileName( "untitled_printer_document" );
// Extension must be .eps so that Qt generates EPS file
QTemporaryFile tmpFile("XXXXXXXX.eps");
if ( !tmpFile.open() )
return false;
psOut.setOutputFileName(tmpFile.fileName());
psOut.setOutputFormat(QPrinter::PostScriptFormat);
psOut.setFullPage(true);
psOut.setPaperSize(image.size(), QPrinter::DevicePixel);
// painting the pixmap to the "printer" which is a file
p.begin( &psOut );
p.drawImage( QPoint( 0, 0 ), image );
p.end();
// Copy file to imageio struct
QFile inFile(tmpFile.fileName());
if ( !inFile.open( QIODevice::ReadOnly ) )
return false;
QTextStream in( &inFile );
in.setCodec( "ISO-8859-1" );
QTextStream out( device() );
out.setCodec( "ISO-8859-1" );
QString szInLine = in.readLine();
out << szInLine << '\n';
while( !in.atEnd() ){
szInLine = in.readLine();
out << szInLine << '\n';
}
inFile.close();
return true;
}
QByteArray EPSHandler::name() const
{
return "eps";
}
bool EPSHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("EPSHandler::canRead() called with no device");
return false;
}
qint64 oldPos = device->pos();
QByteArray head = device->readLine(64);
int readBytes = head.size();
if (device->isSequential()) {
while (readBytes > 0)
device->ungetChar(head[readBytes-- - 1]);
} else {
device->seek(oldPos);
}
return head.contains("%!PS-Adobe");
}
class EPSPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList EPSPlugin::keys() const
{
return QStringList() << "eps" << "EPS" << "epsi" << "EPSI" << "epsf" << "EPSF";
}
QImageIOPlugin::Capabilities EPSPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "eps" || format == "epsi" || format == "EPS" || format == "EPSI" ||
format == "epsf" || format == "EPSF")
return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && EPSHandler::canRead(device))
cap |= CanRead;
if (device->isWritable())
cap |= CanWrite;
return cap;
}
QImageIOHandler *EPSPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new EPSHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(eps, EPSPlugin)

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=eps,epsi,epsf X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-eps X-KDE-MimeType=image/x-eps
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=true X-KDE-Write=false

View file

@ -1,28 +0,0 @@
/**
* QImageIO Routines to read/write EPS images.
* copyright (c) 1998 Dirk Schoenberger <dirk.schoenberger@freenet.de>
*
* This library is distributed under the conditions of the GNU LGPL.
*/
#ifndef EPS_H
#define EPS_H
#include <QtGui/qimageiohandler.h>
class EPSHandler : public QImageIOHandler
{
public:
EPSHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
#endif

View file

@ -1,270 +0,0 @@
// -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
/**
* KImageIO Routines to read (and perhaps in the future, write) images
* in the high dynamic range EXR format.
* Copyright (c) 2003, Brad Hards <bradh@frogmouth.net>
*
* This library is distributed under the conditions of the GNU LGPL.
*/
#include "exr.h"
#include <config.h>
#include <ImfRgbaFile.h>
#include <ImfStandardAttributes.h>
#include <ImathBox.h>
#include <ImfInputFile.h>
#include <ImfBoxAttribute.h>
#include <ImfChannelListAttribute.h>
#include <ImfCompressionAttribute.h>
#include <ImfFloatAttribute.h>
#include <ImfIntAttribute.h>
#include <ImfLineOrderAttribute.h>
#include <ImfStringAttribute.h>
#include <ImfVecAttribute.h>
#include <ImfArray.h>
#include <ImfConvert.h>
#include <ImfVersion.h>
#include <IexThrowErrnoExc.h>
#include <OpenEXRConfig.h>
#include <iostream>
#include <kdebug.h>
#include <QImage>
#include <QDataStream>
#include <QtGui/qimageiohandler.h>
#if defined(OPENEXR_VERSION_MAJOR) && OPENEXR_VERSION_MAJOR >= 3
# define K_OE_INT_TYPE uint64_t
#else
# define K_OE_INT_TYPE Imf::Int64
#endif
class K_IStream: public Imf::IStream
{
public:
K_IStream( QIODevice *dev, const QByteArray& fileName ):
IStream( fileName.data() ), m_dev ( dev )
{}
virtual bool read( char c[], int n );
virtual K_OE_INT_TYPE tellg( );
virtual void seekg( K_OE_INT_TYPE pos );
virtual void clear( );
private:
QIODevice *m_dev;
};
bool K_IStream::read( char c[], int n )
{
qint64 result = m_dev->read( c, n );
if ( result > 0 ) {
return true;
} else if ( result == 0 ) {
throw Iex::InputExc( "Unexpected end of file" );
} else // negative value {
Iex::throwErrnoExc( "Error in read", result );
return false;
}
K_OE_INT_TYPE K_IStream::tellg( )
{
return m_dev->pos();
}
void K_IStream::seekg( K_OE_INT_TYPE pos )
{
m_dev->seek( pos );
}
void K_IStream::clear( )
{
// TODO
}
/* this does a conversion from the ILM Half (equal to Nvidia Half)
* format into the normal 32 bit pixel format. Process is from the
* ILM code.
*/
QRgb RgbaToQrgba(struct Imf::Rgba imagePixel)
{
float r,g,b,a;
// 1) Compensate for fogging by subtracting defog
// from the raw pixel values.
// Response: We work with defog of 0.0, so this is a no-op
// 2) Multiply the defogged pixel values by
// 2^(exposure + 2.47393).
// Response: We work with exposure of 0.0.
// (2^2.47393) is 5.55555
r = imagePixel.r * 5.55555;
g = imagePixel.g * 5.55555;
b = imagePixel.b * 5.55555;
a = imagePixel.a * 5.55555;
// 3) Values, which are now 1.0, are called "middle gray".
// If defog and exposure are both set to 0.0, then
// middle gray corresponds to a raw pixel value of 0.18.
// In step 6, middle gray values will be mapped to an
// intensity 3.5 f-stops below the display's maximum
// intensity.
// Response: no apparent content.
// 4) Apply a knee function. The knee function has two
// parameters, kneeLow and kneeHigh. Pixel values
// below 2^kneeLow are not changed by the knee
// function. Pixel values above kneeLow are lowered
// according to a logarithmic curve, such that the
// value 2^kneeHigh is mapped to 2^3.5 (in step 6,
// this value will be mapped to the display's
// maximum intensity).
// Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
if (r > 1.0)
r = 1.0 + Imath::Math<float>::log ((r-1.0) * 0.184874 + 1) / 0.184874;
if (g > 1.0)
g = 1.0 + Imath::Math<float>::log ((g-1.0) * 0.184874 + 1) / 0.184874;
if (b > 1.0)
b = 1.0 + Imath::Math<float>::log ((b-1.0) * 0.184874 + 1) / 0.184874;
if (a > 1.0)
a = 1.0 + Imath::Math<float>::log ((a-1.0) * 0.184874 + 1) / 0.184874;
//
// 5) Gamma-correct the pixel values, assuming that the
// screen's gamma is 0.4545 (or 1/2.2).
r = Imath::Math<float>::pow (r, 0.4545);
g = Imath::Math<float>::pow (g, 0.4545);
b = Imath::Math<float>::pow (b, 0.4545);
a = Imath::Math<float>::pow (a, 0.4545);
// 6) Scale the values such that pixels middle gray
// pixels are mapped to 84.66 (or 3.5 f-stops below
// the display's maximum intensity).
//
// 7) Clamp the values to [0, 255].
return qRgba( (unsigned char) (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ),
(unsigned char) (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ),
(unsigned char) (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ),
(unsigned char) (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) );
}
EXRHandler::EXRHandler()
{
}
bool EXRHandler::canRead() const
{
if (canRead(device())) {
setFormat("exr");
return true;
}
return false;
}
QByteArray EXRHandler::name() const
{
// TODO
return QByteArray("exr");
}
bool EXRHandler::read( QImage *outImage )
{
try
{
int width, height;
K_IStream istr( device(), QByteArray() );
Imf::RgbaInputFile file( istr );
Imath::Box2i dw = file.dataWindow();
width = dw.max.x - dw.min.x + 1;
height = dw.max.y - dw.min.y + 1;
Imf::Array2D<Imf::Rgba> pixels;
pixels.resizeErase (height, width);
file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
file.readPixels (dw.min.y, dw.max.y);
QImage image(width, height, QImage::Format_RGB32);
if( image.isNull())
return false;
// somehow copy pixels into image
for ( int y=0; y < height; y++ ) {
for ( int x=0; x < width; x++ ) {
// copy pixels(x,y) into image(x,y)
image.setPixel( x, y, RgbaToQrgba( pixels[y][x] ) );
}
}
*outImage = image;
return true;
}
catch (const std::exception &exc)
{
kDebug() << exc.what();
return false;
}
}
bool EXRHandler::write( const QImage &image )
{
// TODO: stub
Q_UNUSED( image );
return false;
}
bool EXRHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("EXRHandler::canRead() called with no device");
return false;
}
const QByteArray head = device->peek(4);
return Imf::isImfMagic( head.data() );
}
/* --- Plugin --- */
QStringList EXRPlugin::keys() const
{
return QStringList() << "exr" << "EXR";
}
QImageIOPlugin::Capabilities EXRPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if ( format == "exr" || format == "EXR" )
return Capabilities(CanRead);
if ( !format.isEmpty() )
return 0;
if ( !device->isOpen() )
return 0;
Capabilities cap;
if (device->isReadable() && EXRHandler::canRead(device))
cap |= CanRead;
return cap;
}
QImageIOHandler *EXRPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new EXRHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2( exr, EXRPlugin )

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=exr X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-exr X-KDE-MimeType=image/x-exr
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=false X-KDE-Write=false

View file

@ -1,68 +0,0 @@
/**
* QImageIO Routines to read (and perhaps in the future, write) images
* in the high definition EXR format.
*
* Copyright (c) 2003, Brad Hards <bradh@frogmouth.net>
*
* This library is distributed under the conditions of the GNU LGPL.
*
*/
#ifndef KIMG_EXR_H
#define KIMG_EXR_H
#include <QtGui/qimageiohandler.h>
class EXRHandler : public QImageIOHandler
{
public:
EXRHandler();
/**
Test if the file / stream can potentially read more data
*/
bool canRead() const;
/**
Read contents from the file / stream into an image
\param outImage pointer to the QImage that the file / stream will
be read into
\return true on a successful read, false on failure
*/
bool read( QImage *outImage );
/**
Write the contents of an image into the file / stream
\param image the image to write out
\return true on a successful write, false on failure
*/
bool write( const QImage &image );
/**
The name of this plugin
\return always returns "exr" for this plugin
*/
QByteArray name() const;
/**
Convenience routine. You should use canRead() instead.
*/
static bool canRead( QIODevice *device );
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
class EXRPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
#endif
#endif

View file

@ -1,416 +0,0 @@
#ifndef GIMP_H
#define GIMP_H
/* -*- c++ -*-
* gimp.h: Header for a Qt 3 plug-in for reading GIMP XCF image files
* Copyright (C) 2001 lignum Computing, Inc. <allen@lignumcomputing.com>
* Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
*
* This plug-in 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
typedef unsigned char uchar;
/*
* These are the constants and functions I extracted from The GIMP source
* code. If the reader fails to work, this is probably the place to start
* looking for discontinuities.
*/
// From GIMP "tile.h" v1.2
const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file.
const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
// From GIMP "paint_funcs.c" v1.2
const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table.
const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table.
const double EPSILON = 0.0001; //!< Roundup in alpha blending.
// From GIMP "paint_funcs.h" v1.2
const uchar OPAQUE_OPACITY = 255; //!< Opaque value for 8-bit alpha component.
// From GIMP "apptypes.h" v1.2
//! Basic GIMP image type. QImage converter may produce a deeper image
//! than is specified here. For example, a grayscale image with an
//! alpha channel must (currently) use a 32-bit Qt image.
typedef enum
{
RGB,
GRAY,
INDEXED
} GimpImageBaseType;
//! Type of individual layers in an XCF file.
typedef enum
{
RGB_GIMAGE,
RGBA_GIMAGE,
GRAY_GIMAGE,
GRAYA_GIMAGE,
INDEXED_GIMAGE,
INDEXEDA_GIMAGE
} GimpImageType;
// From GIMP "libgimp/gimpenums.h" v2.4
//! Effect to apply when layers are merged together.
typedef enum
{
NORMAL_MODE,
DISSOLVE_MODE,
BEHIND_MODE,
MULTIPLY_MODE,
SCREEN_MODE,
OVERLAY_MODE,
DIFFERENCE_MODE,
ADDITION_MODE,
SUBTRACT_MODE,
DARKEN_ONLY_MODE,
LIGHTEN_ONLY_MODE,
HUE_MODE,
SATURATION_MODE,
COLOR_MODE,
VALUE_MODE,
DIVIDE_MODE,
DODGE_MODE,
BURN_MODE,
HARDLIGHT_MODE,
SOFTLIGHT_MODE,
GRAIN_EXTRACT_MODE,
GRAIN_MERGE_MODE
} LayerModeEffects;
// From GIMP "xcf.c" v1.2
//! Properties which can be stored in an XCF file.
typedef enum
{
PROP_END = 0,
PROP_COLORMAP = 1,
PROP_ACTIVE_LAYER = 2,
PROP_ACTIVE_CHANNEL = 3,
PROP_SELECTION = 4,
PROP_FLOATING_SELECTION = 5,
PROP_OPACITY = 6,
PROP_MODE = 7,
PROP_VISIBLE = 8,
PROP_LINKED = 9,
PROP_PRESERVE_TRANSPARENCY = 10,
PROP_APPLY_MASK = 11,
PROP_EDIT_MASK = 12,
PROP_SHOW_MASK = 13,
PROP_SHOW_MASKED = 14,
PROP_OFFSETS = 15,
PROP_COLOR = 16,
PROP_COMPRESSION = 17,
PROP_GUIDES = 18,
PROP_RESOLUTION = 19,
PROP_TATTOO = 20,
PROP_PARASITES = 21,
PROP_UNIT = 22,
PROP_PATHS = 23,
PROP_USER_UNIT = 24
} PropType;
// From GIMP "xcf.c" v1.2
//! Compression type used in layer tiles.
typedef enum
{
COMPRESS_NONE = 0,
COMPRESS_RLE = 1,
COMPRESS_ZLIB = 2,
COMPRESS_FRACTAL = 3 /* Unused. */
} CompressionType;
// From GIMP "paint_funcs.c" v1.2
/*!
* Multiply two color components. Really expects the arguments to be
* 8-bit quantities.
* \param a first minuend.
* \param b second minuend.
* \return product of arguments.
*/
inline int INT_MULT ( int a, int b )
{
int c = a * b + 0x80;
return ( ( c >> 8 ) + c ) >> 8;
}
/*!
* Blend the two color components in the proportion alpha:
*
* result = alpha a + ( 1 - alpha ) b
*
* \param a first component.
* \param b second component.
* \param alpha blend proportion.
* \return blended color components.
*/
inline int INT_BLEND ( int a, int b, int alpha )
{
return INT_MULT( a - b, alpha ) + b;
}
// From GIMP "gimpcolorspace.c" v1.2
/*!
* Convert a color in RGB space to HSV space (Hue, Saturation, Value).
* \param red the red component (modified in place).
* \param green the green component (modified in place).
* \param blue the blue component (modified in place).
*/
static void RGBTOHSV ( uchar& red, uchar& green, uchar& blue )
{
int r, g, b;
double h, s, v;
int min, max;
h = 0.;
r = red;
g = green;
b = blue;
if ( r > g ) {
max = qMax( r, b );
min = qMin( g, b );
}
else {
max = qMax( g, b );
min = qMin( r, b );
}
v = max;
if ( max != 0 )
s = ( ( max - min ) * 255 ) / (double)max;
else
s = 0;
if ( s == 0 )
h = 0;
else {
int delta = max - min;
if ( r == max )
h = ( g - b ) / (double)delta;
else if ( g == max )
h = 2 + ( b - r ) / (double)delta;
else if ( b == max )
h = 4 + ( r - g ) / (double)delta;
h *= 42.5;
if ( h < 0 )
h += 255;
if ( h > 255 )
h -= 255;
}
red = (uchar)h;
green = (uchar)s;
blue = (uchar)v;
}
/*!
* Convert a color in HSV space to RGB space.
* \param hue the hue component (modified in place).
* \param saturation the saturation component (modified in place).
* \param value the value component (modified in place).
*/
static void HSVTORGB ( uchar& hue, uchar& saturation, uchar& value )
{
if ( saturation == 0 ) {
hue = value;
saturation = value;
//value = value;
}
else {
double h = hue * 6. / 255.;
double s = saturation / 255.;
double v = value / 255.;
double f = h - (int)h;
double p = v * ( 1. - s );
double q = v * ( 1. - ( s * f ) );
double t = v * ( 1. - ( s * ( 1. - f ) ) );
// Worth a note here that gcc 2.96 will generate different results
// depending on optimization mode on i386.
switch ((int)h) {
case 0:
hue = (uchar)( v * 255 );
saturation = (uchar)( t * 255 );
value = (uchar)( p * 255 );
break;
case 1:
hue = (uchar)( q * 255 );
saturation = (uchar)( v * 255 );
value = (uchar)( p * 255 );
break;
case 2:
hue = (uchar)( p * 255 );
saturation = (uchar)( v * 255 );
value = (uchar)( t * 255 );
break;
case 3:
hue = (uchar)( p * 255 );
saturation = (uchar)( q * 255 );
value = (uchar)( v * 255 );
break;
case 4:
hue = (uchar)( t * 255 );
saturation = (uchar)( p * 255 );
value = (uchar)( v * 255 );
break;
case 5:
hue = (uchar)( v * 255 );
saturation = (uchar)( p * 255 );
value = (uchar)( q * 255 );
}
}
}
/*!
* Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
* \param red the red component (modified in place).
* \param green the green component (modified in place).
* \param blue the blue component (modified in place).
*/
static void RGBTOHLS ( uchar& red, uchar& green, uchar& blue )
{
int r = red;
int g = green;
int b = blue;
int min, max;
if ( r > g ) {
max = qMax( r, b );
min = qMin( g, b );
}
else {
max = qMax( g, b );
min = qMin( r, b );
}
double h;
double l = ( max + min ) / 2.;
double s;
if ( max == min ) {
s = 0.;
h = 0.;
}
else {
int delta = max - min;
if ( l < 128 )
s = 255 * (double)delta / (double)( max + min );
else
s = 255 * (double)delta / (double)( 511 - max - min );
if ( r == max )
h = ( g - b ) / (double)delta;
else if ( g == max )
h = 2 + ( b - r ) / (double)delta;
else
h = 4 + ( r - g ) / (double)delta;
h *= 42.5;
if ( h < 0 )
h += 255;
else if ( h > 255 )
h -= 255;
}
red = (uchar)h;
green = (uchar)l;
blue = (uchar)s;
}
/*!
* Implement the HLS "double hex-cone".
* \param n1 lightness fraction (?)
* \param n2 saturation fraction (?)
* \param hue hue "angle".
* \return HLS value.
*/
static int HLSVALUE ( double n1, double n2, double hue )
{
double value;
if ( hue > 255 )
hue -= 255;
else if ( hue < 0 )
hue += 255;
if ( hue < 42.5 )
value = n1 + ( n2 - n1 ) * ( hue / 42.5 );
else if ( hue < 127.5 )
value = n2;
else if ( hue < 170 )
value = n1 + ( n2 - n1 ) * ( ( 170 - hue ) / 42.5 );
else
value = n1;
return (int)( value * 255 );
}
/*!
* Convert a color in HLS space to RGB space.
* \param hue the hue component (modified in place).
* \param lightness the lightness component (modified in place).
* \param saturation the saturation component (modified in place).
*/
static void HLSTORGB ( uchar& hue, uchar& lightness, uchar& saturation )
{
double h = hue;
double l = lightness;
double s = saturation;
if ( s == 0 ) {
hue = (uchar)l;
lightness = (uchar)l;
saturation = (uchar)l;
}
else {
double m1, m2;
if ( l < 128 )
m2 = ( l * ( 255 + s ) ) / 65025.;
else
m2 = ( l + s - ( l * s ) / 255. ) / 255.;
m1 = ( l / 127.5 ) - m2;
hue = HLSVALUE( m1, m2, h + 85 );
lightness = HLSVALUE( m1, m2, h );
saturation = HLSVALUE( m1, m2, h - 85 );
}
}
#endif

View file

@ -1,264 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
Copyright (C) 2005 Ignacio Castaño <castanyo@yahoo.es>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#include "hdr.h"
#include <QtGui/QImage>
#include <QtCore/QDataStream>
#include <kdebug.h>
typedef Q_UINT8 uchar;
namespace { // Private.
#define MAXLINE 1024
#define MINELEN 8 // minimum scanline length for encoding
#define MAXELEN 0x7fff // maximum scanline length for encoding
static inline uchar ClipToByte(float value)
{
if (value > 255.0f) return 255;
//else if (value < 0.0f) return 0; // we know value is positive.
return uchar(value);
}
// read an old style line from the hdr image file
// if 'first' is true the first byte is already read
static bool Read_Old_Line (uchar * image, int width, QDataStream & s)
{
int rshift = 0;
int i;
while (width > 0)
{
s >> image[0];
s >> image[1];
s >> image[2];
s >> image[3];
if (s.atEnd()) return false;
if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1))
{
for (i = image[3] << rshift; i > 0; i--)
{
//memcpy(image, image-4, 4);
(uint &)image[0] = (uint &)image[0-4];
image += 4;
width--;
}
rshift += 8;
}
else
{
image += 4;
width--;
rshift = 0;
}
}
return true;
}
static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
{
for (int j = 0; j < width; j++)
{
// v = ldexp(1.0, int(image[3]) - 128);
float v;
int e = int(image[3]) - 128;
if( e > 0 )
{
v = float(1 << e);
}
else
{
v = 1.0f / float(1 << -e);
}
scanline[j] = qRgb( ClipToByte(float(image[0]) * v),
ClipToByte(float(image[1]) * v),
ClipToByte(float(image[2]) * v) );
image += 4;
}
}
// Load the HDR image.
static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
{
uchar val, code;
// Create dst image.
if( !img.create( width, height, 32 ) )
{
return false;
}
QMemArray<uchar> image( width * 4 );
for (int cline = 0; cline < height; cline++)
{
QRgb * scanline = (QRgb *) img.scanLine( cline );
// determine scanline type
if ((width < MINELEN) || (MAXELEN < width))
{
Read_Old_Line(image.data(), width, s);
RGBE_To_QRgbLine(image.data(), scanline, width);
continue;
}
s >> val;
if (s.atEnd())
{
return true;
}
if (val != 2)
{
s.device()->at( s.device()->at() - 1 );
Read_Old_Line(image.data(), width, s);
RGBE_To_QRgbLine(image.data(), scanline, width);
continue;
}
s >> image[1];
s >> image[2];
s >> image[3];
if (s.atEnd())
{
return true;
}
if ((image[1] != 2) || (image[2] & 128))
{
image[0] = 2;
Read_Old_Line(image.data()+4, width-1, s);
RGBE_To_QRgbLine(image.data(), scanline, width);
continue;
}
if ((image[2] << 8 | image[3]) != width)
{
return false;
}
// read each component
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < width; )
{
s >> code;
if (s.atEnd())
{
return false;
}
if (code > 128)
{
// run
code &= 127;
s >> val;
while( code != 0 )
{
image[i + j * 4] = val;
j++;
code--;
}
}
else
{
// non-run
while( code != 0 )
{
s >> image[i + j * 4];
j++;
code--;
}
}
}
}
RGBE_To_QRgbLine(image.data(), scanline, width);
}
return true;
}
} // namespace
KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
{
int len;
char line[MAXLINE];
//bool validHeader = false;
bool validFormat = false;
// Parse header
do {
len = io->ioDevice()->readLine(line, MAXLINE);
/*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
{
validHeader = true;
}*/
if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
{
validFormat = true;
}
} while((len > 0) && (line[0] != '\n'));
if( /*!validHeader ||*/ !validFormat )
{
kDebug(399) << "Unknown HDR format.";
io->setImage( 0 );
io->setStatus( -1 );
return;
}
io->ioDevice()->readLine(line, MAXLINE);
char s1[3], s2[3];
int width, height;
if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
//if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
{
kDebug(399) << "Invalid HDR file.";
io->setImage( 0 );
io->setStatus( -1 );
return;
}
QDataStream s( io->ioDevice() );
QImage img;
if( !LoadHDR(s, width, height, img) )
{
kDebug(399) << "Error loading HDR file.";
io->setImage( 0 );
io->setStatus( -1 );
return;
}
io->setImage( img );
io->setStatus( 0 );
}
KDE_EXPORT void kimgio_hdr_write( QImageIO * )
{
// intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
}

View file

@ -1,7 +0,0 @@
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=hdr
X-KDE-MimeType=image/x-hdr
X-KDE-Read=true
X-KDE-Write=false

View file

@ -1,21 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef KIMG_HDR_H
#define KIMG_HDR_H
class QImageIO;
extern "C" {
void kimgio_hdr_read( QImageIO * );
void kimgio_hdr_write( QImageIO * );
}
#endif

View file

@ -1,511 +0,0 @@
/**
* QImageIO Routines to read/write JPEG2000 images.
* copyright (c) 2002 Michael Ritzert <michael@ritzert.de>
*
* This library is distributed under the conditions of the GNU LGPL.
*/
#include "jp2.h"
#include <config.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <QImage>
#include <QVariant>
#include <QTextStream>
// dirty, but avoids a warning because jasper.h includes jas_config.h.
#undef PACKAGE
#undef VERSION
#include <jasper/jasper.h>
// code taken in parts from JasPer's jiv.c
#define DEFAULT_RATE 0.10
#define MAXCMPTS 256
/************************* JasPer QIODevice stream ***********************/
//unfortunately this is declared as static in JasPer libraries
static jas_stream_t *jas_stream_create()
{
jas_stream_t *stream;
if (!(stream = (jas_stream_t*)jas_malloc(sizeof(jas_stream_t)))) {
return 0;
}
stream->openmode_ = 0;
stream->bufmode_ = 0;
stream->flags_ = 0;
stream->bufbase_ = 0;
stream->bufstart_ = 0;
stream->bufsize_ = 0;
stream->ptr_ = 0;
stream->cnt_ = 0;
stream->ops_ = 0;
stream->obj_ = 0;
stream->rwcnt_ = 0;
stream->rwlimit_ = -1;
return stream;
}
//unfortunately this is declared as static in JasPer libraries
static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
int bufsize)
{
/* If this function is being called, the buffer should not have been
initialized yet. */
assert(!stream->bufbase_);
if (bufmode != JAS_STREAM_UNBUF) {
/* The full- or line-buffered mode is being employed. */
if (!buf) {
/* The caller has not specified a buffer to employ, so allocate
one. */
if ((stream->bufbase_ = (unsigned char*)jas_malloc(JAS_STREAM_BUFSIZE +
JAS_STREAM_MAXPUTBACK))) {
stream->bufmode_ |= JAS_STREAM_FREEBUF;
stream->bufsize_ = JAS_STREAM_BUFSIZE;
} else {
/* The buffer allocation has failed. Resort to unbuffered
operation. */
stream->bufbase_ = stream->tinybuf_;
stream->bufsize_ = 1;
}
} else {
/* The caller has specified a buffer to employ. */
/* The buffer must be large enough to accommodate maximum
putback. */
assert(bufsize > JAS_STREAM_MAXPUTBACK);
stream->bufbase_ = JAS_CAST(uchar *, buf);
stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
}
} else {
/* The unbuffered mode is being employed. */
/* A buffer should not have been supplied by the caller. */
assert(!buf);
/* Use a trivial one-character buffer. */
stream->bufbase_ = stream->tinybuf_;
stream->bufsize_ = 1;
}
stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
stream->ptr_ = stream->bufstart_;
stream->cnt_ = 0;
stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
}
static int qiodevice_read(jas_stream_obj_t *obj, char *buf, unsigned cnt)
{
QIODevice *io = (QIODevice*) obj;
return io->read(buf, cnt);
}
static int qiodevice_write(jas_stream_obj_t *obj, const char *buf, unsigned cnt)
{
QIODevice *io = (QIODevice*) obj;
return io->write(buf, cnt);
}
static long qiodevice_seek(jas_stream_obj_t *obj, long offset, int origin)
{
QIODevice *io = (QIODevice*) obj;
long newpos;
switch (origin) {
case SEEK_SET:
newpos = offset;
break;
case SEEK_END:
newpos = io->size() - offset;
break;
case SEEK_CUR:
newpos = io->pos() + offset;
break;
default:
return -1;
}
if (newpos < 0) {
return -1;
}
if ( io->seek(newpos) )
return newpos;
else
return -1;
}
static int qiodevice_close(jas_stream_obj_t *)
{
return 0;
}
static jas_stream_ops_t jas_stream_qiodeviceops = {
qiodevice_read,
qiodevice_write,
qiodevice_seek,
qiodevice_close
};
static jas_stream_t *jas_stream_qiodevice(QIODevice *iodevice)
{
jas_stream_t *stream;
if ( !iodevice ) return 0;
if (!(stream = jas_stream_create())) {
return 0;
}
/* A stream associated with a memory buffer is always opened
for both reading and writing in binary mode. */
stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0);
/* Select the operations for a memory stream. */
stream->obj_ = (void *)iodevice;
stream->ops_ = &jas_stream_qiodeviceops;
return stream;
}
/************************ End of JasPer QIODevice stream ****************/
typedef struct {
jas_image_t* image;
int cmptlut[MAXCMPTS];
jas_image_t* altimage;
} gs_t;
static jas_image_t*
read_image( QIODevice* io )
{
jas_stream_t* in = 0;
in = jas_stream_qiodevice( io );
if( !in ) return 0;
jas_image_t* image = jas_image_decode( in, -1, 0 );
jas_stream_close( in );
// image may be 0, but that's Ok
return image;
} // read_image
static bool
convert_colorspace( gs_t& gs )
{
jas_cmprof_t *outprof = jas_cmprof_createfromclrspc( JAS_CLRSPC_SRGB );
if( !outprof ) return false;
gs.altimage = jas_image_chclrspc( gs.image, outprof,
JAS_CMXFORM_INTENT_PER );
if( !gs.altimage ) return false;
return true;
} // convert_colorspace
static bool
render_view( gs_t& gs, QImage* outImage )
{
if ( !gs.altimage ) return false;
QImage qti;
if((gs.cmptlut[0] = jas_image_getcmptbytype(gs.altimage,
JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R))) < 0 ||
(gs.cmptlut[1] = jas_image_getcmptbytype(gs.altimage,
JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G))) < 0 ||
(gs.cmptlut[2] = jas_image_getcmptbytype(gs.altimage,
JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))) < 0) {
return false;
} // if
const int* cmptlut = gs.cmptlut;
int v[3];
// check that all components have the same size.
const int width = jas_image_cmptwidth( gs.altimage, cmptlut[0] );
const int height = jas_image_cmptheight( gs.altimage, cmptlut[0] );
for( int i = 1; i < 3; ++i ) {
if (jas_image_cmptwidth( gs.altimage, cmptlut[i] ) != width ||
jas_image_cmptheight( gs.altimage, cmptlut[i] ) != height)
return false;
} // for
jas_matrix_t *cmptmatrix[3];
jas_seqent_t *buf[3];
int prec[3];
for (int k = 0; k < 3; ++k ) {
prec[k] = jas_image_cmptprec(gs.altimage, cmptlut[k]);
if (!(cmptmatrix[k] = jas_matrix_create(1, width))) {
return false;
}
}
qti = QImage( jas_image_width( gs.altimage ), jas_image_height( gs.altimage ),
QImage::Format_RGB32 );
if (qti.isNull()) {
return false;
}
uint32_t* data = (uint32_t*)qti.bits();
for( int y = 0; y < height; ++y ) {
for( int k = 0; k < 3; ++k ) {
if (jas_image_readcmpt(gs.altimage, cmptlut[k], 0, y, width, 1, cmptmatrix[k])) {
return false;
}
buf[k] = jas_matrix_getref(cmptmatrix[k], 0, 0);
}
for( int x = 0; x < width; ++x ) {
for( int k = 0; k < 3; ++k ) {
v[k] = *buf[k];
// if the precision of the component is too small, increase
// it to use the complete value range.
v[k] <<= 8 - prec[k];
if( v[k] < 0 ) v[k] = 0;
else if( v[k] > 255 ) v[k] = 255;
++buf[k];
} // for k
*data++ = qRgb( v[0], v[1], v[2] );
} // for x
} // for y
for (int k = 0; k < 3; ++k ) {
if (cmptmatrix[k]) {
jas_matrix_destroy(cmptmatrix[k]);
}
}
*outImage = qti;
return true;
} // render_view
static jas_image_t*
create_image( const QImage& qi )
{
// prepare the component parameters
jas_image_cmptparm_t* cmptparms = new jas_image_cmptparm_t[ 3 ];
for ( int i = 0; i < 3; ++i ) {
// x and y offset
cmptparms[i].tlx = 0;
cmptparms[i].tly = 0;
// the resulting image will be hstep*width x vstep*height !
cmptparms[i].hstep = 1;
cmptparms[i].vstep = 1;
cmptparms[i].width = qi.width();
cmptparms[i].height = qi.height();
// we write everything as 24bit truecolor ATM
cmptparms[i].prec = 8;
cmptparms[i].sgnd = false;
}
jas_image_t* ji = jas_image_create( 3 /* number components */, cmptparms, JAS_CLRSPC_UNKNOWN );
delete[] cmptparms;
// returning 0 is ok
return ji;
} // create_image
static bool
write_components( jas_image_t* ji, const QImage& qi )
{
const unsigned height = qi.height();
const unsigned width = qi.width();
jas_matrix_t* m = jas_matrix_create( height, width );
if( !m ) return false;
jas_image_setclrspc( ji, JAS_CLRSPC_SRGB );
jas_image_setcmpttype( ji, 0, JAS_IMAGE_CT_RGB_R );
for( uint y = 0; y < height; ++y )
for( uint x = 0; x < width; ++x )
jas_matrix_set( m, y, x, qRed( qi.pixel( x, y ) ) );
jas_image_writecmpt( ji, 0, 0, 0, width, height, m );
jas_image_setcmpttype( ji, 1, JAS_IMAGE_CT_RGB_G );
for( uint y = 0; y < height; ++y )
for( uint x = 0; x < width; ++x )
jas_matrix_set( m, y, x, qGreen( qi.pixel( x, y ) ) );
jas_image_writecmpt( ji, 1, 0, 0, width, height, m );
jas_image_setcmpttype( ji, 2, JAS_IMAGE_CT_RGB_B );
for( uint y = 0; y < height; ++y )
for( uint x = 0; x < width; ++x )
jas_matrix_set( m, y, x, qBlue( qi.pixel( x, y ) ) );
jas_image_writecmpt( ji, 2, 0, 0, width, height, m );
jas_matrix_destroy( m );
return true;
} // write_components
static bool
write_image( const QImage &image, QIODevice* io, int quality )
{
jas_stream_t* stream = 0;
stream = jas_stream_qiodevice( io );
// by here, a jas_stream_t is open
if( !stream ) return false;
jas_image_t* ji = create_image( image );
if( !ji ) {
jas_stream_close( stream );
return false;
} // if
if( !write_components( ji, image ) ) {
jas_stream_close( stream );
jas_image_destroy( ji );
return false;
} // if
// optstr:
// - rate=#B => the resulting file size is about # bytes
// - rate=0.0 .. 1.0 => the resulting file size is about the factor times
// the uncompressed size
// use sprintf for locale-aware string
char rateBuffer[16];
sprintf(rateBuffer, "rate=%.2g\n", (quality < 0) ? DEFAULT_RATE : quality / 100.0);
int i = jp2_encode( ji, stream, rateBuffer);
jas_image_destroy( ji );
jas_stream_close( stream );
if( i != 0 ) return false;
return true;
}
JP2Handler::JP2Handler()
{
quality = 75;
jas_init();
}
JP2Handler::~JP2Handler()
{
jas_cleanup();
}
bool JP2Handler::canRead() const
{
if (canRead(device())) {
setFormat("jp2");
return true;
}
return false;
}
bool JP2Handler::canRead(QIODevice *device)
{
if (!device) {
return false;
}
return device->peek(6) == QByteArray("\x00\x00\x00\x0C\x6A\x50", 6);
}
bool JP2Handler::read(QImage *image)
{
if (!canRead()) return false;
gs_t gs;
if( !(gs.image = read_image( device() )) ) return false;
if( !convert_colorspace( gs ) ) return false;
render_view( gs, image );
if( gs.image ) jas_image_destroy( gs.image );
if( gs.altimage ) jas_image_destroy( gs.altimage );
return true;
}
bool JP2Handler::write(const QImage &image)
{
return write_image(image, device(),quality);
}
bool JP2Handler::supportsOption(ImageOption option) const
{
return option == Quality;
}
QVariant JP2Handler::option(ImageOption option) const
{
if (option == Quality)
return quality;
return QVariant();
}
void JP2Handler::setOption(ImageOption option, const QVariant &value)
{
if (option == Quality)
quality = qBound(-1, value.toInt(), 100);
}
QByteArray JP2Handler::name() const
{
return "jp2";
}
class JP2Plugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList JP2Plugin::keys() const
{
return QStringList() << "jp2";
}
QImageIOPlugin::Capabilities JP2Plugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "jp2")
return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && JP2Handler::canRead(device))
cap |= CanRead;
if (device->isWritable())
cap |= CanWrite;
return cap;
}
QImageIOHandler *JP2Plugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new JP2Handler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(jp2, JP2Plugin)

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=jp2 X-KDE-ImageFormat=magick
X-KDE-MimeType=image/jp2 X-KDE-MimeType=image/jp2
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=true X-KDE-Write=false

View file

@ -1,33 +0,0 @@
/**
* QImageIO Routines to read/write JPEG2000 images.
* copyright (c) 2002 Michael Ritzert <michael@ritzert.de>
*
* This library is distributed under the conditions of the GNU LGPL.
*/
#ifndef KIMG_JP2_H
#define KIMG_JP2_H
#include <QtGui/qimageiohandler.h>
class JP2Handler : public QImageIOHandler
{
public:
JP2Handler();
virtual ~JP2Handler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
bool supportsOption(ImageOption option) const;
QVariant option(ImageOption option) const;
void setOption(ImageOption option, const QVariant &value);
static bool canRead(QIODevice *device);
private:
int quality;
};
#endif

166
kimgio/magick.cpp Normal file
View file

@ -0,0 +1,166 @@
/* This file is part of the KDE libraries
Copyright (C) 2021 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 "magick.h"
#include <QtGui/QImage>
#include <QtCore/QDataStream>
#include <kdebug.h>
#include <Magick++/Functions.h>
#include <Magick++/Blob.h>
#include <Magick++/Image.h>
static const char* const magickpluginformat = "magick";
int initMagick()
{
Magick::InitializeMagick(magickpluginformat);
return 0;
}
Q_CONSTRUCTOR_FUNCTION(initMagick);
MagickHandler::MagickHandler()
{
}
MagickHandler::~MagickHandler()
{
Magick::TerminateMagick();
}
bool MagickHandler::canRead() const
{
if (canRead(device())) {
setFormat(magickpluginformat);
return true;
}
return false;
}
bool MagickHandler::read(QImage *image)
{
const QByteArray data = device()->readAll();
try {
Magick::Blob magickinblob(data.constData(), data.size());
Magick::Image magickinimage;
magickinimage.read(magickinblob);
if (Q_UNLIKELY(!magickinimage.isValid())) {
kWarning() << "image is not valid";
return false;
}
Magick::Blob magickoutblob;
magickinimage.write(&magickoutblob, "PNG");
const Magick::Geometry magicksize = magickinimage.size();
const size_t magickwidth = magicksize.width();
const size_t magickheight = magicksize.height();
if (Q_UNLIKELY(magickwidth > INT_MAX || magickheight > INT_MAX)) {
kWarning() << "image is too big";
return false;
}
image->loadFromData(reinterpret_cast<const char*>(magickoutblob.data()), magickoutblob.length(), "png");
return !image->isNull();
} catch(Magick::Exception &err) {
kWarning() << err.what();
return false;
} catch(std::exception &err) {
kWarning() << err.what();
return false;
} catch (...) {
return false;
}
return false;
}
bool MagickHandler::write(const QImage &image)
{
// this plugin is a read-only catch-all kind of plugin
return false;
}
QByteArray MagickHandler::name() const
{
return magickpluginformat;
}
bool MagickHandler::canRead(QIODevice *device)
{
if (Q_UNLIKELY(!device)) {
kWarning("MagickHandler::canRead() called with no device");
return false;
}
qint64 oldPos = device->pos();
bool isvalid = false;
const QByteArray data = device->readAll();
try {
Magick::Blob magickinblob(data.constData(), data.size());
Magick::Image magickimage;
magickimage.read(magickinblob);
// PNG handler used by this plugin
isvalid = (magickimage.isValid() && (qstrnicmp(magickimage.magick().c_str(), "png", 3) != 0));
} catch(Magick::Exception &err) {
kWarning() << err.what();
} catch(std::exception &err) {
kWarning() << err.what();
} catch (...) {
kWarning() << "exception raised";
}
device->seek(oldPos);
return isvalid;
}
QStringList MagickPlugin::keys() const
{
return QStringList() << magickpluginformat;
}
QImageIOPlugin::Capabilities MagickPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == magickpluginformat)
return Capabilities(CanRead);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && MagickHandler::canRead(device))
cap |= CanRead;
return cap;
}
QImageIOHandler *MagickPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new MagickHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(magick, MagickPlugin)

48
kimgio/magick.h Normal file
View file

@ -0,0 +1,48 @@
/* This file is part of the KDE libraries
Copyright (C) 2021 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_MAGICK_H
#define KIMG_MAGICK_H
#include <QtGui/qimageiohandler.h>
class MagickHandler : public QImageIOHandler
{
public:
MagickHandler();
~MagickHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
class MagickPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
#endif // KIMG_MAGICK_H

View file

@ -1,643 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2002-2005 Nadeem Hasan <nhasan@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (LGPL) as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#include "pcx.h"
#include <QtGui/QImage>
#include <kdebug.h>
static QDataStream &operator>>( QDataStream &s, RGB &rgb )
{
quint8 r, g, b;
s >> r >> g >> b;
rgb.r = r;
rgb.g = g;
rgb.b = b;
return s;
}
static QDataStream &operator>>( QDataStream &s, Palette &pal )
{
for ( int i=0; i<16; ++i )
s >> pal.rgb[ i ];
return s;
}
static QDataStream &operator>>( QDataStream &s, PCXHEADER &ph )
{
quint8 m, ver, enc, bpp;
s >> m >> ver >> enc >> bpp;
ph.Manufacturer = m;
ph.Version = ver;
ph.Encoding = enc;
ph.Bpp = bpp;
quint16 xmin, ymin, xmax, ymax;
s >> xmin >> ymin >> xmax >> ymax;
ph.XMin = xmin;
ph.YMin = ymin;
ph.XMax = xmax;
ph.YMax = ymax;
quint16 hdpi, ydpi;
s >> hdpi >> ydpi;
ph.HDpi = hdpi;
ph.YDpi = ydpi;
Palette colorMap;
quint8 res, np;
s >> colorMap >> res >> np;
ph.ColorMap = colorMap;
ph.Reserved = res;
ph.NPlanes = np;
quint16 bytesperline;
s >> bytesperline; ph.BytesPerLine = bytesperline;
quint16 paletteinfo;
s >> paletteinfo; ph.PaletteInfo = paletteinfo;
quint16 hscreensize, vscreensize;
s >> hscreensize; ph.HScreenSize = hscreensize;
s >> vscreensize; ph.VScreenSize = vscreensize;
// Skip the rest of the header
quint8 byte;
while ( s.device()->pos() < 128 )
s >> byte;
return s;
}
static QDataStream &operator<<( QDataStream &s, const RGB &rgb )
{
s << rgb.r << rgb.g << rgb.b;
return s;
}
static QDataStream &operator<<( QDataStream &s, const Palette &pal )
{
for ( int i=0; i<16; ++i )
s << pal.rgb[ i ];
return s;
}
static QDataStream &operator<<( QDataStream &s, const PCXHEADER &ph )
{
s << ph.Manufacturer;
s << ph.Version;
s << ph.Encoding;
s << ph.Bpp;
s << ph.XMin << ph.YMin << ph.XMax << ph.YMax;
s << ph.HDpi << ph.YDpi;
s << ph.ColorMap;
s << ph.Reserved;
s << ph.NPlanes;
s << ph.BytesPerLine;
s << ph.PaletteInfo;
s << ph.HScreenSize;
s << ph.VScreenSize;
quint8 byte = 0;
for ( int i=0; i<54; ++i )
s << byte;
return s;
}
PCXHEADER::PCXHEADER()
{
// Initialize all data to zero
QByteArray dummy( 128, 0 );
dummy.fill( 0 );
QDataStream s( &dummy, QIODevice::ReadOnly );
s >> *this;
}
static void readLine( QDataStream &s, QByteArray &buf, const PCXHEADER &header )
{
quint32 i=0;
quint32 size = buf.size();
quint8 byte, count;
if ( header.isCompressed() )
{
// Uncompress the image data
while ( i < size )
{
count = 1;
s >> byte;
if ( byte > 0xc0 )
{
count = byte - 0xc0;
s >> byte;
}
while ( count-- && i < size )
buf[ i++ ] = byte;
}
}
else
{
// Image is not compressed (possible?)
while ( i < size )
{
s >> byte;
buf[ i++ ] = byte;
}
}
}
static void readImage1( QImage &img, QDataStream &s, const PCXHEADER &header )
{
QByteArray buf( header.BytesPerLine, 0 );
img = QImage( header.width(), header.height(), QImage::Format_Mono );
img.setColorCount( 2 );
for ( int y=0; y<header.height(); ++y )
{
if ( s.atEnd() )
{
img = QImage();
return;
}
readLine( s, buf, header );
uchar *p = img.scanLine( y );
unsigned int bpl = qMin((quint16)((header.width()+7)/8), header.BytesPerLine);
for ( unsigned int x=0; x< bpl; ++x )
p[ x ] = buf[x];
}
// Set the color palette
img.setColor( 0, qRgb( 0, 0, 0 ) );
img.setColor( 1, qRgb( 255, 255, 255 ) );
}
static void readImage4( QImage &img, QDataStream &s, const PCXHEADER &header )
{
QByteArray buf( header.BytesPerLine*4, 0 );
QByteArray pixbuf( header.width(), 0 );
img = QImage( header.width(), header.height(), QImage::Format_Indexed8 );
img.setColorCount( 16 );
for ( int y=0; y<header.height(); ++y )
{
if ( s.atEnd() )
{
img = QImage();
return;
}
pixbuf.fill( 0 );
readLine( s, buf, header );
for ( int i=0; i<4; i++ )
{
quint32 offset = i*header.BytesPerLine;
for ( int x=0; x<header.width(); ++x )
if ( buf[ offset + ( x/8 ) ] & ( 128 >> ( x%8 ) ) )
pixbuf[ x ] = (int)(pixbuf[ x ]) + ( 1 << i );
}
uchar *p = img.scanLine( y );
for ( int x=0; x<header.width(); ++x )
p[ x ] = pixbuf[ x ];
}
// Read the palette
for ( int i=0; i<16; ++i )
img.setColor( i, header.ColorMap.color( i ) );
}
static void readImage8( QImage &img, QDataStream &s, const PCXHEADER &header )
{
QByteArray buf( header.BytesPerLine, 0 );
img = QImage( header.width(), header.height(), QImage::Format_Indexed8 );
img.setColorCount( 256 );
for ( int y=0; y<header.height(); ++y )
{
if ( s.atEnd() )
{
img = QImage();
return;
}
readLine( s, buf, header );
uchar *p = img.scanLine( y );
unsigned int bpl = qMin(header.BytesPerLine, (quint16)header.width());
for ( unsigned int x=0; x<bpl; ++x )
p[ x ] = buf[ x ];
}
quint8 flag;
s >> flag;
kDebug( 399 ) << "Palette Flag: " << flag;
if ( flag == 12 && ( header.Version == 5 || header.Version == 2 ) )
{
// Read the palette
quint8 r, g, b;
for ( int i=0; i<256; ++i )
{
s >> r >> g >> b;
img.setColor( i, qRgb( r, g, b ) );
}
}
}
static void readImage24( QImage &img, QDataStream &s, const PCXHEADER &header )
{
QByteArray r_buf( header.BytesPerLine, 0 );
QByteArray g_buf( header.BytesPerLine, 0 );
QByteArray b_buf( header.BytesPerLine, 0 );
img = QImage( header.width(), header.height(), QImage::Format_RGB32 );
for ( int y=0; y<header.height(); ++y )
{
if ( s.atEnd() )
{
img = QImage();
return;
}
readLine( s, r_buf, header );
readLine( s, g_buf, header );
readLine( s, b_buf, header );
uint *p = ( uint * )img.scanLine( y );
for ( int x=0; x<header.width(); ++x )
p[ x ] = qRgb( r_buf[ x ], g_buf[ x ], b_buf[ x ] );
}
}
static void writeLine( QDataStream &s, QByteArray &buf )
{
quint32 i = 0;
quint32 size = buf.size();
quint8 count, data;
char byte;
while ( i < size )
{
count = 1;
byte = buf[ i++ ];
while ( ( i < size ) && ( byte == buf[ i ] ) && ( count < 63 ) )
{
++i;
++count;
}
data = byte;
if ( count > 1 || data >= 0xc0 )
{
count |= 0xc0;
s << count;
}
s << data;
}
}
static void writeImage1( QImage &img, QDataStream &s, PCXHEADER &header )
{
img = img.convertToFormat( QImage::Format_Mono );
header.Bpp = 1;
header.NPlanes = 1;
header.BytesPerLine = img.bytesPerLine();
s << header;
QByteArray buf( header.BytesPerLine, 0 );
for ( int y=0; y<header.height(); ++y )
{
quint8 *p = img.scanLine( y );
// Invert as QImage uses reverse palette for monochrome images?
for ( int i=0; i<header.BytesPerLine; ++i )
buf[ i ] = ~p[ i ];
writeLine( s, buf );
}
}
static void writeImage4( QImage &img, QDataStream &s, PCXHEADER &header )
{
header.Bpp = 1;
header.NPlanes = 4;
header.BytesPerLine = header.width()/8;
for ( int i=0; i<16; ++i )
header.ColorMap.setColor( i, img.color( i ) );
s << header;
QByteArray buf[ 4 ];
for ( int i=0; i<4; ++i )
buf[ i ].resize( header.BytesPerLine );
for ( int y=0; y<header.height(); ++y )
{
quint8 *p = img.scanLine( y );
for ( int i=0; i<4; ++i )
buf[ i ].fill( 0 );
for ( int x=0; x<header.width(); ++x )
{
for ( int i=0; i<4; ++i )
if ( *( p+x ) & ( 1 << i ) )
buf[ i ][ x/8 ] = (int)(buf[ i ][ x/8 ])| 1 << ( 7-x%8 );
}
for ( int i=0; i<4; ++i )
writeLine( s, buf[ i ] );
}
}
static void writeImage8( QImage &img, QDataStream &s, PCXHEADER &header )
{
header.Bpp = 8;
header.NPlanes = 1;
header.BytesPerLine = img.bytesPerLine();
s << header;
QByteArray buf( header.BytesPerLine, 0 );
for ( int y=0; y<header.height(); ++y )
{
quint8 *p = img.scanLine( y );
for ( int i=0; i<header.BytesPerLine; ++i )
buf[ i ] = p[ i ];
writeLine( s, buf );
}
// Write palette flag
quint8 byte = 12;
s << byte;
// Write palette
for ( int i=0; i<256; ++i )
s << RGB::from( img.color( i ) );
}
static void writeImage24( QImage &img, QDataStream &s, PCXHEADER &header )
{
header.Bpp = 8;
header.NPlanes = 3;
header.BytesPerLine = header.width();
s << header;
QByteArray r_buf( header.width(), 0 );
QByteArray g_buf( header.width(), 0 );
QByteArray b_buf( header.width(), 0 );
for ( int y=0; y<header.height(); ++y )
{
uint *p = ( uint * )img.scanLine( y );
for ( int x=0; x<header.width(); ++x )
{
QRgb rgb = *p++;
r_buf[ x ] = qRed( rgb );
g_buf[ x ] = qGreen( rgb );
b_buf[ x ] = qBlue( rgb );
}
writeLine( s, r_buf );
writeLine( s, g_buf );
writeLine( s, b_buf );
}
}
PCXHandler::PCXHandler()
{
}
bool PCXHandler::canRead() const
{
if (canRead(device()))
{
setFormat("pcx");
return true;
}
return false;
}
bool PCXHandler::read(QImage *outImage)
{
QDataStream s( device() );
s.setByteOrder( QDataStream::LittleEndian );
if ( s.device()->size() < 128 )
{
return false;
}
PCXHEADER header;
s >> header;
if ( header.Manufacturer != 10 || s.atEnd())
{
return false;
}
int w = header.width();
int h = header.height();
kDebug( 399 ) << "Manufacturer: " << header.Manufacturer;
kDebug( 399 ) << "Version: " << header.Version;
kDebug( 399 ) << "Encoding: " << header.Encoding;
kDebug( 399 ) << "Bpp: " << header.Bpp;
kDebug( 399 ) << "Width: " << w;
kDebug( 399 ) << "Height: " << h;
kDebug( 399 ) << "Window: " << header.XMin << "," << header.XMax << ","
<< header.YMin << "," << header.YMax << endl;
kDebug( 399 ) << "BytesPerLine: " << header.BytesPerLine;
kDebug( 399 ) << "NPlanes: " << header.NPlanes;
QImage img;
if ( header.Bpp == 1 && header.NPlanes == 1 )
{
readImage1( img, s, header );
}
else if ( header.Bpp == 1 && header.NPlanes == 4 )
{
readImage4( img, s, header );
}
else if ( header.Bpp == 8 && header.NPlanes == 1 )
{
readImage8( img, s, header );
}
else if ( header.Bpp == 8 && header.NPlanes == 3 )
{
readImage24( img, s, header );
}
kDebug( 399 ) << "Image Bytes: " << img.byteCount();
kDebug( 399 ) << "Image Bytes Per Line: " << img.bytesPerLine();
kDebug( 399 ) << "Image Depth: " << img.depth();
if ( !img.isNull() )
{
*outImage = img;
return true;
}
else
{
return false;
}
}
bool PCXHandler::write(const QImage &image)
{
QDataStream s( device() );
s.setByteOrder( QDataStream::LittleEndian );
QImage img = image;
int w = img.width();
int h = img.height();
kDebug( 399 ) << "Width: " << w;
kDebug( 399 ) << "Height: " << h;
kDebug( 399 ) << "Depth: " << img.depth();
kDebug( 399 ) << "BytesPerLine: " << img.bytesPerLine();
kDebug( 399 ) << "Num Colors: " << img.colorCount();
PCXHEADER header;
header.Manufacturer = 10;
header.Version = 5;
header.Encoding = 1;
header.XMin = 0;
header.YMin = 0;
header.XMax = w-1;
header.YMax = h-1;
header.HDpi = 300;
header.YDpi = 300;
header.Reserved = 0;
header.PaletteInfo =1;
if ( img.depth() == 1 )
{
writeImage1( img, s, header );
}
else if ( img.depth() == 8 && img.colorCount() <= 16 )
{
writeImage4( img, s, header );
}
else if ( img.depth() == 8 )
{
writeImage8( img, s, header );
}
else if ( img.depth() == 32 )
{
writeImage24( img, s, header );
}
return true;
}
QByteArray PCXHandler::name() const
{
return "pcx";
}
bool PCXHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("PCXHandler::canRead() called with no device");
return false;
}
qint64 oldPos = device->pos();
char head[1];
qint64 readBytes = device->read(head, sizeof(head));
if (readBytes != sizeof(head)) {
if (device->isSequential()) {
while (readBytes > 0)
device->ungetChar(head[readBytes-- - 1]);
} else {
device->seek(oldPos);
}
return false;
}
if (device->isSequential()) {
while (readBytes > 0)
device->ungetChar(head[readBytes-- - 1]);
} else {
device->seek(oldPos);
}
return qstrncmp(head, "\012", 1) == 0;
}
class PCXPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList PCXPlugin::keys() const
{
return QStringList() << "pcx" << "PCX";
}
QImageIOPlugin::Capabilities PCXPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "pcx" || format == "PCX")
return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && PCXHandler::canRead(device))
cap |= CanRead;
if (device->isWritable())
cap |= CanWrite;
return cap;
}
QImageIOHandler *PCXPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new PCXHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(pcx, PCXPlugin)
/* vim: et sw=2 ts=2
*/

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=pcx X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-pcx X-KDE-MimeType=image/x-pcx
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=true X-KDE-Write=false

View file

@ -1,114 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2002-2003 Nadeem Hasan <nhasan@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef PCX_H
#define PCX_H
#include <QtGui/qimageiohandler.h>
#include <QtCore/QDataStream>
#include <QtGui/QColor>
class PCXHandler : public QImageIOHandler
{
public:
PCXHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
class RGB
{
public:
quint8 r;
quint8 g;
quint8 b;
static RGB from( const QRgb &color)
{
RGB c;
c.r = qRed( color );
c.g = qGreen( color );
c.b = qBlue( color );
return c;
}
} Q_PACKED;
class Palette
{
public:
void setColor( int i, const QRgb color )
{
RGB &c = rgb[ i ];
c.r = qRed( color );
c.g = qGreen( color );
c.b = qBlue( color );
}
QRgb color( int i ) const
{
return qRgb( rgb[ i ].r, rgb[ i ].g, rgb[ i ].b );
}
class RGB rgb[ 16 ];
} Q_PACKED;
class PCXHEADER
{
public:
PCXHEADER();
inline int width() const { return ( XMax-XMin ) + 1; }
inline int height() const { return ( YMax-YMin ) + 1; }
inline bool isCompressed() const { return ( Encoding==1 ); }
quint8 Manufacturer; // Constant Flag, 10 = ZSoft .pcx
quint8 Version; // Version information·
// 0 = Version 2.5 of PC Paintbrush·
// 2 = Version 2.8 w/palette information·
// 3 = Version 2.8 w/o palette information·
// 4 = PC Paintbrush for Windows(Plus for
// Windows uses Ver 5)·
// 5 = Version 3.0 and > of PC Paintbrush
// and PC Paintbrush +, includes
// Publisher's Paintbrush . Includes
// 24-bit .PCX files·
quint8 Encoding; // 1 = .PCX run length encoding
quint8 Bpp; // Number of bits to represent a pixel
// (per Plane) - 1, 2, 4, or 8·
quint16 XMin;
quint16 YMin;
quint16 XMax;
quint16 YMax;
quint16 HDpi;
quint16 YDpi;
Palette ColorMap;
quint8 Reserved; // Should be set to 0.
quint8 NPlanes; // Number of color planes
quint16 BytesPerLine; // Number of bytes to allocate for a scanline
// plane. MUST be an EVEN number. Do NOT
// calculate from Xmax-Xmin.·
quint16 PaletteInfo; // How to interpret palette- 1 = Color/BW,
// 2 = Grayscale ( ignored in PB IV/ IV + )·
quint16 HScreenSize; // Horizontal screen size in pixels. New field
// found only in PB IV/IV Plus
quint16 VScreenSize; // Vertical screen size in pixels. New field
// found only in PB IV/IV Plus
} Q_PACKED;
#endif // PCX_H
/* vim: et sw=2 ts=2
*/

View file

@ -1,7 +0,0 @@
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=pic
X-KDE-MimeType=image/x-pic
X-KDE-Read=true
X-KDE-Write=true

View file

@ -1,71 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
#include "pic_io_handler.h"
#include "pic_rw.h"
bool SoftimagePICHandler::canRead() const {
if (!SoftimagePICHandler::canRead(device())) {
return false;
}
setFormat("pic");
return true;
}
bool SoftimagePICHandler::read(QImage *image) {
pic_read(device(), image);
return true;
}
bool SoftimagePICHandler::write(const QImage &image) {
pic_write(device(), &image);
return true;
}
bool SoftimagePICHandler::canRead(QIODevice *device) {
PICHeader hdr;
if (picReadHeader(device, &hdr, true)) {
if (strncmp(hdr.id, "PICT", 4) == 0) {
return true;
}
}
return false;
}
QVariant SoftimagePICHandler::option(ImageOption option) const {
if (option == Size) {
PICHeader hdr;
if (picReadHeader(device(), &hdr, true)) {
return QSize(hdr.width, hdr.height);
} else {
return QSize(-1, -1);
}
}
return QVariant();
}
bool SoftimagePICHandler::supportsOption(ImageOption option) const {
return ( option == Size);
}
QByteArray SoftimagePICHandler::name() const {
return "pic";
}

View file

@ -1,42 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
#ifndef __PIC_IO_HANDLER_H__
#define __PIC_IO_HANDLER_H__
#include "pic_rw.h"
#include <QtCore/QVariant>
#include <QtGui/QImage>
#include <iostream>
class SoftimagePICHandler : public QImageIOHandler {
public:
virtual bool canRead() const;
virtual bool read(QImage * image);
virtual bool write(const QImage &);
static bool canRead(QIODevice *device);
QByteArray name() const;
QVariant option(ImageOption option) const;
bool supportsOption(ImageOption option) const;
};
#endif//__PIC_IO_HANDLER_H__

View file

@ -1,54 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
#include "pic_io_plugin.h"
#include "pic_io_handler.h"
QImageIOPlugin::Capabilities SoftimagePICPlugin::capabilities(QIODevice *device, const QByteArray &format) const {
if (format == "pic") {
return Capabilities(CanRead | CanWrite);
}
if (!(format.isEmpty() && device->isOpen())) {
return 0;
}
Capabilities cap;
if (device->isReadable() && SoftimagePICHandler::canRead(device)) {
cap |= CanRead;
}
if (device->isWritable()) {
cap |= CanWrite;
}
return cap;
}
QStringList SoftimagePICPlugin::keys() const {
return QStringList() << "pic";
}
QImageIOHandler * SoftimagePICPlugin::create(QIODevice *device, const QByteArray &format) const {
QImageIOHandler * handler = new SoftimagePICHandler();
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(softimagePICPlugin, SoftimagePICPlugin)

View file

@ -1,33 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
#ifndef __PIC_IO_PLUGIN_H__
#define __PIC_IO_PLUGIN_H__
#include <QtGui/qimageiohandler.h>
class SoftimagePICPlugin : public QImageIOPlugin {
public:
virtual Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
virtual QStringList keys() const;
virtual QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
#endif//__PIC_IO_PLUGIN_H__

View file

@ -1,266 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
/* This code is based on the GIMP-PIC plugin by Halfdan Ingvarsson,
* and relicensed from GPL to LGPL to accomodate the KDE licensing policy
* with his permission.
* These is the original copyright:
* Copyright (C) 1998 Halfdan Ingvarsson
*/
#include "pic_rw.h"
#include <netinet/in.h>
#include <iostream>
#include <qimage.h>
#include <algorithm>
/**
* Reads the PIC header and checks that it is OK
* @param dev The QT device to read from
* @param hdr A pointer to the PIC header
* @param peek Keep bytes in the device
* @return true on success
*/
bool picReadHeader(QIODevice *dev, PICHeader *hdr, bool peek) {
qint64 result = 0;
if (peek) {
result = dev->peek((char*) hdr, HEADER_SIZE);
} else {
result = dev->read((char*) hdr, HEADER_SIZE);
}
hdr->magic = ntohl(hdr->magic);
hdr->width = ntohs(hdr->width);
hdr->height = ntohs(hdr->height);
hdr->fields = ntohs(hdr->fields);
if (hdr->magic != PIC_MAGIC_NUMBER || strncmp(hdr->id, "PICT", 4)) {
return false;
}
return result == HEADER_SIZE;
}
#define CHANNEL_BYTE(ch, mask) (( ch & mask) ? 1 : 0)
/**
* Gets the channels definition and returns the number of bytes per pixel
* @param channels The channels bitfield
* @return The number of bytes per pixel
*/
static int channels2bpp(char channels) {
return CHANNEL_BYTE(channels, RED)
+ CHANNEL_BYTE(channels, GREEN)
+ CHANNEL_BYTE(channels, BLUE)
+ CHANNEL_BYTE(channels, ALPHA);
}
/**
* Reads the channels info
* @param dev The QT device to read from
* @param channels A pointer to 8 channels
* @return true on success
*/
static bool readChannels(QIODevice *dev, PICChannel *channels, int &bpp) {
int c = 0;
memset(channels, 0, sizeof ( PICChannel) *8);
do {
qint64 result = dev->read((char*) & channels[c], CHANNEL_SIZE);
if (result != CHANNEL_SIZE) {
return false;
} else {
bpp += channels2bpp(channels[c].channel);
c++;
}
} while (channels[c - 1].chained);
return true;
}
/**
* Makes a component map based on the channels info
* @param channels The channel information
* @param cmap The component map to be built
*/
inline static void makeComponentMap(unsigned channel, unsigned char *cmap) {
std::fill(cmap, cmap + 8, 0);
unsigned compos[] = {ALPHA, BLUE, GREEN, RED};
unsigned rgba[] = {3, 2, 1, 0};
unsigned pos = 0;
for (unsigned compo = 0; compo < 4; compo++) {
if (CHANNEL_BYTE(channel, compos[compo])) {
cmap[pos++] = rgba[compo];
}
}
}
/**
* Converts a PIC pixel to 32bits RGBA
* @param src_pixel The source PIC pixel as readed from file
* @param target_pixel The target buffer where to write the pixel info
* @param cmap The component map that maps each component in PIC format to RGBA format
* @param components The number of components in the source pixel
*/
inline static void pic2RGBA(unsigned char *src_pixel, unsigned char *target_pixel, unsigned char *cmap, unsigned components) {
for (unsigned i = 0; i < components; i++) {
target_pixel[cmap[i]] = src_pixel[i];
}
}
/**
* Decodes a Run-lenght encoded chunk
* @param dev The device to read from
* @param row The row pointer to write to
* @param max The maximum length to write
* @param channels The channels header
* @return The number of generated pixels
*/
static int decodeRLE(QIODevice *dev, void *row, qint16 max, int bpp, unsigned channels) {
unsigned char buf[512];
unsigned *ptr = (unsigned *) row;
unsigned char component_map[8];
int len = 0;
makeComponentMap(channels, component_map);
if (dev->read((char*) buf, 1) != 1) {
return -1;
}
/* If last bit is 1, then it is 2 to 127 repetitions */
if (buf[0] > 128) {
len = buf[0] - 127;
if (len > max) {
return -1;
}
qint64 count = dev->read((char*) buf, bpp);
if (count != bpp) {
return -1;
}
for (unsigned i = 0; i < len; i++) {
pic2RGBA(buf, (unsigned char*) (ptr + i), component_map, bpp);
}
} /* If the value is exactly 10000000, it means that it is more than 127 repetitions */
else if (buf[0] == 128) {
qint64 count = dev->read((char*) buf, bpp + 2);
if (count != bpp + 2) {
return -1;
}
len = (buf[0] << 8) | buf[1];
if (len > max) {
return -1;
}
for (unsigned i = 0; i < len; i++) {
pic2RGBA(buf + 2, (unsigned char*) (ptr + i), component_map, bpp);
}
} /** No repetitions */
else {
len = buf[0] + 1;
if (len > max) {
return -1;
}
const qint64 buflen = qint64(len) * bpp;
qint64 count = dev->read((char*) buf, buflen);
if (count != buflen) {
return -1;
}
for (unsigned i = 0; i < len; i++) {
pic2RGBA(buf + (i * bpp), (unsigned char*) (ptr + i), component_map, bpp);
}
}
return len;
}
/**
* Reads a row from the file
* @param dev The device to read from
* @param row The row pointer to write to
* @param width The image width
* @param channels The channels header info
*/
static bool readRow(QIODevice *dev, unsigned *row, qint16 width, PICChannel *channels) {
for (int c = 0; channels[c].channel != 0; c++) {
qint16 remain = width;
int bpp = channels2bpp(channels[c].channel);
if (channels[c].type == (int) RLE) {
unsigned *rowpos = row;
while (remain > 0) {
int readed = decodeRLE(dev, rowpos, remain, bpp, channels[c].channel);
if (readed < 0) {
return false;
}
remain -= readed;
rowpos += readed;
}
} else {
unsigned char component_map[8];
const qint64 rowlen = qint64(width) * bpp;
qint64 count = dev->read((char*) row, rowlen);
if (count != rowlen) {
return false;
}
makeComponentMap(channels[c].channel, component_map);
for (unsigned i = 0; i < width; i++) {
pic2RGBA(((unsigned char*) row) + (i * bpp), (unsigned char*) (row + i), component_map, bpp);
}
}
}
return true;
}
#define FAIL() { \
std::cout << "ERROR Reading PIC!" << std::endl; \
return; \
}
bool hasAlpha(PICChannel *channels) {
int channel = 0;
do {
if (CHANNEL_BYTE(channels[channel].channel, ALPHA)) {
return true;
}
channel++;
} while (channels[channel - 1].chained);
return false;
}
/**
* KDE image reading function. Must have this exact name in order to work
*/
void pic_read(QIODevice *dev, QImage *result) {
PICHeader header;
PICChannel channels[8];
int bpp = 0;
if (!picReadHeader(dev, &header) || !readChannels(dev, channels, bpp)) {
FAIL();
}
QImage img(header.width, header.height, QImage::Format_ARGB32);
for (int r = 0; r < header.height; r++) {
unsigned *row = (unsigned*) img.scanLine(r);
std::fill(row, row + header.width, 0);
if (!readRow(dev, row, header.width, channels)) {
FAIL();
}
}
// img->setAlphaBuffer(hasAlpha(channels));
*result = img;
}

View file

@ -1,108 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
/* This code is based on the GIMP-PIC plugin by Halfdan Ingvarsson,
* and relicensed from GPL to LGPL to accomodate the KDE licensing policy
* with his permission.
* These is the original copyright:
* Copyright (C) 1998 Halfdan Ingvarsson
*/
#ifndef __PIC_RW_H__
#define __PIC_RW_H__
#define PIC_MAGIC_NUMBER 0x5380f634
#include <QtGui/qimageiohandler.h>
/**
* How fields are distributed over the image
*/
typedef enum {
NONE = 0, /* No picture */
ODD = 1, /* Odd scanlines */
EVEN = 2, /* Even scanlines */
BOTH = 3 /* Every scanline */
} PICFields;
/**
* Type of a channel
*/
typedef enum {
UNCOMPRESSED = 0, /* Image is uncompressed */
RLE = 2 /* Run length compression */
} PICChannelType;
/**
* Channel codes
*/
typedef enum {
RED = 0x80, /* Red channel */
GREEN = 0x40, /* Green channel */
BLUE = 0x20, /* Blue channel */
ALPHA = 0x10 /* Alpha channel */
} PICChannelCode;
/**
* PIC format header
*/
typedef struct {
qint32 magic; /* PIC_MAGIC_NUMBER */
float version; /* Version of format */
char comment[80]; /* Prototype description */
char id[4]; /* "PICT" */
qint16 width; /* Image width, in pixels */
qint16 height; /* Image height, in pixels */
float ratio; /* Pixel aspect ratio */
qint16 fields; /* Picture field type */
qint16 pad; /* Unused */
} PICHeader;
/**
* PIC channel header
*/
typedef struct {
char chained; /* 1 if another packet follows, else 0 */
char size; /* Bits per pixel by channel */
char type; /* RLE or uncompressed */
char channel; /* Channel code (which planes are affected by this channel) */
} PICChannel;
#define HEADER_SIZE sizeof(PICHeader)
#define CHANNEL_SIZE sizeof(PICChannel)
/**
* Reads the PIC header and checks that it is OK
* @param dev The QT device to read from
* @param hdr A pointer to the PIC header
* @param peek Keep bytes in the device
* @return true on success
*/
bool picReadHeader(QIODevice *dev, PICHeader *hdr, bool peek = false);
/// Pic read handler for Qt / KDE
void pic_read(QIODevice *dev, QImage *img);
/// Pic write handler for Qt / KDE
void pic_write(QIODevice *dev, const QImage *img);
#endif//__PIC_RW_H__

View file

@ -1,225 +0,0 @@
/**
* PIC_RW - Qt PIC Support
* Copyright (C) 2007 Ruben Lopez <r.lopez@bren.es>
*
* 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 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 library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ----------------------------------------------------------------------------
*/
/* This code is based on the GIMP-PIC plugin by Halfdan Ingvarsson,
* and relicensed from GPL to LGPL to accomodate the KDE licensing policy
* with his permission.
* These is the original copyright:
* Copyright (C) 1998 Halfdan Ingvarsson
*/
#include "pic_rw.h"
#include <netinet/in.h>
#include <iostream>
#include <qimage.h>
/**
* Writes the PIC header info.
* @param dev IO Device
* @param msg Header message
* @param width Image width
* @param height Image height
* @param alpha Image has alpha?
* @return True on success
*/
static bool writeHeader(QIODevice *dev, std::string msg, unsigned width, unsigned height, bool alpha) {
PICHeader h;
PICChannel c;
unsigned count = 0;
memset(&h, 0, sizeof (PICHeader));
h.magic = htonl(PIC_MAGIC_NUMBER);
h.version = 3.71f;
strcpy(h.comment, msg.c_str());
strncpy(h.id, "PICT", 4);
h.width = htons(width);
h.height = htons(height);
h.ratio = 1.0f;
h.fields = htons(BOTH);
count = dev->write((const char*) & h, sizeof (PICHeader));
if (count != sizeof (PICHeader)) {
return false;
}
memset(&c, 0, sizeof (PICChannel));
c.size = 8;
c.type = RLE;
c.channel = RED | GREEN | BLUE;
if (alpha) {
c.chained = 1;
}
count = dev->write((const char*) & c, sizeof (PICChannel));
if (count != sizeof (PICChannel)) {
return false;
}
if (alpha) {
c.channel = ALPHA;
c.chained = 0;
count = dev->write((const char*) & c, sizeof (PICChannel));
if (count != sizeof (PICChannel)) {
return false;
}
}
return true;
}
inline unsigned convertABGRtoRGBA(unsigned pixel) {
unsigned r = pixel & 0xFF;
unsigned g = (pixel >> 8) & 0xFF;
unsigned b = (pixel >> 16) & 0xFF;
unsigned a = (pixel >> 24) & 0xFF;
return a | (b << 8) | (g << 16) | (r << 24);
}
/**
* Encodes a portion of the image in RLE coding
* @param image The image that we want to encode
* @param output The output buffer
* @param channels The number of channels to write
* @param offset Offset in bytes to copy
* @param max The maximum number of pixels to write
* @param oConsumed The number of pixels consumed from image
* @param oProduced The number of bytes produced in out
* @return True on success
*/
static bool encodeRLE(const unsigned *image, unsigned char *output, bool rgb, unsigned max, unsigned &oConsumed, unsigned &oProduced) {
const unsigned *in = image;
unsigned char *out = output;
unsigned count = 0;
unsigned channels = 3;
unsigned offset = 1;
unsigned mask = 0x00FFFFFF;
if (!rgb) {
channels = 1;
offset = 0;
mask = 0xFF000000;
}
for (; (*in & mask) == (*image & mask) && count < 65536 && count < max; in++, count++) {
}
if (count > 127) {
/* Sequence of > 127 identical pixels */
*out++ = 128;
*out++ = count >> 8;
*out++ = count & 0xFF;
unsigned pixel = convertABGRtoRGBA(*image);
memcpy(out, ((char*) & pixel) + offset, channels);
out += channels;
oConsumed = count;
oProduced = out - output;
}
else if (count > 1) {
/* Sequece of < 128 identical pixels */
*out++ = (count + 127);
unsigned pixel = convertABGRtoRGBA(*image);
memcpy(out, ((char*) & pixel) + offset, channels);
out += channels;
oConsumed = count;
oProduced = out - output;
}
else {
in = image + 1;
unsigned previous = *image;
count = 0;
while ((*in & mask) != (previous & mask) && count < 128 && count < max) {
previous = *in;
in++;
count++;
}
// This only happens when it is the end of the row, and it is ok
if (count == 0) {
count = 1;
}
*out++ = (count - 1);
in = image;
for (unsigned c = 0; c < count; ++c) {
unsigned pixel = convertABGRtoRGBA(*in);
memcpy(out, ((char*) & pixel) + offset, channels);
out += channels;
in++;
}
oConsumed = count;
oProduced = out - output;
}
return true;
}
/**
* Writes a row to the file
* @return True on success
*/
static bool writeRow(QIODevice *dev, unsigned *row, unsigned width, bool alpha) {
unsigned char *buf = new unsigned char[width * 4];
unsigned posIn = 0;
unsigned posOut = 0;
memset(buf, 0, width * 4);
unsigned consumed = 0;
unsigned produced = 0;
/* Write the RGB part of the scanline */
while (posIn < width) {
if (!encodeRLE(row + posIn, buf + posOut, true, width - posIn, consumed, produced)) {
delete[] buf;
return false;
}
posIn += consumed;
posOut += produced;
}
/* Write the alpha channel */
if (alpha) {
posIn = 0;
while (posIn < width) {
if (!encodeRLE(row + posIn, buf + posOut, false, width - posIn, consumed, produced)) {
delete[] buf;
return false;
}
posIn += consumed;
posOut += produced;
}
}
dev->write((const char*) buf, posOut);
delete[] buf;
return true;
}
#define FAIL() { \
std::cout << "ERROR Writing PIC!" << std::endl; \
return; \
}
/// Pic write handler for Qt / KDE
void pic_write(QIODevice *dev, const QImage *img) {
bool alpha = img->hasAlphaChannel();
if (!writeHeader(dev, "Created with KDE", img->width(), img->height(), alpha)) {
FAIL();
}
for (int r = 0; r < img->height(); r++) {
unsigned *row = (unsigned*) img->scanLine(r);
if (!writeRow(dev, row, img->width(), alpha)) {
FAIL();
}
}
}

View file

@ -1,371 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003 Ignacio Castaño <castano@ludicon.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This code is based on Thacher Ulrich PSD loading code released
on public domain. See: http://tulrich.com/geekstuff/
*/
/* this code supports:
* reading:
* rle and raw psd files
* writing:
* not supported
*/
#include "psd.h"
#include <QtGui/QImage>
#include <QtCore/QDataStream>
#include <kdebug.h>
typedef quint32 uint;
typedef quint16 ushort;
typedef quint8 uchar;
namespace { // Private.
enum ColorMode {
CM_BITMAP = 0,
CM_GRAYSCALE = 1,
CM_INDEXED = 2,
CM_RGB = 3,
CM_CMYK = 4,
CM_MULTICHANNEL = 7,
CM_DUOTONE = 8,
CM_LABCOLOR = 9
};
struct PSDHeader {
uint signature;
ushort version;
uchar reserved[6];
ushort channel_count;
uint height;
uint width;
ushort depth;
ushort color_mode;
};
static QDataStream & operator>> ( QDataStream & s, PSDHeader & header )
{
s >> header.signature;
s >> header.version;
for( int i = 0; i < 6; i++ ) {
s >> header.reserved[i];
}
s >> header.channel_count;
s >> header.height;
s >> header.width;
s >> header.depth;
s >> header.color_mode;
return s;
}
static bool seekBy(QDataStream& s, uint bytes)
{
char buf[4096];
while (bytes) {
uint num= qMin(bytes, uint(sizeof(buf)));
uint l = num;
s.readRawData(buf, l);
if (l != num) {
return false;
}
bytes -= num;
}
return true;
}
// Check that the header is a valid PSD.
static bool IsValid( const PSDHeader & header )
{
if( header.signature != 0x38425053 ) { // '8BPS'
return false;
}
return true;
}
// Check that the header is supported.
static bool IsSupported( const PSDHeader & header )
{
if( header.version != 1 ) {
return false;
}
if( header.channel_count > 16 ) {
return false;
}
if( header.depth != 8 ) {
return false;
}
if( header.color_mode != CM_RGB ) {
return false;
}
return true;
}
// Load the PSD image.
static bool LoadPSD( QDataStream & s, const PSDHeader & header, QImage & img )
{
// Create dst image.
img = QImage( header.width, header.height, QImage::Format_RGB32 );
uint tmp;
// Skip mode data.
s >> tmp;
s.device()->seek( s.device()->pos() + tmp );
// Skip image resources.
s >> tmp;
s.device()->seek( s.device()->pos() + tmp );
// Skip the reserved data.
s >> tmp;
s.device()->seek( s.device()->pos() + tmp );
// Find out if the data is compressed.
// Known values:
// 0: no compression
// 1: RLE compressed
ushort compression;
s >> compression;
if( compression > 1 ) {
// Unknown compression type.
return false;
}
uint channel_num = header.channel_count;
// Clear the image.
if( channel_num < 4 ) {
img.fill(qRgba(0, 0, 0, 0xFF));
} else {
// Enable alpha.
img = img.convertToFormat(QImage::Format_ARGB32);
// Ignore the other channels.
channel_num = 4;
}
const uint pixel_count = header.height * header.width;
static const uint components[4] = {2, 1, 0, 3}; // @@ Is this endian dependant?
if( compression ) {
qulonglong overflowcheck = qulonglong(header.height) * header.channel_count * sizeof(ushort);
if (overflowcheck > UINT_MAX) {
return false;
}
// Skip row lengths.
if(!seekBy(s, uint(overflowcheck))) {
return false;
}
// Read RLE data.
for(uint channel = 0; channel < channel_num; channel++) {
uchar * ptr = img.bits() + components[channel];
uint count = 0;
while( count < pixel_count ) {
uchar c;
if(s.atEnd()) {
return false;
}
s >> c;
uint len = c;
if( len < 128 ) {
// Copy next len+1 bytes literally.
len++;
count += len;
if ( count > pixel_count ) {
return false;
}
while( len != 0 ) {
s >> *ptr;
ptr += 4;
len--;
}
} else if( len > 128 ) {
// Next -len+1 bytes in the dest are replicated from next source byte.
// (Interpret len as a negative 8-bit int.)
len ^= 0xFF;
len += 2;
count += len;
if(s.atEnd() || count > pixel_count) {
return false;
}
uchar val;
s >> val;
while( len != 0 ) {
*ptr = val;
ptr += 4;
len--;
}
} else if( len == 128 ) {
// No-op.
}
}
}
} else {
// We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
// where each channel consists of an 8-bit value for each pixel in the image.
// Read the data by channel.
for(uint channel = 0; channel < channel_num; channel++) {
uchar * ptr = img.bits() + components[channel];
// Read the data.
uint count = pixel_count;
while( count != 0 ) {
s >> *ptr;
ptr += 4;
count--;
}
}
}
return true;
}
} // Private
PSDHandler::PSDHandler()
{
}
bool PSDHandler::canRead() const
{
if (canRead(device())) {
setFormat("psd");
return true;
}
return false;
}
bool PSDHandler::read(QImage *image)
{
QDataStream s( device() );
s.setByteOrder( QDataStream::BigEndian );
PSDHeader header;
s >> header;
// Check image file format.
if( s.atEnd() || !IsValid( header ) ) {
kDebug(399) << "This PSD file is not valid.";
return false;
}
// Check if it's a supported format.
if( !IsSupported( header ) ) {
kDebug(399) << "This PSD file is not supported.";
return false;
}
QImage img;
if( !LoadPSD(s, header, img) ) {
kDebug(399) << "Error loading PSD file.";
return false;
}
*image = img;
return true;
}
bool PSDHandler::write(const QImage &)
{
// TODO Stub!
return false;
}
QByteArray PSDHandler::name() const
{
return "psd";
}
bool PSDHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("PSDHandler::canRead() called with no device");
return false;
}
qint64 oldPos = device->pos();
char head[4];
qint64 readBytes = device->read(head, sizeof(head));
if (readBytes != sizeof(head)) {
if (device->isSequential()) {
while (readBytes > 0)
device->ungetChar(head[readBytes-- - 1]);
} else {
device->seek(oldPos);
}
return false;
}
if (device->isSequential()) {
while (readBytes > 0) {
device->ungetChar(head[readBytes-- - 1]);
}
} else {
device->seek(oldPos);
}
return qstrncmp(head, "8BPS", 4) == 0;
}
class PSDPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList PSDPlugin::keys() const
{
return QStringList() << "psd" << "PSD";
}
QImageIOPlugin::Capabilities PSDPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "psd" || format == "PSD") {
return Capabilities(CanRead);
}
if (!format.isEmpty() || !device->isOpen()) {
return 0;
}
Capabilities cap;
if (device->isReadable() && PSDHandler::canRead(device)) {
cap |= CanRead;
}
return cap;
}
QImageIOHandler *PSDPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new PSDHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(psd, PSDPlugin)

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=psd X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-psd X-KDE-MimeType=image/x-psd
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=false X-KDE-Write=false

View file

@ -1,30 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003 Ignacio Castaño <castano@ludicon.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef KIMG_PSD_H
#define KIMG_PSD_H
#include <QtGui/qimageiohandler.h>
class PSDHandler : public QImageIOHandler
{
public:
PSDHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
#endif

View file

@ -1,325 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003 Dominik Seichter <domseichter@web.de>
Copyright (C) 2004 Ignacio Castaño <castano@ludicon.com>
Copyright (C) 2010 Troy Unrau <troy@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#include "ras.h"
#include <QtGui/QImage>
#include <QtCore/QDataStream>
#include <kdebug.h>
namespace { // Private.
// format info from http://www.fileformat.info/format/sunraster/egff.htm
// Header format of saved files.
quint32 rasMagicBigEndian = 0x59a66a95;
// quint32 rasMagicLittleEndian = 0x956aa659; # used to support wrong encoded files
enum RASType {
RAS_TYPE_OLD = 0x0,
RAS_TYPE_STANDARD = 0x1,
RAS_TYPE_BYTE_ENCODED = 0x2,
RAS_TYPE_RGB_FORMAT = 0x3,
RAS_TYPE_TIFF_FORMAT = 0x4,
RAS_TYPE_IFF_FORMAT = 0x5,
RAS_TYPE_EXPERIMENTAL = 0xFFFF
};
enum RASColorMapType {
RAS_COLOR_MAP_TYPE_NONE = 0x0,
RAS_COLOR_MAP_TYPE_RGB = 0x1,
RAS_COLOR_MAP_TYPE_RAW = 0x2
};
struct RasHeader {
quint32 MagicNumber;
quint32 Width;
quint32 Height;
quint32 Depth;
quint32 Length;
quint32 Type;
quint32 ColorMapType;
quint32 ColorMapLength;
enum { SIZE = 32 }; // 8 fields of four bytes each
};
static QDataStream & operator>> ( QDataStream & s, RasHeader & head )
{
s >> head.MagicNumber;
s >> head.Width;
s >> head.Height;
s >> head.Depth;
s >> head.Length;
s >> head.Type;
s >> head.ColorMapType;
s >> head.ColorMapLength;
/*qDebug() << "MagicNumber: " << head.MagicNumber
<< "Width: " << head.Width
<< "Height: " << head.Height
<< "Depth: " << head.Depth
<< "Length: " << head.Length
<< "Type: " << head.Type
<< "ColorMapType: " << head.ColorMapType
<< "ColorMapLength: " << head.ColorMapLength;*/
return s;
}
static bool IsSupported( const RasHeader & head )
{
// check magic number
if ( head.MagicNumber != rasMagicBigEndian) {
return false;
}
// check for an appropriate depth
// we support 8bit+palette, 24bit and 32bit ONLY!
// TODO: add support for 1bit
if ( ! ((head.Depth == 8 && head.ColorMapType == 1)
|| head.Depth == 24 || head.Depth == 32) ){
return false;
}
// the Type field adds support for RLE(BGR), RGB and other encodings
// we support Type 1: Normal(BGR) and Type 3: Normal(RGB) ONLY!
// TODO: add support for Type 2: RLE(BGR) & Type 4,5: TIFF/IFF
if ( ! (head.Type == 1 || head.Type == 3) ){
return false;
}
// Old files didn't have Length set - reject them for now
// TODO: add length recalculation to support old files
if ( !head.Length ) {
return false;
}
return true;
}
static bool LoadRAS( QDataStream & s, const RasHeader & ras, QImage &img )
{
s.device()->seek(RasHeader::SIZE);
// Read palette if needed.
QVector<quint8> palette(ras.ColorMapLength);
if ( ras.ColorMapType == 1 ) {
for (quint32 i = 0; i < ras.ColorMapLength; ++i) { s >> palette[i]; }
}
// each line must be a factor of 16 bits, so they may contain padding
// this will be 1 if padding required, 0 otherwise
int paddingrequired = (ras.Width*(ras.Depth/8) % 2);
// qDebug() << "paddingrequired: " << paddingrequired;
// don't trust ras.Length
QVector<quint8> input(ras.Length);
int i = 0;
while ( ! s.atEnd()) {
s >> input[i];
// I guess we need to find out if we're at the end of a line
if ( paddingrequired && i != 0 && !(i % (ras.Width*(ras.Depth/8))) ) {
s >> input[i];
}
i++;
}
// Allocate image
img = QImage(ras.Width, ras.Height, QImage::Format_ARGB32);
// Reconstruct image from RGB palette if we have a palette
// TODO: make generic so it works with 24bit or 32bit palettes
if ( ras.ColorMapType == 1 && ras.Depth == 8) {
quint8 red, green, blue;
for ( quint32 y = 0; y < ras.Height; y++ ){
for ( quint32 x = 0; x < ras.Width; x++ ) {
red = palette[(int)input[y*ras.Width + x]];
green = palette[(int)input[y*ras.Width + x] + (ras.ColorMapLength/3)];
blue = palette[(int)input[y*ras.Width + x] + 2*(ras.ColorMapLength/3)];
img.setPixel(x, y, qRgb(red, green, blue));
}
}
}
if ( ras.ColorMapType == 0 && ras.Depth == 24 && (ras.Type == 1 || ras.Type == 2)) {
quint8 red, green, blue;
for ( quint32 y = 0; y < ras.Height; y++ ){
for ( quint32 x = 0; x < ras.Width; x++ ) {
red = input[y*3*ras.Width + x*3 + 2];
green = input[y*3*ras.Width + x*3 + 1];
blue = input[y*3*ras.Width + x*3];
img.setPixel(x, y, qRgb(red, green, blue));
}
}
}
if ( ras.ColorMapType == 0 && ras.Depth == 24 && ras.Type == 3) {
quint8 red, green, blue;
for ( quint32 y = 0; y < ras.Height; y++ ){
for ( quint32 x = 0; x < ras.Width; x++ ) {
red = input[y*3*ras.Width + x*3];
green = input[y*3*ras.Width + x*3 + 1];
blue = input[y*3*ras.Width + x*3 + 2];
img.setPixel(x, y, qRgb(red, green, blue));
}
}
}
if ( ras.ColorMapType == 0 && ras.Depth == 32 && (ras.Type == 1 || ras.Type == 2)) {
quint8 red, green, blue;
for ( quint32 y = 0; y < ras.Height; y++ ){
for ( quint32 x = 0; x < ras.Width; x++ ) {
red = input[y*4*ras.Width + x*4 + 3];
green = input[y*4*ras.Width + x*4 + 2];
blue = input[y*4*ras.Width + x*4 + 1];
img.setPixel(x, y, qRgb(red, green, blue));
}
}
}
if ( ras.ColorMapType == 0 && ras.Depth == 32 && ras.Type == 3 ) {
quint8 red, green, blue;
for ( quint32 y = 0; y < ras.Height; y++ ){
for ( quint32 x = 0; x < ras.Width; x++ ) {
red = input[y*4*ras.Width + x*4 + 1];
green = input[y*4*ras.Width + x*4 + 2];
blue = input[y*4*ras.Width + x*4 + 3];
img.setPixel(x, y, qRgb(red, green, blue));
}
}
}
return true;
}
} // namespace
RASHandler::RASHandler()
{
}
QByteArray RASHandler::name() const
{
return "ras";
}
bool RASHandler::canRead() const
{
if (canRead(device())) {
setFormat("ras");
return true;
}
return false;
}
bool RASHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("RASHandler::canRead() called with no device");
return false;
}
if (device->isSequential()) {
qWarning("Reading ras files from sequential devices not supported");
return false;
}
qint64 oldPos = device->pos();
QByteArray head = device->read(RasHeader::SIZE); // header is exactly 32 bytes, always FIXME
int readBytes = head.size(); // this should always be 32 bytes
device->seek(oldPos);
if (readBytes < RasHeader::SIZE) {
return false;
}
QDataStream stream(head);
stream.setByteOrder(QDataStream::BigEndian);
RasHeader ras;
stream >> ras;
return IsSupported(ras);
}
bool RASHandler::read(QImage *outImage)
{
QDataStream s( device() );
s.setByteOrder( QDataStream::BigEndian );
// Read image header.
RasHeader ras;
s >> ras;
// TODO: add support for old versions of RAS where Length may be zero in header
s.device()->seek( RasHeader::SIZE + ras.Length + ras.ColorMapLength );
// Check image file format. Type 2 is RLE, which causing seeking to be silly.
if( !s.atEnd() && ras.Type != 2) {
kDebug(399) << "This RAS file is not valid, or an older version of the format.";
return false;
}
// Check supported file types.
if( !IsSupported(ras) ) {
kDebug(399) << "This RAS file is not supported.";
return false;
}
QImage img;
bool result = LoadRAS(s, ras, img);
if( result == false ) {
kDebug(399) << "Error loading RAS file.";
return false;
}
*outImage = img;
return true;
}
/*
bool RASHandler::write(const QImage &image){
return false;
}*/
class RASPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList RASPlugin::keys() const
{
return QStringList() << "ras" << "RAS";
}
QImageIOPlugin::Capabilities RASPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "ras" || format == "RAS")
return Capabilities(CanRead);
// return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && RASHandler::canRead(device))
cap |= CanRead;
if (device->isWritable())
cap |= CanWrite;
return cap;
}
QImageIOHandler *RASPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new RASHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(ras, RASPlugin)

View file

@ -1,7 +0,0 @@
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=ras
X-KDE-MimeType=image/x-sun-raster
X-KDE-Read=true
X-KDE-Write=false

View file

@ -1,31 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2003 Dominik Seichter <domseichter@web.de>
Copyright (C) 2010 Troy Unrau <troy@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the Lesser GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef KIMG_RAS_H
#define KIMG_RAS_H
#include <QtGui/qimageiohandler.h>
class RASHandler : public QImageIOHandler
{
public:
RASHandler();
bool canRead() const;
bool read(QImage *image);
// bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
#endif

View file

@ -1,643 +0,0 @@
// kimgio module for SGI images
//
// Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Lesser GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
/* this code supports:
* reading:
* everything, except images with 1 dimension or images with
* mapmode != NORMAL (e.g. dithered); Images with 16 bit
* precision or more than 4 layers are stripped down.
* writing:
* Run Length Encoded (RLE) or Verbatim (uncompressed)
* (whichever is smaller)
*
* Please report if you come across rgb/rgba/sgi/bw files that aren't
* recognized. Also report applications that can't deal with images
* saved by this filter.
*/
#include "rgb.h"
#include <QtGui/QImage>
#include <kdebug.h>
SGIImage::SGIImage(QIODevice *io) :
_starttab(0),
_lengthtab(0)
{
_dev = io;
_stream.setDevice(_dev);
}
SGIImage::~SGIImage()
{
delete[] _starttab;
delete[] _lengthtab;
}
///////////////////////////////////////////////////////////////////////////////
bool SGIImage::getRow(uchar *dest)
{
int n, i;
if (!_rle) {
for (i = 0; i < _xsize; i++) {
if (_pos >= _data.end())
return false;
dest[i] = uchar(*_pos);
_pos += _bpc;
}
return true;
}
for (i = 0; i < _xsize;) {
if (_bpc == 2)
_pos++;
n = *_pos & 0x7f;
if (!n)
break;
if (*_pos++ & 0x80) {
for (; i < _xsize && n--; i++) {
*dest++ = *_pos;
_pos += _bpc;
}
} else {
for (; i < _xsize && n--; i++)
*dest++ = *_pos;
_pos += _bpc;
}
}
return i == _xsize;
}
bool SGIImage::readData(QImage& img)
{
QRgb *c;
quint32 *start = _starttab;
QByteArray lguard(_xsize, 0);
uchar *line = (uchar *)lguard.data();
unsigned x, y;
if (!_rle)
_pos = _data.begin();
for (y = 0; y < _ysize; y++) {
if (_rle)
_pos = _data.begin() + *start++;
if (!getRow(line))
return false;
c = (QRgb *)img.scanLine(_ysize - y - 1);
for (x = 0; x < _xsize; x++, c++)
*c = qRgb(line[x], line[x], line[x]);
}
if (_zsize == 1)
return true;
if (_zsize != 2) {
for (y = 0; y < _ysize; y++) {
if (_rle)
_pos = _data.begin() + *start++;
if (!getRow(line))
return false;
c = (QRgb *)img.scanLine(_ysize - y - 1);
for (x = 0; x < _xsize; x++, c++)
*c = qRgb(qRed(*c), line[x], line[x]);
}
for (y = 0; y < _ysize; y++) {
if (_rle)
_pos = _data.begin() + *start++;
if (!getRow(line))
return false;
c = (QRgb *)img.scanLine(_ysize - y - 1);
for (x = 0; x < _xsize; x++, c++)
*c = qRgb(qRed(*c), qGreen(*c), line[x]);
}
if (_zsize == 3)
return true;
}
for (y = 0; y < _ysize; y++) {
if (_rle)
_pos = _data.begin() + *start++;
if (!getRow(line))
return false;
c = (QRgb *)img.scanLine(_ysize - y - 1);
for (x = 0; x < _xsize; x++, c++)
*c = qRgba(qRed(*c), qGreen(*c), qBlue(*c), line[x]);
}
return true;
}
bool SGIImage::readImage(QImage& img)
{
qint8 u8;
qint16 u16;
qint32 u32;
kDebug(399) << "reading rgb ";
// magic
_stream >> u16;
if (u16 != 0x01da)
return false;
// verbatim/rle
_stream >> _rle;
kDebug(399) << (_rle ? "RLE" : "verbatim");
if (_rle > 1)
return false;
// bytes per channel
_stream >> _bpc;
kDebug(399) << "bytes per channel: " << int(_bpc);
if (_bpc == 1)
;
else if (_bpc == 2)
kDebug(399) << "dropping least significant byte";
else
return false;
// number of dimensions
_stream >> _dim;
kDebug(399) << "dimensions: " << _dim;
if (_dim < 1 || _dim > 3)
return false;
_stream >> _xsize >> _ysize >> _zsize >> _pixmin >> _pixmax >> u32;
kDebug(399) << "x: " << _xsize;
kDebug(399) << "y: " << _ysize;
kDebug(399) << "z: " << _zsize;
// name
_stream.readRawData(_imagename, 80);
_imagename[79] = '\0';
_stream >> _colormap;
kDebug(399) << "colormap: " << _colormap;
if (_colormap != NORMAL)
return false; // only NORMAL supported
for (int i = 0; i < 404; i++)
_stream >> u8;
if (_dim == 1) {
kDebug(399) << "1-dimensional images aren't supported yet";
return false;
}
if( _stream.atEnd())
return false;
_numrows = _ysize * _zsize;
img = QImage( _xsize, _ysize, QImage::Format_RGB32 );
if (_zsize == 2 || _zsize == 4)
img = img.convertToFormat(QImage::Format_ARGB32);
else if (_zsize > 4)
kDebug(399) << "using first 4 of " << _zsize << " channels";
if (_rle) {
uint l;
_starttab = new quint32[_numrows];
for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
_stream >> _starttab[l];
_starttab[l] -= 512 + _numrows * 2 * sizeof(quint32);
}
_lengthtab = new quint32[_numrows];
for (l = 0; l < _numrows; l++)
_stream >> _lengthtab[l];
}
_data = _dev->readAll();
// sanity check
if (_rle)
for (uint o = 0; o < _numrows; o++)
// don't change to greater-or-equal!
if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
kDebug(399) << "image corrupt (sanity check failed)";
return false;
}
if (!readData(img)) {
kDebug(399) << "image corrupt (incomplete scanline)";
return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
void RLEData::write(QDataStream& s)
{
for (int i = 0; i < size(); i++)
s << at(i);
}
bool RLEData::operator<(const RLEData& b) const
{
uchar ac, bc;
for (int i = 0; i < qMin(size(), b.size()); i++) {
ac = at(i);
bc = b[i];
if (ac != bc)
return ac < bc;
}
return size() < b.size();
}
uint RLEMap::insert(const uchar *d, uint l)
{
RLEData data = RLEData(d, l, _offset);
Iterator it = find(data);
if (it != end())
return it.value();
_offset += l;
return QMap<RLEData, uint>::insert(data, _counter++).value();
}
QVector<const RLEData*> RLEMap::vector()
{
QVector<const RLEData*> v(size());
for (Iterator it = begin(); it != end(); ++it)
v.replace(it.value(), &it.key());
return v;
}
uchar SGIImage::intensity(uchar c)
{
if (c < _pixmin)
_pixmin = c;
if (c > _pixmax)
_pixmax = c;
return c;
}
uint SGIImage::compact(uchar *d, uchar *s)
{
uchar *dest = d, *src = s, patt, *t, *end = s + _xsize;
int i, n;
while (src < end) {
for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++)
n++;
while (n) {
i = n > 126 ? 126 : n;
n -= i;
*dest++ = 0x80 | i;
while (i--)
*dest++ = *src++;
}
if (src == end)
break;
patt = *src++;
for (n = 1; src < end && *src == patt; src++)
n++;
while (n) {
i = n > 126 ? 126 : n;
n -= i;
*dest++ = i;
*dest++ = patt;
}
}
*dest++ = 0;
return dest - d;
}
bool SGIImage::scanData(const QImage& img)
{
quint32 *start = _starttab;
QByteArray lineguard(_xsize * 2, 0);
QByteArray bufguard(_xsize, 0);
uchar *line = (uchar *)lineguard.data();
uchar *buf = (uchar *)bufguard.data();
const QRgb *c;
unsigned x, y;
uint len;
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
buf[x] = intensity(qRed(*c++));
len = compact(line, buf);
*start++ = _rlemap.insert(line, len);
}
if (_zsize == 1)
return true;
if (_zsize != 2) {
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
buf[x] = intensity(qGreen(*c++));
len = compact(line, buf);
*start++ = _rlemap.insert(line, len);
}
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
buf[x] = intensity(qBlue(*c++));
len = compact(line, buf);
*start++ = _rlemap.insert(line, len);
}
if (_zsize == 3)
return true;
}
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
buf[x] = intensity(qAlpha(*c++));
len = compact(line, buf);
*start++ = _rlemap.insert(line, len);
}
return true;
}
void SGIImage::writeHeader()
{
_stream << quint16(0x01da);
_stream << _rle << _bpc << _dim;
_stream << _xsize << _ysize << _zsize;
_stream << _pixmin << _pixmax;
_stream << quint32(0);
for (int i = 0; i < 80; i++)
_imagename[i] = '\0';
_stream.writeRawData(_imagename, 80);
_stream << _colormap;
for (int i = 0; i < 404; i++)
_stream << quint8(0);
}
void SGIImage::writeRle()
{
_rle = 1;
kDebug(399) << "writing RLE data";
writeHeader();
uint i;
// write start table
for (i = 0; i < _numrows; i++)
_stream << quint32(_rlevector[_starttab[i]]->offset());
// write length table
for (i = 0; i < _numrows; i++)
_stream << quint32(_rlevector[_starttab[i]]->size());
// write data
for (i = 0; (int)i < _rlevector.size(); i++)
const_cast<RLEData*>(_rlevector[i])->write(_stream);
}
void SGIImage::writeVerbatim(const QImage& img)
{
_rle = 0;
kDebug(399) << "writing verbatim data";
writeHeader();
const QRgb *c;
unsigned x, y;
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
_stream << quint8(qRed(*c++));
}
if (_zsize == 1)
return;
if (_zsize != 2) {
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
_stream << quint8(qGreen(*c++));
}
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
_stream << quint8(qBlue(*c++));
}
if (_zsize == 3)
return;
}
for (y = 0; y < _ysize; y++) {
c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
for (x = 0; x < _xsize; x++)
_stream << quint8(qAlpha(*c++));
}
}
bool SGIImage::writeImage(const QImage& image)
{
kDebug(399) << "writing "; // TODO add filename
QImage img = image;
if (img.allGray())
_dim = 2, _zsize = 1;
else
_dim = 3, _zsize = 3;
if (img.format() == QImage::Format_ARGB32)
_dim = 3, _zsize++;
img = img.convertToFormat(QImage::Format_RGB32);
if (img.isNull()) {
kDebug(399) << "can't convert image to depth 32";
return false;
}
_bpc = 1;
_xsize = img.width();
_ysize = img.height();
_pixmin = ~0u;
_pixmax = 0;
_colormap = NORMAL;
_numrows = _ysize * _zsize;
_starttab = new quint32[_numrows];
_rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
if (!scanData(img)) {
kDebug(399) << "this can't happen";
return false;
}
_rlevector = _rlemap.vector();
ulong verbatim_size = ulong(_numrows) * _xsize;
ulong rle_size = _numrows * 2 * sizeof(quint32);
for (int i = 0; i < _rlevector.size(); i++)
rle_size += _rlevector[i]->size();
kDebug(399) << "minimum intensity: " << _pixmin;
kDebug(399) << "maximum intensity: " << _pixmax;
kDebug(399) << "saved scanlines: " << _numrows - _rlemap.size();
kDebug(399) << "total savings: " << (verbatim_size - rle_size) << " bytes";
kDebug(399) << "compression: " << (rle_size * 100.0 / verbatim_size) << '%';
if (verbatim_size <= rle_size)
writeVerbatim(img);
else
writeRle();
return true;
}
///////////////////////////////////////////////////////////////////////////////
RGBHandler::RGBHandler()
{
}
bool RGBHandler::canRead() const
{
if (canRead(device())) {
setFormat("rgb");
return true;
}
return false;
}
bool RGBHandler::read(QImage *outImage)
{
SGIImage sgi(device());
return sgi.readImage(*outImage);
}
bool RGBHandler::write(const QImage &image)
{
SGIImage sgi(device());
return sgi.writeImage(image);
}
QByteArray RGBHandler::name() const
{
return "rgb";
}
bool RGBHandler::canRead(QIODevice *device)
{
if (!device) {
qWarning("RGBHandler::canRead() called with no device");
return false;
}
qint64 oldPos = device->pos();
QByteArray head = device->readLine(64);
int readBytes = head.size();
if (device->isSequential()) {
while (readBytes > 0)
device->ungetChar(head[readBytes-- - 1]);
} else {
device->seek(oldPos);
}
const QRegExp regexp("^\x01\xda\x01[\x01\x02]");
QString data(head);
return data.contains(regexp);
}
///////////////////////////////////////////////////////////////////////////////
class RGBPlugin : public QImageIOPlugin
{
public:
QStringList keys() const;
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
};
QStringList RGBPlugin::keys() const
{
return QStringList() << "rgb" << "RGB" << "rgba" << "RGBA" << "bw" << "BW" << "sgi" << "SGI";
}
QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const
{
if (format == "rgb" || format == "RGB" || format == "rgba" || format == "RGBA"
|| format == "bw" || format == "BW" || format == "sgi" || format == "SGI")
return Capabilities(CanRead|CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap;
if (device->isReadable() && RGBHandler::canRead(device))
cap |= CanRead;
if (device->isWritable())
cap |= CanWrite;
return cap;
}
QImageIOHandler *RGBPlugin::create(QIODevice *device, const QByteArray &format) const
{
QImageIOHandler *handler = new RGBHandler;
handler->setDevice(device);
handler->setFormat(format);
return handler;
}
Q_EXPORT_PLUGIN2(rgb, RGBPlugin)

View file

@ -1,7 +0,0 @@
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=rgb,rgba,bw,sgi
X-KDE-MimeType=image/x-rgb
X-KDE-Read=true
X-KDE-Write=true

View file

@ -1,103 +0,0 @@
// kimgio module for SGI images
//
// Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Lesser GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
#ifndef KIMG_RGB_H
#define KIMG_RGB_H
#include <QtGui/qimageiohandler.h>
#include <QtCore/qmap.h>
#include <QtCore/qvector.h>
class RGBHandler : public QImageIOHandler
{
public:
RGBHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
class RLEData : public QVector<uchar> {
public:
RLEData() {}
RLEData(const uchar *d, uint l, uint o) : _offset(o) {
for (uint i = 0; i < l; i++)
append(d[i]);
}
bool operator<(const RLEData&) const;
void write(QDataStream& s);
uint offset() const { return _offset; }
private:
uint _offset;
};
class RLEMap : public QMap<RLEData, uint> {
public:
RLEMap() : _counter(0), _offset(0) {}
uint insert(const uchar *d, uint l);
QVector<const RLEData*> vector();
void setBaseOffset(uint o) { _offset = o; }
private:
uint _counter;
uint _offset;
};
class SGIImage {
public:
SGIImage(QIODevice *device);
~SGIImage();
bool readImage(QImage&);
bool writeImage(const QImage&);
private:
enum { NORMAL, DITHERED, SCREEN, COLORMAP }; // colormap
QIODevice *_dev;
QDataStream _stream;
quint8 _rle;
quint8 _bpc;
quint16 _dim;
quint16 _xsize;
quint16 _ysize;
quint16 _zsize;
quint32 _pixmin;
quint32 _pixmax;
char _imagename[80];
quint32 _colormap;
quint32 *_starttab;
quint32 *_lengthtab;
QByteArray _data;
QByteArray::Iterator _pos;
RLEMap _rlemap;
QVector<const RLEData*> _rlevector;
uint _numrows;
bool readData(QImage&);
bool getRow(uchar *dest);
void writeHeader();
void writeRle();
void writeVerbatim(const QImage&);
bool scanData(const QImage&);
uint compact(uchar *, uchar *);
uchar intensity(uchar);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Service Type=Service
X-KDE-ServiceTypes=QImageIOPlugins X-KDE-ServiceTypes=QImageIOPlugins
X-KDE-ImageFormat=xcf X-KDE-ImageFormat=magick
X-KDE-MimeType=image/x-xcf X-KDE-MimeType=image/x-xcf
X-KDE-Read=true X-KDE-Read=true
X-KDE-Write=false X-KDE-Write=false

View file

@ -1,246 +0,0 @@
#ifndef XCF_H
#define XCF_H
/*
* qxcfi.cpp: A Qt 3 plug-in for reading GIMP XCF image files
* Copyright (C) 2001 lignum Computing, Inc. <allen@lignumcomputing.com>
* Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
*
* This plug-in 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <QtGui/qimageiohandler.h>
#include <QtGui/qimage.h>
#include <QtCore/qvector.h>
#include "gimp.h"
class XCFHandler : public QImageIOHandler
{
public:
XCFHandler();
bool canRead() const;
bool read(QImage *image);
bool write(const QImage &image);
QByteArray name() const;
static bool canRead(QIODevice *device);
};
const float INCHESPERMETER = (100.0f / 2.54f);
/*!
* Each layer in an XCF file is stored as a matrix of
* 64-pixel by 64-pixel images. The GIMP has a sophisticated
* method of handling very large images as well as implementing
* parallel processing on a tile-by-tile basis. Here, though,
* we just read them in en-masse and store them in a matrix.
*/
typedef QVector<QVector<QImage> > Tiles;
class XCFImageFormat {
public:
XCFImageFormat();
bool readXCF(QIODevice *device, QImage *image);
private:
/*!
* Each GIMP image is composed of one or more layers. A layer can
* be one of any three basic types: RGB, grayscale or indexed. With an
* optional alpha channel, there are six possible types altogether.
*
* Note: there is only ever one instance of this structure. The
* layer info is discarded after it is merged into the final QImage.
*/
class Layer {
public:
quint32 width; //!< Width of the layer
quint32 height; //!< Height of the layer
qint32 type; //!< Type of the layer (GimpImageType)
char* name; //!< Name of the layer
quint32 hierarchy_offset; //!< File position of Tile hierarchy
quint32 mask_offset; //!< File position of mask image
uint nrows; //!< Number of rows of tiles (y direction)
uint ncols; //!< Number of columns of tiles (x direction)
Tiles image_tiles; //!< The basic image
//! For Grayscale and Indexed images, the alpha channel is stored
//! separately (in this data structure, anyway).
Tiles alpha_tiles;
Tiles mask_tiles; //!< The layer mask (optional)
//! Additional information about a layer mask.
struct {
quint32 opacity;
quint32 visible;
quint32 show_masked;
uchar red, green, blue;
quint32 tattoo;
} mask_channel;
bool active; //!< Is this layer the active layer?
quint32 opacity; //!< The opacity of the layer
quint32 visible; //!< Is the layer visible?
quint32 linked; //!< Is this layer linked (geometrically)
quint32 preserve_transparency; //!< Preserve alpha when drawing on layer?
quint32 apply_mask; //!< Apply the layer mask?
quint32 edit_mask; //!< Is the layer mask the being edited?
quint32 show_mask; //!< Show the layer mask rather than the image?
qint32 x_offset; //!< x offset of the layer relative to the image
qint32 y_offset; //!< y offset of the layer relative to the image
quint32 mode; //!< Combining mode of layer (LayerModeEffects)
quint32 tattoo; //!< (unique identifier?)
//! As each tile is read from the file, it is buffered here.
uchar tile[TILE_WIDTH * TILE_HEIGHT * sizeof(QRgb)];
//! The data from tile buffer is copied to the Tile by this
//! method. Depending on the type of the tile (RGB, Grayscale,
//! Indexed) and use (image or mask), the bytes in the buffer are
//! copied in different ways.
void (*assignBytes)(Layer& layer, uint i, uint j);
Layer(void) : name(0) {}
~Layer(void) { delete[] name; }
};
/*!
* The in-memory representation of the XCF Image. It contains a few
* metadata items, but is mostly a container for the layer information.
*/
class XCFImage {
public:
quint32 width; //!< width of the XCF image
quint32 height; //!< height of the XCF image
qint32 type; //!< type of the XCF image (GimpImageBaseType)
quint8 compression; //!< tile compression method (CompressionType)
float x_resolution; //!< x resolution in dots per inch
float y_resolution; //!< y resolution in dots per inch
qint32 tattoo; //!< (unique identifier?)
quint32 unit; //!< Units of The GIMP (inch, mm, pica, etc...)
qint32 num_colors; //!< number of colors in an indexed image
QVector<QRgb> palette; //!< indexed image color palette
int num_layers; //!< number of layers
Layer layer; //!< most recently read layer
bool initialized; //!< Is the QImage initialized?
QImage image; //!< final QImage
XCFImage(void) : initialized(false) {}
};
//! In layer DISSOLVE mode, a random number is chosen to compare to a
//! pixel's alpha. If the alpha is greater than the random number, the
//! pixel is drawn. This table merely contains the random number seeds
//! for each ROW of an image. Therefore, the random numbers chosen
//! are consistent from run to run.
static int random_table[RANDOM_TABLE_SIZE];
static bool random_table_initialized;
//! This table is used as a shared grayscale ramp to be set on grayscale
//! images. This is because Qt does not differentiate between indexed and
//! grayscale images.
static QVector<QRgb> grayTable;
//! This table provides the add_pixel saturation values (i.e. 250 + 250 = 255).
//static int add_lut[256][256]; - this is so lame waste of 256k of memory
static int add_lut( int, int );
//! The bottom-most layer is copied into the final QImage by this
//! routine.
typedef void (*PixelCopyOperation)(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
//! Higher layers are merged into the final QImage by this routine.
typedef void (*PixelMergeOperation)(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
//! Layer mode static data.
typedef struct {
bool affect_alpha; //!< Does this mode affect the source alpha?
} LayerModes;
//! Array of layer mode structures for the modes described by
//! LayerModeEffects.
static const LayerModes layer_modes[];
bool loadImageProperties(QDataStream& xcf_io, XCFImage& image);
bool loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes);
bool loadLayer(QDataStream& xcf_io, XCFImage& xcf_image);
bool loadLayerProperties(QDataStream& xcf_io, Layer& layer);
bool composeTiles(XCFImage& xcf_image);
void setGrayPalette(QImage& image);
void setPalette(XCFImage& xcf_image, QImage& image);
static void assignImageBytes(Layer& layer, uint i, uint j);
bool loadHierarchy(QDataStream& xcf_io, Layer& layer);
bool loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp);
static void assignMaskBytes(Layer& layer, uint i, uint j);
bool loadMask(QDataStream& xcf_io, Layer& layer);
bool loadChannelProperties(QDataStream& xcf_io, Layer& layer);
bool initializeImage(XCFImage& xcf_image);
bool loadTileRLE(QDataStream& xcf_io, uchar* tile, int size,
int data_length, qint32 bpp);
static void copyLayerToImage(XCFImage& xcf_image);
static void copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeLayerIntoImage(XCFImage& xcf_image);
static void mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
QImage& image, int m, int n);
static void initializeRandomTable();
static void dissolveRGBPixels(QImage& image, int x, int y);
static void dissolveAlphaPixels(QImage& image, int x, int y);
};
#endif

View file

@ -244,7 +244,6 @@ install(
kcmodule.desktop kcmodule.desktop
kcmoduleinit.desktop kcmoduleinit.desktop
kdatatool.desktop kdatatool.desktop
kfileplugin.desktop
kscan.desktop kscan.desktop
kurifilterplugin.desktop kurifilterplugin.desktop
kfile/kpropertiesdialogplugin.desktop kfile/kpropertiesdialogplugin.desktop

View file

@ -100,7 +100,7 @@ KFileMetaDataWidget::Private::~Private()
void KFileMetaDataWidget::Private::initMetaInfoSettings() void KFileMetaDataWidget::Private::initMetaInfoSettings()
{ {
// increase version, if the blacklist of disabled properties should be updated // increase version, if the blacklist of disabled properties should be updated
static const int currentVersion = 6; static const int currentVersion = 7;
KConfig config("kmetainformationrc", KConfig::NoGlobals); KConfig config("kmetainformationrc", KConfig::NoGlobals);
if (config.group("Misc").readEntry("version", 0) < currentVersion) { if (config.group("Misc").readEntry("version", 0) < currentVersion) {

View file

@ -61,6 +61,7 @@ QString KNfoTranslator::translation(const KUrl& uri)
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#characterCount", i18nc("@label number of characters", "Characters") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#characterCount", i18nc("@label number of characters", "Characters") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#codec", i18nc("@label", "Codec") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#codec", i18nc("@label", "Codec") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#colorDepth", i18nc("@label", "Color Depth") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#colorDepth", i18nc("@label", "Color Depth") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#colorCount", i18nc("@label", "Color Count") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#duration", i18nc("@label", "Duration") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#duration", i18nc("@label", "Duration") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName", i18nc("@label", "Filename") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#fileName", i18nc("@label", "Filename") },
{ "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#hasHash", i18nc("@label", "Hash") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#hasHash", i18nc("@label", "Hash") },

View file

@ -1,105 +0,0 @@
[Desktop Entry]
Type=ServiceType
X-KDE-ServiceType=KFilePlugin
Name=KFile Meta Data Plugin
Name[af]=KFile Metadata inpropmodule
Name[ar]=ملحق KFile Meta Data
Name[as]=KFile -
Name[ast]=Complementu pa metadatos de KFile
Name[be@latin]=Plugin metaźviestak dla KFile
Name[bg]=Приставка за мета данни
Name[bn]=- - -
Name[bn_IN]=KFile ি -
Name[bs]=Priključak za metapodatke (KFile)
Name[ca]=Connector de meta dades KFile
Name[ca@valencia]=Connector de meta dades KFile
Name[cs]=Modul KFile pro metadata
Name[csb]=Wtëkôcz do sprôwianiô pòdôwkama nieznónegò fòrmatu
Name[cy]=Ategyn Meta-ddata KFfeil
Name[da]=KFile Metadata-plugin
Name[de]=KFile: Metadaten-Modul
Name[el]=Πρόσθετο μετα-δεδομένων του KFile
Name[en_GB]=KFile Meta Data Plugin
Name[eo]=KFile-metadatuma kromprogramo
Name[es]=Complemento de meta datos KFile
Name[et]=KFile'i metaandmete plugin
Name[eu]=KFile metadatuen plugin-a
Name[fa]=وصله فراداده KFile
Name[fi]=KFile-metatietoliitännäinen
Name[fr]=Module externe de métadonnées KFile
Name[fy]=KFile Meta Data Plugin
Name[ga]=Breiseán meiteashonraí do KFile
Name[gl]=Complemento de metadatos para KFile
Name[gu]=Meta િ
Name[he]=תוסף מידע קובץ עבור KFile
Name[hi]=-
Name[hne]=-
Name[hr]=KFile priključak za meta-podatke
Name[hsb]=KFile-zašćěpka za Meta-Data
Name[hu]=KFile metaadat-modul
Name[hy]=KFile մետա տեղեկության հարմարանք
Name[ia]=Plugin de Meta datos de KFile
Name[id]=Plugin Data Meta KFile
Name[is]=KFile metagagna-íforrit
Name[it]=Estensione informazioni aggiuntive per KFile
Name[ja]=KFile
Name[kk]=KFile метадеректер модулі
Name[km]= KFile
Name[kn]= () ಿಿ (ಿ)
Name[ko]=KFile
Name[ku]=Pêveka KPel Ser Dane
Name[lb]=KFile-Metadonnéeë-Plugin
Name[lt]=KFile Meta duomenų priedas
Name[lv]=KFile metadatu spraudnis
Name[mai]=-
Name[mk]=KFile приклучок за мета податоци
Name[ml]=
Name[mr]=KFile ि
Name[ms]=Plug masuk Data Meta KFile
Name[nb]=KFile-programtillegg for metadata
Name[nds]=KFile-Metadaten-Moduul
Name[ne]=
Name[nl]=KFile Meta Data Plugin
Name[nn]=KFile-tillegg for metadata
Name[or]=KFile ି
Name[pa]=KFile
Name[pl]=Wtyczka do obsługi danych nieznanego formatu
Name[pt]='Plugin' de Meta-Dados do KFile
Name[pt_BR]=Plugin de metadados KFile
Name[ro]=Modul metadate KFile
Name[ru]=Расширение метаданных для KFile
Name[se]=KFile lassemoduvla metadieđuid várás
Name[si]=KFile
Name[sk]=Modul KFile pre metadáta
Name[sl]=Vstavek za metapodatke pri KFile
Name[sr]=Прикључак за метаподатке (кфајл)
Name[sr@ijekavian]=Прикључак за метаподатке (кфајл)
Name[sr@ijekavianlatin]=Priključak za metapodatke (KFile)
Name[sr@latin]=Priključak za metapodatke (KFile)
Name[sv]=Kfil-metadata-insticksprogram
Name[ta]=KFile ி ி
Name[te]= ి
Name[tg]=Васлкунаки маълумоти KFile Meta
Name[th]= KFile
Name[tr]=KFile Meta Verisi Eklentisi
Name[tt]=KFile мета-файлы өчен өстәмә
Name[ug]=KFile مېتا سانلىق-مەلۇمات قىستۇرمىسى
Name[uk]=Додаток роботи з метаданими KFile
Name[uz]=KFile meta maʼlumot uchun plagin
Name[uz@cyrillic]=KFile мета маълумот учун плагин
Name[vi]=Phn b sung d liu lý lch KFile
Name[wa]=Tchôke-divins meta-dnêyes des fitchîs
Name[xh]=Iplagi yangaphakathi ye KFile Meta Data
Name[x-test]=xxKFile Meta Data Pluginxx
Name[zh_CN]=KFile
Name[zh_HK]=KFile
Name[zh_TW]=KFile
[PropertyDef::PreferredItems]
Type=QStringList
[PropertyDef::PreferredGroups]
Type=QStringList
[PropertyDef::SupportsThumbnail]
Type=bool

View file

@ -297,7 +297,7 @@ public:
QHash<QString, KFileMetaInfoItem> items; QHash<QString, KFileMetaInfoItem> items;
KUrl m_url; KUrl m_url;
void init ( QIODevice& stream, const KUrl& url, time_t mtime, KFileMetaInfo::WhatFlags w = KFileMetaInfo::Everything ); void init ( QIODevice& stream, const KUrl& url, time_t mtime, KFileMetaInfo::WhatFlags w );
void initWriters ( const KUrl& /*file*/ ); void initWriters ( const KUrl& /*file*/ );
void operator= ( const KFileMetaInfoPrivate& k ) { void operator= ( const KFileMetaInfoPrivate& k ) {
items = k.items; items = k.items;
@ -321,6 +321,12 @@ public:
return 65536; // do not read the whole file - this is used for on-the-fly analysis return 65536; // do not read the whole file - this is used for on-the-fly analysis
} }
bool useFactory(Strigi::StreamAnalyzerFactory* factory) const {
Q_UNUSED(factory);
// TODO: filter factories based on m_indexDetail
return true;
}
private: private:
KFileMetaInfo::WhatFlags m_indexDetail; KFileMetaInfo::WhatFlags m_indexDetail;
}; };
@ -370,13 +376,13 @@ KFileMetaInfo::KFileMetaInfo ( const QString& path, KFileMetaInfo::WhatFlags w )
} }
} }
KFileMetaInfo::KFileMetaInfo ( const KUrl& url ) KFileMetaInfo::KFileMetaInfo ( const KUrl& url, KFileMetaInfo::WhatFlags w )
: d ( new KFileMetaInfoPrivate() ) : d ( new KFileMetaInfoPrivate() )
{ {
QFileInfo fileinfo ( url.toLocalFile() ); QFileInfo fileinfo ( url.toLocalFile() );
QFile file ( url.toLocalFile() ); QFile file ( url.toLocalFile() );
if ( file.open ( QIODevice::ReadOnly ) ) { if ( file.open ( QIODevice::ReadOnly ) ) {
d->init ( file, url, fileinfo.lastModified().toTime_t() ); d->init ( file, url, fileinfo.lastModified().toTime_t(), w );
if ( fileinfo.isWritable() ) { if ( fileinfo.isWritable() ) {
d->initWriters ( url ); d->initWriters ( url );
} }

View file

@ -60,8 +60,7 @@ public:
* This is like a preset which can be customized by passing additional * This is like a preset which can be customized by passing additional
* parameters to constructors. * parameters to constructors.
*/ */
enum What enum What {
{
Fastest = 0x1, /**< do the fastest possible read and omit all items Fastest = 0x1, /**< do the fastest possible read and omit all items
that might need a significantly longer time that might need a significantly longer time
than the others */ than the others */
@ -77,7 +76,7 @@ public:
Thumbnail = 0x10, /**< only read the file's thumbnail, if it contains Thumbnail = 0x10, /**< only read the file's thumbnail, if it contains
one */ one */
LinkedData = 0x40, //< extract linked/related files like html links, source #include etc LinkedData = 0x40, //< extract linked/related files like html links, source #include etc
Everything = 0xffff ///< read everything, even if it might take a while Everything = Fastest | TechnicalInfo | ContentInfo | ExternalSources | Thumbnail | LinkedData ///< read everything, even if it might take a while
}; };
Q_DECLARE_FLAGS(WhatFlags, What) Q_DECLARE_FLAGS(WhatFlags, What)
@ -98,7 +97,7 @@ public:
* the resource pointed to by @p url. * the resource pointed to by @p url.
* @note that c'tor is not thread-safe * @note that c'tor is not thread-safe
**/ **/
KFileMetaInfo(const KUrl& url); KFileMetaInfo(const KUrl& url, WhatFlags w = Everything);
/** /**
* @brief Construct an empty, invalid KFileMetaInfo instance. * @brief Construct an empty, invalid KFileMetaInfo instance.
**/ **/
@ -128,7 +127,7 @@ public:
bool isValid() const; bool isValid() const;
QStringList preferredKeys() const; QStringList preferredKeys() const;
QStringList supportedKeys() const; QStringList supportedKeys() const;
KIO_EXPORT friend QDataStream& operator >>(QDataStream& s, KFileMetaInfo& ) KIO_EXPORT friend QDataStream& operator >>(QDataStream& s, KFileMetaInfo&)
; ;
KIO_EXPORT friend QDataStream& operator <<(QDataStream& s, const KFileMetaInfo&); KIO_EXPORT friend QDataStream& operator <<(QDataStream& s, const KFileMetaInfo&);
KFileMetaInfoGroupList groups() const; KFileMetaInfoGroupList groups() const;

View file

@ -25,16 +25,10 @@
* *
* Currently supported formats include: * Currently supported formats include:
* @li DDS \<read\> * @li DDS \<read\>
* @li EPS \<read\> \<write\> * @li EPS \<read\>
* @li EXR \<read\> * @li EXR \<read\>
* @li HDR \<read\> * @li JP2 \<read\>
* @li JP2 \<read\> \<write\>
* @li PCX \<read\> \<write\>
* @li PIC \<read\> \<write\>
* @li PNM \<read\>
* @li PSD \<read\> * @li PSD \<read\>
* @li RAS \<read\>
* @li RGB \<read\> \<write\>
* @li WEBP \<read\> \<write\> * @li WEBP \<read\> \<write\>
* @li XCF \<read\> * @li XCF \<read\>
* *

View file

@ -1,18 +0,0 @@
#include "dummymeta.h"
K_EXPORT_COMPONENT_FACTORY( dummymeta, KGenericFactory<DummyMeta> )
DummyMeta::DummyMeta( QObject *parent, const char *name,
const QStringList &preferredItems )
: KFilePlugin( parent, name, preferredItems )
{
qDebug("---- DummyMeta::DummyMeta: got %i preferred items.", preferredItems.count());
}
bool DummyMeta::readInfo( KFileMetaInfo::Internal & info )
{
qDebug("#### DummyMeta:: readInfo: %s", info.path().toLatin1().constData() );
return 0L;
}
#include "moc_dummymeta.cpp"

View file

@ -1,98 +0,0 @@
[Desktop Entry]
Type=Service
Name=Dummy Meta
Name[af]=Fop Meta
Name[ar]=بيانات وهمية
Name[as]=Dummy Meta
Name[ast]=Falsu Meta
Name[be]=Парожнія звесткі
Name[be@latin]=Pustyja metaźviestki
Name[bg]=Dummy Meta
Name[bn]=ি
Name[bn_IN]=ি ি
Name[bs]=Lažni meta
Name[ca]=Dummy Meta
Name[ca@valencia]=Dummy Meta
Name[cs]=Prázdné meta
Name[csb]=Testowé pòdôwczi
Name[cy]=Meta Dymi
Name[da]=Dummy-meta
Name[de]=Dummy Meta
Name[el]=Εικονικό Meta
Name[en_GB]=Dummy Meta
Name[eo]=Ŝajnaj metadatumoj
Name[es]=Dummy Meta
Name[et]=Dummy meta
Name[eu]=Dummy Meta
Name[fa]=فراساختگی
Name[fi]=Tyhjä meta
Name[fr]=Données factices
Name[fy]=Dummy Meta
Name[ga]=Meitea Caoch
Name[gl]=Dummy Meta
Name[gu]=
Name[he]=מטא מידע סתמי
Name[hi]=
Name[hne]=
Name[hr]=Ogledni meta podatak
Name[hsb]=Dummy Meta
Name[hu]=Üres (dummy) metaadat
Name[ia]=Dummy Meta
Name[id]=Meta Rekaan
Name[is]=Dummy Meta
Name[it]=Informazioni aggiuntive posticce
Name[ja]=Dummy Meta
Name[kk]=Метадерек үлгісі
Name[km]= Dummy
Name[kn]=ಿ (ಿ)
Name[ko]=
Name[ku]=Meta Çêkirîtî
Name[lb]=Dummy-Meta
Name[lt]=Netikras Meta
Name[lv]=Testa metadati
Name[mai]=
Name[ml]=
Name[mr]=
Name[ms]=Meta Olok-olok
Name[nb]=Dummy Meta
Name[nds]=Dummy Meta
Name[ne]=
Name[nl]=Dummy Meta
Name[nn]=Eksempelmeta
Name[or]=ି
Name[pa]=
Name[pl]=Dane testowe
Name[pt]=Dummy Meta
Name[pt_BR]=Metadado fictício
Name[ro]=Test Meta
Name[ru]=Пустые метаданные
Name[se]=Dummy Meta
Name[sk]=Prázdne meta
Name[sl]=Preizkusni Meta
Name[sq]=Dummy Meta
Name[sr]=Лажни мета
Name[sr@ijekavian]=Лажни мета
Name[sr@ijekavianlatin]=Lažni meta
Name[sr@latin]=Lažni meta
Name[sv]=Testmeta
Name[ta]=
Name[te]=ి
Name[tg]=Dummy Meta
Name[th]=
Name[tr]=Kukla Meta
Name[tt]=Ялган Meta
Name[ug]=مۆلچەر مېتا
Name[uk]=Макет метаданих
Name[uz]=Maʼnosiz meta
Name[uz@cyrillic]=Маъносиз мета
Name[vi]=Siêu gi
Name[wa]=Biesse meta-dnêye
Name[xh]=Dummy Meta
Name[x-test]=xxDummy Metaxx
Name[zh_CN]=
Name[zh_HK]=
Name[zh_TW]=
X-KDE-ServiceTypes=KFilePlugin
X-KDE-Library=dummymeta
MimeType=text/plain;
PreferredItems=Author,Title,Date

View file

@ -1,20 +0,0 @@
#ifndef DUMMYMETA_H
#define DUMMYMETA_H
#include <kfilemetainfo.h>
class KFileMetaInfo;
class DummyMeta : public KFilePlugin
{
Q_OBJECT
public:
DummyMeta( QObject *parent, const char *name, const QStringList &args );
~DummyMeta() {}
virtual bool readInfo( KFileMetaInfo::Internal& info );
};
#endif

View file

@ -18,9 +18,6 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#undef QT_USE_FAST_OPERATOR_PLUS
#undef QT_USE_FAST_CONCATENATION
#include "krununittest.h" #include "krununittest.h"
#include "moc_krununittest.cpp" #include "moc_krununittest.cpp"
#include <qtest_kde.h> #include <qtest_kde.h>

View file

@ -442,9 +442,8 @@
</entry> </entry>
</group> </group>
<group name="PreviewSettings" > <group name="PreviewSettings" >
<entry key="BoostSize" type="Bool" /> <entry key="MaximumSize" type="Int" />
<entry key="MaximumSize" type="Bool" /> <entry key="MaximumRemoteSize" type="Int" />
<entry key="UseFileThumbnails" type="Bool" />
<entry key="Plugins" type="StringList" /> <entry key="Plugins" type="StringList" />
<entry key="ar" type="Bool" /> <entry key="ar" type="Bool" />
<entry key="file" type="Bool" /> <entry key="file" type="Bool" />

View file

@ -611,70 +611,6 @@ Notes:
<comment xml:lang="zh_CN">RealAudio 插件文件</comment> <comment xml:lang="zh_CN">RealAudio 插件文件</comment>
<comment xml:lang="zh_TW">RealAudio 外掛程式檔案</comment> <comment xml:lang="zh_TW">RealAudio 外掛程式檔案</comment>
</mime-type> </mime-type>
<mime-type type="image/x-hdr"> <!-- TODO fdo report -->
<comment>HDR image</comment>
<comment xml:lang="ar">صورة HDR</comment>
<comment xml:lang="ast">Imaxe HDR</comment>
<comment xml:lang="bg">Изображение HDR</comment>
<comment xml:lang="bs">HDR slika</comment>
<comment xml:lang="ca">imatge HDR</comment>
<comment xml:lang="ca@valencia">imatge HDR</comment>
<comment xml:lang="cs">HDR obrázek</comment>
<comment xml:lang="da">HDR-billede</comment>
<comment xml:lang="de">HDR-Bild</comment>
<comment xml:lang="el">Εικόνα HDR</comment>
<comment xml:lang="en_GB">HDR image</comment>
<comment xml:lang="es">Imagen HDR</comment>
<comment xml:lang="et">HDR pilt</comment>
<comment xml:lang="eu">HDR irudia</comment>
<comment xml:lang="fi">HDR-kuva</comment>
<comment xml:lang="fr">Image HDR</comment>
<comment xml:lang="ga">Íomhá HDR</comment>
<comment xml:lang="gl">Imaxe de HDR</comment>
<comment xml:lang="hr">HDR slika</comment>
<comment xml:lang="hu">HDR-kép</comment>
<comment xml:lang="ia">Imagine HDR</comment>
<comment xml:lang="is">HDR mynd</comment>
<comment xml:lang="it">immagine HDR</comment>
<comment xml:lang="ja">HDR イメージ</comment>
<comment xml:lang="kk">HDR кескіні</comment>
<comment xml:lang="km">រូបភាព HDR</comment>
<comment xml:lang="ko">HDR 그림</comment>
<comment xml:lang="lt">HDR paveikslėlis</comment>
<comment xml:lang="lv">HDR attēls</comment>
<comment xml:lang="ml">എച്ച് ഡി ആര്‍ ചിത്രം</comment>
<comment xml:lang="mr">HDR प्रतिमा</comment>
<comment xml:lang="ms">Imej HDR</comment>
<comment xml:lang="nb">HDR-bilde</comment>
<comment xml:lang="nds">HDR-Afbild</comment>
<comment xml:lang="nl">HDR-image</comment>
<comment xml:lang="nn">HDR-bilete</comment>
<comment xml:lang="pa">HDR ਚਿੱਤਰ</comment>
<comment xml:lang="pl">Obraz HDR</comment>
<comment xml:lang="pt">Imagem HDR</comment>
<comment xml:lang="pt_BR">Imagem HDR</comment>
<comment xml:lang="ro">Imagine HDR</comment>
<comment xml:lang="ru">изображение HDR</comment>
<comment xml:lang="se">HDR-govva</comment>
<comment xml:lang="sk">HDR obrázok</comment>
<comment xml:lang="sl">Slika HDR</comment>
<comment xml:lang="sq">HDR image</comment>
<comment xml:lang="sr">ХДР слика</comment>
<comment xml:lang="sr@ijekavian">ХДР слика</comment>
<comment xml:lang="sr@ijekavianlatin">HDR slika</comment>
<comment xml:lang="sr@latin">HDR slika</comment>
<comment xml:lang="sv">HDR-bild</comment>
<comment xml:lang="th">ภาพรูปแบบ HDR</comment>
<comment xml:lang="tr">HDR resmi</comment>
<comment xml:lang="ug">HDR سۈرەت</comment>
<comment xml:lang="uk">зображення HDR</comment>
<comment xml:lang="zh_CN">HDR 图像</comment>
<comment xml:lang="zh_TW">HDR 影像</comment>
<acronym>HDR</acronym>
<expanded-acronym>High Dynamic Range</expanded-acronym>
<glob pattern="*.hdr"/>
<glob pattern="*.pic"/>
</mime-type>
<mime-type type="image/x-kde-raw"> <mime-type type="image/x-kde-raw">
<sub-class-of type="image/x-dcraw"/> <sub-class-of type="image/x-dcraw"/>
<comment>KDE raw image formats</comment> <comment>KDE raw image formats</comment>

View file

@ -327,7 +327,7 @@ class PLASMA_EXPORT AbstractRunner : public QObject
* a measure of safety for runners running their own threads. This should * a measure of safety for runners running their own threads. This should
* be used instead of calling KServiceTypeTrader::query(..) directly. * be used instead of calling KServiceTypeTrader::query(..) directly.
* *
* @param serviceType a service type like "Plasma/Applet" or "KFilePlugin" * @param serviceType a service type like "Plasma/Applet"
* @param constraint a constraint to limit the choices returned. * @param constraint a constraint to limit the choices returned.
* @see KServiceTypeTrader::query(const QString&, const QString&) * @see KServiceTypeTrader::query(const QString&, const QString&)
* *