操作图片像素,模板操作;
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPixmap>
#include <QDir>
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include <iostream>
using namespace std;
//typedef class CC complex;
typedef unsigned char byte;
template <class T>
class complex
{
public:
T data[3];
complex()
{
data[0] = 0;
data[1] =0;
data[2] =0;
}
complex(T a1,T a2 ,T a3)
{
data[0] = a1;
data[1] =a2;
data[2] =a3;
}
complex(byte b,int n)
{
data[0] = b;
data[1] =b;
data[2] =b;
}
complex operator +(const complex c)
{
return complex(data[0] +c.data[0],data[1] +c.data[1],data[2] +c.data[2]);
}
complex operator +=(const complex c)
{
return *this = complex(data[0] +c.data[0],data[1] +c.data[1],data[2] +c.data[2]);
}
complex operator -=(const complex c)
{
return *this = complex(data[0] -c.data[0],data[1] -c.data[1],data[2] -c.data[2]);
}
complex operator =(const complex c)
{
data[0] = c.data[0];
data[1] =c.data[1];
data[2] =c.data[2];
return *this;
}
};
//double abs(complex c)
//{
//}
void readImage(complex<double> data[], const QImage &srcImage)
{
const byte *pImageBytes = srcImage.bits(); //数据首地址
int depth = srcImage.depth(); //每个像素的bit数
int lineBytes = srcImage.bytesPerLine(); //每行的字节数
int w = srcImage.width(); //宽
int h = srcImage.height(); //高
const byte *pByte;
//遍历读取每个像素,并转换为灰度值
int i, j;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
if(8 == depth) //采用了256色调色板,8位颜色索引
{
// pByte = pImageBytes + i * lineBytes + j;
// data[i * w + j] = complex<byte>( *pByte, 0);
}
else if(32 == depth)//32位表示,数据格式为0xFFBBGGRR或0xAABBGGRR
{
pByte = pImageBytes + i * lineBytes + j * 4;
// //根据RGB模式转化成YIQ色彩模式的方式,取Y作为灰度值
// byte pixelValue = (byte)(0.299 * (float)pByte[0] + 0.587 * (float)pByte[1]
// + 0.114 * (float)pByte[2]);
// data[i * w + j] = complex<double>( pixelValue, 0);
data[i * w + j] = complex<double>( pByte[0], pByte[1],pByte[2]);
}
else
{
cout << "invalid format. depth = " << depth << " ";
return;
}
}
}
}
void writeImage(QImage &destImage, const complex<double> data[])
{
int lineBytes = destImage.bytesPerLine();
int depth = destImage.depth();
int w = destImage.width();
int h = destImage.height();
byte *pImageBytes = destImage.scanLine(0);
byte *pByte;
for(int i = 0; i < h; i++)
{
for(int j = 0; j < w; j++)
{
// double spectral = abs(data[i * w + j]) * coef; //灰度值调整
// spectral = spectral > 255 ? 255 : spectral;
//根据图像格式写数据
if(8 == depth)
{
// pByte = pImageBytes + i * lineBytes + j;
// *pByte = spectral;
}
else if(32 == depth)
{
pByte = pImageBytes + i * lineBytes + j * 4;
pByte[0] = (byte)data[i * w + j].data[0];
pByte[1] =(byte)data[i * w + j].data[1];
pByte[2] =(byte) data[i * w + j].data[2];
}
else
{
return;
}
}
}
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
fileMenu = menuBar()->addMenu(tr("文件"));
QToolBar *fileToolBar = addToolBar(tr("File"));
// const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
openAct = new QAction( tr("打开"), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("打开"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
saveAct = new QAction(tr("保存"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
exitAct = new QAction(tr("退出"), this);
exitAct->setShortcuts(QKeySequence::Quit);
exitAct->setStatusTip(tr("Exit the application"));
connect(exitAct, &QAction::triggered, this, &MainWindow::close);
fileMenu->addAction(openAct);
fileMenu->addAction(saveAct);
fileMenu->addAction(exitAct);
fileToolBar->addAction(openAct);
fileToolBar->addAction(saveAct);
fileToolBar->addAction(exitAct);
//
// ui->label->setPixmap(QPixmap("./01.png"));
ui->label->setScaledContents(true);
ui->label_2->setScaledContents(true);
// ui->
// complex <double>c;
// c.data[0] = 2;
// c.data[1] =3;
// c.data[2] =4;
// qDebug()<<c.data[2];
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::gaosi()
{
int w = img.width();
int h = img.height();
complex<double> *currentImageData = new complex<double>[w*h];
readImage(currentImageData, img);
qDebug()<<currentImageData->data[0];
complex<double> *buffer = new complex<double>[w * h];
memcpy(buffer, currentImageData, sizeof(complex<double>) * w * h);
qDebug()<<buffer->data[0];
int i, j;
for(i = 1; i < h - 1; i++)
{
for(j = 1; j < w - 1; j++)
{
complex<double> k;
k = buffer[(i - 1) * w + j - 1];
k += buffer[(i - 1) * w + j];
k += buffer[(i - 1) * w + j + 1];
k += buffer[i * w + j - 1];
k += buffer[i * w + j];
k += buffer[i * w + j + 1];
k += buffer[(i + 1) * w + j - 1];
k += buffer[(i + 1) * w + j];
k += buffer[(i + 1) * w + j + 1];
if (i == 1 && j ==1) qDebug()<<k.data[0];
k = complex<double>(k.data[0] / 9.0,k.data[1] / 9.0,k.data[2] / 9.0);
currentImageData[i * w + j] = k;
if (i == 1 && j ==1) qDebug()<<k.data[0];
}
}
writeImage(img, currentImageData);
ui->label_2->setPixmap(QPixmap::fromImage(img));
}
void MainWindow::sharp()
{
int w = img.width();
int h = img.height();
complex<double> *currentImageData = new complex<double>[w*h];
readImage(currentImageData, img);
//拷贝一份数据便于计算
complex<double> *buffer = new complex<double>[w * h];
memcpy(buffer, currentImageData, sizeof(complex<double>) * w * h);
//根据模板进行计算
//为了简化编码忽略了图像边界(i =0 or h, j =0 or w),对于整体效果没有影响
int i, j;
complex<double> k;
for(i = 1; i < h - 1; i++)
{
for(j = 1; j < w - 1; j++)
{
k = buffer[i * w + j];
k = complex<double>(k.data[0] * 5, k.data[1] * 5,k.data[2] * 5);
k -= buffer[(i - 1) * w + j];
k -= buffer[i * w + j - 1];
k -= buffer[i * w + j + 1];
k -= buffer[(i + 1) * w + j];
currentImageData[i * w + j] = k;
}
}
writeImage(img, currentImageData);
ui->label_2->setPixmap(QPixmap::fromImage(img));
}
void MainWindow::open()
{
// infoLabel->setText(tr("Invoked <b>File|Open</b>"));
QString initialName=QDir::currentPath();
// qDebug()<<initialName;
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
initialName,
tr("Images (*.png *.xpm *.jpg)"));
if(!fileName.isEmpty())
{
pic = QPixmap(fileName);
img = QImage(fileName);
img = img.convertToFormat(QImage::Format_RGB32);
qDebug()<<img.format();
ui->label->setPixmap(pic);
ui->label->setScaledContents(true);
}
else
{
}
}
void MainWindow::save()
{
// infoLabel->setText(tr("Invoked <b>File|Save</b>"));
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),QDir::currentPath(),tr("Images (*.png *.xpm *.jpg)"));
if (!fileName.isEmpty())
img.save(fileName);
QMessageBox msgBox;
msgBox.setText(QString("图片保存至:")+fileName);
msgBox.exec();
}
void MainWindow::close()
{
// infoLabel->setText(tr("Invoked <b>File|Save</b>"));
this->close();
}
//label
//A QLabel can contain any of the following content types:
//Content Setting
//Plain text Pass a QString to setText().
//Rich text Pass a QString that contains rich text to setText().
//A pixmap Pass a QPixmap to setPixmap().
//A movie Pass a QMovie to setMovie().
//A number Pass an int or a double to setNum(), which converts the number to plain text.
//Nothing The same as an empty plain text. This is the default. Set by clear().
//label->setPixmap(QPixmap("./pic.jpg"));
//QImage *image= new QImage("./pic.jpg");
//label->setPixmap(QPixmap::fromImage(image));
// QImage *image= new QImage("./pic1.jpg");
//label->setPixmap(QPixmap::fromImage(image));
//...........
//image->load("./pic2.jpg");
void MainWindow::on_pushButton_clicked()
{
if(ui->comboBox->currentIndex() == 0)
{
gaosi();
}
if(ui->comboBox->currentIndex() == 1)
{
sharp();
}
// 3. QImage * newImage = new QImage(origin->width(), origin->height(), QImage::Format_ARGB32);
// 4. QColor oldColor;
// 5. for(int x = 0; x<newImage->width(); x++){
// 6. for(int y = 0; y<newImage->height(); y++){
// 7. oldColor = QColor(origin->pixel(x,y));
// 8. int average = (oldColor.red()+oldColor.green()+oldColor.blue())/3;
// 9. newImage->setPixel(x,y,qRgb(average,average,average));
// 10. }
// 11. }
// 12. return newImage;
}