2011-5-9

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值