mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-17 11:44:16 -04:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
b7cd5cddc1 | |||
ce56b97ee7 | |||
500ce13265 | |||
f03739f222 | |||
69effbf9f5 | |||
f06cf300f1 | |||
2a4d230717 | |||
bdf23e45d5 | |||
e9b52df1d3 | |||
dd98b2b717 | |||
dd76f41c38 | |||
940ca2b081 | |||
b14ef357e5 | |||
bf5502403e | |||
5c4c05257c | |||
7afaacb093 | |||
68bb1a0ee7 |
@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
project(KImageFormats)
|
project(KImageFormats)
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
find_package(ECM 5.62.0 NO_MODULE)
|
find_package(ECM 5.66.0 NO_MODULE)
|
||||||
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules")
|
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
||||||
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ include(KDECMakeSettings)
|
|||||||
|
|
||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
|
|
||||||
set(REQUIRED_QT_VERSION 5.11.0)
|
set(REQUIRED_QT_VERSION 5.12.0)
|
||||||
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
find_package(KF5Archive)
|
find_package(KF5Archive)
|
||||||
@ -46,6 +46,10 @@ set_package_properties(OpenEXR PROPERTIES
|
|||||||
PURPOSE "Required for the QImage plugin for OpenEXR images"
|
PURPOSE "Required for the QImage plugin for OpenEXR images"
|
||||||
)
|
)
|
||||||
add_definitions(-DQT_NO_FOREACH)
|
add_definitions(-DQT_NO_FOREACH)
|
||||||
|
# 050d00 (5.13) triggers a BIC in qimageiohandler.h, in Qt 5.13, so do not enable that until we can require 5.14
|
||||||
|
# https://codereview.qt-project.org/c/qt/qtbase/+/279215
|
||||||
|
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050c00)
|
||||||
|
add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054100)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
add_subdirectory(autotests)
|
add_subdirectory(autotests)
|
||||||
|
@ -55,6 +55,7 @@ endmacro()
|
|||||||
# Loads each <format> image in read/<format>/, and compares the
|
# Loads each <format> image in read/<format>/, and compares the
|
||||||
# result against the data read from the corresponding png file
|
# result against the data read from the corresponding png file
|
||||||
kimageformats_read_tests(
|
kimageformats_read_tests(
|
||||||
|
hdr
|
||||||
pcx
|
pcx
|
||||||
psd
|
psd
|
||||||
ras
|
ras
|
||||||
|
BIN
autotests/read/hdr/rgb.hdr
Normal file
BIN
autotests/read/hdr/rgb.hdr
Normal file
Binary file not shown.
BIN
autotests/read/hdr/rgb.png
Normal file
BIN
autotests/read/hdr/rgb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
autotests/read/xcf/bug411327.png
Normal file
BIN
autotests/read/xcf/bug411327.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
autotests/read/xcf/bug411327.xcf
Normal file
BIN
autotests/read/xcf/bug411327.xcf
Normal file
Binary file not shown.
@ -53,6 +53,11 @@ endif()
|
|||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
|
||||||
|
kimageformats_add_plugin(kimg_hdr JSON "hdr.json" SOURCES hdr.cpp)
|
||||||
|
install(FILES hdr.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)
|
||||||
|
|
||||||
|
##################################
|
||||||
|
|
||||||
kimageformats_add_plugin(kimg_pcx JSON "pcx.json" SOURCES pcx.cpp)
|
kimageformats_add_plugin(kimg_pcx JSON "pcx.json" SOURCES pcx.cpp)
|
||||||
install(FILES pcx.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)
|
install(FILES pcx.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
typedef Q_UINT8 uchar;
|
typedef unsigned char uchar;
|
||||||
|
|
||||||
namespace // Private.
|
namespace // Private.
|
||||||
{
|
{
|
||||||
@ -93,19 +93,22 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
|||||||
uchar val, code;
|
uchar val, code;
|
||||||
|
|
||||||
// Create dst image.
|
// Create dst image.
|
||||||
if (!img.create(width, height, 32)) {
|
img = QImage(width, height, QImage::Format_RGB32);
|
||||||
|
if (img.isNull()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMemArray<uchar> image(width * 4);
|
QByteArray lineArray;
|
||||||
|
lineArray.resize(4 * width);
|
||||||
|
uchar *image = (uchar *) lineArray.data();
|
||||||
|
|
||||||
for (int cline = 0; cline < height; cline++) {
|
for (int cline = 0; cline < height; cline++) {
|
||||||
QRgb *scanline = (QRgb *) img.scanLine(cline);
|
QRgb *scanline = (QRgb *) img.scanLine(cline);
|
||||||
|
|
||||||
// determine scanline type
|
// determine scanline type
|
||||||
if ((width < MINELEN) || (MAXELEN < width)) {
|
if ((width < MINELEN) || (MAXELEN < width)) {
|
||||||
Read_Old_Line(image.data(), width, s);
|
Read_Old_Line(image, width, s);
|
||||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
RGBE_To_QRgbLine(image, scanline, width);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,9 +119,9 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (val != 2) {
|
if (val != 2) {
|
||||||
s.device()->at(s.device()->at() - 1);
|
s.device()->ungetChar(val);
|
||||||
Read_Old_Line(image.data(), width, s);
|
Read_Old_Line(image, width, s);
|
||||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
RGBE_To_QRgbLine(image, scanline, width);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +135,8 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
|||||||
|
|
||||||
if ((image[1] != 2) || (image[2] & 128)) {
|
if ((image[1] != 2) || (image[2] & 128)) {
|
||||||
image[0] = 2;
|
image[0] = 2;
|
||||||
Read_Old_Line(image.data() + 4, width - 1, s);
|
Read_Old_Line(image + 4, width - 1, s);
|
||||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
RGBE_To_QRgbLine(image, scanline, width);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +171,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
RGBE_To_QRgbLine(image, scanline, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -176,7 +179,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Q_DECL_EXPORT void kimgio_hdr_read(QImageIO *io)
|
bool HDRHandler::read(QImage *outImage)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char line[MAXLINE];
|
char line[MAXLINE];
|
||||||
@ -185,7 +188,7 @@ Q_DECL_EXPORT void kimgio_hdr_read(QImageIO *io)
|
|||||||
|
|
||||||
// Parse header
|
// Parse header
|
||||||
do {
|
do {
|
||||||
len = io->ioDevice()->readLine(line, MAXLINE);
|
len = device()->readLine(line, MAXLINE);
|
||||||
|
|
||||||
/*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
|
/*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
|
||||||
{
|
{
|
||||||
@ -199,12 +202,10 @@ Q_DECL_EXPORT void kimgio_hdr_read(QImageIO *io)
|
|||||||
|
|
||||||
if (/*!validHeader ||*/ !validFormat) {
|
if (/*!validHeader ||*/ !validFormat) {
|
||||||
// qDebug() << "Unknown HDR format.";
|
// qDebug() << "Unknown HDR format.";
|
||||||
io->setImage(0);
|
return false;
|
||||||
io->setStatus(-1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
io->ioDevice()->readLine(line, MAXLINE);
|
device()->readLine(line, MAXLINE);
|
||||||
|
|
||||||
char s1[3], s2[3];
|
char s1[3], s2[3];
|
||||||
int width, height;
|
int width, height;
|
||||||
@ -212,27 +213,67 @@ Q_DECL_EXPORT void kimgio_hdr_read(QImageIO *io)
|
|||||||
//if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
|
//if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
|
||||||
{
|
{
|
||||||
// qDebug() << "Invalid HDR file.";
|
// qDebug() << "Invalid HDR file.";
|
||||||
io->setImage(0);
|
return false;
|
||||||
io->setStatus(-1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream s(io->ioDevice());
|
QDataStream s(device());
|
||||||
|
|
||||||
QImage img;
|
QImage img;
|
||||||
if (!LoadHDR(s, width, height, img)) {
|
if (!LoadHDR(s, width, height, img)) {
|
||||||
// qDebug() << "Error loading HDR file.";
|
// qDebug() << "Error loading HDR file.";
|
||||||
io->setImage(0);
|
return false;
|
||||||
io->setStatus(-1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
io->setImage(img);
|
*outImage = img;
|
||||||
io->setStatus(0);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECL_EXPORT void kimgio_hdr_write(QImageIO *)
|
HDRHandler::HDRHandler()
|
||||||
{
|
{
|
||||||
// intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HDRHandler::canRead() const
|
||||||
|
{
|
||||||
|
if (canRead(device())) {
|
||||||
|
setFormat("hdr");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HDRHandler::canRead(QIODevice *device)
|
||||||
|
{
|
||||||
|
if (!device) {
|
||||||
|
qWarning("HDRHandler::canRead() called with no device");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return device->peek(11) == "#?RADIANCE\n" || device->peek(7) == "#?RGBE\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
QImageIOPlugin::Capabilities HDRPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||||
|
{
|
||||||
|
if (format == "hdr") {
|
||||||
|
return Capabilities(CanRead);
|
||||||
|
}
|
||||||
|
if (!format.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!device->isOpen()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Capabilities cap;
|
||||||
|
if (device->isReadable() && HDRHandler::canRead(device)) {
|
||||||
|
cap |= CanRead;
|
||||||
|
}
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImageIOHandler *HDRPlugin::create(QIODevice *device, const QByteArray &format) const
|
||||||
|
{
|
||||||
|
QImageIOHandler *handler = new HDRHandler;
|
||||||
|
handler->setDevice(device);
|
||||||
|
handler->setFormat(format);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
4
src/imageformats/hdr.json
Normal file
4
src/imageformats/hdr.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"Keys": [ "hdr" ],
|
||||||
|
"MimeTypes": [ "image/x-hdr", "image/vnd.radiance" ]
|
||||||
|
}
|
@ -10,12 +10,27 @@
|
|||||||
#ifndef KIMG_HDR_P_H
|
#ifndef KIMG_HDR_P_H
|
||||||
#define KIMG_HDR_P_H
|
#define KIMG_HDR_P_H
|
||||||
|
|
||||||
class QImageIO;
|
#include <QImageIOPlugin>
|
||||||
|
|
||||||
extern "C" {
|
class HDRHandler : public QImageIOHandler
|
||||||
void kimgio_hdr_read(QImageIO *);
|
{
|
||||||
void kimgio_hdr_write(QImageIO *);
|
public:
|
||||||
}
|
HDRHandler();
|
||||||
|
|
||||||
#endif
|
bool canRead() const override;
|
||||||
|
bool read(QImage *outImage) override;
|
||||||
|
|
||||||
|
static bool canRead(QIODevice *device);
|
||||||
|
};
|
||||||
|
|
||||||
|
class HDRPlugin : public QImageIOPlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "hdr.json")
|
||||||
|
|
||||||
|
public:
|
||||||
|
Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
|
||||||
|
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KIMG_HDR_P_H
|
||||||
|
@ -130,9 +130,7 @@ static QDataStream &operator>> (QDataStream &s, QList<PicChannel> &channels)
|
|||||||
PicChannel channel;
|
PicChannel channel;
|
||||||
s >> chained;
|
s >> chained;
|
||||||
s >> channel.size;
|
s >> channel.size;
|
||||||
quint8 encoding;
|
s >> channel.encoding;
|
||||||
s >> encoding;
|
|
||||||
channel.encoding = PicChannelEncoding(encoding);
|
|
||||||
s >> channel.code;
|
s >> channel.code;
|
||||||
channels << channel;
|
channels << channel;
|
||||||
++count;
|
++count;
|
||||||
|
@ -119,7 +119,7 @@ struct PicHeader {
|
|||||||
*/
|
*/
|
||||||
struct PicChannel {
|
struct PicChannel {
|
||||||
quint8 size; /**< Bits per component per pixel. */
|
quint8 size; /**< Bits per component per pixel. */
|
||||||
PicChannelEncoding encoding; /**< How the channel's data is encoded. */
|
quint8 encoding; /**< How the channel's data is encoded. */
|
||||||
quint8 code; /**< Flag field to describe which components are encoded in
|
quint8 code; /**< Flag field to describe which components are encoded in
|
||||||
this channel. */
|
this channel. */
|
||||||
|
|
||||||
|
@ -414,6 +414,7 @@ bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_imag
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_RESOLUTION:
|
case PROP_RESOLUTION:
|
||||||
|
property.setFloatingPointPrecision(QDataStream::SinglePrecision);
|
||||||
property >> xcf_image.x_resolution >> xcf_image.y_resolution;
|
property >> xcf_image.x_resolution >> xcf_image.y_resolution;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -484,9 +485,15 @@ bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_imag
|
|||||||
* \return true if there were no IO errors. */
|
* \return true if there were no IO errors. */
|
||||||
bool XCFImageFormat::loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType)
|
bool XCFImageFormat::loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType)
|
||||||
{
|
{
|
||||||
|
quint32 size;
|
||||||
|
|
||||||
xcf_io >> rawType;
|
xcf_io >> rawType;
|
||||||
if (rawType >= MAX_SUPPORTED_PROPTYPE) {
|
if (rawType >= MAX_SUPPORTED_PROPTYPE) {
|
||||||
type = MAX_SUPPORTED_PROPTYPE;
|
type = MAX_SUPPORTED_PROPTYPE;
|
||||||
|
// we don't support the property, but we still need to read from the device, assume it's like all the
|
||||||
|
// non custom properties that is data_length + data
|
||||||
|
xcf_io >> size;
|
||||||
|
xcf_io.skipRawData(size);
|
||||||
// return true because we don't really want to totally fail on an unsupported property since it may not be fatal
|
// return true because we don't really want to totally fail on an unsupported property since it may not be fatal
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -494,7 +501,6 @@ bool XCFImageFormat::loadProperty(QDataStream &xcf_io, PropType &type, QByteArra
|
|||||||
type = PropType(rawType);
|
type = PropType(rawType);
|
||||||
|
|
||||||
char *data = nullptr;
|
char *data = nullptr;
|
||||||
quint32 size;
|
|
||||||
|
|
||||||
// The colormap property size is not the correct number of bytes:
|
// The colormap property size is not the correct number of bytes:
|
||||||
// The GIMP source xcf.c has size = 4 + ncolors, but it should be
|
// The GIMP source xcf.c has size = 4 + ncolors, but it should be
|
||||||
|
Reference in New Issue
Block a user