QT 减少图片像素点及处理颜色的算法
随手记
问题背景:
需要处理一张图片,提取其中的像素点,用于进行接下来的业务逻辑。但是图片的像素点的个数往往是百万级别,甚至更多,而我们可接受的是几万,几千级别的。所以需要把图片的像素点压缩。
除此外,还需要把图片的颜色重新设置为固定的4中颜色。
压缩算法:
/*
参数1:缩小的倍速参数
参数二:方法
参数三:图片路径,名字
*/
void togray(int sx,int method,char * fileName){
QImage image(fileName);
//图片像素缩小的倍数
int suoxiao = getSuoXiao(sx);
QImage *img = new QImage(image);//原图像
QImage *grayImg;//处理后灰度图像
unsigned char *data=img->bits();//获取图像像素字节数据的首地址
int width=img->width();//图像宽
int height=img->height();//图像高
int bytePerLine=(width*24+31)/8;//图像每行字节对齐
unsigned char *graydata=new unsigned char[bytePerLine*(height)];//存储处理后的数据 bytePerLine*(height/(suoxiao-1))
unsigned char r,g,b;
int rs = 0;
int gs = 0;
int bs = 0;
int sum = 0;
//计算rgb的平均值
for (int i=0;i<height;i++)
{
for (int j=0;j<width;j++)
{
rs = rs+ *(data+2);
gs = gs+ *(data+1);
bs = bs+ *(data);
sum++;
data+=4;
}
}
rs = rs/sum;
gs = gs/sum;
bs = bs/sum;
qDebug()<<"R:"<<rs<<"\t G:"<<gs<<"\t B:"<<bs<<"\t 像素点:"<<sum;
data=img->bits();
int realSum = 0;
for (int i=0,k=0;i<height;i+=suoxiao,k++)
{
for (int j=0,p=0;j<width;j+=suoxiao,p++)
{
r = *(data+2);
g = *(data+1);
b = *data;
//红(255,0,0),黄(255,255,0),蓝(0,0,255),黑(0,0,0)
if(r>(rs)){
r =255;
if(g>(gs+25)){
g = 255;
}else{
g = (g+b)/2;
b = (g+b)/2;
}
}else {
if(b>bs){
b=255;
r = (r+g)/2;
}else{
r = (r+g+b)/3;
g = (r+g+b)/3;
b = (r+g+b)/3;
}
}
if(method ==1 ){
//方式一
graydata[k*bytePerLine+p*3] = r;
graydata[k*bytePerLine+p*3+1] = g;
graydata[k*bytePerLine+p*3+2] = b;
}else{
//方式二
graydata[i*bytePerLine+j*3] = r;
graydata[i*bytePerLine+j*3+1] = g;
graydata[i*bytePerLine+j*3+2] = b;
}
realSum++;
data+=4*suoxiao;
}
data = data+width*4*(suoxiao-1);
}
qDebug()<<"完成!缩小后像素点个数:"<<realSum;
if(method ==1 ){
//方式一
grayImg=new QImage(graydata,width/suoxiao,height/suoxiao,bytePerLine,QImage::Format_RGB888);//Format_RGB888
} else{
//方式二
grayImg=new QImage(graydata,width,height,bytePerLine,QImage::Format_RGB888);//Format_RGB888
}
grayImg->save("result.jpg");
}
压缩算法的思路就是,在原像素矩阵中,每隔固定的像素点后,再取像素点放到新的像素点矩阵中去。
经试验后发现,压缩倍数为二的倍数时,图片才不会变形,故获取压缩倍数的方法:
int getSuoXiao(int suoxiao){
return 2<<suoxiao;
}
但是某天突然发现,压缩后某些图片又变形了,最后发现,并不是2倍数的问题,而是与图片本书的像素点有关,若想压缩后图片不变形,则必须满足条件:width%x =0 x:每隔x行像素点取一行像素 w:图片的宽度
//参数一: 缩小的度
//参数二:图片的宽度
int GetImgDot::getSuoXiao(int sx,int w){
int suoxiao = 2;
if(w%2 ==0)
{
if(sx ==1)
{
if(w%4 ==0)
{
suoxiao = 4;
}
}else if(sx ==2){
if(w%8 ==0)
{
suoxiao = 8;
}
}else
suoxiao = 2;
}
else if(w%3 ==0)
{
suoxiao = 3;
}
else if(w%5 ==0)
{
suoxiao = 5;
}
else if(w%7 ==0)
{
suoxiao = 7;
}else{
qDebug()<<"\n\n无法计算缩小倍数::"<<w;
}
return suoxiao;
}
处理效果:
原图:(名称是b.jpg)

方式一:
调用代码:
//方式1:
int main(int argc, char *argv[]){
togray(1,1,"b");
return 0;
}
图片整齐缩小:

方式二:
调用代码
int main(int argc, char *argv[]){
togray(1,0,"b");
return 0;
}
图片尺寸没变,画面颗粒感十足

浙公网安备 33010602011771号