彩色图片变灰色,图片亮度变暗变亮--图像处理之二
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了。那个由深到浅的色段完全可以看出了。虽然程序很简单,但是自己还是蛮开心的。
首先,在百度上搜下彩色图片变灰色(黑白),有很多的源码,其中它的原理在于亮度
=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了。那个由深到浅的色段完全可以看出了。虽然程序很简单,但是自己还是蛮开心的。
相关文章推荐
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果,滤波,图像截取) 对图片的处理 : 亮度调整 抓屏 翻转 随鼠标画矩形
- Java对图片的处理---缩放图像、图像切割、图像类型转换、彩色转为黑白
- CSS处理图片彩色变灰色
- 图片处理工具类: 功能:缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等
- 让网页图片变灰色将彩色图像变成灰度的三种方法
- 【Matlab图像处理】学习笔记:读取16进制RGB文档转为彩色图片
- android 图像颜色处理 图像的亮度变换 更改图片饱和度
- 基于canvas图像处理的图片 灰色图像
- C#图像亮度调式与伪彩色图的处理教程(推荐)
- c#怎么把一个彩色的图片处理成灰色的呢。
- 图像像素处理_明度/亮度/平均值/灰褐色/滤镜/灰色_canvas_js动画
- 原创 ···DELPHI 图片图形图像处理 PS置换滤镜效果,亮度/对比度,纹理贴图效果
- 本图片处理类功能非常之强大可以实现几乎所有WEB开发中对图像的处理功能都集成了,包括有缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等功能
- ImagesUtil 图片处理 缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印
- 去除图片黑色边框及折角部分的黑色边框(彩色图像和灰度图像均可)
- 图像处理------调整亮度与对比度
- 图像处理------相似图片识别(直方图应用篇) 分类: 视频图像处理 2015-07-24 10:42 56人阅读 评论(0) 收藏
- 图像处理经典图片Lena背后的故事
- 图像处理——第一篇,显示图片
- 怎样用N多小图片拼成一张大图?(数字图像处理)