图像处理
图片加载
图片加载
#define PixMaxSize 4000*3000*2//10000*10000//4000*3000
/**
* @brief 设置图片
* @param image: 要展示图片的地址
*/
void setImage(const QString & image){
{
QImageReader imgReader;
imgReader.setFileName(image);
if (!imgReader.canRead())
{
}
else{
m_imageAttributes.width = imgReader.size().width();
m_imageAttributes.height = imgReader.size().height();
double sizeSum = imgReader.size().width()*imgReader.size().height();
// int maxSum = PixMaxSize*sin(45.0)*sin(45.0);
int maxSum = PixMaxSize/2;
if(sizeSum > maxSum){
// 要求比例
double requireProportion = qSqrt(maxSum*1.00/sizeSum);
int width = imgReader.size().width()*requireProportion;
int height = imgReader.size().height()*requireProportion;
// 缩略图按比例缩放
imgReader.setScaledSize(QSize(width,height));
}
// 读取图片
QImage img = imgReader.read();
// 需要转格式,不然QPainter无法绘制
if (img.format() == QImage::Format_Indexed8) {
img = img.convertToFormat(QImage::Format_ARGB32);
}
if(!img.isNull())
{
m_image = img;
m_originalImage = img;
m_widget->setImage(img);
}
}
}
图片按比例加载
///
/// \brief picScale 图片等比例缩放
/// \param pix 图片
/// \param path 路径
/// \param requiredImageSize 尺寸
/// \param supportIcon 图片找不到,是否支持显示图标
///
static void picScale(QPixmap &pix, QString path, QSize requiredImageSize, bool supportIcon = true)
{
// QImage/QPixmap 的大小限制为32767x32767 像素
QImageReader imgReader;
imgReader.setFileName(path);
if (!imgReader.canRead())
{
}
int nThumbnailWidth = requiredImageSize.width();
int nThumbnailHeight = requiredImageSize.height();
// 图片实际尺寸
QSize sizeImage = imgReader.size();
// 缩放后比例
QSize sizeImageEnd = sizeImage;
// 要求比例
double requireProportion = requiredImageSize.width()*1.00/requiredImageSize.height();
// 实际比例
double actualProportion = sizeImage.width()*1.00/sizeImage.height();
if(requireProportion < actualProportion){
sizeImageEnd.setWidth(requiredImageSize.width());
sizeImageEnd.setHeight(requiredImageSize.width()/actualProportion);
}
else{
sizeImageEnd.setWidth(requiredImageSize.height()*actualProportion);
sizeImageEnd.setHeight(requiredImageSize.height());
}
// 缩略图按比例缩放
imgReader.setScaledSize(sizeImageEnd);
// 读取图片
pix = QPixmap::fromImage(imgReader.read());
if(!pix.isNull()){
}
else {
if(supportIcon){
// 获取系统图标
QFileIconProvider provider;
QIcon icon = provider.icon(path);
pix = icon.pixmap(QSize(nThumbnailWidth,nThumbnailHeight));
}
pix = pix.scaled(sizeImageEnd, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
}
图片转Base64
///
/// \brief pixtoBase64 图片转base64
/// \param pix
/// \return
///
QByteArray pixtoBase64(QPixmap pix, QString type = "png")
{
QByteArray bytearray;
QBuffer buffer(&bytearray);
buffer.open(QIODevice::WriteOnly);
pix.save(&buffer,type.toUtf8().data());
QByteArray img64 = bytearray.toBase64();//base64编码
return img64;
}
Base64转图片
///
/// \brief base64toPix base64转图片
/// \param base64
/// \return
///
QByteArray CommonFunc::imagetoBase64(QImage image, QString type = "png")
{
QByteArray bytearray;
QBuffer buffer(&bytearray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer,type.toUtf8().data());
QByteArray img64 = bytearray.toBase64();//base64编码
return img64;
}
图片算法
水印
///
/// \brief drawWaterMark 给图片添加水印
/// \param image 图片
/// \param text 文本
/// \param type 类型 0全屏 1单行
/// \param fontSize 字号
/// \param foneFamily 字体族
/// \param color 颜色
/// \param angle 角度(0~360)
/// \param opacity 透明度(0~255)
///
static void drawWaterMark(QImage &image, QString text, int type = 0,int fontSize=20,
QString foneFamily="Arail", QColor color=QColor("#FF0000"),
int angle=45, int opacity=255)
{
QFont font;
font.setFamily(foneFamily);
font.setPixelSize(fontSize);
QColor paintColor(color.red(),color.green(),color.blue(),opacity);
QPainter painter(&image);
int spacing = 10;
font.setLetterSpacing(QFont::AbsoluteSpacing, spacing);
painter.setFont(font);
painter.setPen(paintColor);
//painter.translate(0, 0);//调整位置(左上角)
painter.translate(image.width() / 2, image.height() / 2);//调整位置(中心)
painter.rotate(angle);//画笔角度
int squareEdgeSize = (image.width() * sin(45.0) + image.height() * sin(45.0))/2;//对角线长度
int hCount = squareEdgeSize / ((fontSize + spacing) * (text.size() + 1)) + 1;
int x = squareEdgeSize / hCount + (fontSize + spacing) * 3;
int y = x / 2;
int textWidth = painter.fontMetrics().width(text);
int textHeight = painter.fontMetrics().height();
switch (type) {
case 0:
for (int i = 0; i < hCount; i++)
{
for (int j = 0; j < hCount * 2; j++)
{
int drawX = x * i;
int drawY = y * j;
painter.drawText(drawX-textWidth/2, drawY+textHeight/2,text);
if(i==0&&j==0){
continue;
}
painter.drawText(drawX-textWidth/2, -drawY+textHeight/2,text);
painter.drawText(-drawX-textWidth/2, drawY+textHeight/2,text);
painter.drawText(-drawX-textWidth/2, -drawY+textHeight/2,text);
}
}
break;
case 1:
painter.drawText(-textWidth/2, +textHeight/2,text);
break;
default:
break;
}
}
画线
///
/// \brief drawLine 给图片画线
/// \param image 图片
/// \param startPoint 起始点
/// \param endPoint 终止点
/// \param width 宽度
/// \param color 颜色
/// \param paint 状态 0画笔 1橡皮擦 2擦除
///
static void drawLine(QImage &image,QPointF startPoint,QPointF endPoint,int width = 20,
QColor color=QColor("#FF0000"),int paint = 0)
{
QPainter painter(&image);
/**
* 在QPen里面分别设置 颜色、宽度、画笔风格、画笔的端点风格、画笔连接风格
**/
QPen pen(color,width,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);
painter.setPen(pen);
switch (paint) {
case 0:
{
painter.drawLine(startPoint,endPoint);
break;
}
case 1:
{
// 需要橡皮擦时,设置合成模式为 CompositionMode_Clear
painter.setCompositionMode(QPainter::CompositionMode_Clear);
// QRectF eraseRect(startPoint - QPointF(width, width), QSizeF(width * 2, width * 2));
QRectF eraseRect(startPoint - QPointF(width/2.0, width/2.0), QSizeF(width, width));
// painter.drawRect(eraseRect);
painter.drawEllipse(eraseRect);
break;
}
case 2:
{
// 需要橡皮擦时,设置合成模式为 CompositionMode_Clear
painter.setCompositionMode(QPainter::CompositionMode_Clear);
int num = ceil(abs(endPoint.x() - startPoint.x()))+1;
for(int i = 0; i< num; i++){
QRectF eraseRect(startPoint + QPointF(width/2.0, width/2.0)*(2*i-1), QSizeF(width, width));
//painter.drawEllipse(eraseRect); //圆形区域
painter.drawRect(eraseRect); // 矩形区域
}
break;
}
default:
painter.drawLine(startPoint,endPoint);
break;
}
}
图片重叠
///
/// \brief imgQverlap 图片重叠
/// \param src 图片(底图)
/// \param secordImage 图片(上层)
/// \param point 位置
/// \param angle 角度
///
static void imgQverlap(QImage &src,QImage &secordImage,QPoint point= QPoint(0,0),float angle=0)
{
//绘制第一张图片
QPainter painterFirst(&src);
if(abs(angle) > 0.01){
CommonFunc::RotateImage(secordImage,angle);
}
//设置图片的重叠模式
painterFirst.setCompositionMode(QPainter::CompositionMode_SourceOver);
//重叠图片
painterFirst.drawImage(point, secordImage);
}
对比度
///
/// \brief AdjustContrast 调整对比度
/// \param Img 图片
/// \param iContrastValue 对比度
/// \return
///
static QImage AdjustContrast(QImage Img, int iContrastValue)
{
int pixels = Img.width() * Img.height();
unsigned int *data = (unsigned int *)Img.bits();
int red, green, blue, nRed, nGreen, nBlue;
if (iContrastValue > 0 && iContrastValue < 100)
{
float param = 1 / (1 - iContrastValue / 100.0) - 1;
for (int i = 0; i < pixels; ++i)
{
nRed = qRed(data[i]);
nGreen = qGreen(data[i]);
nBlue = qBlue(data[i]);
red = nRed + (nRed - 127) * param;
red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
green = nGreen + (nGreen - 127) * param;
green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
blue = nBlue + (nBlue - 127) * param;
blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;
data[i] = qRgba(red, green, blue, qAlpha(data[i]));
}
}
else
{
for (int i = 0; i < pixels; ++i)
{
nRed = qRed(data[i]);
nGreen = qGreen(data[i]);
nBlue = qBlue(data[i]);
red = nRed + (nRed - 127) * iContrastValue / 100.0;
red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
green = nGreen + (nGreen - 127) * iContrastValue / 100.0;
green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
blue = nBlue + (nBlue - 127) * iContrastValue / 100.0;
blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;
data[i] = qRgba(red, green, blue, qAlpha(data[i]));
}
}
return Img;
}
亮度
///
/// \brief AdjustBrightness 调整亮度
/// \param Img 图片
/// \param iBrightValue 亮度
/// \return
///
static QImage AdjustBrightness(QImage Img, int iBrightValue)
{
int red, green, blue;
int pixels = Img.width() * Img.height();
unsigned int *data = (unsigned int *)Img.bits();
for (int i = 0; i < pixels; ++i)
{
red= qRed(data[i])+ iBrightValue;
red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
green= qGreen(data[i]) + iBrightValue;
green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
blue= qBlue(data[i]) + iBrightValue;
blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue ;
data[i] = qRgba(red, green, blue, qAlpha(data[i]));
}
return Img;
}
饱和度
///
/// \brief AdjustSaturation 调整饱和度
/// \param Img 图片
/// \param iSaturateValue 饱和度
/// \return
///
static QImage AdjustSaturation(QImage Img, int iSaturateValue)
{
int red, green, blue, nRed, nGreen, nBlue;
int pixels = Img.width() * Img.height();
unsigned int *data = (unsigned int *)Img.bits();
float Increment = iSaturateValue/100.0;
float delta = 0;
float minVal, maxVal;
float L, S;
float alpha;
for (int i = 0; i < pixels; ++i)
{
nRed = qRed(data[i]);
nGreen = qGreen(data[i]);
nBlue = qBlue(data[i]);
minVal = min(min(nRed, nGreen), nBlue);
maxVal = max(max(nRed, nGreen), nBlue);
delta = (maxVal - minVal) / 255.0;
L = 0.5*(maxVal + minVal) / 255.0;
S = max(0.5*delta / L, 0.5*delta / (1 - L));
if (Increment > 0)
{
alpha = max(S, 1 - Increment);
alpha = 1.0 / alpha - 1;
red = nRed + (nRed - L*255.0)*alpha;
red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
green = nGreen + (nGreen - L*255.0)*alpha;
green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
blue = nBlue + (nBlue - L*255.0)*alpha;
blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;
}
else
{
alpha = Increment;
red = L*255.0 + (nRed - L * 255.0)*(1+alpha);
red = (red < 0x00) ? 0x00 : (red > 0xff) ? 0xff : red;
green = L*255.0 + (nGreen - L * 255.0)*(1+alpha);
green = (green < 0x00) ? 0x00 : (green > 0xff) ? 0xff : green;
blue = L*255.0 + (nBlue - L * 255.0)*(1+alpha);
blue = (blue < 0x00) ? 0x00 : (blue > 0xff) ? 0xff : blue;
}
data[i] = qRgba(red, green, blue, qAlpha(data[i]));
}
return Img;
}
锐度(待优化)
///
/// \brief AdjustSharpen 调整锐度
/// \param Img 图片
/// \param SharpenValue 锐度
/// \return
///
static QImage AdjustSharpen(QImage Img, int SharpenValue)
{
QImage newImage = Img;
int kernel [3][3]= {{0,-1,0},
{-1,5,-1},
{0,-1,0}};
int kernelSize = 3;
if(SharpenValue == 0){
return Img;
}
int sumKernel = SharpenValue;
int r,g,b;
QColor color;
for(int x=kernelSize/2; x<newImage.width()-(kernelSize/2); x++){
for(int y=kernelSize/2; y<newImage.height()-(kernelSize/2); y++){
r = 0;
g = 0;
b = 0;
for(int i = -kernelSize/2; i<= kernelSize/2; i++){
for(int j = -kernelSize/2; j<= kernelSize/2; j++){
color = QColor(Img.pixel(x+i, y+j));
r += color.red()*kernel[kernelSize/2+i][kernelSize/2+j];
g += color.green()*kernel[kernelSize/2+i][kernelSize/2+j];
b += color.blue()*kernel[kernelSize/2+i][kernelSize/2+j];
}
}
// r = qBound(0, r/sumKernel, 255);
// g = qBound(0, g/sumKernel, 255);
// b = qBound(0, b/sumKernel, 255);
r = qBound(0, r-sumKernel, 255);
g = qBound(0, g-sumKernel, 255);
b = qBound(0, b-sumKernel, 255);
newImage.setPixel(x,y, qRgb(r,g,b));
}
}
return newImage;
}
灰度
///
/// \brief AdjustGray 调整灰度
/// \param image 图片
/// \return
///
static void AdjustGray(QImage &image)
{
if(image.isNull())
{
return;
}
int width = image.width();
int height = image.height();
QRgb color;
int gray;
for(int i = 0; i < width; i++)
{
for(int j= 0; j < height; j++)
{
color = image.pixel(i, j);
gray = qGray(color);//(r*11+g*16+b*5)/32
//gray = (qRed(color)*11+qGreen(color)*16+qBlue(color)*5)/32;
image.setPixel(i, j,
qRgba(gray, gray, gray, qAlpha(color)));
}
}
}
黑白
///
/// \brief AdjustBinarize 调整黑白
/// \param image 图片
/// \param threshold 阈值(大于等于选定的阈值则将该像素置为白色,小于阈值就把像素置为黑色)
/// \return
///
static void AdjustBinarize(QImage &image, int threshold = 128)
{
if(image.isNull())
{
return;
}
int width = image.width();
int height = image.height();
QRgb color;
QRgb avg;
QRgb black = qRgb(0, 0, 0);
QRgb white = qRgb(255, 255, 255);
for(int i = 0; i < width; i++)
{
for(int j= 0; j < height; j++)
{
color = image.pixel(i, j);
avg = (qRed(color) + qGreen(color) + qBlue(color))/3;
image.setPixel(i, j, avg >= threshold ?
white : black);
}
}
}
旋转
///
/// \brief RotateImage 图像旋转
/// \param image 图片
/// \param angle 角度
///
static void RotateImage(QImage &image,float angle)
{
QMatrix matrix;
matrix.rotate(angle);
image = image.transformed(matrix,Qt::SmoothTransformation);
}
图像翻转
///
/// \brief FlipImage 图像翻转
/// \param image 图片
/// \param type 0 上下 1 左右
///
static void FlipImage(QImage &image,int type = 0)
{
bool horizontally = false;
bool vertically = false;
if(type == 0){
vertically = true;
}
else{
horizontally = true;
}
image = image.mirrored(horizontally,vertically);
}
图片等比例缩放
///
/// \brief pixScale 图片等比例缩放
/// \param pix 图片
/// \param requiredImageSize 尺寸
///
static void pixScale(QPixmap &pix, QSize requiredImageSize)
{
if(pix.isNull()){
return;
}
// 图片实际尺寸
QSize sizeImage = pix.size();
// 缩放后比例
QSize sizeImageEnd = sizeImage;
// 要求比例
double requireProportion = requiredImageSize.width()*1.00/requiredImageSize.height();
// 实际比例
double actualProportion = sizeImage.width()*1.00/sizeImage.height();
if(requireProportion < actualProportion){
sizeImageEnd.setWidth(requiredImageSize.width());
sizeImageEnd.setHeight(requiredImageSize.width()/actualProportion);
}
else{
sizeImageEnd.setWidth(requiredImageSize.height()*actualProportion);
sizeImageEnd.setHeight(requiredImageSize.height());
}
// 缩略图按比例缩放
pix = pix.scaled(sizeImageEnd, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}