Add "Align" feature

This commit is contained in:
Vladimir
2025-01-12 23:35:08 +05:00
57 changed files with 1670 additions and 335 deletions

View File

@@ -7,5 +7,5 @@ break-blocks
pad-oper
pad-header
align-pointer=name
add-brackets
add-braces
convert-tabs

View File

@@ -34,6 +34,7 @@
#include "documentoperator.h"
#include "imageinverse.h"
#include "fontresize.h"
#include "imagealign.h"
namespace AppUI
{
@@ -84,6 +85,15 @@ void ActionFontHandlers::fontResize_triggered()
}
}
void ActionFontHandlers::fontAlign_triggered()
{
if (this->editor() != nullptr) {
Operations::DocumentOperator docOp(this);
Operations::ImageAlign imageAlign(this->mMainWindow->parentWidget(), this);
docOp.apply(this->editor()->document(), imageAlign);
}
}
void ActionFontHandlers::fontPreview_triggered()
{
IEditor *editor = this->editor();

View File

@@ -43,6 +43,7 @@ public slots:
void fontChange_triggered();
void fontInverse_triggered();
void fontResize_triggered();
void fontAlign_triggered();
void fontPreview_triggered();
void fontToImage_triggered();
};

View File

@@ -31,6 +31,7 @@
#include "imageimport.h"
#include "imageexport.h"
#include "imageeditinexternaltool.h"
#include "imagealign.h"
namespace AppUI
{
@@ -184,6 +185,18 @@ void ActionImageHandlers::resize_triggered()
}
}
void ActionImageHandlers::align_triggered()
{
if (this->editor() != nullptr) {
QStringList keys = this->editor()->selectedKeys();
Operations::DocumentOperator docOp(this);
docOp.setKeys(keys);
Operations::ImageAlign imageAlign(this->mMainWindow->parentWidget(), this);
docOp.apply(this->editor()->document(), imageAlign);
}
}
void ActionImageHandlers::grayscale_triggered()
{
if (this->editor() != nullptr) {

View File

@@ -53,6 +53,7 @@ public slots:
void shift_down_triggered();
void inverse_triggered();
void resize_triggered();
void align_triggered();
void grayscale_triggered();
void import_triggered();
void export_triggered();

54
classes/data/alignmodes.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef ALIGNMODES_H
#define ALIGNMODES_H
namespace Data
{
enum class HorizontalAlignMode {
// None.
None = 0,
// To left border.
Left,
// To center (- 0.5px for odd).
CenterLeft,
// To center (+ 0.5px for odd).
CenterRight,
// To right border.
Right,
};
enum class VerticalAlignMode {
// None.
None = 0,
// To top border.
Top,
// To center (- 0.5px for odd).
CenterTop,
// To center (+ 0.5px for odd).
CenterBottom,
// To bottom border.
Bottom,
};
} // namespace Data
#endif // ALIGNMODES_H

View File

@@ -0,0 +1,70 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#include "alignmodinfo.h"
#include "alignmodes.h"
namespace Data
{
void AlignModInfo::Mods::reset()
{
this->horizontalMode = Data::HorizontalAlignMode::None;
this->verticalMode = Data::VerticalAlignMode::None;
this->horizontalOffset = 0;
this->verticalOffset = 0;
}
AlignModInfo::AlignModInfo()
{
this->mState.reset();
}
const AlignModInfo::Mods &AlignModInfo::summary() const
{
return this->mState;
}
void AlignModInfo::modify(
Data::HorizontalAlignMode horizontalMode,
int horizontalOffset,
Data::VerticalAlignMode verticalMode,
int verticalOffset)
{
this->mState.horizontalMode = horizontalMode;
this->mState.verticalMode = verticalMode;
this->mState.horizontalOffset = horizontalOffset;
this->mState.verticalOffset = verticalOffset;
}
void AlignModInfo::reset()
{
this->mState.reset();
}
const QString AlignModInfo::toString() const
{
return QString("H:%1(%2),V:%3(%4)")
.arg((int)this->mState.horizontalMode)
.arg(this->mState.horizontalOffset)
.arg((int)this->mState.verticalMode)
.arg(this->mState.verticalOffset);
}
} // namespace Data

View File

@@ -0,0 +1,66 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef ALIGNMODINFO_H
#define ALIGNMODINFO_H
class QString;
#include <QString>
namespace Data
{
enum class HorizontalAlignMode;
enum class VerticalAlignMode;
}
namespace Data
{
class AlignModInfo
{
public:
struct Mods {
Data::HorizontalAlignMode horizontalMode;
Data::VerticalAlignMode verticalMode;
int horizontalOffset;
int verticalOffset;
void reset();
};
AlignModInfo();
const Mods &summary() const;
void modify(HorizontalAlignMode horizontalMode,
int horizontalOffset,
VerticalAlignMode verticalMode,
int verticalOffset);
void reset();
const QString toString() const;
private:
Mods mState;
};
} // namespace Data
#endif // ALIGNMODINFO_H

View File

@@ -1,6 +1,6 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2016 riuson
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* This program is free software: you can redistribute it and/or modify
@@ -17,7 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include "imagesresizedproxy.h"
#include "alignmodproxy.h"
#include "alignmodinfo.h"
#include "bitmaphelper.h"
#include "imagesmodel.h"
#include <QColor>
@@ -27,16 +28,13 @@ namespace Data
namespace Models
{
ImagesResizedProxy::ImagesResizedProxy(QObject *parent)
: QSortFilterProxyModel(parent)
AlignModProxy::AlignModProxy(AlignModInfo *alignModInfo, QObject *parent)
: QSortFilterProxyModel(parent),
mAlignModInfo(alignModInfo)
{
this->mLeft = 0;
this->mRight = 0;
this->mTop = 0;
this->mBottom = 0;
}
QVariant ImagesResizedProxy::headerData(int section, Qt::Orientation orientation, int role) const
QVariant AlignModProxy::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant result = this->sourceModel()->headerData(section, orientation, role);
@@ -45,9 +43,7 @@ QVariant ImagesResizedProxy::headerData(int section, Qt::Orientation orientation
if (orientation == Qt::Horizontal) {
if (section == sourceColumns + 0) {
result = tr("Original size");
} else if (section == sourceColumns + 1) {
result = tr("New size");
result = tr("Size");
}
}
}
@@ -55,17 +51,17 @@ QVariant ImagesResizedProxy::headerData(int section, Qt::Orientation orientation
return result;
}
int ImagesResizedProxy::columnCount(const QModelIndex &parent) const
int AlignModProxy::columnCount(const QModelIndex &parent) const
{
if (this->sourceModel() == nullptr) {
return 0;
}
int sourceColumns = this->sourceModel()->columnCount(parent);
return sourceColumns + 2;
return sourceColumns + 1;
}
QVariant ImagesResizedProxy::data(const QModelIndex &index, int role) const
QVariant AlignModProxy::data(const QModelIndex &index, int role) const
{
QVariant result = this->sourceModel()->data(index, role);
@@ -80,9 +76,13 @@ QVariant ImagesResizedProxy::data(const QModelIndex &index, int role) const
case Qt::DecorationRole: {
if (columnIndex == 1) {
QImage imageSource = result.value<QImage>();
QColor backgroundColor = Parsing::Conversion::BitmapHelper::detectBackgroundColor(&imageSource);
QImage imageScaled = Parsing::Conversion::BitmapHelper::crop(&imageSource, this->mLeft, this->mTop, this->mRight, this->mBottom, backgroundColor);
result = imageScaled;
QImage imageAligned = Parsing::Conversion::BitmapHelper::align(
&imageSource,
this->mAlignModInfo->summary().horizontalMode,
this->mAlignModInfo->summary().horizontalOffset,
this->mAlignModInfo->summary().verticalMode,
this->mAlignModInfo->summary().verticalOffset);
result = imageAligned;
}
break;
@@ -91,7 +91,7 @@ QVariant ImagesResizedProxy::data(const QModelIndex &index, int role) const
case Qt::SizeHintRole: {
if (columnIndex == 1) {
QSize size = result.toSize();
result = this->resized(size);
result = size;
}
break;
@@ -102,11 +102,6 @@ QVariant ImagesResizedProxy::data(const QModelIndex &index, int role) const
QVariant varSize = this->sourceModel()->data(index, Data::Models::ImagesModel::ImageSizeRole);
QSize size = varSize.toSize();
result = QString("%1x%2").arg(size.width()).arg(size.height());
} else if (columnIndex == sourceColumns + 1) {
QVariant varSize = this->sourceModel()->data(index, Data::Models::ImagesModel::ImageSizeRole);
QSize size = varSize.toSize();
size = this->resized(size);
result = QString("%1x%2").arg(size.width()).arg(size.height());
}
break;
@@ -119,24 +114,24 @@ QVariant ImagesResizedProxy::data(const QModelIndex &index, int role) const
return result;
}
QModelIndex ImagesResizedProxy::index(int row, int column, const QModelIndex &parent) const
QModelIndex AlignModProxy::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
return this->createIndex(row, column);
}
QModelIndex ImagesResizedProxy::parent(const QModelIndex &index) const
QModelIndex AlignModProxy::parent(const QModelIndex &index) const
{
Q_UNUSED(index)
return QModelIndex();
}
QModelIndex ImagesResizedProxy::mapFromSource(const QModelIndex &sourceIndex) const
QModelIndex AlignModProxy::mapFromSource(const QModelIndex &sourceIndex) const
{
return this->index(sourceIndex.row(), sourceIndex.column(), sourceIndex.parent());
}
QModelIndex ImagesResizedProxy::mapToSource(const QModelIndex &proxyIndex) const
QModelIndex AlignModProxy::mapToSource(const QModelIndex &proxyIndex) const
{
if (sourceModel() && proxyIndex.isValid()) {
return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());
@@ -145,34 +140,12 @@ QModelIndex ImagesResizedProxy::mapToSource(const QModelIndex &proxyIndex) const
}
}
void ImagesResizedProxy::setCrop(int left, int top, int right, int bottom)
{
emit this->beginResetModel();
this->mLeft = left;
this->mTop = top;
this->mRight = right;
this->mBottom = bottom;
emit this->endResetModel();
}
const QSize ImagesResizedProxy::resized(const QSize &value) const
{
QSize result = value;
result.rwidth() += this->mLeft + this->mRight;
result.rheight() += this->mTop + this->mBottom;
if (result.height() < 1) {
result.setHeight(1);
}
if (result.width() < 1) {
result.setWidth(1);
}
return result;
}
// void AlignModProxy::notifyPreviewChanged()
// {
// emit this->dataChanged(
// index(0, 1),
// index(this->rowCount() - 1, 1));
// }
} // namespace Models
} // namespace Data

