main
Lucky Resistor 2021-03-09 23:24:04 +01:00
rodzic 3cfa77426d
commit 4155acfde7
36 zmienionych plików z 1973 dodań i 1 usunięć

2
.gitignore vendored
Wyświetl plik

@ -30,3 +30,5 @@
*.exe
*.out
*.app
*.pro.user

90
BitmapPanel.cpp 100644
Wyświetl plik

@ -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()));
});
}

51
BitmapPanel.hpp 100644
Wyświetl plik

@ -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.
};

154
BitmapPreview.cpp 100644
Wyświetl plik

@ -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);
}
}

78
BitmapPreview.hpp 100644
Wyświetl plik

@ -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.
};

53
Converter.cpp 100644
Wyświetl plik

@ -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);
}
}

89
Converter.hpp 100644
Wyświetl plik

@ -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 &parameter) 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.
};

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);
};

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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.
};

Wyświetl plik

@ -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");
}

Wyświetl plik

@ -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 &parameter) const override;
};

Wyświetl plik

@ -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");
}

Wyświetl plik

@ -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 &parameter) const override;
};

Wyświetl plik

@ -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");
}

Wyświetl plik

@ -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 &parameter) const override;
};

51
LegendData.cpp 100644
Wyświetl plik

@ -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;
}

76
LegendData.hpp 100644
Wyświetl plik

@ -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.
};

48
LegendEntry.cpp 100644
Wyświetl plik

@ -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;
}

49
LegendEntry.hpp 100644
Wyświetl plik

@ -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;
};

303
MainWindow.cpp 100644
Wyświetl plik

@ -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);
}

89
MainWindow.hpp 100644
Wyświetl plik

@ -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.
};

Wyświetl plik

@ -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

25
OverlayMode.hpp 100644
Wyświetl plik

@ -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
};

71
OverlayPainter.cpp 100644
Wyświetl plik

@ -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);
}

106
OverlayPainter.hpp 100644
Wyświetl plik

@ -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.
};

Wyświetl plik

@ -1 +1,5 @@
# MicroPythonBitmapTool
# MicroPython Bitmap Tool
https://luckyresistor.me/applications/micropython-bitmap-tool/

BIN
data/AppIcon.icns 100644

Plik binarny nie jest wyświetlany.

BIN
data/AppIcon.ico 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 126 KiB

BIN
data/AppLogo.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 8.6 KiB

BIN
data/AppLogo@2x.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 19 KiB

BIN
data/AppLogo@3x.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 30 KiB

Wyświetl plik

@ -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;
}

10
data/data.qrc 100644
Wyświetl plik

@ -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>

38
main.cpp 100644
Wyświetl plik

@ -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();
}