`
cloudtech
  • 浏览: 4606122 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

bmp图片合并算法

 
阅读更多
用到的数据结构如下:
  1. //一个方框
  2. structRectItem
  3. {
  4. unsignedintx;//方框在合并后的图片的x坐标
  5. unsignedinty;//方框在合并后的图片的y坐标
  6. unsignedintwidth;//方框的宽
  7. unsignedintheight;//方框的高
  8. };
  9. //一张图片
  10. structImageItem
  11. {
  12. unsignedintid;//图片item的ID
  13. unsignedintx;//图片item在合并后的图片的x坐标
  14. unsignedinty;//图片item在合并后的图片的y坐标
  15. charfilename[256];//图片名字
  16. BITMAPbmp;//BITMAP结构,只用于到高宽
  17. HBITMAPhbmp;//图片handle,借用windowsAPI合并图片
  18. };
  19. //图片列表
  20. classImageList
  21. {
  22. public:
  23. voidInsert(CStringstrPath);
  24. ImageList();
  25. ~ImageList();
  26. intGetMaxHeight();
  27. intGetMaxWidth();
  28. BOOLmerge(CStringoutfile);//生成合并后的图片
  29. voidInitFromStringArray(CString*pStr,intcount);
  30. voidLoadFromIni(CStringstrPath);
  31. voidSaveToIni(CStringstrPath);
  32. intGetImageCount();
  33. ImageItemimages[128];//待合并的图片数组
  34. private:
  35. voidMyBitBlt(intindex);//计算出images[index]在合并后图片的坐标
  36. voidDeleteRectItem(intindex);
  37. voidInsertRectItem(RectItem*item);
  38. voidclean();
  39. RectItemrects[256];//合并时产生的空隙(方框)数组
  40. intmerge_image_width;//合并后图片的宽,实际上是等于要合并的图片中宽最大的图片的宽
  41. intmerge_image_height;//合并后图片的高
  42. intm_imageCount;//待合并的图片数
  43. intm_rectCount;//空隙(方框)方框数
  44. };
  45. externImageListGlobalImageList;
cpp文件如下:
  1. ImageList::ImageList()
  2. {
  3. memset(images,0,sizeof(images));
  4. memset(rects,0,sizeof(rects));
  5. m_imageCount=0;
  6. m_rectCount=0;
  7. merge_image_width=0;
  8. merge_image_height=0;
  9. }
  10. ImageList::~ImageList()
  11. {
  12. clean();
  13. }
  14. intImageList::GetImageCount()
  15. {
  16. returnm_imageCount;
  17. }
  18. voidImageList::Insert(CStringstrPath)
  19. {
  20. ImageItemitem;
  21. item.hbmp=(HBITMAP)LoadImage(AfxGetInstanceHandle(),
  22. (LPCTSTR)strPath,
  23. IMAGE_BITMAP,
  24. 0,
  25. 0,
  26. LR_LOADFROMFILE);
  27. if(item.hbmp==NULL)
  28. {
  29. CStringstr;
  30. str.Format("无法打开指定的图片:%s",strPath);
  31. AfxMessageBox(str);
  32. }else
  33. {
  34. GetObject(item.hbmp,sizeof(BITMAP),&item.bmp);
  35. }
  36. //memset(images[m_imageCount].filename,0,sizeof(images[m_imageCount].filename);
  37. strcpy(item.filename,strPath.GetBuffer(strPath.GetLength()));
  38. //对images进行排序
  39. for(inti=0;i<m_imageCount;i++)
  40. {
  41. if(item.bmp.bmWidth>images[i].bmp.bmWidth)
  42. break;
  43. if(item.bmp.bmWidth==images[i].bmp.bmWidth&&item.bmp.bmHeight>images[i].bmp.bmHeight)
  44. break;
  45. }
  46. for(intj=m_imageCount;j>i;j--)
  47. {
  48. memcpy(&images[j],&images[j-1],sizeof(ImageItem));
  49. }
  50. memcpy(&images[i],&item,sizeof(ImageItem));
  51. m_imageCount++;
  52. //设置ID
  53. for(i=0;i<m_imageCount;i++)
  54. {
  55. images[i].id=i+1;
  56. }
  57. }
  58. BOOLImageList::merge(CStringoutfile)
  59. {
  60. merge_image_width=GetMaxWidth();
  61. for(inti=0;i<m_imageCount;i++)
  62. {
  63. MyBitBlt(i);
  64. }
  65. unsignedintwidth=merge_image_width;
  66. unsignedintheight=merge_image_height;
  67. HDCimgDC=CreateCompatibleDC(NULL);
  68. VOID*pbits32;
  69. HBITMAPholdBmp,hbm32;
  70. BITMAPFILEHEADERhdr;
  71. BITMAPINFOHEADERbmi;
  72. unsignedchar*buffer;
  73. HANDLEhFile;
  74. intLineDataBytes=width*4;
  75. intZero=(4-((width*3)%4))%4;
  76. intTotalDataBytes=(width*3+Zero)*height;
  77. BOOLresult=FALSE;
  78. if(width<=0||height<=0)
  79. returnFALSE;
  80. hdr.bfType=((WORD)('M'<<8)|'B');//"BM"
  81. hdr.bfReserved1=0;
  82. hdr.bfReserved2=0;
  83. hdr.bfOffBits=(DWORD)(sizeof(hdr)+sizeof(bmi));
  84. hdr.bfSize=(width*3+Zero)*height+hdr.bfOffBits;
  85. bmi.biSize=sizeof(BITMAPINFOHEADER);
  86. bmi.biWidth=width;
  87. bmi.biHeight=height;
  88. bmi.biPlanes=1;
  89. bmi.biBitCount=24;
  90. bmi.biCompression=BI_RGB;
  91. bmi.biSizeImage=0;
  92. bmi.biXPelsPerMeter=0;
  93. bmi.biYPelsPerMeter=0;
  94. bmi.biClrUsed=0;
  95. bmi.biClrImportant=0;
  96. hFile=CreateFile(outfile,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  97. if(INVALID_HANDLE_VALUE!=hFile)
  98. {
  99. DWORDbw;
  100. WriteFile(hFile,(LPSTR)&hdr,sizeof(hdr),&bw,NULL);
  101. WriteFile(hFile,(LPSTR)&bmi,sizeof(bmi),&bw,NULL);
  102. bmi.biBitCount=32;
  103. if(hbm32=CreateDIBSection(imgDC,(BITMAPINFO*)&bmi,DIB_RGB_COLORS,&pbits32,NULL,0))
  104. {
  105. BYTE*p32=(BYTE*)pbits32;
  106. LONG*p;
  107. unsignedinti,j,h=0;
  108. buffer=(unsignedchar*)malloc(TotalDataBytes);
  109. holdBmp=(HBITMAP)SelectObject(imgDC,hbm32);
  110. //TODO:将这些数据都变成局部变量
  111. for(i=0;i<m_imageCount;i++)
  112. {
  113. HDChdc=CreateCompatibleDC(NULL);
  114. HBITMAPhOldBmp=(HBITMAP)SelectObject(hdc,images[i].hbmp);
  115. BitBlt(imgDC,images[i].x,images[i].y,images[i].bmp.bmWidth,images[i].bmp.bmHeight,hdc,0,0,SRCCOPY);
  116. //DeleteObject(SelectObject(hdc,hOldBmp));
  117. DeleteDC(hdc);
  118. }
  119. for(i=0;i<height;i++)
  120. {
  121. for(j=0;j<width;j++)
  122. {
  123. p=(LONG*)p32+j;
  124. buffer[h]=GetRValue(*p);
  125. buffer[h+1]=GetGValue(*p);
  126. buffer[h+2]=GetBValue(*p);
  127. h+=3;
  128. }
  129. if(Zero)h+=Zero;
  130. p32+=LineDataBytes;
  131. }
  132. WriteFile(hFile,(LPSTR)buffer,TotalDataBytes,&bw,NULL);
  133. DeleteObject(SelectObject(imgDC,holdBmp));
  134. free(buffer);
  135. result=TRUE;
  136. }
  137. CloseHandle(hFile);
  138. }
  139. DeleteDC(imgDC);
  140. returnresult;
  141. }
  142. voidImageList::clean()
  143. {
  144. for(inti=0;i<m_imageCount;i++)
  145. {
  146. DeleteObject(images[i].hbmp);
  147. images[i].hbmp=NULL;
  148. }
  149. memset(images,0,sizeof(images));
  150. memset(rects,0,sizeof(rects));
  151. m_imageCount=0;
  152. m_rectCount=0;
  153. merge_image_width=0;
  154. merge_image_height=0;
  155. }
  156. intImageList::GetMaxHeight()
  157. {
  158. intheight=0;
  159. for(inti=0;i<m_imageCount;i++)
  160. {
  161. if(height<images[i].bmp.bmHeight)
  162. {
  163. height=images[i].bmp.bmHeight;
  164. }
  165. }
  166. returnheight;
  167. }
  168. intImageList::GetMaxWidth()
  169. {
  170. intwidth=0;
  171. for(inti=0;i<m_imageCount;i++)
  172. {
  173. if(width<images[i].bmp.bmWidth)
  174. {
  175. width=images[i].bmp.bmWidth;
  176. }
  177. }
  178. returnwidth;
  179. }
  180. voidImageList::SaveToIni(CStringstrPath)
  181. {
  182. CStringsessionName="Bitmap";
  183. charkey[64];
  184. charvalue[1024];
  185. memset(value,0,sizeof(value));
  186. sprintf(value,"%i",m_imageCount);
  187. WritePrivateProfileString(sessionName,"count",value,strPath);
  188. for(inti=0;i<m_imageCount;i++)
  189. {
  190. memset(key,0,sizeof(key));
  191. sprintf(key,"bmp%d",i);
  192. memset(value,0,sizeof(value));
  193. WritePrivateProfileString(sessionName,key,images[i].filename,strPath);
  194. }
  195. }
  196. voidImageList::LoadFromIni(CStringstrPath)
  197. {
  198. CStringsessionName="Bitmap";
  199. charkey[64];
  200. charvalue[1024];
  201. CStringfilePath[100];
  202. intfileCount=0;
  203. //读取bmp文件的个数
  204. memset(value,0,sizeof(value));
  205. GetPrivateProfileString(sessionName,"count","",value,sizeof(value),strPath);
  206. sscanf(value,"%i",&fileCount);
  207. //将每个路径依次存到数据里
  208. for(inti=0;i<fileCount;i++)
  209. {
  210. memset(key,0,sizeof(key));
  211. sprintf(key,"bmp%d",i);
  212. memset(value,0,sizeof(value));
  213. GetPrivateProfileString(sessionName,key,"",value,sizeof(value),strPath);
  214. filePath[i].Format(value);
  215. }
  216. //根据CString数组初始化imagelist
  217. InitFromStringArray(filePath,fileCount);
  218. }
  219. voidImageList::InitFromStringArray(CString*pStr,intcount)
  220. {
  221. clean();
  222. for(inti=0;i<count;i++,pStr++)
  223. {
  224. Insert(*pStr);
  225. }
  226. }
  227. voidImageList::MyBitBlt(intimage_index)
  228. {
  229. inti;
  230. searchproper:
  231. for(i=0;i<m_rectCount;i++)
  232. {
  233. //rect和image一样大小,设置image的坐标,并将删除rects中的一项
  234. if(images[image_index].bmp.bmWidth==rects[i].width&&
  235. images[image_index].bmp.bmHeight==rects[i].height)
  236. {
  237. images[image_index].x=rects[i].x;
  238. images[image_index].y=rects[i].y;
  239. DeleteRectItem(i);
  240. return;
  241. }
  242. //rect和image的宽一样大小,高rect更大
  243. if(images[image_index].bmp.bmWidth==rects[i].width&&
  244. images[image_index].bmp.bmHeight<rects[i].height)
  245. {
  246. images[image_index].x=rects[i].x;
  247. images[image_index].y=rects[i].y;
  248. //TODO:checkright
  249. RectItemtemp;
  250. temp.height=rects[i].height-images[image_index].bmp.bmHeight;
  251. temp.width=rects[i].width;
  252. temp.x=rects[i].x;
  253. temp.y=rects[i].y+images[image_index].bmp.bmHeight;
  254. DeleteRectItem(i);
  255. InsertRectItem(&temp);
  256. return;
  257. }
  258. //rect和image的高一样大小,宽rect更大
  259. if(images[image_index].bmp.bmWidth<rects[i].width&&
  260. images[image_index].bmp.bmHeight==rects[i].height)
  261. {
  262. images[image_index].x=rects[i].x;
  263. images[image_index].y=rects[i].y;
  264. RectItemtemp;
  265. temp.height=rects[i].height;
  266. temp.width=rects[i].width-images[image_index].bmp.bmWidth;
  267. temp.x=rects[i].x+images[image_index].bmp.bmWidth;
  268. temp.y=rects[i].y;
  269. DeleteRectItem(i);
  270. InsertRectItem(&temp);
  271. return;
  272. }
  273. //rect比image高和宽都大
  274. if(images[image_index].bmp.bmWidth<rects[i].width&&
  275. images[image_index].bmp.bmHeight<rects[i].height)
  276. {
  277. images[image_index].x=rects[i].x;
  278. images[image_index].y=rects[i].y;
  279. RectItemtemp1;
  280. temp1.height=images[image_index].bmp.bmHeight;
  281. temp1.width=rects[i].width-images[image_index].bmp.bmWidth;
  282. temp1.x=rects[i].x+images[image_index].bmp.bmWidth;
  283. temp1.y=rects[i].y;
  284. RectItemtemp2;
  285. temp2.height=rects[i].height-images[image_index].bmp.bmHeight;
  286. temp2.width=rects[i].width;
  287. temp2.x=rects[i].x;
  288. temp2.y=rects[i].y+images[image_index].bmp.bmHeight;
  289. DeleteRectItem(i);
  290. InsertRectItem(&temp1);
  291. InsertRectItem(&temp2);
  292. return;
  293. }
  294. }
  295. //找不到合适的rect,就新建一项,并将其插入合适的地方
  296. RectItemnew_item;
  297. new_item.height=images[image_index].bmp.bmHeight;
  298. new_item.width=merge_image_width;
  299. new_item.x=0;
  300. new_item.y=merge_image_height;
  301. merge_image_height+=new_item.height;
  302. InsertRectItem(&new_item);
  303. gotosearchproper;
  304. }
  305. voidImageList::DeleteRectItem(intindex)
  306. {
  307. for(inti=index;i<m_rectCount;i++)
  308. {
  309. memcpy(&rects[i],&rects[i+1],sizeof(RectItem));
  310. }
  311. m_rectCount--;
  312. }
  313. voidImageList::InsertRectItem(RectItem*item)
  314. {
  315. inti,j;
  316. //找到该插入的位置,将其存到i
  317. for(i=0;i<m_rectCount;i++)
  318. {
  319. if(item->width<rects[i].width)
  320. {
  321. break;
  322. }
  323. if(item->width==rects[i].width&&
  324. item->height<rects[i].height)
  325. {
  326. break;
  327. }
  328. }
  329. //插入
  330. for(j=m_rectCount-1;j>=i;j--)
  331. {
  332. memcpy(&rects[j+1],&rects[j],sizeof(RectItem));
  333. }
  334. memcpy(&rects[i],item,sizeof(RectItem));
  335. m_rectCount++;
  336. }
测试代码如下:
  1. CFileDialogfileDlg(TRUE,
  2. NULL,
  3. NULL,
  4. OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,
  5. "bmp文件(*.bmp)|*.bmp||",
  6. NULL);
  7. fileDlg.m_ofn.lpstrFile=newTCHAR[MAX_PATH*100];//最多允许100个文件
  8. fileDlg.m_ofn.nMaxFile=100*MAX_PATH;
  9. ZeroMemory(fileDlg.m_ofn.lpstrFile,sizeof(TCHAR)*fileDlg.m_ofn.nMaxFile);
  10. if(fileDlg.DoModal()!=IDOK)return;
  11. //TODO:initbmpinidata
  12. CStringfilePath[100];
  13. //获取图片路径
  14. POSITIONpos=fileDlg.GetStartPosition();
  15. intfileCount;
  16. for(fileCount=0;pos!=0;fileCount++)
  17. {
  18. CStringfile=fileDlg.GetNextPathName(pos);
  19. if(file.Find(".bmp")==-1)
  20. {
  21. AfxMessageBox("非bmp文件,程序退出。");
  22. exit(1);
  23. }
  24. filePath[fileCount]=file;
  25. }
  26. GlobalImageList.InitFromStringArray(filePath,fileCount);
  27. GlobalImageList.merge("merge.bmp");
以下是合并图片的测试效果:


合并的每一张小图片是从一张合照里剪切下来的,每张小图片的大小是不一样的,而且是未知的。从效果可以看得出,该算法尽可能地将图片挤在一起,但也还有待改进之处。
分享到:
评论

相关推荐

    批量快速将多张bmp图片合并转换为bin文件

    批量快速将多张bmp图片转换为bin文件,bmp图片位深度为24bit,bin文件可选择8bit(RGB323)、16bit(RGB565)、24bit(RGB888) 输出,用于烧录到 外部flash,单片机去读取数据显示图像。因为输出每张bmp图片所在flash里的...

    FreePic2Pdf v5.0一款图片转化或合并成PDF工具.rar

    这是一款将图像文件(包括TIFF、JPG、JP2/J2K/JPC、PNG、GIF、BMP)合并、转换成PDF文件的软件。FAQ Q:FreePic2Pdf是什么?A:这是一个将图像文件(包括TIFF、JPG、JP2/J2K/JPC、PNG、GIF、BMP、webp)合并、转换成...

    FreePic2Pdf V1.15_简体中文绿色免费版_将图像文件合并、转换成PDF文件软件.rar

    将图像文件(包括TIFF、JPG、PNG、GIF、BMP)合并、转换成PDF文件的软件: 对有损压缩的JPG文件及采用JPEG/OJPEG算法压缩的TIFF文件,直接将原始数据流嵌入PDF文件,避免因为重新压缩而造成图像质量下降;对无损压缩...

    图形处理类的实例40个

    基于小波零树的图像压缩算法 利用OpenGL实现动画效果 逆滤波处理 实现图案化和抖动技术以及bmp2txt源代码 屏幕保护程序与源代码 屏幕颜色拾取器源代码 曲线处理 贝塞尔曲线程序 实现图象平滑(去噪声) 锐化算法的源...

    万能图片格式转换已修改免费

    软件采用高级优秀算法,在对原有图片数据最大程度保真的同时,具有特别快速的处理速度; 软件体积小巧,是一款绿色软件,免安装; 操作简单: 回车键,开始/暂停操作; ESC键 ,停止操作。

    智能图像处理技术PDF

    本书主要论述了智能图像处理技术,系统介绍了智能图像处理技术的有代表性的思想、算法与应用,跟踪了图像处理技术的发展前沿。全书共分为15章,重点讨论了图像边缘检测、图像分割、图像特征分析、图像配准、图像融合...

    数字图像处理课设--简单图像处理系统

    1、能对图像文件(bmp、 jpg、 tiff、 gif等)进行打开、保存、另存、打印、退出等功能操作; 2、数字图像的统计信息功能:包括直方图的统计及绘制、区域图的面积、周长的统计、线条图中的距离测量等; 3、数字图像...

    FreePic2Pdf 软件

    将图像文件(包括TIFF、JPG、PNG、GIF、BMP)合并、转换成PDF文件的软件: 对有损压缩的JPG文件及采用JPEG/OJPEG算法压缩的TIFF文件,直接将原始数据流嵌入PDF文件,避免因为重新压缩而造成图像质量下降;对无损压缩...

    数字图像课程设计报告

    1、 能对图像文件(bmp、 jpg、 tiff、 gif等)进行打开、保存、另存、打印、退出等功能操作; 2、 数字图像的统计信息功能:包括直方图的统计及绘制、区域图的面积、周长的统计、线条图中的距离测量等; 3、 数字...

    matlab数字图像处理报告

    1、 能对图像文件(bmp、 jpg、 tiff、 gif等)进行打开、保存、另存、打印、退出等功能操作; 2、 数字图像的统计信息功能:包括直方图的统计及绘制、区域图的面积、周长的统计、线条图中的距离测量等; 3、 数字...

    Ultra Fractal(分形艺术软件)官方正式版64位V6.04 | 含ultra fractal教程

    PNG、JPEG 或 BMP 图像,只需选择包含图像参数的着色算法,大家就可以选择计算机上的任何图像来使用,Ultra Fractal分形艺术软件还允许用户通过使用图层、蒙版、图层组功能到到类似PS那样的合并模式来合成分形综合...

    Ultra Fractal(分形艺术软件)官方正式版32位V6.04 | 含ultra fractal教程

    PNG、JPEG 或 BMP 图像,只需选择包含图像参数的着色算法,大家就可以选择计算机上的任何图像来使用,Ultra Fractal分形艺术软件还允许用户通过使用图层、蒙版、图层组功能到到类似PS那样的合并模式来合成分形综合...

    FreePic2Pdf将图片制作成pdf(也可以解决pdf书签乱码问题)

    这是一个将图像文件(包括TIFF、JPG、JP2/J2K/JPC、PNG、GIF、BMP)合并、转换成PDF文件的软件。 也可以修复pdf书签乱码问题(一般是编码问题) 方法:启动软件,在右下角点击“更改pdf”,点击“从pdf取书签”选择...

    图片转PDF的好工具FreePic2Pdf

     这是一个将图像文件(包括TIFF、JPG、JP2/J2K/JPC、PNG、GIF、BMP)合并、转换成PDF文件的软件。 FreePic2Pdf纯免费,并具有下列特色: 1. 对有损/无损压缩jpeg 2000(jp2/j2k/jpc)文件,或有损压缩JPG文件及...

    《磁盘数据安全技术与编程实例》郑平泰

    第六章 1、Win9x/ME系统下的磁盘扇区...1、基于24位bmp位图的信息隐藏编程实例 2、基于一阶Bézier曲线的信息隐藏编程实例 第十章 1、文件分割与合并实例——单线程模式 2、文件分割与合并实例——多线程模式

    FreePic2Pdf中文版

    这是一个将图像文件(包括TIFF、JPG、JP2/J2K/JPC、PNG、GIF、BMP)合并、转换成PDF文件的软件。纯免费,并具有下列特色: &lt;br&gt;对有损/无损压缩jpeg 2000(jp2/j2k/jpc)文件,或有损压缩JPG文件及采用JPEG/OJPEG...

    动态规划的思想压缩位图

     算法思想: (1)对8、16、24位位图数据的读功能 有一个参数为输入位图文件名(*.bmp),它能解析8、16、24位位图文件格式,获取位图BITMAPINFOHEADER信息和每个像素的数据信息,放入内存中。 (2)对8、16、24位...

    MicroDraw图形控件

    6.图片的合并与切割;7.读取粘贴板上的图片;8.指定大小尺寸保存图片; 属性功能:1.几何属性,颜色,线型,线宽;2.图层属性:显示,隐藏,冻结;3.尺寸属性:颜色,箭头,尺寸线属性,尺寸引线属性,...

Global site tag (gtag.js) - Google Analytics