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);
}
为了显示的更美观,决定将字符画在图片上进行输出(如需文本文件可自行在循环内添加文本输出代码)
最终效果