您的位置:首页 > 其它

彩色图片变灰色,图片亮度变暗变亮--图像处理之二

2012-05-26 22:06 706 查看
今天做了彩色图片变灰色及图片变亮的处理。下面就分享下我的做法。

首先,在百度上搜下彩色图片变灰色(黑白),有很多的源码,其中它的原理在于亮度

=0.299R+0.587G+0.114B(具体怎么回事我赞不深究)。对于每个点,让亮度值替换原来的RGB即可。

根据这样的说法,那程序很简单了。我这里采用简易的公式 亮度=(3R+6G+B)/10。在程序的目录下

有个big.bmp文件(24位,就是用附件图画生成的那种),要生成的灰色文件为bigbmp2.bmp.以下是C语

言程序。

#include<stdio.h>

main()

{

//以下变量有可能有些是不需要的,没有做整理

char ch;

unsigned long cntsize=0;

unsigned long datasize=0;

unsigned int offset=0xffff;

unsigned char offset0,offset1,offset2,offset3;

unsigned char bits=0;

unsigned char width=0,height=0;

unsigned char datap[1000][3];

unsigned int i,k;

unsigned char widthsmall=0,heightsmall=0;

unsigned char widthbig=0,heightbig=0;

unsigned char datapbig[10000][3];//采用的例子big.bmp文件很小,大小不超过100*100,所以这里就定义了一个数组来存放bmp数据

unsigned char filehead[100];

unsigned char gray,maxgray;

unsigned long sumgray;

FILE *inf, * outftxt, * outfbmp;

cntsize=0;

datasize=0;

offset=0xffff;

if((inf=fopen("big.bmp","r"))==NULL)

{

printf("cant open source file!");

goto loopexit;

}

if((outfbmp=fopen("bigbmp.bmp","w"))==NULL)

{

printf("cant open target file!");

goto loopexit;

}

//以下这段是读big.bmp好知道长宽颜色数据在哪里开始之类,了解的同志可以略过

while(!feof(inf))

{

ch=fgetc(inf);

if(cntsize==0x02)printf(" filesize:");

else if(cntsize==0x0a)printf(" offset:");

else if(cntsize==0x0e)printf(" offset=%x ",offset);

else if(cntsize==0x12)printf(" width:");

else if(cntsize==0x16)printf(" height:");

else if(cntsize==0x1a)printf("width=%d height=%d ",width,height);

else if(cntsize==0x1c)printf(" bits:");

else if(cntsize==offset)printf(" offset start: ");

printf("%2x ",(unsigned char)ch);

if(datasize>1){if(datasize%3==2)printf(" ");}

else{filehead[cntsize]=(unsigned char)ch;}

datapbig[datasize/3][datasize%3]=(unsigned char)ch;

if(cntsize==0x0a)offset0=(unsigned char)ch;

else if(cntsize==0x0b)offset1=(unsigned char)ch;

else if(cntsize==0x0c)offset2=(unsigned char)ch;

else if(cntsize==0x0d)

{

offset3=(unsigned char)ch;

offset=(((unsigned int)offset1)<<8)|(((unsigned int)offset0));

}

else if(cntsize==0x12)offset0=(unsigned char)ch;

else if(cntsize==0x13)offset1=(unsigned char)ch;

else if(cntsize==0x14)offset2=(unsigned char)ch;

else if(cntsize==0x15)

{

offset3=(unsigned char)ch;

width=(((unsigned int)offset1)<<8)|(((unsigned int)offset0));

}

else if(cntsize==0x16)offset0=(unsigned char)ch;

else if(cntsize==0x17)offset1=(unsigned char)ch;

else if(cntsize==0x18)offset2=(unsigned char)ch;

else if(cntsize==0x19)

{

offset3=(unsigned char)ch;

height=(((unsigned int)offset1)<<8)|(((unsigned int)offset0));

}

else if(cntsize==0x1c)bits=(unsigned char)ch;

cntsize++;if(cntsize>offset){datasize++;}

fputc(ch,outfbmp);

}

fclose(inf);

fclose(outfbmp);

printf("\n data:\n");

for(i=0;i<(datasize/3);i++)

{

for(k=0;k<3;k++)

{

printf("%x ",datapbig[i][k]);

}

printf(" ");

}

widthsmall=width,heightsmall=height;

//以上bmp文件头部放在filehead[i]里,数据放在datapbig[i][k]里面 ,点个数为datasize

//sumgray为所有亮度之和,maxgray为最亮的点的亮度,这段是为了后面的提高亮度准备的,对于只是要转成灰色图片的同志略过

sumgray=0;maxgray=0;

for(i=0;i<(datasize/3);i++)

{

//得到当前点的亮度,这里R为datapbig[i][2]

gray=(((unsigned int)datapbig[i][0])*1+((unsigned int)datapbig[i][1])*6+((unsigned int)datapbig[i][2])*3)/10;

if(gray>maxgray)maxgray=gray;

sumgray=sumgray+gray;

}

//写灰色到bigbmp2.bmp中

if((outfbmp=fopen("bigbmp2.bmp","w"))==NULL)

{

printf("cant open target file!");

goto loopexit;

}

for(i=0;i<offset;i++)

{

fprintf(outfbmp,"%c",filehead[i]);

//fprintf(outfbmp,"%c",1);

}

for(i=0;i<(datasize/3);i++)

{

gray=(((unsigned int)datapbig[i][0])*1+((unsigned int)datapbig[i][1])*6+((unsigned int)datapbig[i][2])*3)/10;

//gray=gray*255/maxgray;//这句话如果不隐掉则能提高此灰色图片的对比度,即较暗的灰色变白

for(k=0;k<3;k++)

fprintf(outfbmp,"%c",gray);//灰色数据写到bigbmp2.bmp中

}

fclose(outfbmp);

printf("i love frog");

loopexit:

;

}

