Skip to content

Commit

Permalink
Add PNG extractor
Browse files Browse the repository at this point in the history
Textual information, such as author information, creator software,
and a description can be stored in a PNG's tEXt, zTXt, and
iTXt chunks, [1].

libexiv2 can extract EXIF information out of PNGs but does not
support PNG Textual Information, see [2], however Qt's PNG handler
makes this information readily available as textKeys.

[1] https://www.w3.org/TR/PNG/#11keywords
[2] Exiv2/exiv2#1343
  • Loading branch information
kbroulik committed Jul 7, 2022
1 parent cdb65cc commit 1330ba1
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/extractors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,14 @@ if(libappimage_FOUND AND KF5Config_FOUND AND Qt${QT_MAJOR_VERSION}Gui_FOUND)
TARGETS kfilemetadata_appimageextractor
DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf${QT_MAJOR_VERSION}/kfilemetadata)
endif()

add_library(kfilemetadata_pngextractor MODULE pngextractor.cpp )
target_link_libraries(kfilemetadata_pngextractor
KF5::FileMetaData
Qt${QT_MAJOR_VERSION}::Gui
)

set_target_properties(kfilemetadata_pngextractor PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf${QT_MAJOR_VERSION}/kfilemetadata")
install(
TARGETS kfilemetadata_pngextractor
DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf${QT_MAJOR_VERSION}/kfilemetadata)
86 changes: 86 additions & 0 deletions src/extractors/pngextractor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
SPDX-FileCopyrightText: 2022 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include "pngextractor.h"
#include "propertyinfo.h"

#include <QImageReader>

using namespace KFileMetaData;

// Keywords specified in https://www.w3.org/TR/PNG/#11keywords
static const struct {
QString key;
Property::Property property;
} s_textMapping[] = {
// Short (one line) title or caption for image
{QStringLiteral("Title"), Property::Title},
// Name of image's creator
{QStringLiteral("Author"), Property::Author},
// Description of image (possibly long)
{QStringLiteral("Description"), Property::Description},
// Copyright notice
{QStringLiteral("Copyright"), Property::Copyright},
// Time of original image creation
{QStringLiteral("Creation Time"), Property::CreationDate},
// Software used to create the image
{QStringLiteral("Software"), Property::Generator},
// Disclaimer - Legal disclaimer
// Warning - Warning of nature of content
// Source - Device used to create the image
// Miscellaneous comment
{QStringLiteral("Comment"), Property::Comment},
};

PngExtractor::PngExtractor(QObject* parent)
: ExtractorPlugin(parent)
{
}

QStringList PngExtractor::mimetypes() const
{
return {
QStringLiteral("image/png")
};
}

void PngExtractor::extract(ExtractionResult* result)
{
QImageReader reader(result->inputUrl(), "png");
if (!reader.canRead()) {
return;
}

result->addType(Type::Image);

for (const auto &mapping : s_textMapping) {
QString text = reader.text(mapping.key);
if (text.isEmpty()) {
// Spec says, keywords are case-sensitive but of course the real world looks different.
text = reader.text(mapping.key.toLower());
}
if (text.isEmpty()) {
continue;
}

const auto propertyInfo = PropertyInfo(mapping.property);

if (propertyInfo.valueType() == QVariant::DateTime) {
// "For the Creation Time keyword, the date format defined in section 5.2.14 of RFC 1123 is suggested"
// which in turn references RFC822...
const QDateTime dt = QDateTime::fromString(text, Qt::RFC2822Date);

if (!dt.isValid()) {
continue;
}

result->add(mapping.property, dt);
continue;
}

result->add(mapping.property, text);
}
}
31 changes: 31 additions & 0 deletions src/extractors/pngextractor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
SPDX-FileCopyrightText: 2022 Kai Uwe Broulik <kde@broulik.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/

#ifndef PNGEXTRACTOR_H
#define PNGEXTRACTOR_H

#include "extractorplugin.h"

namespace KFileMetaData
{

class PngExtractor : public ExtractorPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.kde.kf5.kfilemetadata.ExtractorPlugin"
FILE "pngextractor.json")
Q_INTERFACES(KFileMetaData::ExtractorPlugin)

public:
explicit PngExtractor(QObject *parent = nullptr);

void extract(ExtractionResult *result) override;
QStringList mimetypes() const override;
};

} // namespace KFileMetaData

#endif // PNGEXTRACTOR_H
7 changes: 7 additions & 0 deletions src/extractors/pngextractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"Name" : "PngExtractor",
"Id" : "org.kde.pngextractor",
"MimeTypes" : {
"image/png" : { "version" : "0.0" }
}
}

0 comments on commit 1330ba1

Please sign in to comment.