关于用VC对图像进行裁剪

来源:互联网 发布:局域网屏幕监视软件 编辑:程序博客网 时间:2024/06/05 05:31

        由于用户的要求,需要采集图像,可以采集到的图像有很大一部分黑色的边框,用户需要把它裁掉,这可难到了我,找了很多资料,也没有现在的东西可用(哈哈,中国的程序员就是这样!),包括CSDN网站搜过,codeproject上search过,也Google了办天,没有找到很合适的函数或是库,
        在网上下了几个例子,关于图像显示、旋转、缩放的,看了看,还是没明白所以(主要是还是对图像的结构没有弄清除造成的),后来拿了一本〖VC++数字图像处理〗,主要是针对位图的基本格式及结构,搞清除后,自已试着用程序来读位图里面的信息,基本成功了(读真彩色图像,没有涉及到调色板)。
        在这个基础上,我想把源图像里面的一个区域拷贝并保存下来,可是这就成问题了,整了我两天时间,还是没有把它拷过来(主要是对位图的像素分布没有搞清楚),拷过来的也是乱七八招的,后来我看了一个叫CDIB(这还是坛子里一个叫laiyiling的发给我的,在此表示感谢!)的类,里面有一个关于Rotate的函数,让我豁然开朗,下面我把这两天幸苦的成果贴出共享!!!

//针对24色位图进行裁剪
//pSrcFile 源位图文件
//pDestFile 目标位图文件
//rect 要拷贝的矩形区域
BOOL CgdiDlg::CropBitmap(LPTSTR pSrcFile,LPTSTR pDestFile,LPRECT rect)
{
 CFile file;
 CFileException fe;
 BOOL ret=FALSE;

 if(!file.Open(pSrcFile,CFile::modeRead,&fe))//打开源位图文件
  return ret;
 CFile f;
 CFileException e;
 if( !f.Open( pDestFile, CFile::modeCreate | CFile::modeWrite, &e ) )//要拷到的位图文件
  return FALSE;

 DWORD retLen=0;
 DWORD dwBitsSize=file.GetLength();//文件长度

 HGLOBAL hImageBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwBitsSize);
 if(!hImageBuf)
 {
  //分配失败则返回
  file.Close();
  return FALSE;
 }

 LPSTR lpImage = (LPSTR)GlobalLock(hImageBuf);
 
 //将图像读入内存
 retLen=file.Read(lpImage,dwBitsSize);
 if(retLen<dwBitsSize)
 {
  if(hImageBuf!=NULL)
  {
   GlobalUnlock (hImageBuf);
   GlobalFree (hImageBuf);
  }
  file.Close();
  return FALSE;
 }

 //分析位图信息,
 int len=sizeof(BITMAPFILEHEADER);
 LPBITMAPFILEHEADER lpFhdr=(LPBITMAPFILEHEADER)lpImage;//文件头信息
 LPBITMAPINFOHEADER lpbmpInfo = (LPBITMAPINFOHEADER)(lpImage+sizeof(BITMAPFILEHEADER));//位图头信息


 int nLineBytes=0,nHeight=0,nWidth=0;
 nHeight = lpbmpInfo->biHeight;//源图像高
 nWidth = lpbmpInfo->biWidth; //源图像宽


 int rectWidth=rect->right-rect->left;
 int rectHeight=rect->bottom-rect->top; 
 
 //另外分配一块内存,存储大小为rectWidth*rectHeight的图像像素
 HGLOBAL hTmpBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,rectWidth*rectHeight*3);
 LPSTR lpPic = (LPSTR)GlobalLock(hTmpBuf);

 //每行不足4的整数位则补足
 if((lpbmpInfo->biWidth)%4!=0)
 {
  nLineBytes=lpbmpInfo->biWidth+(lpbmpInfo->biWidth)%4;
 }
 else
  nLineBytes=lpbmpInfo->biWidth;

// 拷贝原始图像到新分配的图像存储区
 for(int y=0;y< nHeight;y++)
 {
  for(int x=0;x< nLineBytes;x++)
  {
   if(x>=rect->left&&x<rect->right)
   {
    if((y>=rect->top&&y<rect->bottom))
    {
     //源图像像系指针(lpImage+lpFhdr->bfOffBits)
     //+每行的字节数*3(nLineBytes*y*3)
     //+现在每行的偏移量(x*3)

     *lpPic=*(lpImage+lpFhdr->bfOffBits+ nLineBytes*y*3+x*3);
     lpPic++;
     //
     *lpPic=*(lpImage+lpFhdr->bfOffBits+ nLineBytes*y*3+x*3+1);
     lpPic++;
     //
     *lpPic=*(lpImage+lpFhdr->bfOffBits+ nLineBytes*y*3+x*3+2);
     lpPic++;
    }
   }
  }
 }

 //将指针移回开始位置
 lpPic=lpPic-rectWidth*rectHeight*3;

 //存储位图
 //除了高度,宽度,不改变原始图像的其它信息

 lpbmpInfo->biWidth=rectWidth;
 lpbmpInfo->biHeight=rectHeight;

 f.Write(lpFhdr,len);//写文件头
 f.Write( lpbmpInfo,sizeof(BITMAPINFOHEADER));//写位图信息
 f.Write( lpPic,rectWidth*rectHeight*3);//写拷贝过来的图像像素
 f.Close();


 GlobalUnlock (hTmpBuf);//释放
 GlobalFree (hTmpBuf);

 GlobalUnlock (hImageBuf);//释放
 GlobalFree (hImageBuf);
 file.Close();
 return TRUE;
}
    上面这个函数还很不完善,请大虾多多指教!!!!
    
    不过我觉得对VC处理图像的初学者来说是很有帮助的,所以我把这个涵数贴出共享!!!
    主要的参考资料及网站如下:
        1、www.csdn.net(图像处理及算法版)
        2、www.codeproject.com
        3、www.vckbase.com
        4、〖VC++数字图像处理〗第二版

        本人联系方式:largeandsmall@163.com,欢迎多多指教!!!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃了烂洋葱怎么办? 榕树盆景不发芽怎么办? 茶树花掉叶子怎么办 玉米播种后下雨怎么办 多肉长出来的枝怎么办 多肉植物爆盆后怎么办 狗眼发炎了怎么办 旅行箱密码锁打不开怎么办 梅花夏季干支了怎么办 红梅树初夏落叶怎么办 电脑主机开关坏了怎么办 iqos加热片断了怎么办 眼睛容易出泪水怎么办 盖髓后牙齿疼痛怎么办 补牙材质掉了怎么办 补牙上药后痛怎么办 儿童牙缝隙大怎么办 牙齿塞药掉了怎么办啊 补牙后按压疼痛怎么办 补过的牙齿疼怎么办 堵完牙后牙涨疼怎么办 补牙到牙神经怎么办 想换飘窗窗户 大理石面怎么办 出差三个月绿萝怎么办 口红吊兰根烂怎么办 金鱼吊兰干枝怎么办 口红吊兰不开花怎么办 单位上班座位不好怎么办 简易办公室夏天闷热怎么办 开发商不让用公积金贷款怎么办 夏天脚底开裂缝怎么办 晚上脚丫子痒怎么办丫 栀子花长白粉虱怎么办 栀子花花骨朵变黄怎么办 栀子花苞焉了怎么办 水培栀子花焉了怎么办 三角梅叶子焉了怎么办 换瓣手术后出现漏洞怎么办 牙2瓣了怎么办 二件瓣反流已有20多年了怎么办 小阴唇静脉畸形怎么办