diff options
Diffstat (limited to 'tests/manual/imageconversion/main.cpp')
-rw-r--r-- | tests/manual/imageconversion/main.cpp | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/tests/manual/imageconversion/main.cpp b/tests/manual/imageconversion/main.cpp deleted file mode 100644 index d2899f2..0000000 --- a/tests/manual/imageconversion/main.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtWinExtras/QtWin> - -#include <QtGui/QAction> -#include <QtGui/QShortcut> -#include <QtWidgets/QApplication> -#include <QtWidgets/QDialogButtonBox> -#include <QtWidgets/QFileDialog> -#include <QtWidgets/QLabel> -#include <QtWidgets/QMainWindow> -#include <QtWidgets/QMenu> -#include <QtWidgets/QMenuBar> -#include <QtWidgets/QPushButton> -#include <QtWidgets/QVBoxLayout> - -#include <QtGui/QImage> -#include <QtGui/QPainter> -#include <QtGui/QPaintEvent> - -#include <QtCore/QCommandLineOption> -#include <QtCore/QCommandLineParser> -#include <QtCore/QDebug> -#include <QtCore/QTimer> -#include <QtCore/qt_windows.h> - -static void formatData(QDebug d, const void *data, qsizetype size) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - const qsizetype minSize = 20; - d << "\nData: " << QByteArray(reinterpret_cast<const char *>(data), qMin(minSize, size)).toHex(); - if (size > minSize) - d << "..."; - d << "\n 0000000011111111222222223333333344444444"; -} - -QDebug operator<<(QDebug d, const BITMAP &b) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "BITMAP(type=" << b.bmType << ", " << b.bmWidth << 'x' << b.bmHeight - << ", widthBytes=" << b.bmWidthBytes << ", planes=" << b.bmPlanes - << ", bitsPixel=" << b.bmBitsPixel << ", bits=" << b.bmBits << ')'; - return d; -} - -QDebug operator<<(QDebug d, const BITMAPINFOHEADER &bih) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "BITMAPINFOHEADER(" << bih.biWidth << 'x' << qAbs(bih.biHeight) - << (bih.biHeight < 0 ? ", top-down" : ", bottom-up") - << ", planes=" << bih.biPlanes << ", bitCount=" << bih.biBitCount - << ", compression=" << bih.biCompression << ", size=" - << bih.biSizeImage << ')'; - return d; -} - -static void formatImage(QDebug d, const QImage &image) -{ - QDebugStateSaver s(d); - d.noquote(); - d.nospace(); - d << image; - if (const int colorTableSize = image.colorCount()) { - QList<QRgb> colorTable = image.colorTable(); - d << " Color table: " << colorTableSize << " (" << Qt::showbase << Qt::hex; // 256 by standard - int c = 0; - for ( ; c < qMin(8, colorTableSize); ++c) { - if (c) - d << ", "; - d << colorTable[c]; - } - if (c < colorTableSize) - d << "..."; - d << ')' << Qt::noshowbase << Qt::dec; - } - formatData(d, image.constBits(), image.sizeInBytes()); -} - -enum ParseOptionResult { - OptionError, - OptionUnset, - OptionSet -}; - -static ParseOptionResult parseIntOption(const QCommandLineParser &parser, const QCommandLineOption &option, - int minValue, int maxValue, int *target) -{ - if (!parser.isSet(option)) - return OptionUnset; - - const QString spec = parser.value(option); - bool ok; - const int value = spec.toInt(&ok); - if (!ok || value < minValue || value > maxValue) { - qWarning() << "Invalid value" << spec << "for" << option.names(); - return OptionError; - } - *target = value; - return OptionSet; -} - -template <typename Enum> -static ParseOptionResult parseEnumOption(const QCommandLineParser &parser, const QCommandLineOption &option, - Enum minValue, Enum maxValue, Enum *target) -{ - int intValue; - const ParseOptionResult result = parseIntOption(parser, option, int(minValue), int(maxValue), &intValue); - if (result == OptionSet) - *target = static_cast<Enum>(intValue); - return result; -} - -// Display a QImage in a dialog. -class PreviewDialog : public QDialog -{ -public: - explicit PreviewDialog(const QImage &image, QWidget *parent = nullptr); -}; - -PreviewDialog::PreviewDialog(const QImage &image, QWidget *parent) : QDialog(parent) -{ - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - QString description; - QDebug(&description) << image.size() << ", format=" << image.format(); - QLabel *descriptionLabel = new QLabel(description, this); - descriptionLabel->setWordWrap(true); - auto *layout = new QVBoxLayout(this); - layout->addWidget(descriptionLabel); - auto *hLayout = new QHBoxLayout; - QLabel *label = new QLabel(this); - label->setFrameShape(QFrame::Box); - label->setPixmap(QPixmap::fromImage(image)); - hLayout->addStretch(); - hLayout->addWidget(label); - hLayout->addStretch(); - layout->addLayout(hLayout); - QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this); - connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); - layout->addWidget(buttonBox); -} - -// Widget that paints a HBITMAP using GDI API in WM_PAINT. -class PaintWidget : public QWidget -{ - Q_OBJECT -public: - explicit PaintWidget(HBITMAP hBitmap, QWidget *p = nullptr) : QWidget(p), m_hBitmap(hBitmap) { } - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; -#else - bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; -#endif - -public slots: - void saveBitmap(); - void convertBack(); - -protected: - void contextMenuEvent(QContextMenuEvent *) override; - -private: - const HBITMAP m_hBitmap; -}; - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -bool PaintWidget::nativeEvent(const QByteArray &eventType, void *messageIn, qintptr *result) -#else -bool PaintWidget::nativeEvent(const QByteArray &eventType, void *messageIn, long *result) -#endif -{ - MSG *message = reinterpret_cast<MSG *>(messageIn); - if (message->message != WM_PAINT) - return QWidget::nativeEvent(eventType, message, result); - - PAINTSTRUCT paintStruct; - BITMAP bitmap; - - const HDC hdc = BeginPaint(message->hwnd, &paintStruct); - SelectObject(hdc, GetStockObject(BLACK_PEN)); - Rectangle(hdc, 1, 1, width() - 1, height() - 1); - - const HDC hdcMem = CreateCompatibleDC(hdc); - const HGDIOBJ oldBitmap = SelectObject(hdcMem, m_hBitmap); - - GetObject(m_hBitmap, sizeof(bitmap), &bitmap); - { - QDebug d = qDebug(); - d << __FUNCTION__ << bitmap; - formatData(d, bitmap.bmBits, bitmap.bmHeight * bitmap.bmWidthBytes); - } - BitBlt(hdc, 5, 5, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); - SelectObject(hdcMem, oldBitmap); - DeleteDC(hdcMem); - - EndPaint(message->hwnd, &paintStruct); - return true; -} - -void PaintWidget::convertBack() -{ - QImage image = QtWin::imageFromHBITMAP(m_hBitmap); - formatImage(qDebug(), image); - auto *dialog = new PreviewDialog(image, this); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setModal(false); - dialog->setWindowTitle(QLatin1String("QImage - Qt ") + QLatin1String(QT_VERSION_STR)); - dialog->show(); -} - -void PaintWidget::saveBitmap() -{ - QImage image = QtWin::imageFromHBITMAP(m_hBitmap); - formatImage(qDebug(), image); - QFileDialog fileDialog(this); - fileDialog.setAcceptMode(QFileDialog::AcceptSave); - fileDialog.setMimeTypeFilters(QStringList(QStringLiteral("image/png"))); - fileDialog.setDefaultSuffix(QStringLiteral("png")); - fileDialog.selectFile(QStringLiteral("test.png")); - while (fileDialog.exec() == QDialog::Accepted) { - const QString fileName = fileDialog.selectedFiles().first(); - if (image.save(fileName)) { - qDebug().noquote() << "saved" << QDir::toNativeSeparators(fileName); - break; - } - qWarning().noquote() << "Could not save" << QDir::toNativeSeparators(fileName); - } -} - -void PaintWidget::contextMenuEvent(QContextMenuEvent *e) -{ - QMenu contextMenu; - contextMenu.addAction(QStringLiteral("Convert into QImage"), this, &PaintWidget::convertBack); - QAction *saveAction = contextMenu.addAction(QStringLiteral("Save"), this, &PaintWidget::saveBitmap); - saveAction->setShortcut(Qt::CTRL | Qt::Key_S); - contextMenu.exec(e->globalPos()); -} - -static const char description[] = -"\nCreates a HBITMAP from a QImage either passed as file name or by drawing in a\n" -"format determined by a command line option and draws it onto a native window\n" -"for comparison. Provides a context menu for converting the HBITMAP back to a\n" -"QImage and saving that for checking the reverse conversion."; - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QCoreApplication::setApplicationName("imageconversion"); - QCoreApplication::setOrganizationName("QtProject"); - QCoreApplication::setApplicationVersion(QT_VERSION_STR); - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.setApplicationDescription("Qt Windows Extras Image Conversion Tester"); - parser.addHelpOption(); - parser.addVersionOption(); - parser.setApplicationDescription(description); - - const QCommandLineOption formatOption(QStringList{"format", "f"}, - "QImage format", "format"); - parser.addOption(formatOption); - const QCommandLineOption colorOption(QStringList{"color", "c"}, - "Fill color", "color-spec"); - parser.addOption(colorOption); - const QCommandLineOption globalColorOption(QStringList{"globalColor", "g"}, - "Fill color (global color enum value)", "global-color"); - parser.addOption(globalColorOption); - const QCommandLineOption widthOption(QStringList{"width", "w"}, - "Width", "width"); - parser.addOption(widthOption); - const QCommandLineOption heightOption(QStringList{"height", "h"}, - "Height", "height"); - parser.addOption(heightOption); - const QCommandLineOption previewOption(QStringList{"preview", "p"}, - "Show a preview"); - parser.addOption(previewOption); - - parser.addPositionalArgument("file", "The image file to open."); - parser.process(app); - - QColor defaultColor(Qt::red); - if (parser.isSet(colorOption)) { - const QString spec = parser.value(colorOption); - defaultColor = QColor(spec); - if (!defaultColor.isValid()) { - qWarning() << "Invalid color specification" << spec; - return -1; - } - } else { - // Color 0: color0, 1: color1, 2: black, 3: white, 7:red, 9: blue, 8: green - Qt::GlobalColor globalColor = Qt::color0; - if (!parseEnumOption(parser, globalColorOption, Qt::black, Qt::transparent, &globalColor)) - return -1; - if (globalColor != Qt::color0) - defaultColor = QColor(defaultColor); - } - - // Format: 1: mono, 3: Indexed8, 7: RGB 16, 11: RGB555, 13: RGB888 - QImage::Format targetFormat = QImage::Format_ARGB32_Premultiplied; - if (!parseEnumOption(parser, formatOption, QImage::Format_Mono, QImage::Format_Grayscale8, &targetFormat)) - return -1; - // Can't paint on indexed nor mono, need transform? - const QImage::Format drawFormat = targetFormat == QImage::Format_Indexed8 - || targetFormat == QImage::Format_Mono || targetFormat == QImage::Format_MonoLSB - ? QImage::Format_ARGB32_Premultiplied : targetFormat; - - if (targetFormat == QImage::Format_Mono || targetFormat == QImage::Format_MonoLSB) - defaultColor = Qt::white; - - int width = 73; - int height = 57; - if (!parseIntOption(parser, widthOption, 1, 2000, &width) || !parseIntOption(parser, heightOption, 1, 2000, &height)) - return -1; - - const bool preview = parser.isSet(previewOption); - - QImage image; - if (!parser.positionalArguments().isEmpty()) { - QString fileName = parser.positionalArguments().constFirst(); - image = QImage(fileName); - if (image.isNull() || image.size().isEmpty()) { - qWarning().noquote() << "Image load fail" << QDir::toNativeSeparators(fileName); - return -1; - } - } - - if (image.isNull()) { - qDebug() << "Default image color=" << defaultColor - << Qt::showbase << Qt::hex << defaultColor.rgba() << Qt::noshowbase << Qt::dec - << ", format=" << drawFormat; - image = QImage(width, height, drawFormat); - image.fill(defaultColor); - QPainter painter(&image); - painter.drawLine(0, 0, image.width(), image.height()); - } - - if (image.format() != targetFormat) { - qDebug() << "Converting " << image.format() << targetFormat; - image = image.convertToFormat(targetFormat); - } - - formatImage(qDebug(), image); - - const HBITMAP bitmap = QtWin::imageToHBITMAP(image); - if (!bitmap) { - qWarning() << "Failed to create HBITMAP"; - return -1; - } - - int exitCode = 0; - { - PaintWidget paintWidget(bitmap); - auto *quitShortcut = new QShortcut(&paintWidget); - quitShortcut->setKey(Qt::CTRL | Qt::Key_Q); - quitShortcut->setContext(Qt::ApplicationShortcut); - QObject::connect(quitShortcut, &QShortcut::activated, qApp, &QCoreApplication::quit); - paintWidget.setWindowTitle(QLatin1String("HBITMAP - Qt ") + QLatin1String(QT_VERSION_STR)); - paintWidget.show(); - if (preview) { - auto *dialog = new PreviewDialog(image); - dialog->setModal(false); - dialog->setWindowTitle(QLatin1String("QImage - Qt ") + QLatin1String(QT_VERSION_STR)); - dialog->move(paintWidget.frameGeometry().topRight() + QPoint(50, 0)); - dialog->show(); - } - exitCode = app.exec(); - } - - DeleteObject(bitmap); - - return exitCode; -} - -#include "main.moc" |