Initial commit
rodzic
3cfa77426d
commit
4155acfde7
|
@ -30,3 +30,5 @@
|
||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
*.pro.user
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "BitmapPanel.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "Converter.hpp"
|
||||||
|
#include "BitmapPreview.hpp"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
|
||||||
|
BitmapPanel::BitmapPanel(QWidget *parent) : QWidget(parent)
|
||||||
|
{
|
||||||
|
initializeUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPanel::setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
_bitmapPreview->setImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPanel::setConverter(const Converter *converter)
|
||||||
|
{
|
||||||
|
_bitmapPreview->setConverter(converter);
|
||||||
|
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPanel::initializeUi()
|
||||||
|
{
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
setMinimumHeight(300);
|
||||||
|
|
||||||
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(16, 16, 16, 4);
|
||||||
|
mainLayout->setSpacing(4);
|
||||||
|
mainLayout->addWidget(new QLabel(tr("Loaded Bitmap:")));
|
||||||
|
|
||||||
|
auto scrollArea = new QScrollArea();
|
||||||
|
QPalette imagePalette = palette();
|
||||||
|
imagePalette.setColor(QPalette::Window, QColor::fromRgb(32, 32, 32));
|
||||||
|
scrollArea->setPalette(imagePalette);
|
||||||
|
scrollArea->setBackgroundRole(QPalette::Window);
|
||||||
|
mainLayout->addWidget(scrollArea);
|
||||||
|
|
||||||
|
_bitmapPreview = new BitmapPreview();
|
||||||
|
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
||||||
|
_bitmapPreview->setPalette(imagePalette);
|
||||||
|
scrollArea->setWidget(_bitmapPreview);
|
||||||
|
scrollArea->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
auto previewSettingsPanel = new QFrame();
|
||||||
|
auto previewSettingsLayout = new QHBoxLayout(previewSettingsPanel);
|
||||||
|
previewSettingsLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
previewSettingsLayout->setSpacing(4);
|
||||||
|
previewSettingsLayout->addStretch();
|
||||||
|
previewSettingsLayout->addWidget(new QLabel(tr("Overlay Mode:")));
|
||||||
|
_overlaySelector = new QComboBox();
|
||||||
|
_overlaySelector->addItem(tr("None"), static_cast<int>(OverlayMode::None));
|
||||||
|
_overlaySelector->addItem(tr("Bit Assignments"), static_cast<int>(OverlayMode::BitAssigments));
|
||||||
|
_overlaySelector->addItem(tr("Pixel Interpretation"), static_cast<int>(OverlayMode::PixelInterpretation));
|
||||||
|
_overlaySelector->setCurrentIndex(0);
|
||||||
|
previewSettingsLayout->addWidget(_overlaySelector);
|
||||||
|
mainLayout->addWidget(previewSettingsPanel);
|
||||||
|
|
||||||
|
connect(_overlaySelector, &QComboBox::currentIndexChanged, [=]{
|
||||||
|
_bitmapPreview->setOverlayMode(static_cast<OverlayMode>(_overlaySelector->currentData().toInt()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
class BitmapPreview;
|
||||||
|
class Converter;
|
||||||
|
class QComboBox;
|
||||||
|
|
||||||
|
|
||||||
|
class BitmapPanel : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BitmapPanel(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Assign a new image.
|
||||||
|
///
|
||||||
|
void setImage(const QImage &image);
|
||||||
|
|
||||||
|
/// Set the current converter.
|
||||||
|
///
|
||||||
|
void setConverter(const Converter *converter);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initializeUi();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BitmapPreview *_bitmapPreview; ///< The bitmap preview;
|
||||||
|
QComboBox *_overlaySelector; ///< The selector for the overlays.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "BitmapPreview.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "Converter.hpp"
|
||||||
|
#include "OverlayPainter.hpp"
|
||||||
|
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
#include <QtGui/QPaintEvent>
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int cImagePadding = 32;
|
||||||
|
const int cMinimumDisplayFactor = 12;
|
||||||
|
const int cMinimumWidth = 400;
|
||||||
|
const int cMinimumHeight = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BitmapPreview::BitmapPreview(QWidget *parent)
|
||||||
|
:
|
||||||
|
QWidget(parent),
|
||||||
|
_displayFactor(cMinimumDisplayFactor),
|
||||||
|
_minimumSize(cMinimumWidth, cMinimumHeight),
|
||||||
|
_overlayMode(OverlayMode::None),
|
||||||
|
_converter(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
if (_image != image) {
|
||||||
|
_image = image;
|
||||||
|
_pixmap = QPixmap::fromImage(image);
|
||||||
|
if (_converter != nullptr) {
|
||||||
|
setGeneratedSize(_converter->generatedSize(_image.size()));
|
||||||
|
}
|
||||||
|
recalculate();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::setGeneratedSize(const QSize &size)
|
||||||
|
{
|
||||||
|
if (_generatedSize != size) {
|
||||||
|
_generatedSize = size;
|
||||||
|
recalculate();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::setOverlayMode(OverlayMode overlayMode)
|
||||||
|
{
|
||||||
|
if (_overlayMode != overlayMode) {
|
||||||
|
_overlayMode = overlayMode;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::setConverter(const Converter *converter)
|
||||||
|
{
|
||||||
|
if (_converter != converter) {
|
||||||
|
_converter = converter;
|
||||||
|
if (_converter != nullptr) {
|
||||||
|
setGeneratedSize(_converter->generatedSize(_image.size()));
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize BitmapPreview::sizeHint() const
|
||||||
|
{
|
||||||
|
return _minimumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize BitmapPreview::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return _minimumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::paintEvent(QPaintEvent *pe)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
if (!_pixmap.isNull()) {
|
||||||
|
qreal x = (width() - _minimumSize.width())/2 + cImagePadding;
|
||||||
|
qreal y = (height() - _minimumSize.height())/2 + cImagePadding;
|
||||||
|
qreal width = (_pixmap.width()*_displayFactor);
|
||||||
|
qreal height = (_pixmap.height()*_displayFactor);
|
||||||
|
p.fillRect(QRectF(x, y, width, height), Qt::white);
|
||||||
|
p.drawPixmap(QRectF(x, y, width, height), _pixmap, _pixmap.rect());
|
||||||
|
if (_converter != nullptr) {
|
||||||
|
if (_overlayMode != OverlayMode::None) {
|
||||||
|
p.setOpacity(0.75);
|
||||||
|
p.fillRect(rect(), palette().window());
|
||||||
|
}
|
||||||
|
p.setOpacity(1.0);
|
||||||
|
p.translate(x, y);
|
||||||
|
OverlayPainter op(&p, pe->rect(), _displayFactor, _pixmap.size(), _generatedSize);
|
||||||
|
_converter->paintOverlay(op, _overlayMode, _image);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.drawText(QRect(0, 0, width(), height()), Qt::AlignCenter, tr("No Bitmap Loaded"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
recalculate();
|
||||||
|
QWidget::resizeEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::recalculate()
|
||||||
|
{
|
||||||
|
if (_pixmap.isNull()) {
|
||||||
|
_displayFactor = cMinimumDisplayFactor;
|
||||||
|
_minimumSize = QSize(cMinimumWidth, cMinimumHeight);
|
||||||
|
} else {
|
||||||
|
auto calculationSize = _pixmap.size();
|
||||||
|
if (_generatedSize.width() > calculationSize.width() || _generatedSize.height() > calculationSize.height()) {
|
||||||
|
calculationSize = _generatedSize;
|
||||||
|
}
|
||||||
|
int factorX = qMax(cMinimumWidth / calculationSize.width(), cMinimumDisplayFactor);
|
||||||
|
int factorY = qMax(cMinimumWidth / calculationSize.height(), cMinimumDisplayFactor);
|
||||||
|
_displayFactor = qMin(factorX, factorY);
|
||||||
|
_minimumSize = QSize(calculationSize.width()*_displayFactor, calculationSize.height()*_displayFactor)
|
||||||
|
+ QSize(cImagePadding*2, cImagePadding*2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "OverlayMode.hpp"
|
||||||
|
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
#include <QtGui/QPixmap>
|
||||||
|
|
||||||
|
|
||||||
|
class Converter;
|
||||||
|
|
||||||
|
|
||||||
|
/// Preview the bitmap.
|
||||||
|
///
|
||||||
|
class BitmapPreview : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BitmapPreview(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Assign a new image.
|
||||||
|
///
|
||||||
|
void setImage(const QImage &image);
|
||||||
|
|
||||||
|
/// Set the overlay mode.
|
||||||
|
///
|
||||||
|
void setOverlayMode(OverlayMode overlayMode);
|
||||||
|
|
||||||
|
/// Set the current converter.
|
||||||
|
///
|
||||||
|
void setConverter(const Converter *converter);
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
|
protected: // QWidget interface
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Recalculate all sizes
|
||||||
|
///
|
||||||
|
void recalculate();
|
||||||
|
|
||||||
|
/// Set the generated image size.
|
||||||
|
///
|
||||||
|
void setGeneratedSize(const QSize &size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QImage _image; ///< The current image.
|
||||||
|
QSize _generatedSize; ///< The generated image size.
|
||||||
|
QPixmap _pixmap; ///< QPixmap representation of the image.
|
||||||
|
int _displayFactor; ///< The display factor.
|
||||||
|
QSize _minimumSize; ///< The preferred size of this widget.
|
||||||
|
OverlayMode _overlayMode; ///< The overlay mode.
|
||||||
|
const Converter *_converter; ///< The current converter.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "Converter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
Converter::Converter(const QString &displayName)
|
||||||
|
: _displayName(displayName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString Converter::displayName() const
|
||||||
|
{
|
||||||
|
return _displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize Converter::generatedSize(const QSize &imageSize) const
|
||||||
|
{
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegendDataPtr Converter::legendData(OverlayMode) const
|
||||||
|
{
|
||||||
|
auto ld = LegendData::create();
|
||||||
|
ld->addEntry(colorBitmapSizeOriginal, colorBitmapSizeGenerated, QObject::tr("Bitmap Size Original/Generated"));
|
||||||
|
return ld;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Converter::paintOverlay(OverlayPainter &op, OverlayMode, const QImage&) const
|
||||||
|
{
|
||||||
|
op.drawPixelOutline(op.imageRect(), colorBitmapSizeOriginal, 1, 2);
|
||||||
|
if (op.generatedSize().isValid() && !op.generatedSize().isEmpty()) {
|
||||||
|
op.drawPixelOutline(op.generatedRect(), colorBitmapSizeGenerated, 1, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "LegendData.hpp"
|
||||||
|
#include "OverlayPainter.hpp"
|
||||||
|
#include "OverlayMode.hpp"
|
||||||
|
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
|
||||||
|
/// Base class for all converters
|
||||||
|
///
|
||||||
|
class Converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Create a new converter.
|
||||||
|
///
|
||||||
|
/// @param displayName The name displayed in the UI for this coonverter.
|
||||||
|
///
|
||||||
|
Converter(const QString &displayName);
|
||||||
|
|
||||||
|
/// dtor
|
||||||
|
///
|
||||||
|
virtual ~Converter() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Get the display name for the converter.
|
||||||
|
///
|
||||||
|
QString displayName() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Return the size of the generated bitmap data.
|
||||||
|
///
|
||||||
|
/// @param imageSize The size of the image.
|
||||||
|
/// @return The size of the generated bitmap data.
|
||||||
|
///
|
||||||
|
virtual QSize generatedSize(const QSize &imageSize) const;
|
||||||
|
|
||||||
|
/// Generate the code from the given image.
|
||||||
|
///
|
||||||
|
/// @param image The image to convert.
|
||||||
|
/// @param parameter A map with parameters passed to this converter.
|
||||||
|
/// @return The generated code.
|
||||||
|
///
|
||||||
|
virtual QString generateCode(const QImage &image, const QVariantMap ¶meter) const = 0;
|
||||||
|
|
||||||
|
/// Return a legend for the bitmap preview.
|
||||||
|
///
|
||||||
|
virtual LegendDataPtr legendData(OverlayMode mode) const;
|
||||||
|
|
||||||
|
/// Draw the bitmap overlay.
|
||||||
|
///
|
||||||
|
/// @param p The painter.
|
||||||
|
/// @param mode The overlay mode (never `None`).
|
||||||
|
/// @param image The image.
|
||||||
|
///
|
||||||
|
virtual void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// The color for the image frame.
|
||||||
|
///
|
||||||
|
static constexpr QColor colorBitmapSizeOriginal = QColor(64, 64, 255);
|
||||||
|
|
||||||
|
/// The color for the generated frame.
|
||||||
|
///
|
||||||
|
static constexpr QColor colorBitmapSizeGenerated = QColor(128, 128, 255);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _displayName; ///< The displayed name.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ConverterFramebuf.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtCore/QTextStream>
|
||||||
|
|
||||||
|
|
||||||
|
ConverterFramebuf::ConverterFramebuf(const QString &displayName)
|
||||||
|
: Converter(displayName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ConverterFramebuf::createCode(const QByteArray &data, const QSize &size, const QString &format)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
QTextStream ts(&result);
|
||||||
|
ts << "fb = framebuf.FrameBuffer(bytearray(\n";
|
||||||
|
for (int i = 0; i < data.size(); ++i) {
|
||||||
|
if ((i & 0x1f) == 0) {
|
||||||
|
if (i > 0) {
|
||||||
|
ts << "'\n";
|
||||||
|
}
|
||||||
|
ts << " b'";
|
||||||
|
}
|
||||||
|
ts << QString("\\x%1").arg(static_cast<uint32_t>(data.at(i))&0xff, 2, 16, QChar('0'));
|
||||||
|
}
|
||||||
|
ts << "'),\n";
|
||||||
|
ts << " " << size.width() << ", " << size.height() << ", framebuf." << format << ")\n";
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "Converter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/// Base class of framebuf converters.
|
||||||
|
///
|
||||||
|
class ConverterFramebuf : public Converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConverterFramebuf(const QString &displayName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Create a framebuf code segment.
|
||||||
|
///
|
||||||
|
/// @param data The byte data.
|
||||||
|
/// @param size The buffer size.
|
||||||
|
/// @param format The name of the format.
|
||||||
|
///
|
||||||
|
static QString createCode(const QByteArray &data, const QSize &size, const QString &format);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ConverterFramebufMono.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ConverterFramebufMono::ConverterFramebufMono(
|
||||||
|
const QString &displayName,
|
||||||
|
UnitOrientation unitOrientation,
|
||||||
|
BitDirection bitDirection,
|
||||||
|
int unitSize)
|
||||||
|
:
|
||||||
|
ConverterFramebuf(displayName),
|
||||||
|
_unitOrientation(unitOrientation),
|
||||||
|
_bitDirection(bitDirection),
|
||||||
|
_unitSize(unitSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize ConverterFramebufMono::generatedSize(const QSize &imageSize) const
|
||||||
|
{
|
||||||
|
if (_unitOrientation == UnitOrientation::Vertical) {
|
||||||
|
if ((imageSize.height() % _unitSize) != 0) {
|
||||||
|
return QSize(imageSize.width(), ((imageSize.height()/_unitSize)+1)*_unitSize);
|
||||||
|
} else {
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((imageSize.width() % _unitSize) != 0) {
|
||||||
|
return QSize(((imageSize.width()/_unitSize)+1)*_unitSize, imageSize.height());
|
||||||
|
} else {
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegendDataPtr ConverterFramebufMono::legendData(OverlayMode mode) const
|
||||||
|
{
|
||||||
|
auto data = ConverterFramebuf::legendData(mode);
|
||||||
|
if (mode == OverlayMode::BitAssigments) {
|
||||||
|
data->addEntry(colorBitAssignment1, colorBitAssignment2, QObject::tr("Bit Assignment"));
|
||||||
|
} else {
|
||||||
|
data->addEntry(colorPixelInterpretation, QObject::tr("Pixel Interpretation"));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const
|
||||||
|
{
|
||||||
|
ConverterFramebuf::paintOverlay(p, mode, image);
|
||||||
|
if (mode == OverlayMode::BitAssigments) {
|
||||||
|
const auto bitL = (_bitDirection == BitDirection::LSB ? "0" : QString::number(_unitSize-1));
|
||||||
|
const auto bitH = (_bitDirection == BitDirection::LSB ? QString::number(_unitSize-1) : "0");
|
||||||
|
bool colorFlag = false;
|
||||||
|
if (_unitOrientation == UnitOrientation::Vertical) {
|
||||||
|
for (int y = 0; y < p.imageSize().height(); y += _unitSize) {
|
||||||
|
for (int x = 0; x < p.imageSize().width(); ++x) {
|
||||||
|
QRect rect(x, y, 1, _unitSize);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
||||||
|
p.drawPixelOutline(rect, color, 1);
|
||||||
|
p.drawPixelText(QRect(x, y, 1, 1), color, bitL);
|
||||||
|
p.drawPixelText(QRect(x, y+_unitSize-1, 1, 1), color, bitH);
|
||||||
|
}
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
if (p.imageSize().width() % 2 == 0) {
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = 0; y < p.imageSize().height(); ++y) {
|
||||||
|
for (int x = 0; x < p.imageSize().width(); x += _unitSize) {
|
||||||
|
QRect rect(x, y, _unitSize, 1);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
||||||
|
p.drawPixelOutline(rect, color, 1);
|
||||||
|
p.drawPixelText(QRect(x, y, 1, 1), color, bitH);
|
||||||
|
p.drawPixelText(QRect(x+_unitSize-1, y, 1, 1), color, bitL);
|
||||||
|
}
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
if ((p.imageSize().width()/_unitSize) % 2 == 0) {
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (mode == OverlayMode::PixelInterpretation) {
|
||||||
|
for (int y = 0; y < p.generatedSize().height(); ++y) {
|
||||||
|
for (int x = 0; x < p.generatedSize().width(); ++x) {
|
||||||
|
auto text = (getPixel(x, y, image) ? "1" : "0");
|
||||||
|
const QRect rect(x, y, 1, 1);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
p.drawPixelText(rect, colorPixelInterpretation, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ConverterFramebufMono::getPixel(int x, int y, const QImage &image)
|
||||||
|
{
|
||||||
|
if (x < 0 || y < 0 || x >= image.width() || y >= image.height()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto color = image.pixelColor(x, y);
|
||||||
|
float h, s, l, a;
|
||||||
|
color.getHslF(&h, &s, &l, &a);
|
||||||
|
if (a < 0.5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return l < 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t ConverterFramebufMono::readUnit(int x, int y, int dx, int dy, int count, const QImage &image)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
result <<= 1;
|
||||||
|
if (getPixel(x, y, image)) {
|
||||||
|
result |= 0b1;
|
||||||
|
}
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ConverterFramebuf.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/// The base class of all mono converters
|
||||||
|
///
|
||||||
|
class ConverterFramebufMono : public ConverterFramebuf
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
enum class UnitOrientation {
|
||||||
|
Horizontal,
|
||||||
|
Vertical
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BitDirection {
|
||||||
|
LSB,
|
||||||
|
MSB
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create a new mono converter.
|
||||||
|
///
|
||||||
|
/// @param displayName The display name.
|
||||||
|
/// @param unitOrientation The unit direction.
|
||||||
|
/// @param unitSize The number of bits per unit.
|
||||||
|
///
|
||||||
|
ConverterFramebufMono(
|
||||||
|
const QString &displayName,
|
||||||
|
UnitOrientation unitOrientation,
|
||||||
|
BitDirection bitDirection,
|
||||||
|
int unitSize);
|
||||||
|
|
||||||
|
public: // Converter interface
|
||||||
|
QSize generatedSize(const QSize &imageSize) const override;
|
||||||
|
LegendDataPtr legendData(OverlayMode mode) const override;
|
||||||
|
void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Interpret a single pixel.
|
||||||
|
///
|
||||||
|
/// Returns `false` if the pixel is out of bounds.
|
||||||
|
///
|
||||||
|
static bool getPixel(int x, int y, const QImage &image);
|
||||||
|
|
||||||
|
/// Read a single unit.
|
||||||
|
///
|
||||||
|
static uint32_t readUnit(int x, int y, int dx, int dy, int count, const QImage &image);
|
||||||
|
|
||||||
|
/// The colors for the bit assignments
|
||||||
|
///
|
||||||
|
static constexpr QColor colorBitAssignment1 = QColor(240, 40, 40);
|
||||||
|
static constexpr QColor colorBitAssignment2 = QColor(240, 80, 80);
|
||||||
|
static constexpr QColor colorPixelInterpretation = QColor(240, 240, 40);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UnitOrientation _unitOrientation; ///< The unit orientatioon.
|
||||||
|
BitDirection _bitDirection; ///< The bit direction.
|
||||||
|
int _unitSize; ///< The number of bits per unit.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ConverterFramebufMonoHLSB.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtCore/QTextStream>
|
||||||
|
|
||||||
|
|
||||||
|
ConverterFramebufMonoHLSB::ConverterFramebufMonoHLSB()
|
||||||
|
: ConverterFramebufMono("MicroPython Framebuf Mono HLSB", UnitOrientation::Horizontal, BitDirection::LSB, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
for (int y = 0; y < image.height(); ++y) {
|
||||||
|
for (int x = 0; x < image.width(); x += 8) {
|
||||||
|
data.append(static_cast<uint8_t>(readUnit(x, y, 1, 0, 8, image)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createCode(data, generatedSize(image.size()), "MONO_HLSB");
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ConverterFramebufMono.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class ConverterFramebufMonoHLSB : public ConverterFramebufMono
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConverterFramebufMonoHLSB();
|
||||||
|
|
||||||
|
public: // Converter interface
|
||||||
|
QString generateCode(const QImage &image, const QVariantMap ¶meter) const override;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ConverterFramebufMonoHMSB.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ConverterFramebufMonoHMSB::ConverterFramebufMonoHMSB()
|
||||||
|
: ConverterFramebufMono("MicroPython Framebuf Mono HMSB", UnitOrientation::Horizontal,BitDirection::MSB, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
for (int y = 0; y < image.height(); ++y) {
|
||||||
|
for (int x = 0; x < image.width(); x += 8) {
|
||||||
|
data.append(static_cast<uint8_t>(readUnit(x+7, y, -1, 0, 8, image)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createCode(data, generatedSize(image.size()), "MONO_HMSB");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ConverterFramebufMono.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class ConverterFramebufMonoHMSB : public ConverterFramebufMono
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConverterFramebufMonoHMSB();
|
||||||
|
|
||||||
|
public: // Converter interface
|
||||||
|
QString generateCode(const QImage &image, const QVariantMap ¶meter) const override;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ConverterFramebufMonoVLSB.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ConverterFramebufMonoVLSB::ConverterFramebufMonoVLSB()
|
||||||
|
: ConverterFramebufMono("MicroPython Framebuf Mono VLSB", UnitOrientation::Vertical, BitDirection::LSB, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
for (int y = 0; y < image.height(); y += 8) {
|
||||||
|
for (int x = 0; x < image.width(); ++x) {
|
||||||
|
data.append(static_cast<uint8_t>(readUnit(x, y+7, 0, -1, 8, image)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createCode(data, generatedSize(image.size()), "MONO_VLSB");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ConverterFramebufMono.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class ConverterFramebufMonoVLSB : public ConverterFramebufMono
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConverterFramebufMonoVLSB();
|
||||||
|
|
||||||
|
public: // Converter interface
|
||||||
|
QString generateCode(const QImage &image, const QVariantMap ¶meter) const override;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "LegendData.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "LegendEntry.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
LegendDataPtr LegendData::create()
|
||||||
|
{
|
||||||
|
return LegendDataPtr(new LegendData());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegendData::~LegendData()
|
||||||
|
{
|
||||||
|
qDeleteAll(_entryList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LegendData::addEntry(const QColor &color, const QString &text)
|
||||||
|
{
|
||||||
|
_entryList.append(new LegendEntry(color, text));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LegendData::addEntry(const QColor &color1, const QColor &color2, const QString &text)
|
||||||
|
{
|
||||||
|
_entryList.append(new LegendEntry(color1, color2, text));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const QList<const LegendEntry*>& LegendData::entryList() const
|
||||||
|
{
|
||||||
|
return _entryList;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtGui/QColor>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
|
|
||||||
|
class LegendEntry;
|
||||||
|
|
||||||
|
|
||||||
|
class LegendData;
|
||||||
|
using LegendDataPtr = QSharedPointer<LegendData>;
|
||||||
|
|
||||||
|
|
||||||
|
/// Legend data.
|
||||||
|
///
|
||||||
|
class LegendData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Create a new legend data object.
|
||||||
|
///
|
||||||
|
static LegendDataPtr create();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// private ctor
|
||||||
|
///
|
||||||
|
LegendData() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// dtor
|
||||||
|
///
|
||||||
|
~LegendData();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Add a new entry to the legend.
|
||||||
|
///
|
||||||
|
/// @param color The color.
|
||||||
|
/// @param text The text for the entry.
|
||||||
|
///
|
||||||
|
void addEntry(const QColor &color, const QString &text);
|
||||||
|
|
||||||
|
/// Add a new entry to the legend.
|
||||||
|
///
|
||||||
|
/// @param color1 The first color.
|
||||||
|
/// @param color2 The second color.
|
||||||
|
/// @param text The text for the entry.
|
||||||
|
///
|
||||||
|
void addEntry(const QColor &color1, const QColor &color2, const QString &text);
|
||||||
|
|
||||||
|
/// Get the list with all entries.
|
||||||
|
///
|
||||||
|
const QList<const LegendEntry*>& entryList() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<const LegendEntry*> _entryList; ///< The list with all entries.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "LegendEntry.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
LegendEntry::LegendEntry(const QColor &color, const QString &text)
|
||||||
|
: _color1(color), _text(text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegendEntry::LegendEntry(const QColor &color1, const QColor &color2, const QString &text)
|
||||||
|
: _color1(color1), _color2(color2), _text(text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QColor LegendEntry::color1() const
|
||||||
|
{
|
||||||
|
return _color1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QColor LegendEntry::color2() const
|
||||||
|
{
|
||||||
|
return _color2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString LegendEntry::text() const
|
||||||
|
{
|
||||||
|
return _text;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtGui/QColor>
|
||||||
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
|
||||||
|
/// A entry in the legend data.
|
||||||
|
///
|
||||||
|
class LegendEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Identifier : int {
|
||||||
|
BitmapSize = 0,
|
||||||
|
BitAssignment = 1,
|
||||||
|
ReadDirection = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
LegendEntry(const QColor &color, const QString &text);
|
||||||
|
LegendEntry(const QColor &color1, const QColor &color2, const QString &text);
|
||||||
|
|
||||||
|
public:
|
||||||
|
QColor color1() const;
|
||||||
|
QColor color2() const;
|
||||||
|
QString text() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QColor _color1;
|
||||||
|
QColor _color2;
|
||||||
|
QString _text;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "BitmapPanel.hpp"
|
||||||
|
#include "ConverterFramebufMonoVLSB.hpp"
|
||||||
|
#include "ConverterFramebufMonoHLSB.hpp"
|
||||||
|
#include "ConverterFramebufMonoHMSB.hpp"
|
||||||
|
|
||||||
|
#include <QtCore/QSettings>
|
||||||
|
#include <QtGui/QAction>
|
||||||
|
#include <QtGui/QClipboard>
|
||||||
|
#include <QtWidgets/QComboBox>
|
||||||
|
#include <QtWidgets/QFrame>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
#include <QtWidgets/QPushButton>
|
||||||
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
#include <QtWidgets/QMenuBar>
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
|
#include <QtWidgets/QApplication>
|
||||||
|
#include <QtWidgets/QFileDialog>
|
||||||
|
#include <QtWidgets/QPlainTextEdit>
|
||||||
|
#include <QtWidgets/QScrollArea>
|
||||||
|
#include <QtWidgets/QSplitter>
|
||||||
|
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
{
|
||||||
|
initializeConverterList();
|
||||||
|
initializeUi();
|
||||||
|
initializeMenu();
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::initializeConverterList()
|
||||||
|
{
|
||||||
|
_converterList.append(new ConverterFramebufMonoVLSB());
|
||||||
|
_converterList.append(new ConverterFramebufMonoHMSB());
|
||||||
|
_converterList.append(new ConverterFramebufMonoHLSB());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::initializeUi()
|
||||||
|
{
|
||||||
|
setMinimumSize(800, 600);
|
||||||
|
setWindowTitle(tr("Micropython Bitmap Tool by Lucky Resistor"));
|
||||||
|
|
||||||
|
auto centralWidget = new QWidget();
|
||||||
|
centralWidget->setObjectName("CentralWidget");
|
||||||
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
|
auto mainLayout = new QHBoxLayout(centralWidget);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
auto settingsPanel = new QFrame();
|
||||||
|
settingsPanel->setObjectName("SettingsPanel");
|
||||||
|
mainLayout->addWidget(settingsPanel);
|
||||||
|
|
||||||
|
auto settingsLayout = new QVBoxLayout(settingsPanel);
|
||||||
|
settingsLayout->setSpacing(4);
|
||||||
|
|
||||||
|
auto logo = new QLabel();
|
||||||
|
logo->setFixedSize(300, 250);
|
||||||
|
logo->setPixmap(QPixmap(":/images/AppLogo.png"));
|
||||||
|
settingsLayout->addWidget(logo);
|
||||||
|
auto versionLabel = new QLabel(tr("<b>Version %1</b>").arg(qApp->applicationVersion()));
|
||||||
|
versionLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
settingsLayout->addWidget(versionLabel);
|
||||||
|
settingsLayout->addSpacing(16);
|
||||||
|
|
||||||
|
settingsLayout->addWidget(new QLabel(tr("Generated Format:")));
|
||||||
|
_formatSelector = new QComboBox();
|
||||||
|
for (auto converter : _converterList) {
|
||||||
|
_formatSelector->addItem(converter->displayName());
|
||||||
|
}
|
||||||
|
_formatSelector->setCurrentIndex(0);
|
||||||
|
settingsLayout->addWidget(_formatSelector);
|
||||||
|
|
||||||
|
settingsLayout->addStretch();
|
||||||
|
|
||||||
|
settingsLayout->addWidget(new QLabel(tr("<b>Loaded Bitmap Info:</b>")));
|
||||||
|
_bitmapInfo = new QLabel(tr("No Bitmap Loaded"));
|
||||||
|
_bitmapInfo->setObjectName("BitmapInfo");
|
||||||
|
_bitmapInfo->setMinimumHeight(200);
|
||||||
|
_bitmapInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
||||||
|
settingsLayout->addWidget(_bitmapInfo);
|
||||||
|
|
||||||
|
auto loadButton = new QPushButton();
|
||||||
|
loadButton->setText(tr("Load Bitmap"));
|
||||||
|
settingsLayout->addWidget(loadButton);
|
||||||
|
connect(loadButton, &QPushButton::clicked, this, &MainWindow::onLoadBitmap);
|
||||||
|
|
||||||
|
auto previewSplittter = new QSplitter(Qt::Vertical);
|
||||||
|
previewSplittter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
previewSplittter->setChildrenCollapsible(false);
|
||||||
|
mainLayout->addWidget(previewSplittter);
|
||||||
|
|
||||||
|
_bitmapPanel = new BitmapPanel();
|
||||||
|
previewSplittter->addWidget(_bitmapPanel);
|
||||||
|
|
||||||
|
auto codePanel = new QWidget();
|
||||||
|
codePanel->setMinimumHeight(200);
|
||||||
|
auto codeLayout = new QVBoxLayout(codePanel);
|
||||||
|
codeLayout->setContentsMargins(16, 4, 16, 16);
|
||||||
|
codeLayout->setSpacing(4);
|
||||||
|
codeLayout->addWidget(new QLabel(tr("Generated Code:")));
|
||||||
|
_codePreview = new QPlainTextEdit();
|
||||||
|
_codePreview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
_codePreview->setReadOnly(true);
|
||||||
|
_codePreview->setWordWrapMode(QTextOption::NoWrap);
|
||||||
|
codeLayout->addWidget(_codePreview);
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
_codePreview->setFont(QFont("Consolas", 12));
|
||||||
|
#else
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
_codePreview->setFont(QFont("Menlo", 12));
|
||||||
|
#else
|
||||||
|
_codePreview->setFont(QFont("Lucida Console", 12));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto codeActions = new QFrame();
|
||||||
|
auto codeActionsLayout = new QHBoxLayout(codeActions);
|
||||||
|
codeActionsLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
codeActionsLayout->setSpacing(4);
|
||||||
|
codeActionsLayout->addStretch();
|
||||||
|
|
||||||
|
auto copyCodeButton = new QPushButton();
|
||||||
|
copyCodeButton->setText(tr("Copy Code"));
|
||||||
|
codeActionsLayout->addWidget(copyCodeButton);
|
||||||
|
connect(copyCodeButton, &QPushButton::clicked, [=]{
|
||||||
|
qApp->clipboard()->setText(_codePreview->toPlainText());
|
||||||
|
});
|
||||||
|
codeLayout->addWidget(codeActions);
|
||||||
|
|
||||||
|
previewSplittter->addWidget(codePanel);
|
||||||
|
previewSplittter->setStretchFactor(0, 4);
|
||||||
|
previewSplittter->setStretchFactor(1, 1);
|
||||||
|
|
||||||
|
connect(_formatSelector, &QComboBox::currentIndexChanged, [=]{
|
||||||
|
_bitmapPanel->setConverter(selectedConverter());
|
||||||
|
updateBitmapInfo();
|
||||||
|
updateCode();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::initializeMenu()
|
||||||
|
{
|
||||||
|
auto menuFile = menuBar()->addMenu(tr("File"));
|
||||||
|
auto actionLoadBitmap = menuFile->addAction(tr("Load Bitmap..."));
|
||||||
|
actionLoadBitmap->setShortcut(QKeySequence("Ctrl+O"));
|
||||||
|
connect(actionLoadBitmap, &QAction::triggered, this, &MainWindow::onLoadBitmap);
|
||||||
|
auto actionQuit = menuFile->addAction(tr("Quit"));
|
||||||
|
connect(actionQuit, &QAction::triggered, [=]{
|
||||||
|
qApp->quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto menuHelp = menuBar()->addMenu(tr("Help"));
|
||||||
|
auto actionAbout = menuHelp->addAction(tr("About..."));
|
||||||
|
connect(actionAbout, &QAction::triggered, [=]{
|
||||||
|
QMessageBox::about(this, tr("Micropython Bitmap Tool by Lucky Resistor"),
|
||||||
|
tr("<h1>Micropython Bitmap Tool</h1><p>(c)2021 by Lucky Resistor</p>"
|
||||||
|
"<p><b>Version %1</b></p>").arg(qApp->applicationVersion()));
|
||||||
|
});
|
||||||
|
auto actionAboutQt = menuHelp->addAction(tr("Information About Qt..."));
|
||||||
|
connect(actionAboutQt, &QAction::triggered, [=]{
|
||||||
|
QMessageBox::aboutQt(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::loadSettings()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
restoreGeometry(settings.value("mainWindow.geometry").toByteArray());
|
||||||
|
restoreState(settings.value("mainWindow.state").toByteArray());
|
||||||
|
_formatSelector->setCurrentIndex(settings.value("format.index").toInt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::saveSettings()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue("mainWindow.geometry", saveGeometry());
|
||||||
|
settings.setValue("mainWindow.state", saveState());
|
||||||
|
settings.setValue("format.index", _formatSelector->currentIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Converter *MainWindow::selectedConverter() const
|
||||||
|
{
|
||||||
|
auto converter = _converterList.value(_formatSelector->currentIndex());
|
||||||
|
if (converter == nullptr) {
|
||||||
|
converter = _converterList.first();
|
||||||
|
}
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::updateBitmapInfo()
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
QTextStream ts(&text);
|
||||||
|
ts << "<p>";
|
||||||
|
ts << "Bitmap Size: " << _currentImage.width() << "x" << _currentImage.height() << "<br>";
|
||||||
|
ts << "Bit Depth: " << _currentImage.depth() << "<br>";
|
||||||
|
ts << "Color Format: ";
|
||||||
|
switch (_currentImage.pixelFormat().colorModel()) {
|
||||||
|
case QPixelFormat::RGB: ts << "RGB"; break;
|
||||||
|
case QPixelFormat::BGR: ts << "BGR"; break;
|
||||||
|
case QPixelFormat::Indexed: ts << "Indexed"; break;
|
||||||
|
case QPixelFormat::Grayscale: ts << "Grayscale"; break;
|
||||||
|
case QPixelFormat::CMYK: ts << "CMYK"; break;
|
||||||
|
case QPixelFormat::HSL: ts << "HSL"; break;
|
||||||
|
case QPixelFormat::HSV: ts << "HSV"; break;
|
||||||
|
case QPixelFormat::YUV: ts << "YUV"; break;
|
||||||
|
case QPixelFormat::Alpha: ts << "Alpha"; break;
|
||||||
|
}
|
||||||
|
ts << "<br>";
|
||||||
|
const auto gs = selectedConverter()->generatedSize(_currentImage.size());
|
||||||
|
ts << "Generated Size: " << gs.width() << "x" << gs.height() << "</p>";
|
||||||
|
_bitmapInfo->setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::updateCode()
|
||||||
|
{
|
||||||
|
QString code;
|
||||||
|
if (!_currentImage.isNull()) {
|
||||||
|
code = selectedConverter()->generateCode(_currentImage, QVariantMap());
|
||||||
|
}
|
||||||
|
_codePreview->setPlainText(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onLoadBitmap()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
auto lastDir = settings.value("bitmap.lastDir").toString();
|
||||||
|
auto fileName = QFileDialog::getOpenFileName(
|
||||||
|
this,
|
||||||
|
tr("Open Bitmap"),
|
||||||
|
lastDir,
|
||||||
|
tr("Images (*.png *.jpg *.jpeg *.gif *.pbm *.pgm *.ppm *.xbm *.xpm *.bpm)"));
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFileInfo fileInfo(fileName);
|
||||||
|
settings.setValue("bitmap.lastDir", fileInfo.absoluteDir().path());
|
||||||
|
QImage newImage;
|
||||||
|
if (!newImage.load(fileName)) {
|
||||||
|
QMessageBox::warning(this, tr("Loading Image Failed"),
|
||||||
|
tr("<h1>Failed to load the image</h1>"
|
||||||
|
"<p>Could not load the specified image file. "
|
||||||
|
"Make sure the image is in a supported format.</p>"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newImage.width() > 0x100 || newImage.height() > 0x100) {
|
||||||
|
QMessageBox::warning(this, tr("Image is Too Large"),
|
||||||
|
tr("<h1>Image is Too Large</h1>"
|
||||||
|
"<p>One dimension of the loaded image is larger than "
|
||||||
|
"256 pixel. This software is designed for small bitmaps.</p>"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentImage = newImage;
|
||||||
|
_bitmapPanel->setImage(newImage);
|
||||||
|
_bitmapPanel->setConverter(selectedConverter());
|
||||||
|
updateBitmapInfo();
|
||||||
|
updateCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
saveSettings();
|
||||||
|
QMainWindow::closeEvent(event);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtWidgets/QMainWindow>
|
||||||
|
|
||||||
|
|
||||||
|
class Converter;
|
||||||
|
class QPlainTextEdit;
|
||||||
|
class QComboBox;
|
||||||
|
class QLabel;
|
||||||
|
class BitmapPanel;
|
||||||
|
|
||||||
|
|
||||||
|
/// The main widnow
|
||||||
|
///
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget *parent = nullptr);
|
||||||
|
~MainWindow() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Initialize the converter list
|
||||||
|
///
|
||||||
|
void initializeConverterList();
|
||||||
|
|
||||||
|
/// Initialize the user interface.
|
||||||
|
///
|
||||||
|
void initializeUi();
|
||||||
|
|
||||||
|
/// Initialize the menu
|
||||||
|
///
|
||||||
|
void initializeMenu();
|
||||||
|
|
||||||
|
/// Load all settings
|
||||||
|
///
|
||||||
|
void loadSettings();
|
||||||
|
|
||||||
|
/// Save all settings.
|
||||||
|
///
|
||||||
|
void saveSettings();
|
||||||
|
|
||||||
|
/// The current converter.
|
||||||
|
///
|
||||||
|
Converter* selectedConverter() const;
|
||||||
|
|
||||||
|
/// Update the bitmap info.
|
||||||
|
///
|
||||||
|
void updateBitmapInfo();
|
||||||
|
|
||||||
|
/// Update the code.
|
||||||
|
///
|
||||||
|
void updateCode();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
/// Load a bitmap.
|
||||||
|
///
|
||||||
|
void onLoadBitmap();
|
||||||
|
|
||||||
|
protected: // Implement QWidget
|
||||||
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QComboBox *_formatSelector; ///< The format selector.
|
||||||
|
QPlainTextEdit *_codePreview; ///< The generated code.
|
||||||
|
BitmapPanel *_bitmapPanel; ///< The bitmap panel.
|
||||||
|
QImage _currentImage; ///< The current loaded image
|
||||||
|
QLabel *_bitmapInfo; ///< The label with the image info.
|
||||||
|
QList<Converter*> _converterList; ///< A list of available converters.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
QT += core gui
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
CONFIG += c++17
|
||||||
|
|
||||||
|
TARGET = "MicroPython Bitmap Tool"
|
||||||
|
|
||||||
|
# You can make your code fail to compile if it uses deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
BitmapPanel.cpp \
|
||||||
|
BitmapPreview.cpp \
|
||||||
|
Converter.cpp \
|
||||||
|
ConverterFramebuf.cpp \
|
||||||
|
ConverterFramebufMono.cpp \
|
||||||
|
ConverterFramebufMonoHLSB.cpp \
|
||||||
|
ConverterFramebufMonoHMSB.cpp \
|
||||||
|
ConverterFramebufMonoVLSB.cpp \
|
||||||
|
LegendData.cpp \
|
||||||
|
LegendEntry.cpp \
|
||||||
|
OverlayPainter.cpp \
|
||||||
|
main.cpp \
|
||||||
|
MainWindow.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
BitmapPanel.hpp \
|
||||||
|
BitmapPreview.hpp \
|
||||||
|
Converter.hpp \
|
||||||
|
ConverterFramebuf.hpp \
|
||||||
|
ConverterFramebufMono.hpp \
|
||||||
|
ConverterFramebufMonoHLSB.hpp \
|
||||||
|
ConverterFramebufMonoHMSB.hpp \
|
||||||
|
ConverterFramebufMonoVLSB.hpp \
|
||||||
|
LegendData.hpp \
|
||||||
|
LegendEntry.hpp \
|
||||||
|
MainWindow.hpp \
|
||||||
|
OverlayMode.hpp \
|
||||||
|
OverlayPainter.hpp
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
data/data.qrc
|
||||||
|
|
||||||
|
macos:ICON = data/AppIcon.icns
|
||||||
|
win32:RC_ICONS = data/AppIcon.ico
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
data/application.css
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
enum class OverlayMode : int {
|
||||||
|
None = 0,
|
||||||
|
BitAssigments = 1,
|
||||||
|
PixelInterpretation = 2
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "OverlayPainter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
OverlayPainter::OverlayPainter(
|
||||||
|
QPainter *painter,
|
||||||
|
const QRect &updateRect,
|
||||||
|
int displayFactor,
|
||||||
|
const QSize &imageSize,
|
||||||
|
const QSize &generatedSize)
|
||||||
|
:
|
||||||
|
_p(painter),
|
||||||
|
_updateRect(updateRect),
|
||||||
|
_displayFactor(displayFactor),
|
||||||
|
_imageSize(imageSize),
|
||||||
|
_generatedSize(generatedSize)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
_pixelFont = QFont("Consolas");
|
||||||
|
#else
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
_pixelFont = QFont("Menlo");
|
||||||
|
#else
|
||||||
|
_pixelFont = QFont("Lucida Console");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
_pixelFont.setPixelSize(displayFactor - 1);
|
||||||
|
_p->setFont(_pixelFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OverlayPainter::drawPixelOutline(const QRect &rect, const QColor &outlineColor, int outlineWidth, int offset)
|
||||||
|
{
|
||||||
|
_p->setBrush(QBrush());
|
||||||
|
_p->setPen(QPen(outlineColor, outlineWidth, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
|
||||||
|
const qreal offset1 = static_cast<qreal>(outlineWidth)/2 - static_cast<qreal>(offset);
|
||||||
|
const qreal offset2 = -static_cast<qreal>(outlineWidth)/2 + static_cast<qreal>(offset);
|
||||||
|
const auto rectToDraw = pixelRectF(rect).adjusted(offset1, offset1, offset2, offset2);
|
||||||
|
_p->drawRect(rectToDraw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OverlayPainter::drawPixelText(const QRect &rect, const QColor &textColor, const QString &text)
|
||||||
|
{
|
||||||
|
_p->setBrush(QBrush());
|
||||||
|
_p->setPen(QPen(textColor));
|
||||||
|
_p->drawText(pixelRectF(rect), Qt::AlignCenter, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool OverlayPainter::arePixelUpdated(const QRect &rect) const
|
||||||
|
{
|
||||||
|
const auto rectToDraw = pixelRectF(rect).adjusted(-64, -64, 64, 64);
|
||||||
|
return rectToDraw.intersects(_updateRect);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
|
||||||
|
|
||||||
|
/// The overlay painter.
|
||||||
|
///
|
||||||
|
class OverlayPainter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
OverlayPainter(
|
||||||
|
QPainter *painter,
|
||||||
|
const QRect &updateRect,
|
||||||
|
int displayFactor,
|
||||||
|
const QSize &imageSize,
|
||||||
|
const QSize &generatedSize);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Access the painter.
|
||||||
|
///
|
||||||
|
inline QPainter *painter() const { return _p; };
|
||||||
|
|
||||||
|
/// Access the display factor.
|
||||||
|
///
|
||||||
|
inline int displayFactor() const { return _displayFactor; };
|
||||||
|
|
||||||
|
/// Access the image size.
|
||||||
|
///
|
||||||
|
inline const QSize& imageSize() const { return _imageSize; }
|
||||||
|
|
||||||
|
/// Access the generated size.
|
||||||
|
///
|
||||||
|
inline const QSize& generatedSize() const { return _generatedSize; }
|
||||||
|
|
||||||
|
/// Access the image rect.
|
||||||
|
///
|
||||||
|
inline const QRect imageRect() const { return QRect(QPoint(0, 0), imageSize()); }
|
||||||
|
|
||||||
|
/// Access the generated rect
|
||||||
|
///
|
||||||
|
inline const QRect generatedRect() const { return QRect(QPoint(0, 0), generatedSize()); }
|
||||||
|
|
||||||
|
/// Get a rectangle for a pixal area.
|
||||||
|
///
|
||||||
|
inline QRectF pixelRectF(int x, int y, int width, int height) const {
|
||||||
|
return QRectF(x * _displayFactor, y * _displayFactor, width * _displayFactor, height * _displayFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a rectangle for a pixel rect.
|
||||||
|
///
|
||||||
|
inline QRectF pixelRectF(const QRect &rect) const {
|
||||||
|
return pixelRectF(rect.x(), rect.y(), rect.width(), rect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw a outline around a pixel area.
|
||||||
|
///
|
||||||
|
/// @param rect The rect for the pixel area.
|
||||||
|
/// @param outlineColor The color of the outline.
|
||||||
|
/// @param outlineWidth THe width of the outline in pixels.
|
||||||
|
/// @param offset The offset of the outline. +1 = around the area, 0 in the area.
|
||||||
|
///
|
||||||
|
void drawPixelOutline(
|
||||||
|
const QRect &rect,
|
||||||
|
const QColor &outlineColor,
|
||||||
|
int outlineWidth = 1,
|
||||||
|
int offset = 0);
|
||||||
|
|
||||||
|
/// Write text into a pixel area
|
||||||
|
///
|
||||||
|
void drawPixelText(
|
||||||
|
const QRect &rect,
|
||||||
|
const QColor &textColor,
|
||||||
|
const QString &text);
|
||||||
|
|
||||||
|
/// Check if a pixel region ready for repaint.
|
||||||
|
///
|
||||||
|
bool arePixelUpdated(const QRect &rect) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPainter *_p; ///< The painter used.
|
||||||
|
QRect _updateRect; ///< The update rect.
|
||||||
|
int _displayFactor; ///< The display factor.
|
||||||
|
QSize _imageSize; ///< The size of the image.
|
||||||
|
QSize _generatedSize; ///< The generated size.
|
||||||
|
QFont _pixelFont; ///< The font used to draw into the pixels.
|
||||||
|
};
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
# MicroPythonBitmapTool
|
# MicroPython Bitmap Tool
|
||||||
|
|
||||||
|
https://luckyresistor.me/applications/micropython-bitmap-tool/
|
||||||
|
|
||||||
|
|
||||||
|
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 126 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 8.6 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 19 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 30 KiB |
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
#CentralWidget, QMainWindow {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SettingsPanel {
|
||||||
|
background-color: #616875;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#BitmapInfo {
|
||||||
|
border: 1px solid rgba(0,0,0,0.25);
|
||||||
|
padding: 8px;
|
||||||
|
margin: 0px 0px 16px 0px;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/images">
|
||||||
|
<file>AppLogo.png</file>
|
||||||
|
<file>AppLogo@2x.png</file>
|
||||||
|
<file>AppLogo@3x.png</file>
|
||||||
|
</qresource>
|
||||||
|
<qresource prefix="/stylesheet">
|
||||||
|
<file>application.css</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
|
#include <QtWidgets/QApplication>
|
||||||
|
#include <QtCore/QFile>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
a.setApplicationName("MicroPython Bitmap Tool");
|
||||||
|
a.setApplicationVersion("1.0");
|
||||||
|
a.setApplicationDisplayName("MicroPython Bitmap Tool");
|
||||||
|
a.setOrganizationDomain("luckyresistor.me");
|
||||||
|
a.setOrganizationName("Lucky Resistoor");
|
||||||
|
QFile styleSheet(":/stylesheet/application.css");
|
||||||
|
styleSheet.open(QIODevice::ReadOnly);
|
||||||
|
a.setStyleSheet(QString::fromUtf8(styleSheet.readAll()));
|
||||||
|
styleSheet.close();
|
||||||
|
|
||||||
|
MainWindow w;
|
||||||
|
w.show();
|
||||||
|
return a.exec();
|
||||||
|
}
|
Ładowanie…
Reference in New Issue