Implement exporting PNG images

This commit is contained in:
G.K.MacGregor
2021-06-03 22:26:54 +01:00
parent 23c2623bcf
commit c8e57150eb
5 changed files with 90 additions and 1 deletions

View File

@@ -140,6 +140,16 @@ void TeletextWidget::timerEvent(QTimerEvent *event)
QWidget::timerEvent(event); QWidget::timerEvent(event);
} }
void TeletextWidget::pauseFlash(bool pauseNow)
{
if (pauseNow && m_flashTiming != 0) {
m_flashTimer.stop();
m_flashPhase = 0;
update();
} else if (m_flashTiming != 0)
m_flashTimer.start((m_flashTiming == 1) ? 500 : 167, this);
}
void TeletextWidget::setInsertMode(bool insertMode) void TeletextWidget::setInsertMode(bool insertMode)
{ {
m_insertMode = insertMode; m_insertMode = insertMode;
@@ -654,6 +664,24 @@ void LevelOneScene::toggleGrid(bool gridOn)
m_sidePanelGridItemGroup[i]->setVisible(gridOn); m_sidePanelGridItemGroup[i]->setVisible(gridOn);
} }
void LevelOneScene::hideGUIElements(bool hidden)
{
if (hidden) {
m_mainGridItemGroup->setVisible(false);
m_cursorRectItem->setVisible(false);
m_selectionRectItem->setVisible(false);
for (int i=0; i<32; i++)
if (m_sidePanelGridNeeded[i])
m_sidePanelGridItemGroup[i]->setVisible(false);
} else {
if (static_cast<TeletextWidget *>(m_levelOneProxyWidget->widget())->document()->selectionActive())
m_selectionRectItem->setVisible(true);
m_cursorRectItem->setVisible(true);
toggleGrid(m_grid);
}
}
bool LevelOneScene::eventFilter(QObject *object, QEvent *event) bool LevelOneScene::eventFilter(QObject *object, QEvent *event)
{ {
Q_UNUSED(object); Q_UNUSED(object);

View File

@@ -64,6 +64,7 @@ public slots:
void toggleReveal(bool); void toggleReveal(bool);
void toggleMix(bool); void toggleMix(bool);
void updateFlashTimer(int); void updateFlashTimer(int);
void pauseFlash(bool);
void refreshRow(int); void refreshRow(int);
void setControlBit(int, bool); void setControlBit(int, bool);
@@ -119,6 +120,7 @@ public slots:
void updateCursor(); void updateCursor();
void updateSelection(); void updateSelection();
void toggleGrid(bool); void toggleGrid(bool);
void hideGUIElements(bool);
void setFullScreenColour(const QColor &); void setFullScreenColour(const QColor &);
void setFullRowColour(int, const QColor &); void setFullRowColour(int, const QColor &);

View File

@@ -20,9 +20,11 @@
#include <QApplication> #include <QApplication>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFileDialog> #include <QFileDialog>
#include <QImage>
#include <QList> #include <QList>
#include <QMenuBar> #include <QMenuBar>
#include <QMessageBox> #include <QMessageBox>
#include <QPainter>
#include <QPushButton> #include <QPushButton>
#include <QRadioButton> #include <QRadioButton>
#include <QSaveFile> #include <QSaveFile>
@@ -120,6 +122,56 @@ bool MainWindow::saveAs()
return saveFile(fileName); return saveFile(fileName);
} }
void MainWindow::exportPNG()
{
QString exportFileName = QFileDialog::getSaveFileName(this, tr("Export PNG"), QString(), "PNG image (*.png)");
if (exportFileName.isEmpty())
return;
// Prepare widget image for extraction
m_textWidget->pauseFlash(true);
m_textScene->hideGUIElements(true);
bool reshowCodes = m_textWidget->pageRender()->showCodes();
if (reshowCodes)
m_textWidget->pageRender()->setShowCodes(false);
// Disable exporting in Mix mode as it corrupts the background
bool reMix = m_textWidget->pageRender()->mix();
if (reMix)
m_textWidget->pageRender()->setMix(false);
// Extract the image from the scene
QImage interImage = QImage(m_textScene->sceneRect().size().toSize(), QImage::Format_RGB32);
// This ought to make the background transparent in Mix mode, but it doesn't
// if (m_textWidget->pageRender()->mix())
// interImage.fill(QColor(0, 0, 0, 0));
QPainter interPainter(&interImage);
m_textScene->render(&interPainter);
// Now we're extracted the image we can put the GUI things back
m_textScene->hideGUIElements(false);
if (reshowCodes)
m_textWidget->pageRender()->setShowCodes(true);
if (reMix)
m_textWidget->pageRender()->setMix(true);
m_textWidget->pauseFlash(false);
// Now scale the extracted image to the selected aspect ratio
// We do this in two steps so that anti-aliasing only occurs on vertical lines
// Double the vertical height first
const QImage doubleHeightImage = interImage.scaled(interImage.width(), interImage.height()*2, Qt::IgnoreAspectRatio, Qt::FastTransformation);
// If aspect ratio is Pixel 1:2 we're already at the correct scale
if (m_viewAspectRatio != 3) {
// Scale it horizontally to the selected aspect ratio
const QImage scaledImage = doubleHeightImage.scaled((int)((float)doubleHeightImage.width() * aspectRatioHorizontalScaling[m_viewAspectRatio] * 2), doubleHeightImage.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (!scaledImage.save(exportFileName, "PNG"))
QMessageBox::warning(this, tr("QTeletextMaker"), tr("Cannot export file %1.").arg(QDir::toNativeSeparators(exportFileName)));
} else if (!doubleHeightImage.save(exportFileName, "PNG"))
QMessageBox::warning(this, tr("QTeletextMaker"), tr("Cannot export file %1.").arg(QDir::toNativeSeparators(exportFileName)));
}
void MainWindow::exportZXNet() void MainWindow::exportZXNet()
{ {
QDesktopServices::openUrl(QUrl("http://zxnet.co.uk/teletext/editor/" + exportHashStringPage(m_textWidget->document()->currentSubPage()) + exportHashStringPackets(m_textWidget->document()->currentSubPage()))); QDesktopServices::openUrl(QUrl("http://zxnet.co.uk/teletext/editor/" + exportHashStringPage(m_textWidget->document()->currentSubPage()) + exportHashStringPackets(m_textWidget->document()->currentSubPage())));
@@ -257,6 +309,10 @@ void MainWindow::createActions()
setRecentFilesVisible(MainWindow::hasRecentFiles()); setRecentFilesVisible(MainWindow::hasRecentFiles());
QAction *exportPNGAct = fileMenu->addAction(tr("Export subpage as PNG..."));
exportPNGAct->setStatusTip("Export a PNG image of this subpage");
connect(exportPNGAct, &QAction::triggered, this, &MainWindow::exportPNG);
QMenu *exportHashStringSubMenu = fileMenu->addMenu(tr("Export subpage to online editor")); QMenu *exportHashStringSubMenu = fileMenu->addMenu(tr("Export subpage to online editor"));
QAction *exportZXNetAct = exportHashStringSubMenu->addAction(tr("Open in zxnet.co.uk")); QAction *exportZXNetAct = exportHashStringSubMenu->addAction(tr("Open in zxnet.co.uk"));
@@ -555,7 +611,6 @@ void MainWindow::createActions()
void MainWindow::setSceneDimensions() void MainWindow::setSceneDimensions()
{ {
const float aspectRatioHorizontalScaling[4] = { 0.6, 0.6, 0.8, 0.5 };
const int topBottomBorders[3] = { 0, 10, 19 }; const int topBottomBorders[3] = { 0, 10, 19 };
const int pillarBoxSizes[3] = { 672, 720, 854 }; const int pillarBoxSizes[3] = { 672, 720, 854 };
const int leftRightBorders[3] = { 0, 24, 77 }; const int leftRightBorders[3] = { 0, 24, 77 };

View File

@@ -58,6 +58,7 @@ private slots:
void open(); void open();
bool save(); bool save();
bool saveAs(); bool saveAs();
void exportPNG();
void exportZXNet(); void exportZXNet();
void exportEditTF(); void exportEditTF();
void updateRecentFileActions(); void updateRecentFileActions();
@@ -82,6 +83,7 @@ private slots:
private: private:
enum { m_MaxRecentFiles = 10 }; enum { m_MaxRecentFiles = 10 };
const float aspectRatioHorizontalScaling[4] = { 0.6, 0.6, 0.8, 0.5 };
void init(); void init();
void createActions(); void createActions();

View File

@@ -189,6 +189,8 @@ public:
void decodePage(); void decodePage();
void renderPage(); void renderPage();
void renderPage(int r); void renderPage(int r);
bool mix() const { return m_mix; };
bool showCodes() const { return m_showCodes; };
void setTeletextPage(LevelOnePage *); void setTeletextPage(LevelOnePage *);
void updateSidePanels(); void updateSidePanels();
void buildEnhanceMap(TextLayer *, int=0); void buildEnhanceMap(TextLayer *, int=0);