View File

@@ -1,6 +1,6 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2016 riuson
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* This program is free software: you can redistribute it and/or modify
@@ -17,23 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#ifndef IMAGESRESIZEDPROXY_H
#define IMAGESRESIZEDPROXY_H
#ifndef ALIGNMODPROXY_H
#define ALIGNMODPROXY_H
#include <QSortFilterProxyModel>
template <class Key, class Value> class QMap;
namespace Data
{
class AlignModInfo;
namespace Models
{
class ImagesResizedProxy : public QSortFilterProxyModel
class AlignModProxy : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit ImagesResizedProxy(QObject *parent = 0);
virtual ~ImagesResizedProxy() {}
explicit AlignModProxy(
Data::AlignModInfo *alignModInfo,
QObject *parent = nullptr);
virtual ~AlignModProxy() Q_DECL_OVERRIDE {}
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
@@ -44,18 +50,13 @@ public:
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE;
QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE;
void setCrop(int left, int top, int right, int bottom);
// void notifyPreviewChanged();
private:
int mLeft;
int mRight;
int mTop;
int mBottom;
const QSize resized(const QSize &value) const;
Data::AlignModInfo *mAlignModInfo;
};
} // namespace Models
} // namespace Data
#endif // IMAGESRESIZEDPROXY_H
#endif // ALIGNMODPROXY_H

View File

@@ -1,3 +1,22 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2019 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#include "canvasmodinfo.h"
namespace Data

View File

@@ -1,3 +1,22 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2019 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef CANVASMODINFO_H
#define CANVASMODINFO_H

View File

@@ -0,0 +1,75 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#include "imagealign.h"
#include "dialogalign.h"
#include "idocument.h"
#include "datacontainer.h"
#include "bitmaphelper.h"
#include "alignmodes.h"
#include "alignmodinfo.h"
namespace Operations
{
ImageAlign::ImageAlign(QWidget *parentWidget, QObject *parent)
: QObject(parent)
{
this->mParentWidget = parentWidget;
}
bool ImageAlign::prepare(const Data::Containers::IDocument *doc, const QStringList &keys)
{
AppUI::CommonDialogs::DialogAlign dialog(
doc->dataContainer(),
keys,
this->mParentWidget);
if (dialog.exec() == QDialog::Accepted) {
const Data::AlignModInfo *modInfo = dialog.alignInfo();
this->mMods = modInfo->summary();
return true;
}
return false;
}
void ImageAlign::applyDocument(Data::Containers::IDocument *doc, const QStringList &keys)
{
Q_UNUSED(doc)
Q_UNUSED(keys)
}
void ImageAlign::applyItem(Data::Containers::IDocument *doc, const QString &itemKey)
{
if (this->mMods.horizontalMode != Data::HorizontalAlignMode::None ||
this->mMods.verticalMode != Data::VerticalAlignMode::None) {
Data::AlignModInfo::Mods mods = this->mMods;
const QImage *original = doc->dataContainer()->image(itemKey);
QImage result = Parsing::Conversion::BitmapHelper::align(
original,
mods.horizontalMode,
mods.horizontalOffset,
mods.verticalMode,
mods.verticalOffset);
doc->dataContainer()->setImage(itemKey, &result);
}
}
} // namespace Operations

View File

@@ -0,0 +1,51 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef IMAGEALIGN_H
#define IMAGEALIGN_H
#include <QWidget>
#include <QMap>
#include "ioperation.h"
#include "alignmodinfo.h"
namespace Operations
{
class ImageAlign : public QObject, public IOperation
{
Q_OBJECT
Q_INTERFACES(Operations::IOperation)
public:
explicit ImageAlign(QWidget *parentWidget = 0, QObject *parent = 0);
virtual ~ImageAlign() {}
bool prepare(const Data::Containers::IDocument *doc, const QStringList &keys) Q_DECL_OVERRIDE;
void applyDocument(Data::Containers::IDocument *doc, const QStringList &keys) Q_DECL_OVERRIDE;
void applyItem(Data::Containers::IDocument *doc, const QString &itemKey) Q_DECL_OVERRIDE;
protected:
QWidget *mParentWidget;
Data::AlignModInfo::Mods mMods;
};
} // namespace Operations
#endif // IMAGEALIGN_H

View File

@@ -50,19 +50,19 @@ void ImageShift::applyItem(Data::Containers::IDocument *doc, const QString &item
switch (this->mDirection) {
case Direction::Left:
result = Parsing::Conversion::BitmapHelper::shiftLeft(original);
result = Parsing::Conversion::BitmapHelper::shift(original, -1, 0);
break;
case Direction::Right:
result = Parsing::Conversion::BitmapHelper::shiftRight(original);
result = Parsing::Conversion::BitmapHelper::shift(original, 1, 0);
break;
case Direction::Up:
result = Parsing::Conversion::BitmapHelper::shiftUp(original);
result = Parsing::Conversion::BitmapHelper::shift(original, 0, -1);
break;
case Direction::Down:
result = Parsing::Conversion::BitmapHelper::shiftDown(original);
result = Parsing::Conversion::BitmapHelper::shift(original, 0, 1);
break;
case Direction::None:

View File

@@ -18,6 +18,7 @@
*/
#include "bitmaphelper.h"
#include "alignmodes.h"
#include "limits"
#include <QPainter>
@@ -103,6 +104,38 @@ QImage BitmapHelper::shiftLeft(const QImage *source)
return result;
}
template <typename T> int sgn(T val)
{
return (T(0) < val) - (val < T(0));
}
QImage BitmapHelper::shift(const QImage *source, int horizontalDirection, int verticalDirection)
{
QImage result = QImage(source->width(), source->height(), source->format());
result.fill(QColor(0, 0, 0, 0));
int width = source->width();
int height = source->height();
horizontalDirection %= width;
verticalDirection %= height;
QPainter painter(&result);
for (int i = 0; i < 3; i++) {
int x = -width + (width * i) + horizontalDirection;
for (int j = 0; j < 3; j++) {
int y = -height + (height * j) + verticalDirection;
painter.drawImage(
x,
y,
*source);
}
}
return result;
}
QImage BitmapHelper::flipHorizontal(const QImage *source)
{
QImage result = source->mirrored(true, false);
@@ -315,5 +348,88 @@ QColor BitmapHelper::fromRgba(QRgb value)
return QColor(qRed(value), qGreen(value), qBlue(value), qAlpha(value));
}
QImage BitmapHelper::align(
const QImage *source,
Data::HorizontalAlignMode horizontalMode,
int horizontalOffset,
Data::VerticalAlignMode verticalMode,
int verticalOffset)
{
int l, t, r, b;
bool hEmpty, vEmpty;
Parsing::Conversion::BitmapHelper::findEmptyArea(source, l, t, r, b, hEmpty, vEmpty);
int moveX = 0;
int moveY = 0;
switch (horizontalMode) {
case Data::HorizontalAlignMode::Left:
moveX = -l + horizontalOffset;
break;
case Data::HorizontalAlignMode::CenterLeft: {
int space = l + r;
moveX = (space / 2) - horizontalOffset - l;
break;
}
case Data::HorizontalAlignMode::CenterRight: {
int space = l + r;
if ((space & 1) == 0) {
moveX = (space / 2) + horizontalOffset - l;
} else {
moveX = (space / 2) + 1 + horizontalOffset - l;
}
break;
}
case Data::HorizontalAlignMode::Right:
moveX = r - horizontalOffset;
break;
case Data::HorizontalAlignMode::None:
default:
break;
}
switch (verticalMode) {
case Data::VerticalAlignMode::Top:
moveY = -t + verticalOffset;
break;
case Data::VerticalAlignMode::CenterTop: {
int space = t + b;
moveY = (space / 2) - verticalOffset - t;
break;
}
case Data::VerticalAlignMode::CenterBottom: {
int space = t + b;
if ((space & 1) == 0) {
moveY = (space / 2) + verticalOffset - t;
} else {
moveY = (space / 2) + 1 + verticalOffset - t;
}
break;
}
case Data::VerticalAlignMode::Bottom:
moveY = b - verticalOffset;
break;
case Data::VerticalAlignMode::None:
default:
break;
}
QImage result = shift(source, moveX, moveY);
return result;
}
} // namespace Conversion
} // namespace Parsing

View File

