2011-5-9
2011年05月09日
考虑到现有的数字图像处理都是基于Windows平台,都或多或少使用了Win32 API函数,不能移植到Linux或者嵌入式系统中。为了使程序可移植,采用标准C语言建立了数字图像处理的基本框架,如下图所示:
程序参考了网上一些博客的内容,并进行了改变,建立了符合自己习惯的数据结构。主要实现了bmp格式图像的打开、保存、创建、图像颜色空间转换等功能,暂时还没有添加具体的处理函数。我想,既然有了程序的框架,添加算法只是编写一个个函数的问题。
本程序具体实现的功能如下:
* 打开和保存bmp文件,这里使用自定义数据结构Bitmap,相关函数定义如下:
bmp.h:
int CreateBitmap(Bitmap* bmp, int width, int height, int bitCount);
void ReleaseBitmap(Bitmap* bmp);
int CheckPath(char *path);
int ReadBitmap(char* path, Bitmap* bmp);
int SaveBitmap(char* path, Bitmap* bmp);
* 图像格式转换
basicprocess.h:
int RGB2Gray(Bitmap* src, Bitmap* dst);
int Gray2RGB(Bitmap* src, Bitmap* dst);
int Gray2BW(Bitmap* src, Bitmap* dst, int threshold);
void hsv2rgb(float H, float S, float V, float *R, float *G, float *B);
void rgb2hsv(float R, float G, float B, float *H, float *S, float* V);
程序源码如下,
1
19#ifndef BMP_H_INCLUDED
20#define BMP_H_INCLUDED
21
22#include
23#include
24#include
25#include
26#include
27
28
31typedef unsigned short WORD;
32typedef unsigned long DWORD;
33typedef long LONG;
34typedef unsigned char BYTE;
35
36
37typedef struct tagBITMAPFILEHEADER {
38 WORD bfType;
39 DWORD bfSize;
40 WORD bfReserved1;
41 WORD bfReserved2;
42 DWORD bfOffBits;
43} BITMAPFILEHEADER;
44
45
46typedef struct tagBITMAPINFOHEADER {
47 DWORD biSize; // 结构长度 40B
48 LONG biWidth;
49 LONG biHeight;
50 WORD biPlanes; // 1
51 WORD biBitCount; // 表示颜色要用到的位数
52 DWORD biCompression; // 压缩格式
53 DWORD biSizeImage; // 位图占用字节数=biWidth'(4的整倍数)*biHeight
54 LONG biXPelsPerMeter; // 水平分辨率
55 LONG biYPelsPerMeter; // 垂直分辨率
56 DWORD biClrUsed; // 本图像用到的颜色数
57 DWORD biClrImportant; // 本图像的重要颜色数
58} BITMAPINFOHEADER;
59
60
61typedef struct tagRGBQUAD {
62 BYTE rgbBlue;
63 BYTE rgbGreen;
64 BYTE rgbRed;
65 BYTE rgbReserved;
66} RGBQUAD;
67
68
69typedef struct tagBITMAPINFO {
70 BITMAPINFOHEADER bmiHeader;
71 RGBQUAD bmiColors[1];
72} BITMAPINFO;
73
74
75typedef struct _Bitmap
76{
77 BITMAPFILEHEADER bmfh;
78 BITMAPINFOHEADER bmih;
79 int width;
80 int height;
81 int bitCount; // 8 或者24
82 int imageSize; // 图像数据大小(imageSize=height*widthStep)字节
83 BYTE* imageData;//排列的图像数据
84 int widthStep; //排列的图像行大小
85}Bitmap;
86
87
94int CreateBitmap(Bitmap* bmp, int width, int height, int bitCount)
95{
96 bmp->width=width;
97 bmp->height=height;
98 bmp->bmih.biWidth=width;
99 bmp->bmih.biHeight=height;
100
101 bmp->widthStep=(int)((width*bitCount+31)/32)*4; //计算排列的宽度
102 bmp->imageSize=bmp->height*bmp->widthStep*sizeof(BYTE);//计算排列的图像大小
103
104 if(bitCount==8)
105 {
106 bmp->bitCount=8;
107 bmp->bmfh.bfType=0x4d42; //注意是4d42 这个地方折磨我一下午啊
108 bmp->bmfh.bfReserved1=0;
109 bmp->bmfh.bfReserved2=0;
110 bmp->bmih.biBitCount=8;
111 bmp->bmih.biSize=40;
112 bmp->bmih.biPlanes=1;
113 bmp->bmfh.bfSize=54+256*4+height*bmp->widthStep;
114 bmp->bmfh.bfOffBits=1078;
115 bmp->bmih.biBitCount=8;
116 bmp->bmih.biCompression=0;
117 bmp->bmih.biSizeImage=bmp->imageSize;
118 bmp->bmih.biClrUsed=0;
119 bmp->bmih.biClrImportant=0;
120 bmp->bmih.biXPelsPerMeter=0;
121 bmp->bmih.biYPelsPerMeter=0;
122 }
123 else if (bitCount==24)
124 {
125 bmp->bitCount=24;
126 bmp->bmfh.bfType=0x4d42;
127 bmp->bmih.biBitCount=24;
128 bmp->bmfh.bfReserved1=0;
129 bmp->bmfh.bfReserved2=0;
130 bmp->bmih.biSize=40;
131 bmp->bmih.biPlanes=1;
132 bmp->bmfh.bfSize=54+height*bmp->widthStep;
133 bmp->bmfh.bfOffBits=54;
134 bmp->bmih.biBitCount=24;
135 bmp->bmih.biSizeImage=bmp->imageSize;
136 bmp->bmih.biClrUsed=0;
137 bmp->bmih.biCompression=0;
138 bmp->bmih.biClrImportant=0;
139 bmp->bmih.biXPelsPerMeter=0;
140 bmp->bmih.biYPelsPerMeter=0;
141 }
142 else
143 {
144 printf("Error(CreateBitmap): only supported 8 or 24 bits bitmap.\n");
145 return -1;
146 }
147
148 bmp->imageData=(BYTE*)malloc(bmp->imageSize); //分配数据空间
149 if(!(bmp->imageData))
150 {
151 printf("Error(CreateBitmap): can not allocate bitmap memory.\n");
152 return -1;
153 }
154 return 0;
155}
156
157
163void ReleaseBitmap(Bitmap* bmp)
164{
165 free(bmp->imageData);
166 bmp->imageData=NULL;
167 free(bmp);
168 bmp=NULL;
169}
170
171
178int CheckPath(char *path)
179{
180 FILE *fd;
181 int len = strlen(path) / sizeof(char);
182 char ext[3];
183 //check whether the path include the characters "bmp" at end
184 strncpy(ext, &path[len - 3], 3);
185 if (!(ext[0] == 'b' && ext[1] == 'm' && ext[2] == 'p')) {
186 printf("Error(CheckPath): the extension of the file is not bmp.\n");
187 return -1;
188 }
189
190 //check whether the file can be read or not
191 fd = fopen(path, "r");
192 if (!fd)
193 {
194 printf("Error(CheckPath): can not open the file.\n");
195 return -1;
196 }
197 fclose(fd);
198
199 return 0;
200}
201
202
210int ReadBitmap(char* path, Bitmap* bmp)
211{
212 int ret;
213 FILE *fd;
214
215 //检查路径是否可读
216 ret=CheckPath(path);
217 if(ret==-1)
218 {
219 printf("Error(ReadBitmap): the path of the image is invalid.\n");
220 return -1;
221 }
222
223 //打开文件
224 fd=fopen(path,"rb");
225 if(fd==0)
226 {
227 printf("Error(ReadBitmap): can not open the image.\n");
228 return -1;
229 }
230
231 //读取文件信息头 14字节
232 fread(&(bmp->bmfh.bfType),sizeof(WORD),1,fd);
233 fread(&(bmp->bmfh.bfSize),sizeof(DWORD),1,fd);
234 fread(&(bmp->bmfh.bfReserved1),sizeof(WORD),1,fd);
235 fread(&(bmp->bmfh.bfReserved2),sizeof(WORD),1,fd);
236 fread(&(bmp->bmfh.bfOffBits),sizeof(DWORD),1,fd);
237
238 //读取位图信息头 40字节
239 fread(&(bmp->bmih.biSize),sizeof(DWORD),1,fd);
240 fread(&(bmp->bmih.biWidth),sizeof(DWORD),1,fd);
241 fread(&(bmp->bmih.biHeight),sizeof(DWORD),1,fd);
242 fread(&(bmp->bmih.biPlanes),sizeof(WORD),1,fd);
243 fread(&(bmp->bmih.biBitCount),sizeof(WORD),1,fd);
244 fread(&(bmp->bmih.biCompression),sizeof(DWORD),1,fd);
245 fread(&(bmp->bmih.biSizeImage),sizeof(DWORD),1,fd);
246 fread(&(bmp->bmih.biXPelsPerMeter),sizeof(DWORD),1,fd);
247 fread(&(bmp->bmih.biYPelsPerMeter),sizeof(DWORD),1,fd);
248 fread(&(bmp->bmih.biClrUsed),sizeof(DWORD),1,fd);
249 fread(&(bmp->bmih.biClrImportant),sizeof(DWORD),1,fd);
250
251 //创建位图结构
252 ret=CreateBitmap(bmp, bmp->bmih.biWidth, bmp->bmih.biHeight, bmp->bmih.biBitCount);
253 if(ret==-1)
254 {
255 printf("Error(CreateBitmap): can not CreateBitmap.\n");
256 return -1;
257 }
258
259 //读取图像数据
260 //由于4字节对齐格式
261 fseek(fd,bmp->bmfh.bfOffBits,SEEK_SET); //定位到图像数据区
262 ret=fread(bmp->imageData,bmp->imageSize,1,fd);
263 if(ret==0)
264 {
265 if(feof(fd)) //if the file pointer point to the end of the file
266 {
267 }
268 if(ferror(fd)) //if error happened while read the pixel data
269 {
270 printf("Error(ReadBitmap): can not read the pixel data.\n");
271 fclose(fd);
272 return -1;
273 }
274 }
275
276 //关闭文件
277 fclose(fd);
278 return 0;
279}
280
281
289int SaveBitmap(char* path, Bitmap* bmp)
290{
291 int ret;
292 FILE *fd;
293
294 //检查路径是否正确
295 int len = strlen(path) / sizeof(char);
296 char ext[3];
297 //check whether the path include the characters "bmp" at end
298 strncpy(ext, &path[len - 3], 3);
299 if (!(ext[0] == 'b' && ext[1] == 'm' && ext[2] == 'p'))
300 {
301 printf("Error(SaveBitmap): the extension of the file is not bmp.\n");
302 return -1;
303 }
304
305 //打开文件
306 fd=fopen(path,"wb");
307 if(fd==0)
308 {
309 printf("Error(SaveBitmap): can not open the image.\n");
310 return -1;
311 }
312
313 //保存文件信息头 14字节
314 fwrite(&(bmp->bmfh.bfType),sizeof(WORD),1,fd);
315 fwrite(&(bmp->bmfh.bfSize),sizeof(DWORD),1,fd);
316 fwrite(&(bmp->bmfh.bfReserved1),sizeof(WORD),1,fd);
317 fwrite(&(bmp->bmfh.bfReserved2),sizeof(WORD),1,fd);
318 fwrite(&(bmp->bmfh.bfOffBits),sizeof(DWORD),1,fd);
319
320 //保存位图信息头 40字节
321 fwrite(&(bmp->bmih.biSize),sizeof(DWORD),1,fd);
322 fwrite(&(bmp->bmih.biWidth),sizeof(DWORD),1,fd);
323 fwrite(&(bmp->bmih.biHeight),sizeof(DWORD),1,fd);
324 fwrite(&(bmp->bmih.biPlanes),sizeof(WORD),1,fd);
325 fwrite(&(bmp->bmih.biBitCount),sizeof(WORD),1,fd);
326 fwrite(&(bmp->bmih.biCompression),sizeof(DWORD),1,fd);
327 fwrite(&(bmp->bmih.biSizeImage),sizeof(DWORD),1,fd);
328 fwrite(&(bmp->bmih.biXPelsPerMeter),sizeof(DWORD),1,fd);
329 fwrite(&(bmp->bmih.biYPelsPerMeter),sizeof(DWORD),1,fd);
330 fwrite(&(bmp->bmih.biClrUsed),sizeof(DWORD),1,fd);
331 fwrite(&(bmp->bmih.biClrImportant),sizeof(DWORD),1,fd);
332
333 //如果为8位,则保存调色板
334 RGBQUAD pal[256];
335 int i;
336 if(bmp->bitCount==8)
337 {
338 for(i=0;ibmp->imageData,bmp->imageSize,1,fd);
355 if(ret!=1)
356 {
357 printf("Error(SaveBitmap): can not save the pixel data.\n");
358 return -1;
359 }
360
361 //关闭文件
362 fclose(fd);
363
364 return 0;
365}
366
367#endif // BMP_H_INCLUDED
368
369
370
371
372
373
391
392#ifndef BASICPROCESS_H_
393#define BASICPROCESS_H_
394
395#include "bmp.h"
396#include
397
400int RGB2Gray(Bitmap* src, Bitmap* dst)
401{
402 int ret;
403 int n=0,i,j;
404 BYTE r,g,b,gray;
405
406 //检查图像格式是否合法
407 if(src->bitCount!=24)
408 {
409 printf("Error(RGB2Gray): the source image must be in RGB format.\n");
410 return -1;
411 }
412
413 //为dst图像分配数据空间
414 ret=CreateBitmap(dst,src->width,src->height,8);
415 if(ret==-1)
416 {
417 printf("Error(RGB2Gray): can't create target image.\n");
418 return -1;
419 }
420
421 //计算灰度数据
422 for(i=0;iheight;i++)
423 {
424 n=0;
425 for(j=0;jwidth*3;j++,n++)
426 {
427 b=*(src->imageData+src->widthStep*(src->height-1-i)+j);
428 j++;
429 g=*(src->imageData+src->widthStep*(src->height-1-i)+j);
430 j++;
431 r=*(src->imageData+src->widthStep*(src->height-1-i)+j);
432 gray=(r*19595 + g*38469 + b*7472) >> 16;
433 *(dst->imageData+dst->widthStep*(dst->height-1-i)+n)=gray;
434 }
435 }
436
437 return 0;
438}
439
440
449int Gray2RGB(Bitmap* src, Bitmap* dst)
450{
451 int ret;
452 int n=0,i,j;
453 BYTE r;
454
455 //检查图像格式是否合法
456 if(src->bitCount!=8)
457 {
458 printf("Error(Gray2RGB): the source image must be in gray scale.\n");
459 return -1;
460 }
461
462 //为dst图像分配数据空间
463 ret=CreateBitmap(dst,src->width,src->height,24);
464 if(ret==-1)
465 {
466 printf("Error(Gray2RGB): can't create target image.\n");
467 return -1;
468 }
469
470 //计算灰度数据
471 for(i=0;iheight;i++)
472 {
473 n=0;
474 for(j=0;jwidth;j++,n++)
475 {
476 r=*(src->imageData+src->widthStep*(src->height-1-i)+j);
477 *(dst->imageData+dst->widthStep*(dst->height-1-i)+n)=r;
478 n++;
479 *(dst->imageData+dst->widthStep*(dst->height-1-i)+n)=r;
480 n++;
481 *(dst->imageData+dst->widthStep*(dst->height-1-i)+n)=r;
482 }
483 }
484
485 return 0;
486}
487
488
497int Gray2BW(Bitmap* src, Bitmap* dst, int threshold)
498{
499 int ret;
500 int n=0,i,j;
501 BYTE r;
502
503 //检查图像格式是否合法
504 if(src->bitCount!=8)
505 {
506 printf("Error(Gray2BW): the source image must be in gray scale.\n");
507 return -1;
508 }
509
510 //为dst图像分配数据空间
511 ret=CreateBitmap(dst,src->width,src->height,8);
512 if(ret==-1)
513 {
514 printf("Error(Gray2BW): can't create target image.\n");
515 return -1;
516 }
517
518 //计算灰度数据
519 for(i=0;iheight;i++)
520 {
521 for(j=0;jwidth;j++,n++)
522 {
523 r=*(src->imageData+src->widthStep*(src->height-1-i)+j);
524 if(r>=threshold)
525 {
526 n=255;
527 }
528 else
529 {
530 n=0;
531 }
532 *(dst->imageData+dst->widthStep*(dst->height-1-i)+j)=n;
533 }
534 }
535
536 return 0;
537}
538
539
547void rgb2hsv(float R, float G, float B, float *H, float *S, float* V)
548{
549 float min, max, delta,tmp;
550 tmp = RG?R:G;
553 max = tmp>B?tmp:B;
554 *V = max; // v
555
556 delta = max - min;
557
558 if( max != 0 )
559 *S = delta / max; // s
560 else
561 {
562 // r = g = b = 0 // s = 0, v is undefined
563 *S = 0;
564 *H = -1;
565 return;
566 }
567 if( R == max )
568 *H = ( G - B ) / delta; // between yellow & magenta
569 else if( G == max )
570 *H = 2 + ( B - R ) / delta; // between cyan & yellow
571 else
572 *H = 4 + ( R - G ) / delta; // between magenta & cyan
573
574 (*H) *= 60; // degrees
575 if( *H < 0 )
576 (*H) += 360;
577}
578
579
580
588void hsv2rgb(float H, float S, float V, float *R, float *G, float *B)
589{
590 int i;
591 float f, p, q, t;
592
593 if( S == 0 )
594 {
595 *R =*G = *B = V;
596 return;
597 }
598
599 H /= 60; // sector 0 to 5
600 i = floor( H );
601 f = H - i; // factorial part of h
602 p = V * ( 1 - S );
603 q = V * ( 1 - S * f );
604 t = V * ( 1 - S * ( 1 - f ) );
605
606 switch( i )
607 {
608 case 0:
609 *R = V;
610 *G = t;
611 *B = p;
612 break;
613 case 1:
614 *R = q;
615 *G = V;
616 *B = p;
617 break;
618 case 2:
619 *R = p;
620 *G = V;
621 *B = t;
622 break;
623 case 3:
624 *R = p;
625 *G = q;
626 *B = V;
627 break;
628 case 4:
629 *R = t;
630 *G = p;
631 *B = V;
632 break;
633 default: // case 5:
634 *R = V;
635 *G = p;
636 *B = q;
637 break;
638 }
639}
640
641
645int HistEqualization(Bitmap* dstBmp, Bitmap* srcBmp)
646{
647 return 0;
648}
649
650
653
654int MedFilt(Bitmap* dstBmp, Bitmap* srcBmp)
655{
656 return 0;
657}
658
659#endif
发表评论
-
html 特殊转义字符
2012-01-20 01:39 541html 特殊转义字符 2010年08月11日 HTM ... -
Notepad2 V4.1.24.62 免费版 是一个外观类似系统记事本的文本编辑工具
2012-01-20 01:39 529Notepad2 V4.1.24.62 免费版 是一个外观类似 ... -
简析HTML七种网页加密解密方法
2012-01-20 01:39 878简析HTML七种网页加密解 ... -
IIS服务器排错指南及错误代码大全
2012-01-20 01:39 680IIS服务器排错指南及错误代码大全 2011年06月22日 ... -
游侠在线自由测试版正式发布啦!!!
2012-01-20 01:39 565游侠在线自由测试版正式发布啦!!! 2010年08月26日 ... -
DDS 文件
2012-01-19 09:29 716DDS 文件 2012年01月04日 dds是Direc ... -
美化工具栏摘计
2012-01-19 09:29 646美化工具栏摘计 2011年02月06日 这种感觉就像是。 ... -
GDI+入门(十三、GDI+实例――灰度效果)
2012-01-19 09:28 680GDI+入门(十三、GDI+实例――灰度效果) 2011年1 ... -
VB获取图象的象素
2012-01-19 09:28 830VB获取图象的象素 2011 ... -
vc网络编程常用函数2
2012-01-17 02:04 840vc网络编程常用函数2 20 ... -
延时批处理
2012-01-17 02:04 634延时批处理 2012年01月12日 举个例子,我们要延时 ... -
Zigbee入门指导(二)
2012-01-17 02:03 802Zigbee入门指导(二) 2010年08月06日 Zi ... -
socket 相关函数
2012-01-17 02:03 360socket 相关函数 2011年03 ... -
Extjs IE内存问题
2012-01-17 02:03 624Extjs IE内存问题 2011年08月25日 《1. ... -
毕业纪念册
2012-01-15 21:25 454毕业纪念册 2009年06月27日 -
客家风情二(你将再次捧腹大笑)
2012-01-15 21:25 692客家风情二(你将再次捧腹大笑) 2009年11月12日 ... -
心情日记
2012-01-15 21:25 327心情日记 2010年10月09日 前段时间 ... -
日语N1~N2听力通关必备知识汇总及讲解(一)
2012-01-15 21:25 367日语N1~N2听力通关必备知识汇总及讲解(一) 2010年1 ...
相关推荐
e5v3和5代i7至尊都是LGA2011-3的,针脚定义没有区别,e5v3的datasheet里intel把针脚1-2011编号了,看得更加清楚点。 e7v2和e7v3都是LGA2011-1的,但是针脚定义不一定一样。 注2: LGA2011-3oc底座比公版多加的...
2011-2022年北大数字普惠金融指数“第五期”(包括省市县) 1、时间:2011-2022年 其中县级的时间为2014-2022年 ...5、参考文献:郭峰,王靖一,王芳,孔涛,张勋,程志云.测度中国数字普惠金融发展:指数编制与空间特征
本资源封装了针对Access通用的操作类库、和通用的数据分页、包含1000多个平时很常用的方法的封装。使用方便、如下类:AccessHelper、FTP、HttpClient、JScript、Json。新增功能:Excel导入导出功能、Access数据库增...
河南理工大学-《C语言程序设计》2010-2011-2A(2011-5-26)试卷-及答案.pdf
人事管理系统专业证书及职称2011-5-4人事管理系统专业证书及职称2011-5-4人事管理系统专业证书及职称2011-5-4
•改善了安装程序对 Win7 / Vista 的支持 (2011-6-9); •提高了安装程序对中文系统的兼容性 (2011-7-16)); •提高了安装程序的兼容性 (2011-10-31)。 如果您在使用 EasyX 当中遇到了问题,或者有更好的建议...
C++IE密码杀手111代码2011-5-5 还有很未完成的工作 大家自己看代码
CS-Numerical-2011-5-21瑞士信贷的银行题目
变电运行值班员竞赛题2011-9-5.pdf
无线电2011-5.
2011-12-5 MSN.docx
2011-5-17 数据库原理.doc
2014年汽车理论课程设计任务书--车辆2011-5-6.pdf
2010-2011-2数字图像处理实验指导书-5.pdf 2010-2011-2数字图像处理实验指导书-5.pdf
装大师智能cad系统+2011-5-23
linux精通必学2011-01-11.part5linux精通必学2011-01-11.part5
2011-2020各省金融业增加值_亿元2011-2020各省金融业增加值_亿元 2011-2020各省金融业增加值_亿元 2011-2020各省金融业增加值_ 亿元 2011-2020各省金融业增加值_亿元 行政区划代码 年份 所属省份 地 区 所属地域 ...
Uniblue PowerSuite 2011 3.0.1.3序列号(2011-5-10) 已测试可用
全球UML工具简介与推荐-2011-5更新
VB选择题(2011-5整理)-.pdf