QPainter的是如何绘制特殊颜色纹理(QPainter how draw texture wit

2019-09-25 18:19发布

我有一些图案它们是黑色的α和有我想提请符合模式的几点思考。

我觉得QBrush可以通过纹理构造,但我不知道如何用不同颜色绘制。

这个答案显示的方式在这里的C#代码,但我不知道如何改变图案颜色与嘉洛斯。

Answer 1:

使用5×5的颜色矩阵的图像的RGBA值的修改提醒我的转化齐次坐标如何它常常在计算机图形中使用。 如果你想像的RGBA值4维的颜色/ alpha空间的使用变换矩阵听起来并不革命性色彩的转变。 (不是说你让我错了 - 这让我印象深刻了,我忍不住要立刻尝试了这一点)。因此,我不知道为什么需要一个5X5矩阵,虽然只有4个颜色分量。 (例如,如果颜色值的翻译意第五维卡梅斯发挥作用。)

我必须承认,我首先应用于从电脑动画我认识到这个问题,我比较的方法来MSDN上描述的一个使用彩色矩阵变换到一个单一的颜色之后。 后来我明白了,原来纸相比,矿采用互换的向量和矩阵。 这只是作为数学

(ⅴTm T)T = V” = M v

如果我没有记错的权利。

实际上,这意味着我必须使用矩阵的行,列,当我尝试重现如的样品嘉洛斯指南 。 (这在某种程度上觉得我的权利,因为它是完全一样的,我们描述了在三维空间中,即平移变换是变换矩阵的最后一列。)

示例代码:

colorMatrix.h

#ifndef COLOR_MATRIX_H
#define COLOR_MATRIX_H

#include <algorithm>

struct ColorMatrix {
  float values[5][5];
  ColorMatrix() { }
  ColorMatrix(const float(&values)[25])
  {
    std::copy(std::begin(values), std::end(values), (float*)this->values);
  }
  float (&operator[](unsigned i))[5] { return values[i]; }
  const float(&operator[](unsigned i) const)[5] { return values[i]; }
};

struct ColorVector {
  float values[5];
  ColorVector(const float(&values)[5])
  {
    std::copy(std::begin(values), std::end(values), (float*)this->values);
  }
  float& operator[](size_t i) { return values[i]; }
  const float& operator[](size_t i) const { return values[i]; }
};

#endif // COLOR_MATRIX_H

colorMatrix.cc

#include <algorithm>

#include <QtWidgets>

#include "colorMatrix.h"
#include "QColorMatrixView.h"

ColorVector operator*(const ColorMatrix &m, const ColorVector &v)
{
  return ColorVector({
    m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3] + m[0][4] * v[4],
    m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3] + m[1][4] * v[4],
    m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3] + m[2][4] * v[4],
    m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3] + m[3][4] * v[4],
    m[4][0] * v[0] + m[4][1] * v[1] + m[4][2] * v[2] + m[4][3] * v[3] + m[4][4] * v[4]
  });
}

const ColorMatrix Identity({
  1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
  0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  0.0f, 0.0f, 0.0f, 0.0f, 1.0f
});

template <typename T>
T clamp(T value, T min, T max)
{
  return value < min ? min
    : value > max ? max
    : value;
}

QRgb transform(const ColorMatrix &mat, const QRgb &color)
{
  ColorVector vec({
    qRed(color) / 255.0f, qGreen(color) / 255.0f, qBlue(color) / 255.0f, qAlpha(color) / 255.0f, 1.0f });
  vec = mat * vec;
  if (vec[4] != 0.0f) {
    vec[0] /= vec[4]; vec[1] /= vec[4]; vec[2] /= vec[4]; vec[3] /= vec[4]; // vec[4] = 1.0f;
  }
  return qRgba(
    clamp<int>(255 * vec[0], 0, 255),
    clamp<int>(255 * vec[1], 0, 255),
    clamp<int>(255 * vec[2], 0, 255),
    clamp<int>(255 * vec[3], 0, 255));
}

QImage transform(const ColorMatrix &mat, const QImage &qImg)
{
  const int w = qImg.width(), h = qImg.height();
  QImage qImgDst(w, h, qImg.format());
  for (int y = 0; y < h; ++y) for (int x = 0; x < w; ++x) {
    qImgDst.setPixel(x, y, transform(mat, qImg.pixel(x, y)));
  }
  return qImgDst;
}

QImage open(QWidget *pQParent)
{
  return QImage(
    QFileDialog::getOpenFileName(pQParent,
      QString::fromUtf8("Open Image File"),
      QString()));
}

void update(
  QLabel &qLblViewResult,
  const QColorMatrixView &qEditColMat, const QLabel &qLblViewOrig)
{
  ColorMatrix colMat = qEditColMat.values();
  const QPixmap *pQPixmap = qLblViewOrig.pixmap();
  const QImage qImg = pQPixmap ? pQPixmap->toImage() : QImage();
  qLblViewResult.setPixmap(
    QPixmap::fromImage(transform(colMat, qImg)));
}