@@ -27,17 +27,16 @@
class QFontMetrics;
class QPainterPath;
namespace Data
{
enum class HorizontalAlignMode;
enum class VerticalAlignMode;
}
namespace Parsing
{
namespace Conversion
{
typedef struct {
int width;
int height;
int offsetX;
int offsetY;
bool center;
} tResizeInfo;
class BitmapHelper
{
@@ -45,10 +44,11 @@ public:
static QImage rotate90(const QImage *source);
static QImage rotate180(const QImage *source);
static QImage rotate270(const QImage *source);
static QImage shiftUp(const QImage *source);
static QImage shiftRight(const QImage *source);
static QImage shiftDown(const QImage *source);
static QImage shiftLeft(const QImage *source);
Q_DECL_DEPRECATED static QImage shiftUp(const QImage *source);
Q_DECL_DEPRECATED static QImage shiftRight(const QImage *source);
Q_DECL_DEPRECATED static QImage shiftDown(const QImage *source);
Q_DECL_DEPRECATED static QImage shiftLeft(const QImage *source);
static QImage shift(const QImage *source, int horizontalDirection, int verticalDirection);
static QImage flipHorizontal(const QImage *source);
static QImage flipVertical(const QImage *source);
static QImage crop(const QImage *source, int left, int top, int right, int bottom, const QColor &backColor);
@@ -60,6 +60,12 @@ public:
static QColor detectBackgroundColor(const QImage *image);
static QImage fromSvg(const QString &path, int size);
static QColor fromRgba(QRgb value);
static QImage align(
const QImage *source,
Data::HorizontalAlignMode horizontalMode,
int horizontalOffset,
Data::VerticalAlignMode verticalMode,
int verticalOffset);
};
} // namespace Conversion

View File

@@ -267,10 +267,8 @@ void ConverterHelper::processPixels(Settings::Presets::Preset *preset, QVector<q
void ConverterHelper::packData(
Settings::Presets::Preset *preset,
QVector<quint32> *inputData, int inputWidth, int inputHeight,
QVector<quint32> *outputData,
int *outputWidth, int *outputHeight)
QVector<quint32> *outputData)
{
*outputHeight = inputHeight;
outputData->clear();
int resultWidth = 0;
@@ -298,8 +296,6 @@ void ConverterHelper::packData(
// get row blocks count
resultWidth = qMax(resultWidth, rowLength);
}
*outputWidth = resultWidth;
} else {
/* Number_Of_Rows equals to Height
*
@@ -319,28 +315,19 @@ void ConverterHelper::packData(
// get row blocks count
resultWidth = qMax(resultWidth, rowLength);
}
*outputWidth = resultWidth;
}
} else {
// All data in one row
// process entire data
ConverterHelper::packDataRow(preset, inputData, 0, inputData->size(), outputData, &rowLength);
// get blocks count
*outputWidth = rowLength;
*outputHeight = 1;
}
}
void ConverterHelper::reorder(
Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
int inputWidth,
int inputHeight,
QVector<quint32> *outputData,
int *outputWidth,
int *outputHeight)
QVector<quint32> *outputData)
{
for (int i = 0; i < inputData->size(); i++) {
quint32 value = inputData->at(i);
@@ -365,29 +352,19 @@ void ConverterHelper::reorder(
outputData->append(valueNew);
}
*outputWidth = inputWidth;
*outputHeight = inputHeight;
}
void ConverterHelper::compressData(Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
int inputWidth, int inputHeight,
QVector<quint32> *outputData,
int *outputWidth, int *outputHeight)
QVector<quint32> *outputData)
{
if (preset->image()->compressionRle()) {
Utils::Compression::RleCompressor compressor;
compressor.compress(inputData, preset->image()->blockSize(), outputData, preset->image()->compressionRleMinLength());
*outputWidth = outputData->size();
*outputHeight = 1;
} else {
for (int i = 0; i < inputData->size(); i++) {
outputData->append(inputData->at(i));
}
*outputWidth = inputWidth;
*outputHeight = inputHeight;
}
}
@@ -613,15 +590,11 @@ QString ConverterHelper::uint2string(Settings::Presets::DataNumeralSystem numera
QString ConverterHelper::dataToString(
Settings::Presets::Preset *preset,
QVector<quint32> *data, int width, int height)
QVector<quint32> *data)
{
QString result, converted;
int blockPerLine = width;
if (preset->image()->blocksPerLine() > 0) {
blockPerLine = preset->image()->blocksPerLine();
}
int blockPerLine = preset->image()->blocksPerLine();
Settings::Presets::DataBlockSize blockSize = preset->image()->blockSize();
QString prefix = preset->image()->blockPrefix();
@@ -630,8 +603,10 @@ QString ConverterHelper::dataToString(
Settings::Presets::DataNumeralSystem numeralSystem = preset->image()->numeralSystem();
for (auto i = 0; i < data->size(); i++) {
if ((i > 0) && ((i % blockPerLine) == 0)) {
result.append("\n");
if (blockPerLine > 0) {
if ((i > 0) && ((i % blockPerLine) == 0)) {
result.append("\n");
}
}
quint32 value = data->at(i);

View File

@@ -58,30 +58,28 @@ public:
static void processPixels(Settings::Presets:: Preset *preset, QVector<quint32> *data);
// pack data
static void packData(
Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
int inputWidth,
int inputHeight,
QVector<quint32> *outputData,
int *outputWidth,
int *outputHeight);
Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
int inputWidth,
int inputHeight,
QVector<quint32> *outputData);
// bits reordering
static void reorder(
Settings::Presets::Preset *preset,
QVector<quint32> *inputData, int inputWidth, int inputHeight,
QVector<quint32> *outputData, int *outputWidth, int *outputHeight);
Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
QVector<quint32> *outputData);
static void compressData(
Settings::Presets::Preset *preset,
QVector<quint32> *inputData, int inputWidth, int inputHeight,
QVector<quint32> *outputData, int *outputWidth, int *outputHeight);
Settings::Presets::Preset *preset,
QVector<quint32> *inputData,
QVector<quint32> *outputData);
static void prepareImage(Settings::Presets::Preset *preset, const QImage *source, QImage *result);
static void createImagePreview(Settings::Presets::Preset *preset, QImage *source, QImage *result);
static QString uint2string(Settings::Presets::DataNumeralSystem numeralSystem, Settings::Presets::DataBlockSize blockSize, quint32 value);
static QString dataToString(Settings::Presets::Preset *preset,
QVector<quint32> *data, int width, int height);
QVector<quint32> *data);
static QString previewDataToString(Settings::Presets::Preset *preset,
const QVector<quint32> *data, int width, int height);

View File

@@ -90,35 +90,28 @@ ParsedImageData::ParsedImageData(Settings::Presets::Preset *preset, const QImage
Parsing::Conversion::ConverterHelper::processPixels(preset, &sourceData);
QVector<quint32> packedData;
int packedWidth, packedHeight;
Parsing::Conversion::ConverterHelper::packData(
preset,
&sourceData, sourceWidth, sourceHeight,
&packedData, &packedWidth, &packedHeight);
&packedData);
QVector<quint32> reorderedData;
int reorderedWidth, reorderedHeight;
Parsing::Conversion::ConverterHelper::reorder(
preset,
&packedData, packedWidth, packedHeight,
&reorderedData, &reorderedWidth, &reorderedHeight);
&packedData,
&reorderedData);
QVector<quint32> compressedData;
int compressedWidth, compressedHeight;
Parsing::Conversion::ConverterHelper::compressData(
preset,
&reorderedData,
reorderedWidth,
reorderedHeight,
&compressedData,
&compressedWidth,
&compressedHeight);
&compressedData);
this->mTags->setTagValue(TagsList::Tag::OutputBlocksCount, QString("%1").arg(compressedData.size()));
this->mPreparedOutputImageData = Parsing::Conversion::ConverterHelper::dataToString(
preset,
&compressedData, compressedWidth, compressedHeight);
&compressedData);
// get hash
QString hashStr = QString("data: %1, width: %2, height: %3").arg(this->mPreparedOutputImageData).arg(image->width()).arg(image->height());

View File

@@ -0,0 +1,53 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#include "alignsettings.h"
#include <QVariant>
#include <appsettings.h>
namespace Settings
{
int AlignSettings::scale()
{
AppSettings appsett;
QSettings &sett = appsett.get();
sett.beginGroup("align-preview");
bool ok;
int result = sett.value("scale", QVariant(1)).toInt(&ok);
sett.endGroup();
if (ok) {
return result;
}
return 1;
}
void AlignSettings::setScale(int value)
{
AppSettings appsett;
QSettings &sett = appsett.get();
sett.beginGroup("align-preview");
sett.setValue("scale", QVariant(value));
sett.endGroup();
}
} // namespace Settings

View File

@@ -0,0 +1,34 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2022 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef ALIGNSETTINGS_H
#define ALIGNSETTINGS_H
namespace Settings
{
class AlignSettings{
public:
static int scale();
static void setScale(int value);
};
} // namespace Settings
#endif // ALIGNSETTINGS_H

View File

@@ -55,7 +55,7 @@ ImageOptions::ImageOptions(QObject *parent) :
this->mBlockDefaultOnes = false;
this->mCompressionRle = false;
this->mCompressionRleMinLength = 2;
this->mBlocksPerLine = 8;
this->mBlocksPerLine = 0;
this->mBlockPrefix = "0x";
this->mBlockSuffix = "";
this->mBlockDelimiter = ", ";

View File

@@ -0,0 +1,182 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2013 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#include "dialogalign.h"
#include "ui_dialogalign.h"
#include <QItemSelectionModel>
#include <QMap>
#include <QWheelEvent>
#include "alignmodes.h"
#include "alignmodinfo.h"
#include "alignmodproxy.h"
#include "imagesmodel.h"
#include "imagesscaledproxy.h"
#include "imagesfilterproxy.h"
#include "transposeproxy.h"
#include "columnsreorderproxy.h"
#include "alignsettings.h"
#include "datacontainer.h"
#include "bitmaphelper.h"
namespace AppUI
{
namespace CommonDialogs
{
DialogAlign::DialogAlign(Data::Containers::DataContainer *container,
const QStringList &keys,
QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogAlign),
mKeys(keys)
{
ui->setupUi(this);
this->mContainer = container;
this->mAlignModInfo = new Data::AlignModInfo();
this->mModel = new Data::Models::ImagesModel(container, this);
this->mAlignMod = new Data::Models::AlignModProxy(this->mAlignModInfo, this);
this->mAlignMod->setSourceModel(this->mModel);
this->mScaledProxy = new Data::Models::ImagesScaledProxy(this);
this->mScaledProxy->setSourceModel(this->mAlignMod);
this->mFilter = new Data::Models::ImagesFilterProxy(this);
this->mFilter->setSourceModel(this->mScaledProxy);
this->mFilter->setFilter(this->mKeys);
this->mReorderProxy = new Data::Models::ColumnsReorderProxy();
this->mReorderProxy->setSourceModel(this->mFilter);
this->mReorderProxy->setReorder(1, 2);
this->mTranspose = new Data::Models::TransposeProxy(this);
this->mTranspose->setSourceModel(this->mReorderProxy);
this->ui->tableView->setModel(this->mTranspose);
this->ui->comboBoxHorizontalMode->addItem(tr("None"), QVariant((int)Data::HorizontalAlignMode::None));
this->ui->comboBoxHorizontalMode->addItem(tr("Left"), QVariant((int)Data::HorizontalAlignMode::Left));
this->ui->comboBoxHorizontalMode->addItem(tr("Center Left"), QVariant((int)Data::HorizontalAlignMode::CenterLeft));
this->ui->comboBoxHorizontalMode->addItem(tr("Center Right"), QVariant((int)Data::HorizontalAlignMode::CenterRight));
this->ui->comboBoxHorizontalMode->addItem(tr("Right"), QVariant((int)Data::HorizontalAlignMode::Right));
this->ui->comboBoxVerticalMode->addItem(tr("None"), QVariant((int)Data::VerticalAlignMode::None));
this->ui->comboBoxVerticalMode->addItem(tr("Top"), QVariant((int)Data::VerticalAlignMode::Top));
this->ui->comboBoxVerticalMode->addItem(tr("Center Top"), QVariant((int)Data::VerticalAlignMode::CenterTop));
this->ui->comboBoxVerticalMode->addItem(tr("Center Bottom"), QVariant((int)Data::VerticalAlignMode::CenterBottom));
this->ui->comboBoxVerticalMode->addItem(tr("Bottom"), QVariant((int)Data::VerticalAlignMode::Bottom));
this->connect(this->ui->comboBoxHorizontalMode, SIGNAL(currentIndexChanged(int)), SLOT(operationValuesChanged(int)));
this->connect(this->ui->comboBoxVerticalMode, SIGNAL(currentIndexChanged(int)), SLOT(operationValuesChanged(int)));
this->connect(this->ui->spinBoxHorizontalOffset, SIGNAL(valueChanged(int)), SLOT(operationValuesChanged(int)));
this->connect(this->ui->spinBoxVerticalOffset, SIGNAL(valueChanged(int)), SLOT(operationValuesChanged(int)));
this->connect(this->ui->spinBoxScale, SIGNAL(valueChanged(int)), this->mScaledProxy, SLOT(setScale(int)));
this->connect(this->mScaledProxy, SIGNAL(scaleChanged(int)), SLOT(on_scaleChanged(int)));
int scale = Settings::AlignSettings::scale();
this->mScaledProxy->setScale(scale);
this->on_scaleChanged(scale);
}
DialogAlign::~DialogAlign()
{
Settings::AlignSettings::setScale(this->ui->spinBoxScale->value());
delete this->mAlignModInfo;
delete ui;
}
const Data::AlignModInfo *DialogAlign::alignInfo() const
{
return this->mAlignModInfo;
}
void DialogAlign::wheelEvent(QWheelEvent *event)
{
if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) {
QPoint point = event->globalPosition().toPoint();
point = this->mapFromGlobal(point);
if (qAbs(event->angleDelta().x()) < qAbs(event->angleDelta().y())) {
int scale = this->mScaledProxy->scale();
if (event->angleDelta().y() > 0) {
scale++;
} else {
scale--;
}
this->mScaledProxy->setScale(scale);
}
event->accept();
}
}
void DialogAlign::operationValuesChanged(int value)
{
Q_UNUSED(value);
QVariant data = this->ui->comboBoxHorizontalMode->itemData(this->ui->comboBoxHorizontalMode->currentIndex());
bool isHorizontalOffsetOk;
int horizontalMode = data.toInt(&isHorizontalOffsetOk);
data = this->ui->comboBoxVerticalMode->itemData(this->ui->comboBoxVerticalMode->currentIndex());
bool isVerticalOffsetOk;
int verticalMode = data.toInt(&isVerticalOffsetOk);
if (isHorizontalOffsetOk && isVerticalOffsetOk) {
int horizontalOffset = this->ui->spinBoxHorizontalOffset->value();
int verticalOffset = this->ui->spinBoxVerticalOffset->value();
this->mAlignModInfo->modify(
(Data::HorizontalAlignMode)horizontalMode,
horizontalOffset,
(Data::VerticalAlignMode)verticalMode,
verticalOffset);
// TODO: Workaround for TableView update.
auto focused = this->focusWidget();
this->ui->spinBoxHorizontalOffset->setFocus();
this->ui->tableView->setFocus();
focused->setFocus();
// this->resizeToContents();
}
}
void DialogAlign::resizeToContents()
{
this->ui->tableView->resizeRowsToContents();
this->ui->tableView->resizeColumnsToContents();
}
void DialogAlign::on_scaleChanged(int value)
{
if (this->ui->spinBoxScale->value() != value) {
this->ui->spinBoxScale->setValue(value);
}
this->resizeToContents();
}
} // namespace CommonDialogs
} // namespace AppUI

View File

@@ -0,0 +1,96 @@
/*
* LCD Image Converter. Converts images and fonts for embedded applications.
* Copyright (C) 2013 riuson
* mailto: riuson@gmail.com
*
* 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 <http://www.gnu.org/licenses/
*/
#ifndef DIALOGCANVASRESIZE_H
#define DIALOGCANVASRESIZE_H
#include <QDialog>
template <class Key, class Value> class QMap;
namespace Ui
{
class DialogAlign;
}
class QItemSelection;
namespace Data
{
namespace Containers
{
class DataContainer;
}
namespace Models
{
class ImagesModel;
class ImagesScaledProxy;
class ImagesFilterProxy;
class ColumnsReorderProxy;
class TransposeProxy;
class AlignModProxy;
}
class AlignModInfo;
}
namespace AppUI
{
namespace CommonDialogs
{
class DialogAlign : public QDialog
{
Q_OBJECT
public:
explicit DialogAlign(
Data::Containers::DataContainer *container,
const QStringList &keys,
QWidget *parent = nullptr);
virtual ~DialogAlign() Q_DECL_OVERRIDE;
const Data::AlignModInfo *alignInfo() const;
protected:
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
private:
Ui::DialogAlign *ui;
Data::Containers::DataContainer *mContainer;
Data::Models::ImagesModel *mModel;
Data::Models::ImagesScaledProxy *mScaledProxy;
Data::Models::ImagesFilterProxy *mFilter;
Data::Models::ColumnsReorderProxy *mReorderProxy;
Data::Models::TransposeProxy *mTranspose;
Data::Models::AlignModProxy *mAlignMod;
const QStringList &mKeys;
Data::AlignModInfo *mAlignModInfo;
private slots:
void operationValuesChanged(int value);
void resizeToContents();
void on_scaleChanged(int value);
};
} // namespace CommonDialogs
} // namespace AppUI
#endif // DIALOGCANVASRESIZE_H

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogAlign</class>
<widget class="QDialog" name="DialogAlign">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>757</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Align</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mode:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Offset:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="spinBoxScale">
<property name="suffix">
<string notr="true"> x</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Horizontal:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxHorizontalMode"/>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="spinBoxHorizontalOffset">
<property name="suffix">
<string notr="true"> px</string>
</property>
<property name="minimum">
<number>-65535</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Vertical:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxVerticalMode"/>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="spinBoxVerticalOffset">
<property name="suffix">
<string notr="true"> px</string>
</property>
<property name="minimum">
<number>-65535</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableView" name="tableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogAlign</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>378</x>
<y>458</y>
</hint>
<hint type="destinationlabel">
<x>378</x>
<y>239</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogAlign</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>378</x>
<y>458</y>
</hint>
<hint type="destinationlabel">
<x>378</x>
<y>239</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -232,6 +232,7 @@ void MainWindow::createHandlers()
this->mImageHandlers->connect(this->ui->actionImageShiftDown, SIGNAL(triggered()), SLOT(shift_down_triggered()));
this->mImageHandlers->connect(this->ui->actionImageInverse, SIGNAL(triggered()), SLOT(inverse_triggered()));
this->mImageHandlers->connect(this->ui->actionImageResize, SIGNAL(triggered()), SLOT(resize_triggered()));
this->mImageHandlers->connect(this->ui->actionImageAlign, SIGNAL(triggered()), SLOT(align_triggered()));
this->mImageHandlers->connect(this->ui->actionImageTo_Grayscale, SIGNAL(triggered()), SLOT(grayscale_triggered()));
this->mImageHandlers->connect(this->ui->actionImageImport, SIGNAL(triggered()), SLOT(import_triggered()));
this->mImageHandlers->connect(this->ui->actionImageExport, SIGNAL(triggered()), SLOT(export_triggered()));
@@ -241,6 +242,7 @@ void MainWindow::createHandlers()
this->mFontHandlers->connect(this->ui->actionFontChange, SIGNAL(triggered()), SLOT(fontChange_triggered()));
this->mFontHandlers->connect(this->ui->actionFontInverse, SIGNAL(triggered()), SLOT(fontInverse_triggered()));
this->mFontHandlers->connect(this->ui->actionFontResize, SIGNAL(triggered()), SLOT(fontResize_triggered()));
this->mFontHandlers->connect(this->ui->actionFontAlign, SIGNAL(triggered()), SLOT(fontAlign_triggered()));
this->mFontHandlers->connect(this->ui->actionFontPreview, SIGNAL(triggered()), SLOT(fontPreview_triggered()));
this->mFontHandlers->connect(this->ui->actionFontToImage, SIGNAL(triggered()), SLOT(fontToImage_triggered()));

View File

@@ -90,6 +90,7 @@
<addaction name="menuShift"/>
<addaction name="menuRotate"/>
<addaction name="actionImageResize"/>
<addaction name="actionImageAlign"/>
<addaction name="actionImageInverse"/>
<addaction name="actionImageTo_Grayscale"/>
<addaction name="separator"/>
@@ -104,6 +105,7 @@
<addaction name="actionFontChange"/>
<addaction name="separator"/>
<addaction name="actionFontResize"/>
<addaction name="actionFontAlign"/>
<addaction name="actionFontInverse"/>
<addaction name="actionFontPreview"/>
<addaction name="actionFontToImage"/>
@@ -427,6 +429,16 @@
<string>Close All</string>
</property>
</action>
<action name="actionImageAlign">
<property name="text">
<string>Align...</string>
</property>
</action>
<action name="actionFontAlign">
<property name="text">
<string>Align...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>

View File

@@ -27,7 +27,6 @@
#include "canvasmodproxy.h"
#include "imagesmodel.h"
#include "imagesscaledproxy.h"
#include "imagesresizedproxy.h"
#include "imagesfilterproxy.h"
#include "transposeproxy.h"
#include "columnsreorderproxy.h"

View File

@@ -96,20 +96,17 @@ void DialogPreview::updatePreview()
Parsing::Conversion::ConverterHelper::processPixels(this->mPreset, &sourceData);
QVector<quint32> packedData;
int packedWidth, packedHeight;
Parsing::Conversion::ConverterHelper::packData(this->mPreset, &sourceData, sourceWidth, sourceHeight, &packedData, &packedWidth, &packedHeight);
Parsing::Conversion::ConverterHelper::packData(this->mPreset, &sourceData, sourceWidth, sourceHeight, &packedData);
QVector<quint32> reorderedData;
int reorderedWidth, reorderedHeight;
Parsing::Conversion::ConverterHelper::reorder(this->mPreset, &packedData, packedWidth, packedHeight, &reorderedData, &reorderedWidth, &reorderedHeight);
Parsing::Conversion::ConverterHelper::reorder(this->mPreset, &packedData, &reorderedData);
QVector<quint32> compressedData;
int compressedWidth, compressedHeight;
Parsing::Conversion::ConverterHelper::compressData(this->mPreset, &reorderedData, reorderedWidth, reorderedHeight, &compressedData, &compressedWidth, &compressedHeight);
Parsing::Conversion::ConverterHelper::compressData(this->mPreset, &reorderedData, &compressedData);
QString dataString = Parsing::Conversion::ConverterHelper::dataToString(
this->mPreset,
&compressedData, compressedWidth, compressedHeight);
&compressedData);
this->ui->plainTextEdit->setPlainText(dataString);
}

