位图 c语言算法
2013-04-22 23:09 keiigzy123 阅读(339) 评论(0) 收藏 举报//<<<<<<<<<<<<<<<<<<<<<<<<author gaizengyuan <<<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<<< time 2013.04.22<<<<<<<<<<<<<<<<<<< //<<<<<<<<<<<<<<<<<<<<<<没有完善,后续继续改进<<<<<<<<<<<<<<<<<<< #include <stdio.h> #include <stdlib.h> #include <string.h> #define GET_gray(bmp,i,j) ( *( bmp.ptr + bmp.line_width * i + j ) )//找到i行j列的像素地址 #define SET_gray(bmp,i,j,v) ( *( bmp.ptr + bmp.line_width * i + j ) = v ) typedef unsigned char BYTE;//定义BYTE类型,占1个字节 typedef unsigned short USHORT;//定义USHORT类型,占2个字节 typedef unsigned long ULONG;//定义ULONG类型,占4个字节 //<<<<<<<<<<<<<<<<<<<<<<<< 图像数据的全局参数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,// ULONG off_bits , width , height , line_width ; USHORT bit_count , pal_length ; //<<<<<<<<<<<<<<<<<<< 滤波掩膜的设置量(全局参数) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<// int nSize=3; int nW=nSize/2; int nWSize=nSize*nSize; int* OffSetX=(int*)malloc(nSize*sizeof(int));//X方向的偏移量 int* OffSetY=(int*)malloc(nSize*sizeof(int));//Y方向的偏移量 BYTE*MedianArray=(BYTE*)malloc(nWSize*sizeof(BYTE));//中间求中值的时候需要的数组 BYTE*dst=(BYTE*)malloc( line_width*height*sizeof(BYTE));//处理完后把数据放在dst中 //////////////////定义结构体//////////////////////////////// typedef struct tagCxBitmap //定义CxBitmap结构体 { BYTE* ptr; //指向位图的像素数据(0~255之间) ULONG width; //位图的宽度 ULONG height; //位图的高度 USHORT bit_count; //位图的位数 ULONG line_width; //位图每行像素所占的字节数 USHORT pal_length; //位图调色板的长度 BYTE* palette; //指向位图的调色板 }CxBitmap; //>>>>>>>>>>>>>>>>>>>定义找出数组的中值函数>>>>>>>>>>>>>>>>>>>>>>>>>// BYTE GetMedianNum(BYTE* bArray,int ilen) { //循环变量 int i,j; BYTE bTemp; for(i=0;i<ilen-1;++i) { for(j=0;j<ilen-i-1;++j) { if (bArray[j]>bArray[j+1]) { bTemp=bArray[j]; bArray[i]=bArray[i+1]; bArray[i+1]=bTemp; } } } if((ilen&1)>0) { bTemp=bArray[(ilen/2+1)]; } else { bTemp=(bArray[ilen/2]+bArray[ilen/2+1])/2; } return bTemp; }; /////////////////////// main主函数 ////////////////////////////// int main() { BYTE b = 0; CxBitmap bmp; FILE *fp = 0; ULONG dw = 0; USHORT w = 0; char path[256]; char outpath[256]; printf("Input the bitmap path: "); scanf("%s",path); if((fp = fopen( path, "rb" )) == NULL) { printf("can not open the bitmap " ); return 1; } else printf("read OK"); //////////////读入图像参数////////////////////////////////////////////////////// fseek( fp, 10, 0 );//set fp's 位置以0为基准偏移10 fread( &off_bits, 4, 1, fp );//从fp中读1个4长度的值到&off_bits fseek( fp, 18, 0 ); fread( &width, 4, 1, fp );//图像的宽度 fread( &height, 4, 1, fp );//图像的高度 fseek( fp, 28, 0 ); fread( &bit_count, 2, 1, fp );//位图的位数 //<<<<<<<<<<<<<<<<<<<<<< 读取调色板的信息<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<// pal_length = off_bits - 54; //调色板的颜色个数,前五十四个字节为文件头结构体和图像信息结构体。 if( bit_count == 8 ) { bmp.palette = (BYTE*)malloc( pal_length * sizeof(BYTE) );//调色板内存 if( !bmp.palette ) { printf("调色板申请内存失败"); return 0; } } else { bmp.palette = 0;//如果不是8位,就不用调色板 } if( bmp.palette ) { fseek( fp, 54, 0 ); fread( bmp.palette, pal_length, 1, fp );//把调色板数据读取到申请的内存中 } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 图像数据区的读取 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,// line_width = ( width * bit_count + 31 ) / 32 * 4;//位图每行像素所占的字节数=(位图的宽度*位图的位数+31)/32*4 bmp.line_width = line_width; bmp.width = width; bmp.height = height; bmp.bit_count = bit_count; bmp.pal_length = pal_length; bmp.ptr = (BYTE*)malloc( line_width * height * sizeof(BYTE) );//指向位图的像素数据(0~255之间) /*把图像像素复制到B中*/ if( !bmp.ptr ) { printf("为图像数据区申请内存失败"); bmp.width = 0; bmp.height = 0; bmp.bit_count = 0; return 0; } fseek( fp, off_bits, 0 ); fread( bmp.ptr, line_width * height, 1, fp ); fclose( fp );//参数读完,关闭文件 /////////////////////////////////////////////////////////////////////////////////////////// printf("Bitmap Width: %ld\n",bmp.width); printf("Bitmap Height: %ld\n",bmp.height); printf("Bitmap BitCount: %d\n",bmp.bit_count); printf("loaded the bitmap successfully...\n"); //////////////////////////////////处理图像矩阵(中值滤波)////////////////////////////////////////////////////// //循环变量 int k,i = 0, j = 0; int index; //<<<<<<<<<<,nSize*nSize模<<<<<<<<<<<<<<<<<<<<<<<<< for(i=0;i<nSize;i++) { for(j=0;j<nSize;j++) { OffSetY[i*nSize+j]=-nW+i; OffSetX[i*nSize+j]=-nW+j; } }; index=0; for(i=0;i<height-1;i++) { for(j=0;j<width-1;j++) { if(i<nW||j<nW||i>height-nW-1||j>width-nW-1)//图像边缘部分的处理 { dst[index]= GET_gray(bmp,i,j); } else{ for(k=0;k<nWSize;k++) { MedianArray[k]= GET_gray(bmp,(i+OffSetY[k]),(j+OffSetX[k])); } dst[index]=GetMedianNum(MedianArray,nWSize);//图像中央部分的处理 index++; } } }; int index2=0; for( i = 0; i < bmp.height; i++ ) { for( j = 0; j < bmp.width ; j ++ ) { index2=i*bmp.line_width+j; b=dst[index2]; //处理的数据写会到源图像中 SET_gray( bmp, i, j ,b); } } //////////////////////////保存/////////////////////////////////////////////////////////// printf("Input the bitmap path for save: "); scanf("%s",outpath); if( ( fp = fopen( outpath, "wb" ) ) == NULL ) { printf("can not create the bitmap : %s\n", outpath ); return 0; } //<<<<<<<<<<<<<<<<<图像文件头的读入<<<<<<<<<<<<<<<<<<<<<<<<<<, w = 19778;//第一个标志位,也就是‘BM’ fwrite( &w, 2, 1, fp ); dw = 14;// 图像文件头的大小14字节 fwrite( &dw, 4, 1, fp ); w = 0; fwrite( &w, 2, 1, fp );//保留位 fwrite( &w, 2, 1, fp );//保留位 if( bmp.bit_count == 8 ) dw = 1078;//从文件数据开始到数据区的偏移量,包含三部分(文件头,信息头,调色板) else dw = 54;//没有调色板的情况下,只有两个头结构体 fwrite( &dw, 4, 1, fp ); dw = 40;//信息头文件的大小 fwrite( &dw, 4, 1, fp ); dw = bmp.width; fwrite( &dw, 4, 1, fp );//写入宽度 dw = bmp.height; fwrite( &dw, 4, 1, fp );//写入高度 w = 0; fwrite( &w, 2, 1, fp );//位平面数 w = bmp.bit_count; fwrite( &w, 2, 1, fp );//写入单位像素位数 dw = 0; fwrite( &dw, 4, 1, fp );//写入压缩特性0表示无压缩 dw = bmp.height * ( bmp.width * bmp.bit_count + 31 ) / 32 * 4;//求出像素区的大小 fwrite( &dw, 4, 1, fp );//写入像素数据区区的大小的值 dw = 0; fwrite( &dw, 4, 1, fp );//水平颜色分辨率,这里写默认值 fwrite( &dw, 4, 1, fp );//垂直颜色分辨率,同上 fwrite( &dw, 4, 1, fp );//使用所有的颜色索引表 fwrite( &dw, 4, 1, fp );//所有的颜色都重要 if( bmp.palette != 0 ) { fwrite( bmp.palette, 1024, 1, fp );//这里是256*4,一共使用256个索引表,每个索引表占四个字节 } dw = bmp.height * ( bmp.width * bmp.bit_count + 31 ) / 32 * 4; fwrite( bmp.ptr, dw, 1, fp );//写入图像部分 fclose(fp); ///////////////////////////////////////////////////////////////////////////////////// return 0; }