Qt中的线插值? [英] Line interpolation in Qt?

查看:263
本文介绍了Qt中的线插值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过划分线的长度来减少我的笔触间距(在QPixmap上)。如果我乘以那条线,则间距会增加,但间距永远不会减小。同样,该行可以显示的最小长度是1。显然,将其除以可以降低-可能低于允许的数量?不确定是否会负面影响像素图的绘制。

I am trying to decrease the spacing of my brush strokes (on a QPixmap) by dividing the length of the line. If I multiply the line then the spacing increases, but the spacing never decreases. Also it appears the minimum length the line can have is one. Obviously dividing it will decrease that - possibly below the allowed amount? Not sure if that'd affect the drawing of the pixmap negatively or not.

这是令人讨厌的代码:

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

以下是此特定文件中的所有代码:

And here is all of the code in this particular file:

#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();

}


推荐答案

Don' t使用 QLineF ,使用 QPainterPath -它有一些非常方便的方法:

Don't use QLineF, use QPainterPath - it has a few very convenient methods:

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

因此,您无需使用 QLineF 来创建画家路径,该路径仅包含一条从旧光标到新绘图光标位置的单行,获取该行的长度,然后遍历长度增加的间隔(以空格为单位)以获得百分比值,从中可以得到 QPointF 必须绘制画笔像素图的每个位置。就是这么简单。

So instead of using a QLineF you create a painter path that consists only of a single line from the old to the new drawing cursor position, get the length of that line, and iterate over the length incrementing by the spacing to get a percent value, from which you can get a QPointF for every location the brush pixmap must be drawn. It is that simple.

编辑:好的,这是,还没有测试过,大脑到终端,但是像这样:

OK, here it is, haven't tested it, brain to terminal, but something like this:

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

这篇关于Qt中的线插值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