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;
}

图片尺寸没变,画面颗粒感十足

 

 

posted @ 2018-11-23 09:53  q彩虹海q  阅读(366)  评论(0)    收藏  举报