Optimize tool

This commit is contained in:
Jakub Melka 2020-11-01 18:50:21 +01:00
parent e131ca769c
commit d335aaa266
5 changed files with 171 additions and 0 deletions

View File

@ -54,6 +54,7 @@ SOURCES += \
pdftoolinfonameddestinations.cpp \
pdftoolinfopageboxes.cpp \
pdftoolinfostructuretree.cpp \
pdftooloptimize.cpp \
pdftoolrender.cpp \
pdftoolseparate.cpp \
pdftoolunite.cpp \
@ -84,6 +85,7 @@ HEADERS += \
pdftoolinfonameddestinations.h \
pdftoolinfopageboxes.h \
pdftoolinfostructuretree.h \
pdftooloptimize.h \
pdftoolrender.h \
pdftoolseparate.h \
pdftoolunite.h \

View File

@ -303,6 +303,14 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
parser->addOption(QCommandLineOption("render-msaa-samples", "MSAA sample count for GPU rendering.", "samples", "4"));
parser->addOption(QCommandLineOption("render-rasterizers", "Number of rasterizer contexts.", "rasterizers", QString::number(pdf::PDFRasterizerPool::getDefaultRasterizerCount())));
}
if (optionFlags.testFlag(Optimize))
{
for (const PDFToolOptions::OptimizeFeatureInfo& info : PDFToolOptions::getOptimizeFlagInfos())
{
parser->addOption(QCommandLineOption(info.option, info.description));
}
}
}
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
@ -820,6 +828,18 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
options.uniteFiles = positionalArguments;
}
if (optionFlags.testFlag(Optimize))
{
options.optimizeFlags = pdf::PDFOptimizer::None;
for (const PDFToolOptions::OptimizeFeatureInfo& info : PDFToolOptions::getOptimizeFlagInfos())
{
if (parser->isSet(info.option))
{
options.optimizeFlags |= info.flag;
}
}
}
return options;
}
@ -969,4 +989,17 @@ std::vector<PDFToolOptions::RenderFeatureInfo> PDFToolOptions::getRenderFeatures
};
}
std::vector<PDFToolOptions::OptimizeFeatureInfo> PDFToolOptions::getOptimizeFlagInfos()
{
return {
OptimizeFeatureInfo{ "opt-deref-simple", "Dereference referenced simple objects (integers, bools, ...).", pdf::PDFOptimizer::DereferenceSimpleObjects },
OptimizeFeatureInfo{ "opt-remove-null", "Remove null objects from dictionary entries.", pdf::PDFOptimizer::RemoveNullObjects },
OptimizeFeatureInfo{ "opt-remove-unused", "Remove not referenced objects.", pdf::PDFOptimizer::RemoveUnusedObjects },
OptimizeFeatureInfo{ "opt-merge-identical", "Merge identical objects.", pdf::PDFOptimizer::MergeIdenticalObjects },
OptimizeFeatureInfo{ "opt-shrink-storage", "Shrink object storage by renumbering objects.", pdf::PDFOptimizer::ShrinkObjectStorage },
OptimizeFeatureInfo{ "opt-recompress-flate", "Recompress flate streams with maximal compression.", pdf::PDFOptimizer::RecompressFlateStreams },
OptimizeFeatureInfo{ "opt-all", "Use all optimization algorithms.", pdf::PDFOptimizer::All }
};
}
} // pdftool

View File

@ -23,6 +23,7 @@
#include "pdfdocumenttextflow.h"
#include "pdfrenderer.h"
#include "pdfcms.h"
#include "pdfoptimizer.h"
#include <QtGlobal>
#include <QString>
@ -135,6 +136,9 @@ struct PDFToolOptions
// For option 'Unite'
QStringList uniteFiles;
// For option 'Optimize'
pdf::PDFOptimizer::OptimizationFlags optimizeFlags = pdf::PDFOptimizer::None;
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
/// \param pageCount Page count
/// \param[out] errorMessage Error message
@ -150,6 +154,16 @@ struct PDFToolOptions
/// Returns a list of available renderer features
static std::vector<RenderFeatureInfo> getRenderFeatures();
struct OptimizeFeatureInfo
{
QString option;
QString description;
pdf::PDFOptimizer::OptimizationFlag flag;
};
/// Returns a list of available optimize features
static std::vector<OptimizeFeatureInfo> getOptimizeFlagInfos();
};
/// Base class for all applications
@ -203,6 +217,7 @@ public:
RenderFlags = 0x00020000, ///< Render flags for page image rasterizer
Separate = 0x00040000, ///< Settings for Separate tool
Unite = 0x00080000, ///< Settings for Unite tool
Optimize = 0x00100000, ///< Settings for Optimize
};
Q_DECLARE_FLAGS(Options, Option)

View File

@ -0,0 +1,85 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt 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
// (at your option) any later version.
//
// PdfForQt 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 PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#include "pdftooloptimize.h"
#include "pdfdocumentwriter.h"
namespace pdftool
{
static PDFToolOptimize s_optimizeApplication;
QString PDFToolOptimize::getStandardString(PDFToolAbstractApplication::StandardString standardString) const
{
switch (standardString)
{
case Command:
return "optimize";
case Name:
return PDFToolTranslationContext::tr("Optimize");
case Description:
return PDFToolTranslationContext::tr("Optimize document size using various algorithms.");
default:
Q_ASSERT(false);
break;
}
return QString();
}
int PDFToolOptimize::execute(const PDFToolOptions& options)
{
if (!options.optimizeFlags)
{
PDFConsole::writeError(PDFToolTranslationContext::tr("No optimization option has been set."), options.outputCodec);
return ErrorInvalidArguments;
}
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
{
return ErrorDocumentReading;
}
pdf::PDFOptimizer optimizer(options.optimizeFlags, nullptr);
QObject::connect(&optimizer, &pdf::PDFOptimizer::optimizationProgress, &optimizer, [&options](QString text) { PDFConsole::writeError(text, options.outputCodec); }, Qt::DirectConnection);
optimizer.setDocument(&document);
optimizer.optimize();
document = optimizer.takeOptimizedDocument();
pdf::PDFDocumentWriter writer(nullptr);
pdf::PDFOperationResult result = writer.write(options.document, &document, true);
if (!result)
{
PDFConsole::writeError(PDFToolTranslationContext::tr("Failed to write optimize document. %1").arg(result.getErrorMessage()), options.outputCodec);
return ErrorFailedWriteToFile;
}
return ExitSuccess;
}
PDFToolAbstractApplication::Options PDFToolOptimize::getOptionsFlags() const
{
return ConsoleFormat | OpenDocument | Optimize;
}
} // namespace pdftool

36
PdfTool/pdftooloptimize.h Normal file
View File

@ -0,0 +1,36 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt 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
// (at your option) any later version.
//
// PdfForQt 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 PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFTOOLOPTIMIZE_H
#define PDFTOOLOPTIMIZE_H
#include "pdftoolabstractapplication.h"
namespace pdftool
{
class PDFToolOptimize : 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 // PDFTOOLOPTIMIZE_H