View File

@@ -51,6 +51,9 @@ SetupTabImage::SetupTabImage(Settings::Presets::Preset *preset, QWidget *parent)
this->ui->comboBoxNumeralSystem->addItem(tr("Decimal"), static_cast<int>(Parsing::Conversion::Options::DataNumeralSystem::Decimal));
this->ui->comboBoxNumeralSystem->addItem(tr("Hecadecimal"), static_cast<int>(Parsing::Conversion::Options::DataNumeralSystem::Hexadecimal));
this->ui->checkBoxSplitToRows->setToolTip(tr("Check to split data by rows/bands on packing."));
this->ui->spinBoxBlocksPerLine->setToolTip(tr("Number of blocks per line code. 0 to single line."));
this->matrixChanged();
}

View File

@@ -68,6 +68,8 @@ SOURCES += main.cpp \
classes/cmdline/modeparserbase.cpp \
classes/compression/rlecompressor.cpp \
classes/compression/rlesequence.cpp \
classes/data/alignmodinfo.cpp \
classes/data/alignmodproxy.cpp \
classes/data/canvasmodinfo.cpp \
classes/data/canvasmodproxy.cpp \
classes/data/datacontainer.cpp \
@@ -91,6 +93,7 @@ SOURCES += main.cpp \
classes/imageeditor/toolzoom.cpp \
classes/operations/documentoperator.cpp \
classes/operations/fontresize.cpp \
classes/operations/imagealign.cpp \
classes/operations/imageeditinexternaltool.cpp \
classes/operations/imageexport.cpp \
classes/operations/imageflip.cpp \
@@ -109,6 +112,7 @@ SOURCES += main.cpp \
classes/parser/parsedimagedata.cpp \
classes/parser/parser.cpp \
classes/parser/tagslist.cpp \
classes/settings/alignsettings.cpp \
classes/settings/appsettings.cpp \
classes/settings/conversionpreviewoptions.cpp \
classes/settings/externaltooloptions.cpp \
@@ -129,6 +133,7 @@ SOURCES += main.cpp \
classes/status/statusdata.cpp \
classes/status/statusmanager.cpp \
controls/about/dialogabout.cpp \
controls/align/dialogalign.cpp \
controls/fonts/font-changed/dialogfontchanged.cpp \
controls/fonts/font-editor/editortabfont.cpp \
controls/fonts/font-new/charactersmodel.cpp \
@@ -146,7 +151,6 @@ SOURCES += main.cpp \
controls/resize/columnsreorderproxy.cpp \
controls/resize/dialogcanvasresize.cpp \
controls/resize/imagesfilterproxy.cpp \
controls/resize/imagesresizedproxy.cpp \
controls/save-changes/dialogsavechanges.cpp \
controls/setup/dialogexternaleditor.cpp \
controls/setup/dialogoptions.cpp \
@@ -182,6 +186,9 @@ HEADERS += \
classes/cmdline/modeparserbase.h \
classes/compression/rlecompressor.h \
classes/compression/rlesequence.h \
classes/data/alignmodes.h \
classes/data/alignmodinfo.h \
classes/data/alignmodproxy.h \
classes/data/canvasmodinfo.h \
classes/data/canvasmodproxy.h \
classes/data/datacontainer.h \
@@ -211,6 +218,7 @@ HEADERS += \
classes/imageeditor/toolzoom.h \
classes/operations/documentoperator.h \
classes/operations/fontresize.h \
classes/operations/imagealign.h \
classes/operations/imageeditinexternaltool.h \
classes/operations/imageexport.h \
classes/operations/imageflip.h \
@@ -231,6 +239,7 @@ HEADERS += \
classes/parser/parsedimagedata.h \
classes/parser/parser.h \
classes/parser/tagslist.h \
classes/settings/alignsettings.h \
classes/settings/appsettings.h \
classes/settings/conversionpreviewoptions.h \
classes/settings/externaltooloptions.h \
@@ -252,6 +261,7 @@ HEADERS += \
classes/status/statusdata.h \
classes/status/statusmanager.h \
controls/about/dialogabout.h \
controls/align/dialogalign.h \
controls/fonts/font-changed/dialogfontchanged.h \
controls/fonts/font-editor/editortabfont.h \
controls/fonts/font-new/charactersmodel.h \
@@ -269,7 +279,6 @@ HEADERS += \
controls/resize/columnsreorderproxy.h \
controls/resize/dialogcanvasresize.h \
controls/resize/imagesfilterproxy.h \
controls/resize/imagesresizedproxy.h \
controls/save-changes/dialogsavechanges.h \
controls/setup/dialogexternaleditor.h \
controls/setup/dialogoptions.h \
@@ -296,6 +305,7 @@ HEADERS += \
FORMS += \
controls/about/dialogabout.ui \
controls/align/dialogalign.ui \
controls/fonts/font-changed/dialogfontchanged.ui \
controls/fonts/font-editor/editortabfont.ui \
controls/fonts/font-new/dialogfontselect.ui \
@@ -336,6 +346,7 @@ INCLUDEPATH += $$PWD \
$$PWD/classes/settings/presets \
$$PWD/controls \
$$PWD/controls/about \
$$PWD/controls/align \
$$PWD/controls/fonts/font-changed \
$$PWD/controls/fonts/font-editor \
$$PWD/controls/fonts/font-new \

View File

@@ -18,8 +18,10 @@
<item category="added">Added glyph's size calculation for new font.</item>
<item category="added">Added selection of size units for font - pixels or points.</item>
<item category="added">Added tag fnt_size_units - px or pt.</item>
<item category="added">Added align operation.</item>
<item category="changed">Minimal required Qt version 5.15.</item>
<item category="changed">Number of blocks per code line is configured by user.</item>
<item category="changed">SplitToRows is only used to pack pixel data into blocks. Splitting blocks into lines of code uses BlocksPerCodeLine.</item>
<item category="fixed">Fix including QPainterPath header.</item>
<item category="fixed">Don't translate default preset names.</item>
<item category="fixed">Using character code direct, when character cannot be presented with selected encoding.</item>

View File

@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>AlignModProxy</name>
<message>
<location filename="../classes/data/alignmodproxy.cpp" line="46"/>
<source>Size</source>
<translation>Размер</translation>
</message>
</context>
<context>
<name>AppUI::CommonDialogs::DialogSaveChanges</name>
<message>
@@ -22,23 +30,23 @@
<context>
<name>AppUI::Fonts::DialogFontSelect</name>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="398"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="399"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="428"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="429"/>
<source>Max size (w × h): %1 × %2</source>
<translation>Макс размер (w × h): %1 × %2</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="397"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="427"/>
<source>Count: %1</source>
<translation>Количество: %1</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="407"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="437"/>
<source>Fore Color: %1</source>
<translation>Цвет переднего плана: %1</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="412"/>
<location filename="../controls/fonts/font-new/dialogfontselect.cpp" line="442"/>
<source>Back Color: %1</source>
<translation>Цвет заднего плана: %1</translation>
</message>
@@ -54,12 +62,12 @@
<context>
<name>AppUI::MainWindow</name>
<message>
<location filename="../controls/main/mainwindow.cpp" line="317"/>
<location filename="../controls/main/mainwindow.cpp" line="319"/>
<source>XML Files (*.xml)</source>
<translation>Файлы XML (*.xml)</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.cpp" line="319"/>
<location filename="../controls/main/mainwindow.cpp" line="321"/>
<source>Save file as</source>
<translation>Сохранить файл как</translation>
</message>
@@ -297,6 +305,16 @@
<source>Hecadecimal</source>
<translation>16-ричная</translation>
</message>
<message>
<location filename="../controls/setup/parts/image/setuptabimage.cpp" line="54"/>
<source>Check to split data by rows/bands on packing.</source>
<translation>Выбрать для разбиения данных по строкам или полосам при упаковке.</translation>
</message>
<message>
<location filename="../controls/setup/parts/image/setuptabimage.cpp" line="55"/>
<source>Number of blocks per line code. 0 to single line.</source>
<translation>Количество блоков данных на строку кода. Установите 0 для получения единственной строки.</translation>
</message>
</context>
<context>
<name>AppUI::Setup::Parts::Matrix::MatrixPreviewModel</name>
@@ -798,6 +816,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Data::Models::ImagesAlignedProxy</name>
<message>
<source>Original size</source>
<translation type="obsolete">Исходный размер</translation>
</message>
<message>
<source>New size</source>
<translation type="obsolete">Новый размер</translation>
</message>
</context>
<context>
<name>Data::Models::ImagesModel</name>
<message>
@@ -815,14 +844,12 @@
<context>
<name>Data::Models::ImagesResizedProxy</name>
<message>
<location filename="../controls/resize/imagesresizedproxy.cpp" line="48"/>
<source>Original size</source>
<translation>Исходный размер</translation>
<translation type="vanished">Исходный размер</translation>
</message>
<message>
<location filename="../controls/resize/imagesresizedproxy.cpp" line="50"/>
<source>New size</source>
<translation>Новый размер</translation>
<translation type="vanished">Новый размер</translation>
</message>
</context>
<context>
@@ -855,6 +882,85 @@ Qt %4</source>
Qt: %4</translation>
</message>
</context>
<context>
<name>DialogAlign</name>
<message>
<location filename="../controls/align/dialogalign.ui" line="14"/>
<source>Align</source>
<translation>Выравнивание</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.ui" line="27"/>
<source>Mode:</source>
<translation>Режим:</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.ui" line="39"/>
<source>Offset:</source>
<translation>Смещение:</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.ui" line="57"/>
<source>Scale:</source>
<translation>Масштаб:</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.ui" line="95"/>
<source>Horizontal:</source>
<translation>По горизонтали:</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.ui" line="126"/>
<source>Vertical:</source>
<translation>По вертикали:</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="77"/>
<location filename="../controls/align/dialogalign.cpp" line="83"/>
<source>None</source>
<translation>Нет</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="78"/>
<source>Left</source>
<translation>Влево</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="79"/>
<source>Center Left</source>
<translation>По центру лвее</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="80"/>
<source>Center Right</source>
<translation>По центру правее</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="81"/>
<source>Right</source>
<translation>Вправо</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="84"/>
<source>Top</source>
<translation>Вверх</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="85"/>
<source>Center Top</source>
<translation>По центру выше</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="86"/>
<source>Center Bottom</source>
<translation>По центру ниже</translation>
</message>
<message>
<location filename="../controls/align/dialogalign.cpp" line="87"/>
<source>Bottom</source>
<translation>Вниз</translation>
</message>
</context>
<context>
<name>DialogCanvasResize</name>
<message>
@@ -1014,103 +1120,103 @@ Qt: %4</translation>
<translation>Размер:</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="183"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="190"/>
<source>Parameters</source>
<translation>Параметры</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="193"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="200"/>
<source>Proportional</source>
<translation>Пропорциональный</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="203"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="210"/>
<source>Monospaced</source>
<translation>Моноширинный</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="236"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="243"/>
<source>Multiplicity of width</source>
<translation>Кратность ширины</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="239"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="246"/>
<source>W /</source>
<translation>Ш /</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="252"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="259"/>
<source>Multiplicity of height</source>
<translation>Кратность высоты</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="255"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="262"/>
<source>H /</source>
<translation>В /</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="283"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="290"/>
<source>Antialiasing</source>
<translation>Сглаживание</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="311"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="318"/>
<source>Fore Color</source>
<translation>Цвет переднего плана</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="401"/>
<source>Max char size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="408"/>
<source>Max glyph size</source>
<translation type="unfinished"></translation>
<source>Max char size</source>
<translation>Макс. разм. символа</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="298"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="415"/>
<source>Max glyph size</source>
<translation>Макс. разм. изображения</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="305"/>
<source>Back Color</source>
<translation>Цвет заднего плана</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="138"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="145"/>
<source>Enter filter...</source>
<translation>Введите фильтр...</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="111"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="118"/>
<source>Characters</source>
<translation>Символы</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="125"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="132"/>
<source>Filter:</source>
<translation>Фильтр:</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="158"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="165"/>
<source>Append Selected</source>
<translation>Добавить выбранные</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="165"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="172"/>
<source>Append Range...</source>
<translation>Добавить диапазон...</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="339"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="346"/>
<source>Sort</source>
<translation>Отсортировать</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="368"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="371"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="375"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="378"/>
<source>Selected characters</source>
<translation>Выбранные символы</translation>
</message>
<message>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="394"/>
<location filename="../controls/fonts/font-new/dialogfontselect.ui" line="401"/>
<source>Count</source>
<translation>Количество</translation>
</message>
@@ -1235,17 +1341,17 @@ Qt: %4</translation>
<context>
<name>ImageEditor::Tools::ToolLine</name>
<message>
<location filename="../classes/imageeditor/toolline.cpp" line="66"/>
<location filename="../classes/imageeditor/toolline.cpp" line="67"/>
<source>Line</source>
<translation>Линия</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolline.cpp" line="71"/>
<location filename="../classes/imageeditor/toolline.cpp" line="72"/>
<source>&lt;b&gt;Draw line&lt;/b&gt;&lt;br/&gt;Use left mouse button to draw forecolor.&lt;br/&gt;Use right mouse button to draw backcolor.</source>
<translation>&lt;b&gt;Рисование линии&lt;/b&gt;&lt;br/&gt;Левая кнопка мыши для рисования цветом переднего плана.&lt;br/&gt;Правая кнопка мыши для рисования цветом заднего плана.</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolline.cpp" line="148"/>
<location filename="../classes/imageeditor/toolline.cpp" line="149"/>
<source>Line Width</source>
<translation>Толщина линии</translation>
</message>
@@ -1302,43 +1408,43 @@ Qt: %4</translation>
<context>
<name>ImageEditor::Tools::ToolRect</name>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="66"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="67"/>
<source>Rectangle</source>
<translation>Прямоугольник</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="71"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="72"/>
<source>&lt;b&gt;Draw rectangle&lt;/b&gt;&lt;br/&gt;Left mouse button: outline - forecolor, filling - backcolor.&lt;br/&gt;Right mouse button: outline - backcolor, filling - forecolor.</source>
<translation>&lt;b&gt;Рисование прямоугольника&lt;/b&gt;&lt;br/&gt;Левая кнопка мыши: границы цвета переднего плана, заливка - заднего.&lt;br/&gt;Правая кнопка мыши: границы цвета заднего плана, заливка - переднего.</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="148"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="149"/>
<source>Outline Width</source>
<translation>Ширина границ</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="155"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="156"/>
<source>Outline</source>
<translation>Границы</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="156"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="157"/>
<source>Outline only</source>
<translation>Только границы</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="165"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="166"/>
<source>Filled Outline</source>
<translation>Заливка и границы</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="166"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="167"/>
<source>Filled with Outline</source>
<translation>Заливка с границами</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolrect.cpp" line="175"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="176"/>
<location filename="../classes/imageeditor/toolrect.cpp" line="177"/>
<source>Filled</source>
<translation>Заливка</translation>
</message>
@@ -1386,7 +1492,7 @@ Qt: %4</translation>
<message>
<location filename="../classes/imageeditor/toolzoom.cpp" line="67"/>
<source>Zoom image</source>
<translation>Измение масштаба изображения</translation>
<translation>Изменение масштаба изображения</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolzoom.cpp" line="115"/>
@@ -1428,231 +1534,237 @@ Qt: %4</translation>
<translation>Сдвиг</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="102"/>
<location filename="../controls/main/mainwindow.ui" line="103"/>
<source>Font</source>
<translation>Шрифт</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="113"/>
<location filename="../controls/main/mainwindow.ui" line="115"/>
<source>Help</source>
<translation>Справка</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="122"/>
<location filename="../controls/main/mainwindow.ui" line="124"/>
<source>Options</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="126"/>
<location filename="../controls/main/mainwindow.ui" line="128"/>
<source>Language</source>
<translation>Язык</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="136"/>
<location filename="../controls/main/mainwindow.ui" line="138"/>
<source>Edit</source>
<translation>Правка</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="154"/>
<location filename="../controls/main/mainwindow.ui" line="156"/>
<source>New Image...</source>
<translation>Новое изображение...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="159"/>
<location filename="../controls/main/mainwindow.ui" line="161"/>
<source>New Font...</source>
<translation>Новый шрифт...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="164"/>
<location filename="../controls/main/mainwindow.ui" line="166"/>
<source>Open...</source>
<translation>Открыть...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="172"/>
<location filename="../controls/main/mainwindow.ui" line="174"/>
<source>Save</source>
<translation>Сохранить</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="180"/>
<location filename="../controls/main/mainwindow.ui" line="182"/>
<source>Save As...</source>
<translation>Сохранить как...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="188"/>
<location filename="../controls/main/mainwindow.ui" line="190"/>
<source>Close</source>
<translation>Закрыть</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="196"/>
<location filename="../controls/main/mainwindow.ui" line="198"/>
<source>Quit</source>
<translation>Выйти</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="204"/>
<location filename="../controls/main/mainwindow.ui" line="206"/>
<source>Flip Horizontal</source>
<translation>Отразить по горизонтали</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="209"/>
<location filename="../controls/main/mainwindow.ui" line="211"/>
<source>Flip Vertical</source>
<translation>Отразить по вертикали</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="214"/>
<location filename="../controls/main/mainwindow.ui" line="216"/>
<source>90 Clockwise</source>
<translation>90 по часовой</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="222"/>
<location filename="../controls/main/mainwindow.ui" line="224"/>
<source>180</source>
<translation>180</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="227"/>
<location filename="../controls/main/mainwindow.ui" line="229"/>
<source>90 Counter-Clockwise</source>
<translation>90 против часовой</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="235"/>
<location filename="../controls/main/mainwindow.ui" line="281"/>
<location filename="../controls/main/mainwindow.ui" line="237"/>
<location filename="../controls/main/mainwindow.ui" line="283"/>
<source>Inverse</source>
<translation>Инвертировать</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="243"/>
<location filename="../controls/main/mainwindow.ui" line="245"/>
<source>Convert...</source>
<translation>Преобразовать...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="251"/>
<location filename="../controls/main/mainwindow.ui" line="294"/>
<location filename="../controls/main/mainwindow.ui" line="253"/>
<location filename="../controls/main/mainwindow.ui" line="296"/>
<source>Conversion...</source>
<translation>Преобразование...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="256"/>
<location filename="../controls/main/mainwindow.ui" line="258"/>
<source>Import...</source>
<translation>Импортировать...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="261"/>
<location filename="../controls/main/mainwindow.ui" line="263"/>
<source>Export...</source>
<translation>Экспортировать...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="266"/>
<location filename="../controls/main/mainwindow.ui" line="276"/>
<location filename="../controls/main/mainwindow.ui" line="268"/>
<location filename="../controls/main/mainwindow.ui" line="278"/>
<source>Resize...</source>
<translation>Изменение размеров...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="286"/>
<location filename="../controls/main/mainwindow.ui" line="288"/>
<source>About...</source>
<translation>О программе...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="317"/>
<location filename="../controls/main/mainwindow.ui" line="319"/>
<source>Home Page...</source>
<translation>Домашняя страница...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="322"/>
<location filename="../controls/main/mainwindow.ui" line="324"/>
<source>To Image</source>
<translation>В изображение</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="327"/>
<location filename="../controls/main/mainwindow.ui" line="329"/>
<source>Convert All</source>
<translation>Преобразовать все</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="332"/>
<location filename="../controls/main/mainwindow.ui" line="334"/>
<source>Edit in external tool...</source>
<translation>Открыть во внешнем редакторе...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="343"/>
<location filename="../controls/main/mainwindow.ui" line="345"/>
<source>External editor...</source>
<translation>Внешний редактор...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="348"/>
<location filename="../controls/main/mainwindow.ui" line="350"/>
<source>Left</source>
<translation>Влево</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="356"/>
<location filename="../controls/main/mainwindow.ui" line="358"/>
<source>Right</source>
<translation>Вправо</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="364"/>
<location filename="../controls/main/mainwindow.ui" line="366"/>
<source>Up</source>
<translation>Вверх</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="372"/>
<location filename="../controls/main/mainwindow.ui" line="374"/>
<source>Down</source>
<translation>Вниз</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="380"/>
<location filename="../controls/main/mainwindow.ui" line="382"/>
<source>Undo</source>
<translation>Отменить</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="388"/>
<location filename="../controls/main/mainwindow.ui" line="390"/>
<source>Redo</source>
<translation>Повторить</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="396"/>
<location filename="../controls/main/mainwindow.ui" line="398"/>
<source>Updates...</source>
<translation>Обновления...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="401"/>
<location filename="../controls/main/mainwindow.ui" line="403"/>
<source>Copy</source>
<translation>Копировать</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="409"/>
<location filename="../controls/main/mainwindow.ui" line="411"/>
<source>Paste</source>
<translation>Вставить</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="417"/>
<location filename="../controls/main/mainwindow.ui" line="419"/>
<source>About Qt...</source>
<translation>О Qt...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="422"/>
<location filename="../controls/main/mainwindow.ui" line="424"/>
<source>To Grayscale</source>
<translatorcomment>Преобразовать изображение из цветного в градации серого</translatorcomment>
<translation>В градации серого</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="427"/>
<location filename="../controls/main/mainwindow.ui" line="429"/>
<source>Close All</source>
<translation>Закрыть все</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="307"/>
<location filename="../controls/main/mainwindow.ui" line="434"/>
<location filename="../controls/main/mainwindow.ui" line="439"/>
<source>Align...</source>
<translation>Выравнивание...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="309"/>
<source>Rename...</source>
<translation>Переименовать...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="312"/>
<location filename="../controls/main/mainwindow.ui" line="314"/>
<source>Preview...</source>
<translation>Предпросмотр...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="271"/>
<location filename="../controls/main/mainwindow.ui" line="273"/>
<source>Change...</source>
<translation>Изменить...</translation>
</message>
<message>
<location filename="../controls/main/mainwindow.ui" line="302"/>
<location filename="../controls/main/mainwindow.ui" line="304"/>
<source>English</source>
<translatorcomment>не переводить</translatorcomment>
<translation>English</translation>
@@ -2120,12 +2232,12 @@ Only minimal amount (%3) will be imported.</source>
<context>
<name>ToolFill</name>
<message>
<location filename="../classes/imageeditor/toolfill.cpp" line="68"/>
<location filename="../classes/imageeditor/toolfill.cpp" line="69"/>
<source>Fill</source>
<translation>Заполнение</translation>
</message>
<message>
<location filename="../classes/imageeditor/toolfill.cpp" line="73"/>
<location filename="../classes/imageeditor/toolfill.cpp" line="74"/>
<source>&lt;b&gt;Fill area&lt;/b&gt;&lt;br/&gt;Use left mouse button to fill with forecolor.&lt;br/&gt;Use right mouse button to fill with backcolor.</source>
<translation>&lt;b&gt;Заливка площади&lt;/b&gt;&lt;br/&gt;Левая кнопка мыши для заливки цветом переднего плана.&lt;br/&gt;Правая кнопка мыши для заливки цветом заднего плана.</translation>
</message>

