C语言实现二值图像模拟灰值图像显示效果

2022-07-21,,,

本文实例为大家分享了c语言实现二值图像模拟灰值图像显示效果的具体代码,供大家参考,具体内容如下

图案法

图案法(patterning)是指灰度可以用一定比例的黑白点组成的区域表示,从而达到整体图象的灰度感。黑白点的位置选择称为图案化。

下面介绍的一种设计标准图案的算法,是由limb在1969年提出的。

先以一个2×2的矩阵开始:

通过递归关系有:

其中mn和un均为2n×2n的方阵,un的所有元素都是1。
根据这个算法m2如下,为16级灰度的标准图案:

m3(8×8阵)比较特殊,称为bayer抖动表。m4是一个16×16的矩阵。

m3 表模拟灰值图像显示效果:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1)   //全紧凑模式

typedef struct {
 unsigned char bftype[2];
 unsigned long bfsize;
 unsigned short bfreserved1;
 unsigned short bfreserved2;
 unsigned long bfoffbits;
}bitmapfileheader;

typedef struct {
 unsigned long bisize;
 unsigned long biwidth;
 unsigned long biheight;
 unsigned short biplanes;
 unsigned short bibitcount;
 unsigned long bicompression;
 unsigned long bisizeimage;
 long bixpixpermeter;
 long biypixpermeter;
 unsigned long biclrused;
 unsigned long biclrimportant;
}bitmapinfoheader;


typedef struct{
 unsigned char rgbblue;
 unsigned char rgbgreen;
 unsigned char rgbred;
 unsigned char rgbreserved;

}rgbquad;

typedef struct{
 bitmapfileheader bfheader;
 bitmapinfoheader biheader;
 rgbquad palette[256];
 unsigned char *imgdata;
}bmp;

int main(){
 file *fp;
 if((fp=fopen("d:\temp\\test_gray.bmp","rb"))==null){
  perror("can not open file!");
  return -1;
 }
 //读入彩色bmp图像文件头,信息头和图像数据
 bitmapfileheader bfheader;
 fread(&bfheader,14,1,fp);
 bitmapinfoheader biheader;
 fread(&biheader,40,1,fp);
 int imsize=biheader.bisizeimage;
 int width=biheader.biwidth;
 int height=biheader.biheight;
 int bitcount=biheader.bibitcount;
 int linebytes=(width*bitcount+31)/32*4;
 
 fseek(fp,bfheader.bfoffbits,seek_set);
 unsigned char*imagedata=(unsigned char*)malloc(imsize*sizeof(unsigned char));
 fread(imagedata,imsize*sizeof(unsigned char),1,fp); 
 fclose(fp);

 bmp b;
 memcpy(&(b.bfheader),&bfheader,sizeof(bfheader));
 memcpy(&(b.biheader),&biheader,sizeof(biheader));
 b.imgdata=(unsigned char*)malloc(sizeof(unsigned char)*imsize);
 memset(b.imgdata,0,sizeof(unsigned char)*imsize);
 for(int i=0;i<256;i++){
  b.palette[i].rgbblue=i;
  b.palette[i].rgbgreen=i;
  b.palette[i].rgbred=i;
 }
 
 int i,j,temp;
 unsigned char bayer[8][8]={  
  0,32,8,40,2,34,10,42,
  48,16,56,24,50,18,58,26,
  12,44,4,36,14,46,6,38,
  60,28,52,20,62,30,54,22,
  3,35,11,43,1,33,9,41,
        51,19,59,27,49,17,57,25,
  15,47,7,39,13,45,5,37,
        63,31,55,23,61,29,53,21
 };
 for(i=0;i<height;i++){ 
  for(j=0;j<width;j++){ 
   temp=imagedata[linebytes*i+j];
   if((temp>>2)>bayer[i&7][j&7])
    b.imgdata[linebytes*i+j]=255;
   else
    b.imgdata[linebytes*i+j]=0;
  }
 }
 
 char savepath[]="d:\temp\\save_test.bmp";
 file *f_save=fopen(savepath,"wb");
 if(f_save==null){
  perror("can not open file!");
  return -2;
 }

 fwrite(&b.bfheader,sizeof(bitmapfileheader),1,f_save);
 fwrite(&b.biheader,sizeof(bitmapinfoheader),1,f_save);
 fwrite(&b.palette,1024,1,f_save);
 fwrite(b.imgdata,sizeof(unsigned char)*b.biheader.bisizeimage,1,f_save);
 fclose(f_save);
 
 free(imagedata);
 free(b.imgdata);
 getchar();
 return 0;
}

代码效果:

抖动法

假设灰度级别的范围从b(black)到w(white),中间值t为(b+w)/2,对应256级灰度,b=0,w=255,t=127.5。设原图中象素的灰度为g,误差值为e,则新图中对应象素的值用如下的方法得到:

if g > t then
  打白点
  e=g-w
else 
  打黑点
  e=g-b
 3/8 × e 加到右边的象素
 3/8 × e 加到上边的象素
 1/4 × e 加到右上方的象素

实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1)   //全紧凑模式

typedef struct {
 unsigned char bftype[2];
 unsigned long bfsize;
 unsigned short bfreserved1;
 unsigned short bfreserved2;
 unsigned long bfoffbits;
}bitmapfileheader;

typedef struct {
 unsigned long bisize;
 unsigned long biwidth;
 unsigned long biheight;
 unsigned short biplanes;
 unsigned short bibitcount;
 unsigned long bicompression;
 unsigned long bisizeimage;
 long bixpixpermeter;
 long biypixpermeter;
 unsigned long biclrused;
 unsigned long biclrimportant;
}bitmapinfoheader;


typedef struct{
 unsigned char rgbblue;
 unsigned char rgbgreen;
 unsigned char rgbred;
 unsigned char rgbreserved;

}rgbquad;

typedef struct{
 bitmapfileheader bfheader;
 bitmapinfoheader biheader;
 rgbquad palette[256];
 unsigned char *imgdata;
}bmp;

int main(){
 file *fp;
 if((fp=fopen("d:\temp\\test_gray.bmp","rb"))==null){
  perror("can not open file!");
  return -1;
 }
 //读入彩色bmp图像文件头,信息头和图像数据
 bitmapfileheader bfheader;
 fread(&bfheader,14,1,fp);
 bitmapinfoheader biheader;
 fread(&biheader,40,1,fp);
 int imsize=biheader.bisizeimage;
 int width=biheader.biwidth;
 int height=biheader.biheight;
 int bitcount=biheader.bibitcount;
 int linebytes=(width*bitcount+31)/32*4;
 
 fseek(fp,bfheader.bfoffbits,seek_set);
 unsigned char*imagedata=(unsigned char*)malloc(imsize*sizeof(unsigned char));
 fread(imagedata,imsize*sizeof(unsigned char),1,fp); 
 fclose(fp);

 bmp b;
 memcpy(&(b.bfheader),&bfheader,sizeof(bfheader));
 memcpy(&(b.biheader),&biheader,sizeof(biheader));
 b.imgdata=(unsigned char*)malloc(sizeof(unsigned char)*imsize);
 memset(b.imgdata,0,sizeof(unsigned char)*imsize);
 for(int i=0;i<256;i++){
  b.palette[i].rgbblue=i;
  b.palette[i].rgbgreen=i;
  b.palette[i].rgbred=i;
 }
 
 int i,j,temp;
 double e,f;
 for(i=0;i<height;i++){
  for(j=0;j<width;j++){
   b.imgdata[linebytes*i+j]=imagedata[linebytes*i+j]; //拷贝数据
  }
 }
 
 for(i=0;i<height;i++){ 
  for(j=0;j<width;j++){ 
   temp=b.imgdata[linebytes*i+j];
   if(temp>128){
    b.imgdata[linebytes*i+j]=255;
    e=(float)(temp-255);
   }
   else{
    b.imgdata[linebytes*i+j]=0;
    e=(float)temp;
   }
   if(j<width-1){
    f=b.imgdata[linebytes*i+j+1];
    f+=3.0/8.0*e;
    b.imgdata[linebytes*i+j+1]=(unsigned char)f; //向右传播
   }
   if(i<height-1){
    f=b.imgdata[linebytes*(i+1)+j];
    f+=3.0/8.0*e;
    b.imgdata[linebytes*(i+1)+j]=(unsigned char)f; //向上传播
    f=b.imgdata[linebytes*(i+1)+j+1];
    f+=1.0/4.0*e;
    b.imgdata[linebytes*(i+1)+j+1]=(unsigned char)f; //向右上传播
   }
  }
 }
 
 
 char savepath[]="d:\temp\\save_test.bmp";
 file *f_save=fopen(savepath,"wb");
 if(f_save==null){
  perror("can not open file!");
  return -2;
 }

 fwrite(&b.bfheader,sizeof(bitmapfileheader),1,f_save);
 fwrite(&b.biheader,sizeof(bitmapinfoheader),1,f_save);
 fwrite(&b.palette,1024,1,f_save);
 fwrite(b.imgdata,sizeof(unsigned char)*b.biheader.bisizeimage,1,f_save);
 fclose(f_save);
 
 free(imagedata);
 free(b.imgdata);
 getchar();
 return 0;
}

代码效果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

《C语言实现二值图像模拟灰值图像显示效果.doc》

下载本文的Word格式文档,以方便收藏与打印。