Qt中的直线插值

Line interpolation in Qt?

本文关键字:插值 Qt      更新时间:2023-10-16

我正试图通过分割线条的长度来减少画笔笔划的间距(在QPixmap上)。如果我乘以这条线,那么间距会增加,但间距永远不会减少。此外,这条线的最小长度似乎是一。很明显,将其分割会减少——可能会低于允许的金额?不确定这是否会对像素图的绘制产生负面影响。

以下是违规代码:

QLineF line = QLineF(lastPoint, endPoint);
float lineLength = line.length();
qDebug() << line.length();
line.setLength(lineLength / 50.0f);
qDebug() << line.length();
painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap);

下面是这个特定文件中的所有代码:

#include "inkspot.h"
#include "inkpuppet.h"
#include "ui_inkpuppet.h"
#include "newdialog.h"
#include "ui_newdialog.h"
#include <QtCore>
#include <QtGui>
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
InkSpot::InkSpot(QWidget *parent) :
    QWidget(parent)
{
    widget = this;
    drawing = false;
}
void InkSpot::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        lastPoint = event->pos();
        drawing = true;
    }
}
void InkSpot::mouseMoveEvent(QMouseEvent *event)
{
    if((event->buttons() & Qt::LeftButton) && drawing)
    {
        drawLineTo(event->pos());
    }
}
void InkSpot::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && drawing)
    {
        drawLineTo(event->pos());
        drawing = false;
    }
}
void InkSpot::drawLineTo(const QPoint &endPoint)
{
    QPainter painter(&pixmap);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::NoBrush);
    QFile *stencilInput; // file for input, assumes a SQUARE RAW 8 bit grayscale image, no JPG no GIF, no size/format header, just 8 bit values in the file
    char *brushPrototype; // raw brush prototype
    uchar *brushData; // raw brush data
    stencilInput = new QFile("C:/brush3.raw");  // open raw file
    stencilInput->open(QIODevice::ReadOnly);
    QDataStream in;
    in.setDevice(stencilInput);
    int size = stencilInput->size();  // set size to the length of the raw file
    brushPrototype = new char[size];  // create the brush prototype array
    in.readRawData(brushPrototype, size);  // read the file into the prototype
    brushData = new uchar[size];  // create the uchar array you need to construct QImage
    for (int i = 0; i < size; ++i)
        brushData[i] = (uchar)brushPrototype[i];  // copy the char to the uchar array
    QImage test(brushData, 128, 128, QImage::Format_Indexed8); // create QImage from the brush data array
     // 128x128 was my raw file, for any file size just use the square root of the size variable provided it is SQUARE
    QImage test2(128, 128, QImage::Format_ARGB32);

   QVector<QRgb> vectorColors(256);  // create a color table for the image
    for (int c = 0; c < 256; c++)
        vectorColors[c] = qRgb(c, c, c);
    test.setColorTable(vectorColors);  // set the color table to the image
    for (int iX = 0; iX < 128; ++iX)  // fill all pixels with 255 0 0 (red) with random variations for OIL PAINT effect
    // use your color of choice and remove random stuff for solid color
    // the fourth parameter of setPixel is the ALPHA, use that to make your brush transparent by multiplying by opacity 0 to 1
    {
        for (int iY = 0; iY < 128; ++iY)
        {
            test2.setPixel(iX, iY, qRgba(255, 100, 100, (255-qGray(test.pixel(iX, iY)))*0.5));
        }
    }
    // final convertions of the stencil and color brush
    QPixmap testPixmap = QPixmap::fromImage(test2);
    QPixmap testPixmap2 = QPixmap::fromImage(test);
    painter.setBrush(Qt::NoBrush);
    painter.setPen(Qt::NoPen);
    // in a paint event you can test out both pixmaps
    QLineF line = QLineF(lastPoint, endPoint);
    float lineLength = line.length();
    qDebug() << line.length();
    line.setLength(lineLength / 50.0f);
    qDebug() << line.length();
    painter.drawPixmap(line.p1().x() - 16, line.p2().y() - 16, 32, 32, testPixmap);
    //delete all dynamically allocated objects with no parents
    delete [] brushPrototype;
    delete [] brushData;
    delete stencilInput;

    lastPoint = endPoint;
}

void InkSpot::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::NoBrush);
    QRect rect = event->rect();
    painter.drawPixmap(rect, pixmap, rect);
    update();
}

不要使用QLineF,使用QPainterPath-它有几个非常方便的方法:

qreal QPainterPath::percentAtLength ( qreal len ) const
QPointF QPainterPath::pointAtPercent ( qreal t ) const
qreal length () const

因此,不使用QLineF,而是创建一个绘制器路径,该路径仅由从旧绘制光标位置到新绘制光标位置的一条直线组成,获取该直线的长度,并在长度上按间距递增迭代以获得一个百分比值,从中可以为必须绘制画笔像素图的每个位置获得QPointF。就这么简单。

编辑:好吧,它在这里,还没有测试过,大脑到终端,但类似这样的东西:

QPointF lastPosition, currentPosition;
qreal spacing;
void draw() {
    QPainterPath path;
    path.moveTo(lastPosition);
    path.lineTo(currentPosition);
    qreal length = path.length();
    qreal pos = 0;
    while (pos < length) {
        qreal percent = path.percentAtLength(pos);
        drawYourPixmapAt(path.pointAtPercent(percent)); // pseudo method, use QPainter and your brush pixmap instead
        pos += spacing;
    }
}