View File

@@ -39,8 +39,8 @@ void TestBitmapHelper::rotate270()
void TestBitmapHelper::shiftUp()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/up");
QImage test = Parsing::Conversion::BitmapHelper::shiftUp(&original);
QImage expected = QImage(":/shift/0_-1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 0, -1);
this->compareSizeAndPixels(&expected, &test);
}
@@ -48,8 +48,8 @@ void TestBitmapHelper::shiftUp()
void TestBitmapHelper::shiftRight()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/right");
QImage test = Parsing::Conversion::BitmapHelper::shiftRight(&original);
QImage expected = QImage(":/shift/1_0");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 1, 0);
this->compareSizeAndPixels(&expected, &test);
}
@@ -57,8 +57,8 @@ void TestBitmapHelper::shiftRight()
void TestBitmapHelper::shiftDown()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/down");
QImage test = Parsing::Conversion::BitmapHelper::shiftDown(&original);
QImage expected = QImage(":/shift/0_1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 0, 1);
this->compareSizeAndPixels(&expected, &test);
}
@@ -66,8 +66,53 @@ void TestBitmapHelper::shiftDown()
void TestBitmapHelper::shiftLeft()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/left");
QImage test = Parsing::Conversion::BitmapHelper::shiftLeft(&original);
QImage expected = QImage(":/shift/-1_0");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, -1, 0);
this->compareSizeAndPixels(&expected, &test);
}
void TestBitmapHelper::shiftLeftDown()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/-1_1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, -1, 1);
this->compareSizeAndPixels(&expected, &test);
}
void TestBitmapHelper::shiftLeftUp()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/-1_-1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, -1, -1);
this->compareSizeAndPixels(&expected, &test);
}
void TestBitmapHelper::shiftRightDown()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/1_1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 1, 1);
this->compareSizeAndPixels(&expected, &test);
}
void TestBitmapHelper::shiftRightUp()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/1_-1");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 1, -1);
this->compareSizeAndPixels(&expected, &test);
}
void TestBitmapHelper::shiftMore()
{
QImage original = QImage(":/shift/original");
QImage expected = QImage(":/shift/2_4");
QImage test = Parsing::Conversion::BitmapHelper::shift(&original, 2, 4);
this->compareSizeAndPixels(&expected, &test);
}