下面说下灰色图片提高对比度,我这里说的不是人家标准的对比度的意思,如果big.bmp整体颜色都很

灰暗,那我怎么才能看清楚这幅图呢?我只需把稍微亮的点变成较亮的点就可以了,而原来黑色点还是

保持黑色就可以了。比如说我检测到整幅图的最亮的点值为0x30,比较亮的点值为0x20,那我想把最亮的

点值提高到0xff,那么较亮的点提高为 0x20*0xff/0x30;所以只要把上面的程序

中//gray=gray*255/maxgray;的双斜杠去掉就可以了。当然,不是一定要最亮点非要提高到0xff,提高的

值自己可以改成自己的喜欢的。

刚才说的是灰色图片提高对比度的问题,那彩色图片呢?我搜了下百度,我好像没有看到统一的一个说

法,所以我这里就用最简单的方法,RGB每个颜色提高同样的比值,既写数据那段改成如下:

for(i=0;i<(datasize/3);i++)

{

for(k=0;k<3;k++)

{

//在函数开头定义了databigfinite为unsigned int型

databigfinite=((unsigned int)datapbig[i][k])*200/maxgray;//这里假使最亮的点亮度为200,不是上面举例的255

if(databigfinite>255)databigfinite=255;//如果R或G或B大于255,就简单处理为255

datapbig[i][k]=databigfinite;

fprintf(outfbmp,"%c",datapbig[i][k]);

}

}

通过实验效果还行,但是对于图片的由深到浅的红色一块效果就不好了,究其原因是因为当RGB中一个值提高大于255就简单的当做255处理了事了。那如何解决这个问题呢?我们可以用个简单的办法下了解下这个问题的本质。

看附件图画里选择颜色双击会有具体的颜色条,比如红色,那个颜色条会有RGB分别为255 0 0,如果把颜色往浅色调的话,则GB同时增加值。根据这个原理(其实我不太清楚具体原理啦)在程序中如果R多余255,则把多出来的值平均分给GB。下面是对这段处理的程序(因为编个简洁的程序比较费脑子,我又急于看结果,所以就分成琐碎的好几个 if语句)

for(i=0;i<(datasize/3);i++)

{

for(k=0;k<3;k++)

{

//这个databigfinite[k]代替上面的databigfinite 定义为数组databigfinite[3]

databigfinite[k]=((unsigned int)datapbig[i][k])*200/maxgray;

}

if((databigfinite[0]>255)||(databigfinite[1]>255)||(databigfinite[2]>255))

{

if((databigfinite[0]+databigfinite[1]+databigfinite[2])>3*255)

{

databigfinite[0]=255;databigfinite[1]=255;databigfinite[2]=255;

}

else if((databigfinite[0]>255)&&(databigfinite[1]>255))

{

databigfinite[2]=databigfinite[2]+(databigfinite[0]-255+databigfinite[1]-255);

databigfinite[0]=255;databigfinite[1]=255;

}

else if((databigfinite[0]>255)&&(databigfinite[2]>255))

{

databigfinite[1]=databigfinite[1]+(databigfinite[0]-255+databigfinite[2]-255);

databigfinite[0]=255;databigfinite[2]=255;

}

else if((databigfinite[2]>255)&&(databigfinite[1]>255))

{

databigfinite[0]=databigfinite[0]+(databigfinite[2]-255+databigfinite[1]-255);

databigfinite[2]=255;databigfinite[1]=255;

}

else if(databigfinite[0]>255)

{

databigfinite[1]=databigfinite[1]+(databigfinite[0]-255)/2;

databigfinite[2]=databigfinite[2]+(databigfinite[0]-255)/2;

databigfinite[0]=255;

}

else if(databigfinite[1]>255)

{

databigfinite[0]=databigfinite[0]+(databigfinite[1]-255)/2;

databigfinite[2]=databigfinite[2]+(databigfinite[1]-255)/2;

databigfinite[1]=255;

}

else if(databigfinite[2]>255)

{

databigfinite[1]=databigfinite[1]+(databigfinite[2]-255)/2;

databigfinite[0]=databigfinite[0]+(databigfinite[2]-255)/2;

databigfinite[2]=255;

}

}

for(k=0;k<3;k++)

{

datapbig[i][k]=databigfinite[k];

fprintf(outfbmp,"%c",datapbig[i][k]);

}

}

到这里就OK了。那个由深到浅的色段完全可以看出了。虽然程序很简单,但是自己还是蛮开心的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