Issue #107: Conversion algorithm

This commit is contained in:
Jakub Melka
2023-11-17 13:45:49 +01:00
parent cf7d65dc82
commit c5ddb521ed
6 changed files with 434 additions and 96 deletions

View File

@ -24,6 +24,7 @@
#include "pdfdbgheap.h"
#include "pdfexception.h"
#include "pdfwidgetutils.h"
#include "pdfimageconversion.h"
#include <QCheckBox>
#include <QPushButton>
@ -39,6 +40,64 @@
namespace pdfviewer
{
PDFCreateBitonalDocumentPreviewWidget::PDFCreateBitonalDocumentPreviewWidget(QWidget* parent) :
QWidget(parent)
{
}
PDFCreateBitonalDocumentPreviewWidget::~PDFCreateBitonalDocumentPreviewWidget()
{
}
void PDFCreateBitonalDocumentPreviewWidget::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.fillRect(rect(), Qt::white);
// Caption rect
QRect captionRect = rect();
captionRect.setHeight(painter.fontMetrics().lineSpacing() * 2);
painter.fillRect(captionRect, QColor::fromRgb(0, 0, 128, 255));
if (!m_caption.isEmpty())
{
painter.setPen(Qt::white);
painter.drawText(captionRect, m_caption, QTextOption(Qt::AlignCenter));
}
QRect imageRect = rect();
imageRect.setTop(captionRect.bottom());
imageRect = imageRect.adjusted(16, 16, -32, -32);
if (imageRect.isValid() && !m_image.isNull())
{
QRect imageDrawRect = imageRect;
imageDrawRect.setSize(m_image.size().scaled(imageRect.size(), Qt::KeepAspectRatio));
imageDrawRect.moveCenter(imageRect.center());
painter.drawImage(imageDrawRect, m_image);
}
}
void PDFCreateBitonalDocumentPreviewWidget::setCaption(QString caption)
{
if (m_caption != caption)
{
m_caption = caption;
update();
}
}
void PDFCreateBitonalDocumentPreviewWidget::setImage(QImage image)
{
m_image = std::move(image);
update();
}
class ImagePreviewDelegate : public QStyledItemDelegate
{
public:
@ -148,10 +207,18 @@ PDFCreateBitonalDocumentDialog::PDFCreateBitonalDocumentDialog(const pdf::PDFDoc
m_cms(cms),
m_createBitonalDocumentButton(nullptr),
m_conversionInProgress(false),
m_processed(false)
m_processed(false),
m_leftPreviewWidget(new PDFCreateBitonalDocumentPreviewWidget(this)),
m_rightPreviewWidget(new PDFCreateBitonalDocumentPreviewWidget(this))
{
ui->setupUi(this);
m_leftPreviewWidget->setCaption(tr("ORIGINAL"));
m_rightPreviewWidget->setCaption(tr("BITONIC"));
ui->mainGridLayout->addWidget(m_leftPreviewWidget, 1, 1);
ui->mainGridLayout->addWidget(m_rightPreviewWidget, 1, 2);
m_classifier.classify(document);
m_imageReferences = m_classifier.getObjectsByType(pdf::PDFObjectClassifier::Image);
@ -159,6 +226,10 @@ PDFCreateBitonalDocumentDialog::PDFCreateBitonalDocumentDialog(const pdf::PDFDoc
connect(m_createBitonalDocumentButton, &QPushButton::clicked, this, &PDFCreateBitonalDocumentDialog::onCreateBitonalDocumentButtonClicked);
connect(ui->automaticThresholdRadioButton, &QRadioButton::clicked, this, &PDFCreateBitonalDocumentDialog::updateUi);
connect(ui->manualThresholdRadioButton, &QRadioButton::clicked, this, &PDFCreateBitonalDocumentDialog::updateUi);
connect(ui->automaticThresholdRadioButton, &QRadioButton::clicked, this, &PDFCreateBitonalDocumentDialog::updatePreview);
connect(ui->manualThresholdRadioButton, &QRadioButton::clicked, this, &PDFCreateBitonalDocumentDialog::updatePreview);
connect(ui->imageListWidget, &QListWidget::currentItemChanged, this, &PDFCreateBitonalDocumentDialog::updatePreview);
connect(ui->thresholdEditBox, &QSpinBox::editingFinished, this, &PDFCreateBitonalDocumentDialog::updatePreview);
pdf::PDFWidgetUtils::scaleWidget(this, QSize(640, 380));
updateUi();
@ -167,6 +238,7 @@ PDFCreateBitonalDocumentDialog::PDFCreateBitonalDocumentDialog(const pdf::PDFDoc
ui->imageListWidget->setItemDelegate( new ImagePreviewDelegate(&m_imagesToBeConverted, this));
loadImages();
updatePreview();
}
PDFCreateBitonalDocumentDialog::~PDFCreateBitonalDocumentDialog()
@ -243,6 +315,40 @@ void PDFCreateBitonalDocumentDialog::updateUi()
m_createBitonalDocumentButton->setEnabled(!m_conversionInProgress);
}
void PDFCreateBitonalDocumentDialog::updatePreview()
{
QModelIndex index = ui->imageListWidget->currentIndex();
m_previewImageLeft = QImage();
m_previewImageRight = QImage();
if (index.isValid())
{
const ImageConversionInfo& info = m_imagesToBeConverted.at(index.row());
std::optional<pdf::PDFImage> pdfImage = getImageFromReference(info.imageReference);
Q_ASSERT(pdfImage);
pdf::PDFCMSGeneric cmsGeneric;
pdf::PDFRenderErrorReporterDummy reporter;
QImage image = pdfImage->getImage(&cmsGeneric, &reporter, nullptr);
pdf::PDFImageConversion imageConversion;
imageConversion.setConversionMethod(ui->automaticThresholdRadioButton->isChecked() ? pdf::PDFImageConversion::ConversionMethod::Automatic : pdf::PDFImageConversion::ConversionMethod::Manual);
imageConversion.setThreshold(ui->thresholdEditBox->value());
imageConversion.setImage(image);
if (imageConversion.convert())
{
m_previewImageLeft = image;
m_previewImageRight = imageConversion.getConvertedImage();
}
}
m_leftPreviewWidget->setImage(m_previewImageLeft);
m_rightPreviewWidget->setImage(m_previewImageRight);
}
std::optional<pdf::PDFImage> PDFCreateBitonalDocumentDialog::getImageFromReference(pdf::PDFObjectReference reference) const
{
std::optional<pdf::PDFImage> pdfImage;
@ -285,3 +391,5 @@ std::optional<pdf::PDFImage> PDFCreateBitonalDocumentDialog::getImageFromReferen
}
} // namespace pdfviewer

View File

@ -34,6 +34,24 @@ class PDFCreateBitonalDocumentDialog;
namespace pdfviewer
{
class PDFCreateBitonalDocumentPreviewWidget : public QWidget
{
Q_OBJECT
public:
PDFCreateBitonalDocumentPreviewWidget(QWidget* parent);
virtual ~PDFCreateBitonalDocumentPreviewWidget() override;
virtual void paintEvent(QPaintEvent* event) override;
void setCaption(QString caption);
void setImage(QImage image);
private:
QString m_caption;
QImage m_image;
};
class PDFCreateBitonalDocumentDialog : public QDialog
{
Q_OBJECT
@ -56,6 +74,7 @@ private:
void loadImages();
void updateUi();
void updatePreview();
std::optional<pdf::PDFImage> getImageFromReference(pdf::PDFObjectReference reference) const;
@ -70,6 +89,12 @@ private:
pdf::PDFObjectClassifier m_classifier;
std::vector<pdf::PDFObjectReference> m_imageReferences;
std::vector<ImageConversionInfo> m_imagesToBeConverted;
QImage m_previewImageLeft;
QImage m_previewImageRight;
PDFCreateBitonalDocumentPreviewWidget* m_leftPreviewWidget;
PDFCreateBitonalDocumentPreviewWidget* m_rightPreviewWidget;
};
} // namespace pdfviewer

View File

@ -13,13 +13,23 @@
<property name="windowTitle">
<string>Create Bitonal Document</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,1,0" columnstretch="2,1,1">
<layout class="QGridLayout" name="mainGridLayout" rowstretch="0,1,0" columnstretch="2,1,1">
<item row="2" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="createBitonalSettingsGroupBox">
<property name="title">
<string>Color to Bitonal Conversion Options</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QGridLayout" name="optionsGridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="automaticThresholdRadioButton">
<property name="text">
@ -50,99 +60,7 @@
</layout>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QLabel" name="originalImageLabel">
<property name="palette">
<palette>
<active>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>240</red>
<green>240</green>
<blue>240</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="2">
<widget class="QLabel" name="convertedImageLabel">
<property name="palette">
<palette>
<active>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>240</red>
<green>240</green>
<blue>240</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<item row="0" column="0" rowspan="2">
<widget class="QListWidget" name="imageListWidget">
<property name="resizeMode">
<enum>QListView::Adjust</enum>