View File

@@ -24,6 +24,11 @@ private slots:
void shiftRight();
void shiftDown();
void shiftLeft();
void shiftLeftDown();
void shiftLeftUp();
void shiftRightDown();
void shiftRightUp();
void shiftMore();
void flipHorizontal();
void flipVertical();
void cleanupTestCase();

View File

@@ -1,5 +1,6 @@
#include "testbitstream.h"
#include <QRandomGenerator>
#include "preset.h"
#include "prepareoptions.h"
#include "matrixoptions.h"
@@ -58,11 +59,11 @@ void TestBitStream::preparePackData(
QVector<quint32> *source, QVector<quint32> *packed)
{
const int count = 1000;
qsrand(QTime::currentTime().msec());
QRandomGenerator prng(QTime::currentTime().msec());
// fill source data
for (int i = 0; i < count; i++) {
quint32 value = qrand();
quint32 value = prng.generate();
value = 0x00ffff11;
source->append(value);
}

View File

@@ -2,6 +2,7 @@
#include <QVector>
#include <QCoreApplication>
#include <QRandomGenerator>
#include "qt-version-check.h"
#include "converterhelper.h"
#include "preset.h"
@@ -32,10 +33,10 @@ void TestConverterHelper::processPixels()
// equals by default
QVector<quint32> source, sample;
qsrand(QTime::currentTime().msec());
QRandomGenerator prng(QTime::currentTime().msec());
for (int i = 0; i < count; i++) {
quint32 value = qrand();
quint32 value = prng.generate();
source << value;
sample << value;
}
@@ -54,7 +55,7 @@ void TestConverterHelper::processPixels()
sample.clear();
for (int i = 0; i < count; i++) {
quint32 value = qrand();
quint32 value = prng.generate();
quint32 a = 0;
a |= (value & 0x12345678) << 3;
a |= (value & 0x87654321) >> 1;
@@ -76,7 +77,7 @@ void TestConverterHelper::processPixels()
sample.clear();
for (int i = 0; i < count; i++) {
quint32 value = qrand();
quint32 value = prng.generate();
quint32 a = value & 0xabcdef01;
source << a;
sample << value;
@@ -96,7 +97,7 @@ void TestConverterHelper::processPixels()
sample.clear();
for (int i = 0; i < count; i++) {
quint32 value = qrand();
quint32 value = prng.generate();
quint32 a = value | 0x1a5b5e4d;
source << a;
sample << value;
@@ -125,21 +126,17 @@ void TestConverterHelper::packData()
this->mPreset->image()->setSplitToRows(true);
QVector<quint32> source, expected;
int widthExpected, heightExpected;
this->preparePackData(
0x00ffffff, 0xffffffff,
&source, 1000, 1000,
true,
&expected, &widthExpected, &heightExpected);
&expected);
QVector<quint32> sample;
int widthSample, heightSample;
Parsing::Conversion::ConverterHelper::packData(this->mPreset,
&source, 1000, 1000,
&sample, &widthSample, &heightSample);
&sample);
QCOMPARE(widthSample, widthExpected);
QCOMPARE(heightSample, heightExpected);
QCOMPARE(sample.count(), expected.count());
for (int i = 0; i < sample.count(); i++) {
@@ -152,21 +149,17 @@ void TestConverterHelper::packData()
this->mPreset->image()->setSplitToRows(false);
QVector<quint32> source, expected;
int widthExpected, heightExpected;
this->preparePackData(
0x00ffffff, 0xffffffff,
&source, 1000, 1000,
false,
&expected, &widthExpected, &heightExpected);
&expected);
QVector<quint32> sample;
int widthSample, heightSample;
Parsing::Conversion::ConverterHelper::packData(this->mPreset,
&source, 1000, 1000,
&sample, &widthSample, &heightSample);
&sample);
QCOMPARE(widthSample, widthExpected);
QCOMPARE(heightSample, heightExpected);
QCOMPARE(sample.count(), expected.count());
for (int i = 0; i < sample.count(); i++) {
@@ -180,11 +173,11 @@ void TestConverterHelper::dataToString()
const int count = 10;
// fill source data
QVector<quint32> source;
qsrand(QTime::currentTime().msec());
QRandomGenerator prng(QTime::currentTime().msec());
for (int y = 0; y < count; y++) {
for (int x = 0; x < count; x++) {
quint32 value = qrand();
quint32 value = prng.generate();
source << value;
}
}
@@ -199,33 +192,80 @@ void TestConverterHelper::dataToString()
// test splitted data
{
this->mPreset->image()->setSplitToRows(true);
bool splitToRows = true;
quint32 blocksPerLine = 0;
this->mPreset->image()->setSplitToRows(splitToRows);
this->mPreset->image()->setBlockPrefix("");
this->mPreset->image()->setBlockSuffix("");
this->mPreset->image()->setBlockDelimiter(", ");
this->mPreset->image()->setBlocksPerLine(blocksPerLine);
// create expected strings
QString expected8, expected16, expected24, expected32;
this->prepareStringData(&source, count, count, true, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, true, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, true, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, true, Settings::Presets::DataBlockSize::Data32, &expected32);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data32, &expected32);
// create test strings
QString test8, test16, test24, test32;
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data8);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data16);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data24);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data32);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
// compare
// this->compareStrings(test8, expected8);
QCOMPARE(test8, expected8);
// this->compareStrings(test16, expected16);
QCOMPARE(test16, expected16);
// this->compareStrings(test24, expected24);
QCOMPARE(test24, expected24);
// this->compareStrings(test32, expected32);
QCOMPARE(test32, expected32);
}
// test data with specified number of blocks per line
{
bool splitToRows = true;
quint32 blocksPerLine = 9;
this->mPreset->image()->setSplitToRows(splitToRows);
this->mPreset->image()->setBlockPrefix("");
this->mPreset->image()->setBlockSuffix("");
this->mPreset->image()->setBlockDelimiter(", ");
this->mPreset->image()->setBlocksPerLine(blocksPerLine);
// create expected strings
QString expected8, expected16, expected24, expected32;
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data32, &expected32);
// create test strings
QString test8, test16, test24, test32;
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data8);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data16);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data24);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data32);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
// compare
QCOMPARE(test8, expected8);
@@ -233,32 +273,73 @@ void TestConverterHelper::dataToString()
QCOMPARE(test24, expected24);
QCOMPARE(test32, expected32);
}
// test linear data
{
this->mPreset->image()->setSplitToRows(false);
bool splitToRows = false;
quint32 blocksPerLine = 0;
this->mPreset->image()->setSplitToRows(splitToRows);
this->mPreset->image()->setBlocksPerLine(blocksPerLine);
// create expected strings
QString expected8, expected16, expected24, expected32;
this->prepareStringData(&source, count, count, false, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, false, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, false, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, false, Settings::Presets::DataBlockSize::Data32, &expected32);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data32, &expected32);
// create test strings
QString test8, test16, test24, test32;
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data8);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data16);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data24);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data32);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source, count, count);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
// compare
QCOMPARE(test8, expected8);
QCOMPARE(test16, expected16);
QCOMPARE(test24, expected24);
QCOMPARE(test32, expected32);
}
// test lineardata with specified number of blocks per line
{
bool splitToRows = false;
quint32 blocksPerLine = 9;
this->mPreset->image()->setSplitToRows(splitToRows);
this->mPreset->image()->setBlocksPerLine(blocksPerLine);
// create expected strings
QString expected8, expected16, expected24, expected32;
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data8, &expected8);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data16, &expected16);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data24, &expected24);
this->prepareStringData(&source, count, count, blocksPerLine, Settings::Presets::DataBlockSize::Data32, &expected32);
// create test strings
QString test8, test16, test24, test32;
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data8);
test8 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data16);
test16 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data24);
test24 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
this->mPreset->image()->setBlockSize(Settings::Presets::DataBlockSize::Data32);
test32 = Parsing::Conversion::ConverterHelper::dataToString(this->mPreset, &source);
// compare
QCOMPARE(test8, expected8);
@@ -297,10 +378,11 @@ void TestConverterHelper::uint2binary()
void TestConverterHelper::uint2string()
{
QRandomGenerator prng(QTime::currentTime().msec());
quint32 values[50];
for (quint32 v = 0; v < sizeof(values) / sizeof(quint32); v++) {
values[v] = static_cast<quint32>(qrand());
values[v] = prng.generate();
}
Settings::Presets::DataNumeralSystem nums[] = {
@@ -390,16 +472,16 @@ void TestConverterHelper::preparePackData(
quint32 maskUsed, quint32 maskFill,
QVector<quint32> *source, int width, int height,
bool splitToRows,
QVector<quint32> *packed, int *widthOut, int *heightOut)
QVector<quint32> *packed)
{
int packedRowWidth = 0;
qsrand(QTime::currentTime().msec());
QRandomGenerator prng(QTime::currentTime().msec());
// fill source data
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
quint32 value = qrand();
quint32 value = prng.generate();
value = 0x00ffff11;
source->append(value);
}
@@ -481,20 +563,21 @@ void TestConverterHelper::preparePackData(
packedRowWidth = counter;
height = 1;
}
*widthOut = packedRowWidth;
*heightOut = height;
}
void TestConverterHelper::prepareStringData(
QVector<quint32> *source, int width, int height,
bool splitToRows,
int blocksPerLine,
Parsing::Conversion::Options::DataBlockSize size, QString *string)
{
QString result;
quint32 mask = 0;
int digits = 1;
if (blocksPerLine < 1) {
blocksPerLine = 0;
}
switch (size) {
case Parsing::Conversion::Options::DataBlockSize::Data8: {
mask = 0x000000ff;
@@ -521,28 +604,65 @@ void TestConverterHelper::prepareStringData(
}
}
if (splitToRows) {
for (int y = 0; y < height; y++) {
if (y > 0) {
result.append("\n");
}
QStringList list;
for (auto i = 0; i < source->count(); i++) {
quint32 value = source->at(i);
list.append(QString("%1, ").arg(value & mask, digits, 16, QChar('0')));
}
if (blocksPerLine < 1) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
quint32 value = source->at(x + width * y);
result.append(QString("%1, ").arg(value & mask, digits, 16, QChar('0')));
result.append(list.at(x + width * y));
}
}
} else {
for (int i = 0; i < width; i++) {
quint32 value = source->at(i);
result.append(QString("%1, ").arg(value & mask, digits, 16, QChar('0')));
int blockerPerLineCounter = 0;
for (int i = 0; i < source->count(); i++) {
result.append(list.at(i));
blockerPerLineCounter++;
if ((blocksPerLine > 0) && (blockerPerLineCounter >= blocksPerLine)) {
blockerPerLineCounter = 0;
result.append("\n");
}
}
}
result.truncate(result.length() - 2);
result = result.trimmed();
if (result.endsWith(",")) {
result.truncate(result.length() - 1);
}
*string = result;
}
void TestConverterHelper::compareStrings(const QString &actual, const QString &expected)
{
if (actual != expected) {
qDebug() << "Strings do not match:";
qDebug() << "Actual: " << actual;
qDebug() << "Expected: " << expected;
int minLength = qMin(actual.length(), expected.length());
for (int i = 0; i < minLength; ++i) {
if (actual[i] != expected[i]) {
qDebug() << "Difference at position" << i << ": Actual='" << actual[i] << "', Expected='" << expected[i] << "'";
}
}
if (actual.length() > expected.length()) {
qDebug() << "Actual string is longer by" << actual.length() - expected.length() << "characters.";
} else if (expected.length() > actual.length()) {
qDebug() << "Expected string is longer by" << expected.length() - actual.length() << "characters.";
}
}
}
TestConvImage::TestConvImage(const QImage *image, QObject *parent) :
Parsing::Conversion::ConvImageScan(image, parent)
{

View File

@@ -24,12 +24,14 @@ public:
private:
Settings::Presets::Preset *mPreset;
void preparePackData(
quint32 maskUsed, quint32 maskFill,
QVector<quint32> *source, int width, int height,
bool splitToRows, QVector<quint32> *packed, int *widthOut, int *heightOut);
quint32 maskUsed, quint32 maskFill,
QVector<quint32> *source, int width, int height,
bool splitToRows, QVector<quint32> *packed);
void prepareStringData(
QVector<quint32> *source, int width, int height,
bool splitToRows, Parsing::Conversion::Options::DataBlockSize size, QString *string);
int blockPerLine,
Parsing::Conversion::Options::DataBlockSize size, QString *string);
void compareStrings(const QString &actual, const QString& expected);
private slots:
void initTestCase();

