Edytując post poprawiłem swój kod ze wszystkich literówek (było ich troszkę :) ). Poza tym dla wygody zmieniłem format obrazka na QImage::Format_RGB32
, bo okazało się, że w formacie QImage::Format_RGB888
piksele są ciasno upakowane, a nie wyrównywane do podwójnego słowa. Przed użyciem tej funkcji należy zadbać by QImage był we właściwym formacie:
if (image.format()!=QImage::Format_RGB32)
image=image.convertToFormat(QImage::Format_RGB32);
Kod testowałem i raczej działa jak należy.
a tu napisałem maskę którą można edytować za pomocą
QTableView (fajny przykład jak należy korzystać z modeli danych):
#ifndef EDITABLEMASK_H
#define EDITABLEMASK_H
#include <QAbstractTableModel>
#include "maska.h"
const int MaxMaskSize = 16;
const int MaxMaskRadius = (MaxMaskSize-1)/2;
class EditableMask : public QAbstractTableModel , public Maska
{
Q_OBJECT
Q_PROPERTY(int radius
READ radius
WRITE setRadius
NOTIFY radiusChanged)
Q_PROPERTY(int norm
READ norm
WRITE setNorm
NOTIFY normChanged
RESET setDefaultNorm)
public:
explicit EditableMask(QObject *parent = 0);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
Qt::ItemFlags flags(const QModelIndex &index) const;
int width() const;
int height() const;
int norm() const;
const int *operator[](int row) const;
int radius() const;
int defaultNorm() const;
signals:
void radiusChanged(int);
void normChanged(int);
public slots:
void setRadius(int);
void setNorm(int norma);
void setDefaultNorm();
private:
int mOffset;
int mSize;
mutable int mNorma;
int mData[MaxMaskSize][MaxMaskSize];
};
#endif // EDITABLEMASK_H
#include "editablemask.h"
EditableMask::EditableMask(QObject *parent) :
QAbstractTableModel(parent)
{
std::fill(mData[0], mData[0]+MaxMaskSize*MaxMaskSize, 0);
mSize = 3;
mOffset = MaxMaskRadius - 1;
mData[MaxMaskRadius][MaxMaskRadius] = 1;
mNorma = 1;
}
int EditableMask::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return mSize;
}
int EditableMask::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return mSize;
}
QVariant EditableMask::data(const QModelIndex &index, int role) const
{
switch(role) {
case Qt::DisplayRole:
case Qt::EditRole:
return QString::number(mData[index.row()+mOffset][index.column()+mOffset]);
default:
return QVariant();
}
}
bool EditableMask::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role!=Qt::EditRole)
return false;
bool ok = false;
int x = value.toInt(&ok);
if (ok) {
mData[index.row()+mOffset][index.column()+mOffset] = x;
return true;
}
return false;
}
Qt::ItemFlags EditableMask::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
int EditableMask::width() const
{
return mSize;
}
int EditableMask::height() const
{
return mSize;
}
int EditableMask::norm() const
{
return mNorma;
}
const int *EditableMask::operator [](int row) const
{
return mData[mOffset+row]+mOffset;
}
int EditableMask::radius() const
{
return (mSize-1)/2;
}
void EditableMask::setRadius(int newRadius)
{
int oldRadius = (mSize-1)/2;
newRadius = qBound(1, newRadius, MaxMaskRadius);
if (newRadius>0 && oldRadius!=newRadius) {
int diff = newRadius-oldRadius;
if (diff>0) {
beginInsertRows( QModelIndex(), 0, diff-1);
beginInsertColumns(QModelIndex(), 0, diff-1);
mOffset -= diff;
mSize += diff;
endInsertRows();
endInsertColumns();
beginInsertRows( QModelIndex(), mSize, mSize + diff-1);
beginInsertColumns(QModelIndex(), mSize, mSize + diff-1);
mSize += diff;
endInsertRows();
endInsertColumns();
} else {
beginRemoveRows( QModelIndex(), 0, -diff-1);
beginRemoveColumns(QModelIndex(), 0, -diff-1);
mOffset -= diff;
mSize += diff;
endRemoveRows();
endRemoveColumns();
beginRemoveRows (QModelIndex(), mSize+diff, mSize-1);
beginRemoveColumns(QModelIndex(), mSize+diff, mSize-1);
mSize += diff;
endRemoveRows();
endRemoveColumns();
}
emit radiusChanged(newRadius);
}
}
void EditableMask::setNorm(int norma)
{
if (norma == 0) {
norma = defaultNorm();
if (norma == 0)
norma = 1;
}
if (norma != mNorma) {
mNorma = norma;
emit normChanged(norma);
}
}
void EditableMask::setDefaultNorm()
{
setNorm(0);
}
int EditableMask::defaultNorm() const
{
int sum = 0;
for(int i=0; i<mSize; ++i)
for(int j=0; j<mSize; ++j)
sum += mData[mOffset+i][mOffset+j];
return sum;
}
Tę maskę można edytować, powiększać pomniejszać