【QT小玩具】将图片转换为字符

1、首先是界面

widget.h

#include <QWidget>
#include <QImage>
#include <QFileDialog>
#include <QPushButton>
#include <QLabel>
#include <QPainter>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = 0);
    ~Widget();
protected:
    QPushButton *getImageBtn;
    QPushButton *transformBtn;
    QLineEdit *inputRatioEdit;
    QLineEdit *outputRatioEdit;

    QLabel *showImageLabel;
    QLabel *printLabel;

    QVBoxLayout *optionLayout;
    QHBoxLayout *mainLayout;
};

 widget.cpp 

 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    getImageBtn = new QPushButton("打开图片",this);
    transformBtn = new QPushButton("开始转换",this);
    inputRatioEdit = new QLineEdit("1-输入比例",this);
    outputRatioEdit = new QLineEdit("1-输出比例",this);

    showImageLabel = new QLabel(this);
    printLabel = new QLabel(this);

    optionLayout = new QVBoxLayout;
    optionLayout->addWidget(getImageBtn,0);
    optionLayout->addWidget(transformBtn,1);
    optionLayout->addWidget(inputRatioEdit,2);
    optionLayout->addWidget(outputRatioEdit,3);

    mainLayout = new QHBoxLayout(this);
    mainLayout->addWidget(showImageLabel,0);
    mainLayout->addLayout(optionLayout,1);
    mainLayout->addWidget(printLabel,2);
}

 ok到此为止我们需要的界面就完成了,虽然很简陋就是了 

2、连接槽

在类内添加如下代码

 
    QString m_image;
    double inputScalingRatio;
    double outputScalingRatio;

public slots:
    void readFile();
    void transformation();
    void inputScalingRatioChange(QString str);
    void outputScalingRatioChange(QString str);

 在构造函数内连接槽 

    connect(transformBtn,SIGNAL(clicked()),this,SLOT(transformation()));
    connect(inputRatioEdit,SIGNAL(textEdited(QString)),this,SLOT(inputScalingRatioChange(QString)));
    connect(outputRatioEdit,SIGNAL(textEdited(QString)),this,SLOT(outputScalingRatioChange(QString)));

 槽函数的实现 

readFile()

{
    QString s=QFileDialog::getOpenFileName(this,"open Image","/",
                                           "Images (*.png *.jpg)");
    if(s.isEmpty())
        return;
    m_image = s;
    QPixmap pixmap(s);
    pixmap = pixmap.scaled(pixmap.width()*inputScalingRatio,pixmap.height()*inputScalingRatio,Qt::KeepAspectRatio);
    showImageLabel->setPixmap(pixmap);
}

 读取文件并保存文件信息,之后把图片进行缩放后显示到showImageLabel里  

inputScalingRadioChange()

{
    if(str.toDouble()<0||str.toDouble()>10)
    {
        inputRatioEdit->setText(QString::number(inputScalingRatio));
        return;
    }

    inputScalingRatio = str.toDouble();

    if(showImageLabel->pixmap() == 0)
        return;

    QPixmap pixmap(m_image);
    pixmap = pixmap.scaled(pixmap.width()*inputScalingRatio,pixmap.height()*inputScalingRatio,Qt::KeepAspectRatio);
    showImageLabel->setPixmap(pixmap);
}

 改变输入的缩放比,在确认输入有意义后将重新设置显示 

outputScalingRatioChange()

void Widget::outputScalingRatioChange(QString str)
{
    if(str.toDouble()<0||str.toDouble()>10)
    {
        outputRatioEdit->setText(QString::number(inputScalingRatio));
        return;
    }

    outputScalingRatio = str.toDouble();

    if(printLabel->pixmap() == 0)
            return;

    transformation();
}

同上,改变输出比例

剩下一个槽单独进行讲解


3、transformation()

这个槽也就是最关键的转换了,在贴代码之前先解释一下其原理

转换分为4个步骤

1.获取图片

2.缩放

3.将像素值灰度化后存入数组

4.根据灰度值转换为字符并显示


先在头文件里定义

#define W_G 0.59
#define W_B 0.3

#define CW 5
#define CH 10

const QString print_char(".,`^*~:;!\\+(){}[]&$%#@");

 这三项分别是灰度化转换时的权重,显示时字符间距和所要显示的字符 

transformation()

void Widget::transformation()
{
    QImage image = showImageLabel->pixmap()->toImage();

    image = image.scaled(image.width()/CW*outputScalingRatio,image.height()/CH*outputScalingRatio);

    int **RGBArray = toRGBArray(image);
    if(RGBArray == 0)
        return;

    printText(RGBArray,image.width(),image.height());

    for(int i = 0;i < image.width();i++)
        delete[] RGBArray[i];
    delete[] RGBArray;
}

直接从showImageLabel里获取图片,将其根据缩放比和字符距离进行缩放,

然后通过toRGBArray()进行转换,再通过printText进行输出,

最后释放创建的数组


在类内添加

private:
    int** toRGBArray(QImage image);
    void printText(int** RGBArray,int W,int H);

用于实现第三步和第四步


toRGBArray()

int** Widget::toRGBArray(QImage image)
{
    if(image.isNull())
        return 0;

    int W = image.width();
    int H = image.height();

    int **RGBArray = new int*[W];
    for(int i = 0;i < W;i++)
    {
        RGBArray[i] = new int[H];
    }

    for(int x = 0;x < W;x++)
        for(int y = 0;y < H;y++)
        {
            QColor rgb = image.pixel(x,y);
            RGBArray[x][y] = rgb.red()*W_R + rgb.green()*W_G + rgb.blue()*W_B;
        }

    return RGBArray;
}

将对应像素的rgb值根据权重转换为灰度值后存入数组

printText()

void Widget::printText(int** RGBArray, int W, int H)
{
    QPixmap pixmap(CW*W,CH*H);
    pixmap.fill(QColor(0,0,0));

    QPainter painter(&pixmap);
    painter.setPen(QColor(255,255,255));

    for(int y = 0;y < H;y++)
    {
        for(int x = 0;x < W;x++)
        {
            painter.drawText(CW*x,CH*y,CW,CH,Qt::AlignCenter,print_char[RGBArray[x][y]/12]);
        }
    }

    printLabel->setPixmap(pixmap);
}

为了显示的更美观,决定将字符画在图片上进行输出(如需文本文件可自行在循环内添加文本输出代码)


最终效果













评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值