View File

@@ -1,11 +1,11 @@
#include "testsettings.h"
#include <QBuffer>
#include <QDir>
#include <QDomDocument>
#include <QDomNodeList>
#include <QFile>
#include <QTemporaryDir>
#include <QXmlInputSource>
#include <QXmlSimpleReader>
TestSettings::TestSettings(QObject *parent) :
QObject(parent)
@@ -162,14 +162,11 @@ void TestSettings::save_load()
QCOMPARE(file.exists(), true);
QCOMPARE(file.open(QFile::ReadOnly), true);
QXmlInputSource source(&file);
QXmlSimpleReader reader;
QDomDocument doc;
QString errorMsg;
int errorColumn, errorLine;
if (doc.setContent(&source, &reader, &errorMsg, &errorLine, &errorColumn)) {
if (doc.setContent(&file, false, &errorMsg, &errorLine, &errorColumn)) {
QDomElement root = doc.documentElement();
QCOMPARE(root.tagName(), QString("configuration"));
} else {

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -11,11 +11,16 @@
<file alias="vertical">resources/samples/flip/flip-vertical.png</file>
</qresource>
<qresource prefix="/shift">
<file alias="down">resources/samples/shift/down.png</file>
<file alias="left">resources/samples/shift/left.png</file>
<file alias="original">resources/samples/shift/original.png</file>
<file alias="right">resources/samples/shift/right.png</file>
<file alias="up">resources/samples/shift/up.png</file>
<file alias="0_1">resources/samples/shift/0_1.png</file>
<file alias="0_-1">resources/samples/shift/0_-1.png</file>
<file alias="1_0">resources/samples/shift/1_0.png</file>
<file alias="-1_0">resources/samples/shift/-1_0.png</file>
<file alias="1_1">resources/samples/shift/1_1.png</file>
<file alias="1_-1">resources/samples/shift/1_-1.png</file>
<file alias="-1_1">resources/samples/shift/-1_1.png</file>
<file alias="-1_-1">resources/samples/shift/-1_-1.png</file>
<file alias="2_4">resources/samples/shift/2_4.png</file>
</qresource>
<qresource prefix="/scan_scripts">
<file alias="scan_template">../resources/scan_scripts/scan_template.js</file>

View File

@@ -83,6 +83,7 @@ HEADERS += \
parts/testtemplateoptions.h \
../classes/compression/rlecompressor.h \
../classes/compression/rlesequence.h \
../classes/data/alignmodes.h \
../classes/parser/convert/bitstream.h \
../classes/parser/convert/bitmaphelper.h \
../classes/parser/convert/conversion_options.h \
@@ -104,6 +105,7 @@ INCLUDEPATH += . \
../ \
./parts \
../classes \
../classes/data \
../classes/compression \
../classes/parser/convert \
../classes/settings \