基于标准C语言的数字图像处理基本框架
2013-10-09 22:05
246 查看
/article/4716064.html
考虑到现有的数字图像处理都是基于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
/*
2
****************************************Copyright (c)**************************************************
3
** Feisky
4
** http://www.cnblogs.com/feisky/
5
**
6
**------------------------------------- File Info ------------------------------------------------------
7
** File name: bmp.h
8
** Last modified Date: 2009-9-25
9
** Last Version: 1.0
10
** Descriptions: 位图文件结构及基本函数定义 打开和保存bmp文件
11
**
12
** Created by: Feisky
13
** Created date: 2009-07-25
14
** Version: 1.0
15
** Descriptions: Preliminary version.
16
**
17
**------------------------------------------------------------------------------------------------------
18
*/
19
#ifndef BMP_H_INCLUDED
20
#define BMP_H_INCLUDED
21
22
#include <ctype.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <malloc.h>
26
#include <string.h>
27
28
/**
29
* 位图文件结构及基本函数定义 打开和保存bmp文件
30
*/
31
typedef unsigned short WORD;
32
typedef unsigned long DWORD;
33
typedef long LONG;
34
typedef unsigned char BYTE;
35
36
/* 位图文件头结构 14字节 */
37
typedef struct tagBITMAPFILEHEADER {
38
WORD bfType;
39
DWORD bfSize;
40
WORD bfReserved1;
41
WORD bfReserved2;
42
DWORD bfOffBits;
43
} BITMAPFILEHEADER;
44
45
/* 位图信息头结构 40字节 */
46
typedef 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
/* 调色板 4字节 */
61
typedef struct tagRGBQUAD {
62
BYTE rgbBlue;
63
BYTE rgbGreen;
64
BYTE rgbRed;
65
BYTE rgbReserved;
66
} RGBQUAD;
67
68
/* 定义图像信息 */
69
typedef struct tagBITMAPINFO {
70
BITMAPINFOHEADER bmiHeader;
71
RGBQUAD bmiColors[1];
72
} BITMAPINFO;
73
74
/* 定义位图图像 */
75
typedef 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
/**
88
* 位图创建函数 创建一个Bitmap结构,并为图像数据分配空间
89
*
90
* 使用方法:
91
* Bitmap *bmp=(Bitmap*)malloc(sizeof(Bitmap));
92
* ret=CreateBitmap(bmp,50,50,3);
93
*/
94
int 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
/**
158
* 位图指针释放函数 释放位图数据空间
159
*
160
* 使用方法:
161
* ReleaseBitmap(bmp);
162
*/
163
void ReleaseBitmap(Bitmap* bmp)
164
{
165
free(bmp->imageData);
166
bmp->imageData=NULL;
167
free(bmp);
168
bmp=NULL;
169
}
170
171
/**
172
* 路径检查函数:是否为BMP文件,是否可读
173
* 正确返回0,错误返回-1
174
*
175
* 使用方法
176
* ret=CheckPath(path);
177
*/
178
int 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
/**
203
* 从文件中读取位图函数
204
* 正确返回0,错误返回-1
205
*
206
* 使用方法:
207
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
208
* ret=ReadBitmap(path, bmp);
209
*/
210
int 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
/**
282
* 保存位图到文件中去
283
* 正确返回0,错误返回-1
284
*
285
* 使用方法:
286
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
287
* ret=SaveBitmap(path, bmp);
288
*/
289
int 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;i<256;i++)
339
{
340
pal[i].rgbBlue=i;
341
pal[i].rgbGreen=i;
342
pal[i].rgbRed=i;
343
pal[i].rgbReserved=0;
344
}
345
if(fwrite(pal,sizeof(RGBQUAD)*256,1,fd)!=1)
346
{
347
printf("Error(SaveBitmap): can not write Color Palette.\n");
348
return -1;
349
}
350
}
351
352
353
//保存图像数据
354
ret=fwrite(bmp->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
/*
374
****************************************Copyright (c)**************************************************
375
** Feisky
376
** http://www.cnblogs.com/feisky/
377
**
378
**------------------------------------- File Info ------------------------------------------------------
379
** File name: basicprocess.h
380
** Last modified Date: 2009-9-28
381
** Last Version: 1.0
382
** Descriptions: 位图图像基本处理函数 图像格式转换
383
**
384
** Created by: Feisky
385
** Created date: 2009-9-28
386
** Version: 1.0
387
** Descriptions: Preliminary version.
388
**
389
**------------------------------------------------------------------------------------------------------
390
*/
391
392
#ifndef BASICPROCESS_H_
393
#define BASICPROCESS_H_
394
395
#include "bmp.h"
396
#include <math.h>
397
/**
398
* <font color="#3f7f5f">位图图像基本处理函数 图像格式转换</font>
399
*/
400
int 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;i<src->height;i++)
423
{
424
n=0;
425
for(j=0;j<src->width*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
/**
441
* Gray2RGB
442
*
443
* 使用方法:
444
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
445
* ret=ReadBitmap(path, bmp);
446
* dstbmp=(Bitmap*)malloc(sizeof(Bitmap));
447
* ret=Gray2RGB(bmp,dstbmp);
448
*/
449
int 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;i<src->height;i++)
472
{
473
n=0;
474
for(j=0;j<src->width;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
/**
489
* Gray2BW 图像二值化
490
*
491
* 使用方法:
492
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
493
* ret=ReadBitmap(path, bmp);
494
* dstbmp=(Bitmap*)malloc(sizeof(Bitmap));
495
* ret=Gray2BW(bmp,dstbmp);
496
*/
497
int 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;i<src->height;i++)
520
{
521
for(j=0;j<src->width;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
/**
540
* rgb2hsv
541
* r,g,b values are from 0 to 1
542
* h = [0,360], s = [0,1], v = [0,1]
543
* if s == 0, then h = -1 (undefined)
544
* 使用方法:
545
* rgb2hsv(0.2,0.3,0.3,&x,&y,&z);
546
*/
547
void rgb2hsv(float R, float G, float B, float *H, float *S, float* V)
548
{
549
float min, max, delta,tmp;
550
tmp = R<G?R:G;
551
min = tmp<B?tmp:B;
552
tmp = R>G?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
/**
581
* hsv2rgb
582
* r,g,b values are from 0 to 1
583
* h = [0,360], s = [0,1], v = [0,1]
584
* if s == 0, then h = -1 (undefined)
585
* 使用方法:
586
* hsv2rgb(60,0.3,0.5,&x,&y,&z);
587
*/
588
void 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
/**
642
* 直方图均衡化
643
* 返回 0正确 -1错误
644
*/
645
int HistEqualization(Bitmap* dstBmp, Bitmap* srcBmp)
646
{
647
return 0;
648
}
649
650
/*
651
* 中值滤波
652
*/
653
654
int MedFilt(Bitmap* dstBmp, Bitmap* srcBmp)
655
{
656
return 0;
657
}
658
659
#endif /* BASICPROCESS_H_ */
考虑到现有的数字图像处理都是基于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
/*
2
****************************************Copyright (c)**************************************************
3
** Feisky
4
** http://www.cnblogs.com/feisky/
5
**
6
**------------------------------------- File Info ------------------------------------------------------
7
** File name: bmp.h
8
** Last modified Date: 2009-9-25
9
** Last Version: 1.0
10
** Descriptions: 位图文件结构及基本函数定义 打开和保存bmp文件
11
**
12
** Created by: Feisky
13
** Created date: 2009-07-25
14
** Version: 1.0
15
** Descriptions: Preliminary version.
16
**
17
**------------------------------------------------------------------------------------------------------
18
*/
19
#ifndef BMP_H_INCLUDED
20
#define BMP_H_INCLUDED
21
22
#include <ctype.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <malloc.h>
26
#include <string.h>
27
28
/**
29
* 位图文件结构及基本函数定义 打开和保存bmp文件
30
*/
31
typedef unsigned short WORD;
32
typedef unsigned long DWORD;
33
typedef long LONG;
34
typedef unsigned char BYTE;
35
36
/* 位图文件头结构 14字节 */
37
typedef struct tagBITMAPFILEHEADER {
38
WORD bfType;
39
DWORD bfSize;
40
WORD bfReserved1;
41
WORD bfReserved2;
42
DWORD bfOffBits;
43
} BITMAPFILEHEADER;
44
45
/* 位图信息头结构 40字节 */
46
typedef 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
/* 调色板 4字节 */
61
typedef struct tagRGBQUAD {
62
BYTE rgbBlue;
63
BYTE rgbGreen;
64
BYTE rgbRed;
65
BYTE rgbReserved;
66
} RGBQUAD;
67
68
/* 定义图像信息 */
69
typedef struct tagBITMAPINFO {
70
BITMAPINFOHEADER bmiHeader;
71
RGBQUAD bmiColors[1];
72
} BITMAPINFO;
73
74
/* 定义位图图像 */
75
typedef 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
/**
88
* 位图创建函数 创建一个Bitmap结构,并为图像数据分配空间
89
*
90
* 使用方法:
91
* Bitmap *bmp=(Bitmap*)malloc(sizeof(Bitmap));
92
* ret=CreateBitmap(bmp,50,50,3);
93
*/
94
int 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
/**
158
* 位图指针释放函数 释放位图数据空间
159
*
160
* 使用方法:
161
* ReleaseBitmap(bmp);
162
*/
163
void ReleaseBitmap(Bitmap* bmp)
164
{
165
free(bmp->imageData);
166
bmp->imageData=NULL;
167
free(bmp);
168
bmp=NULL;
169
}
170
171
/**
172
* 路径检查函数:是否为BMP文件,是否可读
173
* 正确返回0,错误返回-1
174
*
175
* 使用方法
176
* ret=CheckPath(path);
177
*/
178
int 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
/**
203
* 从文件中读取位图函数
204
* 正确返回0,错误返回-1
205
*
206
* 使用方法:
207
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
208
* ret=ReadBitmap(path, bmp);
209
*/
210
int 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
/**
282
* 保存位图到文件中去
283
* 正确返回0,错误返回-1
284
*
285
* 使用方法:
286
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
287
* ret=SaveBitmap(path, bmp);
288
*/
289
int 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;i<256;i++)
339
{
340
pal[i].rgbBlue=i;
341
pal[i].rgbGreen=i;
342
pal[i].rgbRed=i;
343
pal[i].rgbReserved=0;
344
}
345
if(fwrite(pal,sizeof(RGBQUAD)*256,1,fd)!=1)
346
{
347
printf("Error(SaveBitmap): can not write Color Palette.\n");
348
return -1;
349
}
350
}
351
352
353
//保存图像数据
354
ret=fwrite(bmp->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
/*
374
****************************************Copyright (c)**************************************************
375
** Feisky
376
** http://www.cnblogs.com/feisky/
377
**
378
**------------------------------------- File Info ------------------------------------------------------
379
** File name: basicprocess.h
380
** Last modified Date: 2009-9-28
381
** Last Version: 1.0
382
** Descriptions: 位图图像基本处理函数 图像格式转换
383
**
384
** Created by: Feisky
385
** Created date: 2009-9-28
386
** Version: 1.0
387
** Descriptions: Preliminary version.
388
**
389
**------------------------------------------------------------------------------------------------------
390
*/
391
392
#ifndef BASICPROCESS_H_
393
#define BASICPROCESS_H_
394
395
#include "bmp.h"
396
#include <math.h>
397
/**
398
* <font color="#3f7f5f">位图图像基本处理函数 图像格式转换</font>
399
*/
400
int 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;i<src->height;i++)
423
{
424
n=0;
425
for(j=0;j<src->width*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
/**
441
* Gray2RGB
442
*
443
* 使用方法:
444
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
445
* ret=ReadBitmap(path, bmp);
446
* dstbmp=(Bitmap*)malloc(sizeof(Bitmap));
447
* ret=Gray2RGB(bmp,dstbmp);
448
*/
449
int 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;i<src->height;i++)
472
{
473
n=0;
474
for(j=0;j<src->width;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
/**
489
* Gray2BW 图像二值化
490
*
491
* 使用方法:
492
* bmp=(Bitmap*)malloc(sizeof(Bitmap));
493
* ret=ReadBitmap(path, bmp);
494
* dstbmp=(Bitmap*)malloc(sizeof(Bitmap));
495
* ret=Gray2BW(bmp,dstbmp);
496
*/
497
int 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;i<src->height;i++)
520
{
521
for(j=0;j<src->width;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
/**
540
* rgb2hsv
541
* r,g,b values are from 0 to 1
542
* h = [0,360], s = [0,1], v = [0,1]
543
* if s == 0, then h = -1 (undefined)
544
* 使用方法:
545
* rgb2hsv(0.2,0.3,0.3,&x,&y,&z);
546
*/
547
void rgb2hsv(float R, float G, float B, float *H, float *S, float* V)
548
{
549
float min, max, delta,tmp;
550
tmp = R<G?R:G;
551
min = tmp<B?tmp:B;
552
tmp = R>G?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
/**
581
* hsv2rgb
582
* r,g,b values are from 0 to 1
583
* h = [0,360], s = [0,1], v = [0,1]
584
* if s == 0, then h = -1 (undefined)
585
* 使用方法:
586
* hsv2rgb(60,0.3,0.5,&x,&y,&z);
587
*/
588
void 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
/**
642
* 直方图均衡化
643
* 返回 0正确 -1错误
644
*/
645
int HistEqualization(Bitmap* dstBmp, Bitmap* srcBmp)
646
{
647
return 0;
648
}
649
650
/*
651
* 中值滤波
652
*/
653
654
int MedFilt(Bitmap* dstBmp, Bitmap* srcBmp)
655
{
656
return 0;
657
}
658
659
#endif /* BASICPROCESS_H_ */
相关文章推荐
- C语言中闰年与素数算法
- 编译Rob Hess基于OpenCV的SIFT算法的C语言实现
- ※C++随笔※=>☆C++基础☆=>※№→友元●友元函数●友元类●友元模板
- (转)c语言随机数srandom( )
- C/C++中Static的作用详述
- C语言趣味编程--同时显示正弦曲线和余弦曲线
- C++进阶——初始化列表
- c++ typedef 函数指针的用法
- vs2012通过ADO连接Access2013(x64)
- c++ 虚函数
- C/C++数据对齐
- CppUnit快速入门
- c++基础
- I2C总线--C语言
- 编程基础—学习C语言基础的总结
- C++ primer(十三)--类继承、构造函数成员初始化、虚函数、抽象基类
- trie树--详解
- 调节系统显示亮度cpp代码
- C++进阶——虚函数和纯虚函数(转载)
- 主机字节序 大端小端