您的位置:首页 > 编程语言 > C语言/C++

基于标准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_ */

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: