diff --git a/PdfTool/PdfTool.pro b/PdfTool/PdfTool.pro
index e419f66..7ab3ae7 100644
--- a/PdfTool/PdfTool.pro
+++ b/PdfTool/PdfTool.pro
@@ -60,6 +60,7 @@ SOURCES += \
pdftooloptimize.cpp \
pdftoolrender.cpp \
pdftoolseparate.cpp \
+ pdftoolstatistics.cpp \
pdftoolunite.cpp \
pdftoolverifysignatures.cpp \
pdftoolxml.cpp
@@ -94,6 +95,7 @@ HEADERS += \
pdftooloptimize.h \
pdftoolrender.h \
pdftoolseparate.h \
+ pdftoolstatistics.h \
pdftoolunite.h \
pdftoolverifysignatures.h \
pdftoolxml.h
diff --git a/PdfTool/pdftoolstatistics.cpp b/PdfTool/pdftoolstatistics.cpp
new file mode 100644
index 0000000..807fa7f
--- /dev/null
+++ b/PdfTool/pdftoolstatistics.cpp
@@ -0,0 +1,174 @@
+// Copyright (C) 2021 Jakub Melka
+//
+// This file is part of Pdf4Qt.
+//
+// Pdf4Qt 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 3 of the License, or
+// with the written consent of the copyright owner, any later version.
+//
+// Pdf4Qt 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 Pdf4Qt. If not, see .
+
+#include "pdftoolstatistics.h"
+#include "pdfobjectutils.h"
+
+namespace pdftool
+{
+
+static PDFToolStatisticsApplication s_statisticsApplication;
+
+QString PDFToolStatisticsApplication::getStandardString(StandardString standardString) const
+{
+ switch (standardString)
+ {
+ case Command:
+ return "statistics";
+
+ case Name:
+ return PDFToolTranslationContext::tr("Statistics");
+
+ case Description:
+ return PDFToolTranslationContext::tr("Compute statistics of internal objects used in a document.");
+
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+
+ return QString();
+}
+
+int PDFToolStatisticsApplication::execute(const PDFToolOptions& options)
+{
+ pdf::PDFDocument document;
+ QByteArray sourceData;
+ if (!readDocument(options, document, &sourceData, false))
+ {
+ return ErrorDocumentReading;
+ }
+
+ pdf::PDFObjectClassifier classifier;
+ classifier.classify(&document);
+ pdf::PDFObjectClassifier::Statistics statistics = classifier.calculateStatistics(&document);
+
+ QLocale locale;
+
+ PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
+ formatter.beginDocument("info", PDFToolTranslationContext::tr("Information about document %1").arg(options.document));
+ formatter.endl();
+
+ {
+ formatter.beginTable("statistics-objects-by-class", PDFToolTranslationContext::tr("Statistics by Object Class"));
+
+ formatter.beginTableHeaderRow("header");
+ formatter.writeTableHeaderColumn("class", PDFToolTranslationContext::tr("Class"), Qt::AlignLeft);
+ formatter.writeTableHeaderColumn("percentage", PDFToolTranslationContext::tr("Percentage [%]"), Qt::AlignLeft);
+ formatter.writeTableHeaderColumn("count", PDFToolTranslationContext::tr("Count [#]"), Qt::AlignLeft);
+ formatter.writeTableHeaderColumn("space-usage", PDFToolTranslationContext::tr("Space Usage [bytes]"), Qt::AlignLeft);
+ formatter.endTableHeaderRow();
+
+ qint64 totalBytesCount = 0;
+ for (const auto& item : statistics.statistics)
+ {
+ totalBytesCount += item.second.bytes;
+ }
+
+ auto addRow = [&](pdf::PDFObjectClassifier::Type type, QString classText)
+ {
+ auto it = statistics.statistics.find(type);
+
+ if (it == statistics.statistics.cend())
+ {
+ // Jakub Melka: no type found
+ return;
+ }
+
+ const pdf::PDFObjectClassifier::StatisticsItem& statisticsItem = it->second;
+
+ qreal percentage = qreal(100.0) * qreal(statisticsItem.bytes) / qreal(totalBytesCount);
+
+ formatter.beginTableRow("item", int(type));
+ formatter.writeTableColumn("class", classText);
+ formatter.writeTableColumn("percentage", locale.toString(percentage, 'f', 2), Qt::AlignRight);
+ formatter.writeTableColumn("count", locale.toString(statisticsItem.count), Qt::AlignRight);
+ formatter.writeTableColumn("byte-usage", locale.toString(statisticsItem.bytes), Qt::AlignRight);
+ formatter.endTableRow();
+ };
+
+ addRow(pdf::PDFObjectClassifier::Page, PDFToolTranslationContext::tr("Page"));
+ addRow(pdf::PDFObjectClassifier::ContentStream, PDFToolTranslationContext::tr("Content Stream"));
+ addRow(pdf::PDFObjectClassifier::GraphicState, PDFToolTranslationContext::tr("Graphic State"));
+ addRow(pdf::PDFObjectClassifier::ColorSpace, PDFToolTranslationContext::tr("Color Space"));
+ addRow(pdf::PDFObjectClassifier::Pattern, PDFToolTranslationContext::tr("Pattern"));
+ addRow(pdf::PDFObjectClassifier::Shading, PDFToolTranslationContext::tr("Shading"));
+ addRow(pdf::PDFObjectClassifier::Image, PDFToolTranslationContext::tr("Image"));
+ addRow(pdf::PDFObjectClassifier::Form, PDFToolTranslationContext::tr("Form"));
+ addRow(pdf::PDFObjectClassifier::Font, PDFToolTranslationContext::tr("Font"));
+ addRow(pdf::PDFObjectClassifier::Action, PDFToolTranslationContext::tr("Action"));
+ addRow(pdf::PDFObjectClassifier::Annotation, PDFToolTranslationContext::tr("Annotation"));
+ addRow(pdf::PDFObjectClassifier::None, PDFToolTranslationContext::tr("Other"));
+
+ formatter.endTable();
+ }
+
+ formatter.endl();
+
+ {
+ formatter.beginTable("statistics-objects-by-type", PDFToolTranslationContext::tr("Statistics by Object Type"));
+
+ formatter.beginTableHeaderRow("header");
+ formatter.writeTableHeaderColumn("class", PDFToolTranslationContext::tr("Type") , Qt::AlignLeft);
+ formatter.writeTableHeaderColumn("percentage", PDFToolTranslationContext::tr("Percentage [%]"), Qt::AlignLeft);
+ formatter.writeTableHeaderColumn("count", PDFToolTranslationContext::tr("Count [#]"), Qt::AlignLeft);
+ formatter.endTableHeaderRow();
+
+ qint64 totalObjectCount = 0;
+ for (pdf::PDFObject::Type type : pdf::PDFObject::getTypes())
+ {
+ const qint64 currentObjectCount = statistics.objectCountByType[size_t(type)];
+ totalObjectCount += currentObjectCount;
+ }
+
+ if (totalObjectCount > 0)
+ {
+ for (pdf::PDFObject::Type type : pdf::PDFObject::getTypes())
+ {
+ const qint64 currentObjectCount = statistics.objectCountByType[size_t(type)];
+
+ if (currentObjectCount == 0)
+ {
+ continue;
+ }
+
+ qreal percentage = qreal(100.0) * qreal(currentObjectCount) / qreal(totalObjectCount);
+
+ formatter.beginTableRow("item", int(type));
+ formatter.writeTableColumn("type", pdf::PDFObjectUtils::getObjectTypeName(type));
+ formatter.writeTableColumn("percentage", locale.toString(percentage, 'f', 2), Qt::AlignRight);
+ formatter.writeTableColumn("count", locale.toString(currentObjectCount), Qt::AlignRight);
+ formatter.endTableRow();
+ }
+ }
+
+ formatter.endTable();
+ }
+
+ formatter.endDocument();
+
+ PDFConsole::writeText(formatter.getString(), options.outputCodec);
+
+ return ExitSuccess;
+}
+
+PDFToolAbstractApplication::Options PDFToolStatisticsApplication::getOptionsFlags() const
+{
+ return ConsoleFormat | OpenDocument;
+}
+
+} // namespace pdftool
diff --git a/PdfTool/pdftoolstatistics.h b/PdfTool/pdftoolstatistics.h
new file mode 100644
index 0000000..e2d8d8f
--- /dev/null
+++ b/PdfTool/pdftoolstatistics.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 Jakub Melka
+//
+// This file is part of Pdf4Qt.
+//
+// Pdf4Qt 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 3 of the License, or
+// with the written consent of the copyright owner, any later version.
+//
+// Pdf4Qt 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 Pdf4Qt. If not, see .
+
+#ifndef PDFTOOLSTATISTICS_H
+#define PDFTOOLSTATISTICS_H
+
+#include "pdftoolabstractapplication.h"
+
+namespace pdftool
+{
+
+class PDFToolStatisticsApplication : public PDFToolAbstractApplication
+{
+public:
+ virtual QString getStandardString(StandardString standardString) const override;
+ virtual int execute(const PDFToolOptions& options) override;
+ virtual Options getOptionsFlags() const override;
+};
+
+} // namespace pdftool
+
+#endif // PDFTOOLSTATISTICS_H