int main(int argc, char **argv)
{
  QApplication app(argc, argv);
  // setup GUI
  QWidget qWin;
  qWin.setWindowTitle(QString::fromUtf8("Qt Color Matrix Demo"));
  QGridLayout qGrid;
  QVBoxLayout qVBoxColMat;
  QLabel qLblColMat(QString::fromUtf8("Color Matrix:"));
  qVBoxColMat.addWidget(&qLblColMat, 0);
  QColorMatrixView qEditColMat;
  qEditColMat.setValues(Identity);
  qVBoxColMat.addWidget(&qEditColMat);
  QPushButton qBtnReset(QString::fromUtf8("Identity"));
  qVBoxColMat.addWidget(&qBtnReset);
  QPushButton qBtnGray(QString::fromUtf8("Grayscale"));
  qVBoxColMat.addWidget(&qBtnGray);
  qVBoxColMat.addStretch(1);
  qGrid.addLayout(&qVBoxColMat, 0, 0, 2, 1);
  QLabel qLblX(QString::fromUtf8(" \xc3\x97 "));
  qGrid.addWidget(&qLblX, 0, 1);
  QLabel qLblViewOrig;
  qGrid.addWidget(&qLblViewOrig, 0, 2);
  QPushButton qBtnLoad(QString::fromUtf8("Open..."));
  qGrid.addWidget(&qBtnLoad, 1, 2);
  QLabel qLblEq(QString::fromUtf8(" = "));
  qGrid.addWidget(&qLblEq, 0, 3);
  QLabel qLblViewResult;
  qGrid.addWidget(&qLblViewResult, 0, 4);
  qWin.setLayout(&qGrid);
  qWin.show();
  // install signal handlers
  QObject::connect(&qEditColMat, &QColorMatrixView::editingFinished,
    [&]() { update(qLblViewResult, qEditColMat, qLblViewOrig); });
  QObject::connect(&qBtnReset, &QPushButton::clicked,
    [&]() {
      qEditColMat.setValues(Identity);
      update(qLblViewResult, qEditColMat, qLblViewOrig);
    });
  QObject::connect(&qBtnGray, &QPushButton::clicked,
    [&]() {
      qEditColMat.setValues(ColorMatrix({
        0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
        0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
        0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
        0.00f, 0.00f, 0.00f, 1.0f, 0.0f,
        0.00f, 0.00f, 0.00f, 0.0f, 1.0f
      }));
      update(qLblViewResult, qEditColMat, qLblViewOrig);
    });
  QObject::connect(&qBtnLoad, &QPushButton::clicked,
    [&]() {
      qLblViewOrig.setPixmap(QPixmap::fromImage(open(&qBtnLoad)));
      update(qLblViewResult, qEditColMat, qLblViewOrig);
    });
  // initial contents
  {
    QImage qImg("colorMatrixDefault.jpg");
    qLblViewOrig.setPixmap(QPixmap::fromImage(qImg));
    update(qLblViewResult, qEditColMat, qLblViewOrig);
  }
  // runtime loop
  return app.exec();
}

QColorMatrixView.h

#ifndef Q_COLOR_MATRIX_VIEW_H
#define Q_COLOR_MATRIX_VIEW_H

#include <QLineEdit>
#include <QGridLayout>
#include <QWidget>

#include "colorMatrix.h"

class QColorMatrixView: public QWidget {
  Q_OBJECT
  private:
    QGridLayout _qGrid;
    QLineEdit _qEdit[5][5];
  signals:
    void editingFinished();
  public:
    QColorMatrixView(QWidget *pQParent = nullptr);
    virtual ~QColorMatrixView() = default;
    QColorMatrixView(const QColorMatrixView&) = delete;
    QColorMatrixView& operator=(const QColorMatrixView&) = delete;
    ColorMatrix values() const;
    void setValues(const ColorMatrix &mat);
};

#endif // Q_COLOR_MATRIX_VIEW_H

QColorMatrixView.cc

#include "QColorMatrixView.h"

QColorMatrixView::QColorMatrixView(QWidget *pQParent):
  QWidget(pQParent)
{
  QFontMetrics qFontMetrics(font());
  const int w = qFontMetrics.boundingRect(QString("-000.000")).width() + 10;
  for (int r = 0; r < 5; ++r) {
    for (int c = 0; c < 5; ++c) {
      QLineEdit &qEdit = _qEdit[r][c];
      _qGrid.addWidget(&qEdit, r, c);
      qEdit.setFixedWidth(w);
      QObject::connect(&qEdit, &QLineEdit::editingFinished,
        [this, r, c]() {
        _qEdit[r][c].setText(
          QString::number(_qEdit[r][c].text().toFloat(), 'f', 3));
        editingFinished();
      });
    }
  }
  setLayout(&_qGrid);
}

ColorMatrix QColorMatrixView::values() const
{
  ColorMatrix mat;
  for (int r = 0; r < 5; ++r) for (int c = 0; c < 5; ++c) {
    mat[r][c] = _qEdit[r][c].text().toFloat();
  }
  return mat;
}

void QColorMatrixView::setValues(const ColorMatrix &mat)
{
  for (int r = 0; r < 5; ++r) for (int c = 0; c < 5; ++c) {
    _qEdit[r][c].setText(QString::number(mat[r][c], 'f', 3));
  }
}

moc_colorMatrix.cc (考虑MOC生成源):

#include "moc_QColorMatrixView.cpp"

colorMatrix.pro (中的qmake项目文件):

SOURCES = colorMatrix.cc QColorMatrixView.cc
HEADERS = colorMatrix.h QColorMatrixView.h
SOURCES += moc_colorMatrix.cc
MOC_DIR = .

QT += widgets

和默认的样本图像colorMatrixDefault.jpg如果没有(猫)照片文件就在眼前:

虽然,我已经开发并在VS2013测试的应用程序,我建的和还测试上的cygwin ,以确保Qmake工程已经完成,自立式:

$ qmake-qt5 colorMatrix.pro

$ make

$ ./colorMatrix

此示例代码的增强版本,可以在github上发现的Qt彩色矩阵演示



文章来源: QPainter how draw texture with special color