现将一张图片分成n*n张图片,每张图片宽度与高度一致,要求用CImage将随机排序的图片拼回原状

思路分析

  1. 先用windows API读取文件夹下的图片列表
  2. 用CImage读取每张图片
  3. 读取每张图片的边界点并计算灰度值,公式: b * 0.114 + g * 0.587 + r * 0.299;
  4. 计算边界与对应边界之间的每个点的灰度值的平方差之和作为权值
  5. 找出权值最小且相同的对应边,构造n*n数组
  6. 绘制图片

难点

讲道理我也是刚刚才接触这些内容的,上手之后第一个问题就是string怎么转换为LPCTSTR使得CImage可以构造,具体解决是通过cstring作为中间转换

String str = "abc";
CString resultDir = str.c_str();
LPCTSTR destFilePath = (LPCTSTR)resultDir;

然后是权值的计算,一开始的解决方案是分别计算bgr的平方差,再求和,这样就导致了相邻的边却不是最小值这种情况(可跑出案例中前两种情况),于是听说了灰度计算,尝试了一下,即可跑出所有案例

最后是构造最后的n*n的数组,一开始的想法是从图片列表数组中按顺序插入数组中,后来通过先找左上角的图片(即左边上边无相邻图片)实现

#include<iostream>
#include<atlimage.h>
#include<cmath>
#include <io.h>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
class Image{
public:CImage src;BYTE *pData;//存放所有的rgbBYTE **lineP = new BYTE *[4];//存放所有边上的rgbint width, height, bpp, pitch;//图片参数int next[4] = { -1,-1,-1,-1 };//上右下左四个方向的图片double **linePower;//四条边上与其他图片的权值void load(LPCTSTR file) {src = CImage();src.Load(file);//加载图片pData = (BYTE *)src.GetBits();//获取每个点//获取部分参数width = src.GetWidth();height = src.GetHeight();bpp = src.GetBPP();pitch = src.GetPitch();//加载边界loadLine();}void loadLine() {lineP[0] = new BYTE[width];//上边0lineP[1] = new BYTE[height];//右边1lineP[2] = new BYTE[width];//下边2lineP[3] = new BYTE[height];//左边3for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){int p[2] = { -1 ,-1};if (x == 0) {p[0] = 3;//左边}else if (x == width - 1){p[0] = 1;//右边}if (y == 0){p[1] = 0;//上边}else if (y == height - 1){p[1] = 2;//上边}//参数0 左右边 参数1 上下边for (int i = 0; i < 2; i++) {if (p[i] != -1) {BYTE b = *(pData + pitch * y + x * bpp / 8 + 0);BYTE g = *(pData + pitch * y + x * bpp / 8 + 1);BYTE r = *(pData + pitch * y + x * bpp / 8 + 2);lineP[p[i]][i == 0 ? y : x] = b * 0.114 + g * 0.587 + r * 0.299;}}}}}};
void join(LPCTSTR srcFilePath[], LPCTSTR destFilePath, int cnt)
{Image *srcImage = new Image[cnt];CImage destImage;int sqr = sqrt(cnt);//X*Xfor (int i = 0; i < cnt; i++){srcImage[i].load(srcFilePath[i]);srcImage[i].linePower = new double *[cnt];//其他cnt张图片的边界权值}int height = srcImage[0].height, width = srcImage[0].width, bpp = srcImage[0].bpp;int length[4] = {width,height,width,height};//用于记录四条边的长度destImage.Create(width * sqr, height * sqr, bpp);//创建新的图片//计算每张图片每条边与别的图片的平方差for (int i = 0; i < cnt; i++){for (int j = 0; j < cnt; j++) {srcImage[i].linePower[j] = new double[4];//四条边的权值if (i == j) {for (int line = 0; line < 4; line++) {//-1为跳过标识srcImage[i].next[line] = -1;}continue;//当前图片跳过本次循环}for (int line = 0; line < 4; line++) {int otherLine = (line + 2) % 4;//0->2 1->3 2->0 3->1int count = 0;//平方差之和for (int point = 0; point < length[line]; point++) {count += pow(srcImage[i].lineP[line][point] - srcImage[j].lineP[otherLine][point], 2);}srcImage[i].linePower[j][line] = count / length[line];//平均平方差}}for (int line = 0; line < 4; line++) {int min = -1;//标记for (int j = 0; j < cnt; j++) {if (i == j) continue;//本张图片跳过if (min==-1 || srcImage[i].linePower[min][line] > srcImage[i].linePower[j][line]) {min = j;//权值最小的图片下标}}srcImage[i].next[line] = min;//该条边上权值最小的图片}}//判断是否是彼此的唯一for (int i = 0; i < cnt; i++) {for (int line = 0; line < 4; line++) {if (srcImage[i].next[line] != -1) {if (i != srcImage[srcImage[i].next[line]].next[(line + 2) % 4]) {srcImage[i].next[line] = -1;//不是彼此的唯一最小则打回原形}}}}/**string tip[4] = {"上","右","下","左"};for (int i = 0; i < cnt; i++) {cout << "第" << i << "张图片" ;for (int line = 0; line < 4; line++) {cout << endl<< tip[line] << srcImage[i].next[line] << '\t' << endl;for (int j = 0; j < cnt; j++) {if (i == j) continue;cout << srcImage[i].linePower[j][line] << '\t';}}cout << endl;}**/int begin;//找到右下角的图片for (int i = 0; i < cnt; i++) {if (srcImage[i].next[2] == -1 && srcImage[i].next[1] == -1) {begin = i;break;}}//声明一个用于存储九宫格下标的二维数组int **despair = new int*[sqr];for (int i = 0; i < sqr; i++) {despair[i] = new int[sqr];}for (int i = sqr-1; i >=0; i--) {for (int j = sqr - 1; j >=0; j--) {if (i== sqr - 1) {if (j == sqr - 1) { despair[i][j] = begin; //右下角赋值}else {despair[i][j] = srcImage[despair[i][j + 1]].next[0];//其余右边第一列}}else {despair[i][j] = srcImage[despair[i + 1][j]].next[3];}}}for (int i = 0; i < sqr; i++) {for (int j = 0; j < sqr; j++) {cout << despair[j][i] << '\t';}cout << endl;}for (int i = 0; i < sqr; i++){for (int j = 0; j < sqr; j++){srcImage[despair[j][i]].src.Draw(destImage.GetDC(), width*j, height*i, width, height, 0, 0, width, height);destImage.ReleaseDC();}}destImage.Save(destFilePath);
}/*
path: 指定目录
files: 保存结果
fileType: 指定的文件格式,如 .jpg
*/
void getAllFiles(string path, vector<string>& files, string fileType)
{//文件句柄long hFile = 0;//文件信息struct _finddata_t fileinfo;string p;if ((hFile = _findfirst(p.assign(path).append("\\*" + fileType).c_str(), &fileinfo)) != -1) {do {//保存文件的全路径files.push_back(p.assign(path).append("\\").append(fileinfo.name));} while (_findnext(hFile, &fileinfo) == 0); //寻找下一个,成功返回0,否则-1_findclose(hFile);}
}
//----------------------------------------------------------------------------------int main()
{string fileName[4] = {"大作业第1组测试案例2x2","大作业第2组测试案例3x3" ,"大作业第3组测试案例6x6" ,"大作业第4组测试案例3x3" };string dir = "C:\\Users\\xjc82\\Desktop\\Day4\\";for (int i = 0; i < 4; i++) {vector<string> temp;getAllFiles(dir+fileName[i], temp, ".jpg");//读取图片列表int cnt = temp.size();//图片的数量//将图片地址String转为LPCTSTRLPCTSTR *srcFilePath = new LPCTSTR[cnt];CString *cs = new CString[cnt];for (int i = 0; i < cnt; i++){cs[i] = temp[i].c_str();srcFilePath[i] = (LPCTSTR)cs[i];}//将导出图片地址String转为LPCTSTRCString resultDir = (dir + fileName[i] + ".jpg").c_str();LPCTSTR destFilePath = (LPCTSTR)resultDir;join(srcFilePath, destFilePath, cnt);}return 0;
}

案例的图片素材:案例.rar

用C++ CImage实现九宫格图片拼接相关推荐

  1. android 图片拼接工具,拼接图片工具app

    截图拼接是一款非常好用的手机长图拼接工具,它的功能非常强大,支持图片拼接,无论是横向还是竖向拼接,一键设置,在这里小伙伴可以随时参与图片制作,帮助小伙伴制作出最佳的图片效果,操作也是很简单的,非常的方 ...

  2. 如何将图片拼接成九宫格?

    在日常生活中,经常会看到九宫格的图片拼接样式,那么大家知道自己怎么操作能够快速的将图片拼接成九宫格形状吗?接下来教大家使用找图设计网站的**拼图**https://www.zhaotu.com/pin ...

  3. 用纯css实现一个图片拼接九宫格

    <style> body{ margin: 0; padding: 0; // 设定居中 display: flex; justify-content: center; align-ite ...

  4. 微信彩色个性昵称 游戏取名 九宫格切图 多图拼接工具箱微信小程序源码

    简介: 流量主系列,没有后台,直接上传小程序就能使用了 这是一款多功能工具箱小程序! 目前由N款小功能组合成 比如: 图片拼接 九宫格切图 透明昵称 文字表情 等等上面说的只是一部分 该款小程序无需服 ...

  5. ImageMagick将多张图片拼接成一张图片_高逼格九宫格图片,2020年朋友圈图片,自己做不求人...

    元旦快乐!! 2019年过去了,2020年你的计划里不知道还有没有2018年的待完成事项呢?(拖延症的话,经常是拖着拖着就没了吧= =)无论如何在许下愿望列下清单的那一刻我们也是斗志满分阿! 今天给大 ...

  6. php九宫格图片合成,多宫格图片合成

    多宫格图片合成工具可以实现多种不同的图片合成以及图片特效图片加文字diy图片等组合功能. 它能够将多张图片按多宫格样式拼接合成为一张宫格图片,可自由设置拼接而成的图片大小以及每张之间的上下距离以及左右 ...

  7. python朋友圈头像_Python读取微信好友头像,拼成祝福语九宫格

    今天有位老哥过生日,结合着微信头像和点阵字,搞了个头像拼字的代码,朋友圈九宫格效果如下: 其中,每个字都是16*16的点阵,点阵中每个点可以拆解为4个好友头像图片: 代码中汉字文本可以自定义输入,头像 ...

  8. 图像处理(C++ CImage class)学习笔记

    基础篇 A. 图像三原色及灰度值 A1. 彩色图像的三原色 图像三原色 - R:红色red - G:绿色green - B:蓝色blue 三原色的取值范围:0(无)~255(满) - 红色:R=255 ...

  9. 【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面

    这是我们最终想要达到的效果,并且支持任意宽高缩放不变形.注意哟这次不一样的是有透明度! 开始准备物料 第一步:切片,建议用九宫格的形式,切割有考究,主要是最大限度.最小尺寸囊括多个边界转角处的样式(亮 ...

最新文章

  1. 8种常被忽视的SQL错误用法,快来认领一下!
  2. 探索 20 年,依然难落地,是谁阻止了教授们的「学术休假」?
  3. 清华大学孙茂松:自然语言处理一瞥,知往鉴今瞻未来
  4. android qq 进程保活,Android保活从入门到放弃:乖乖引导用户加白名单吧(附7大机型加白示例)...
  5. Vscode 用Filter Line看日志,很爽
  6. android iphone对比度,对比度对比:显示器优势明显_苹果 MacBook Pro_液晶显示器评测-中关村在线...
  7. TCP/IP数据包结构详解
  8. teamcity和jmeter结合进行接口自动化测试
  9. Python-os.mkdir() 方法
  10. C++复习中相关要点记录(三)
  11. 从淘宝服务器IP地址服务获取IP地址信息的方法
  12. 一种基于多维时序数据预测综合判定的方法(内存告警)
  13. oracle sql 不等 优化6,oracle sql 优化(三)
  14. 超详细分析Windows变慢原因及解决方法
  15. ThingsBoard RPC control
  16. centos6.8服务器中了挖矿程序病毒的解决方法
  17. Acer Linux改win7,宏基台式机win10如何改win7系统_宏基台式机预装win10怎么换win7
  18. PHP curl 中文gbk转utf8
  19. 157 亿美元!Salesforce收购Tableau,全球最大CRM巨头与大数据平台在一起了!
  20. JAVA将证件号打星号

热门文章

  1. 基于JAVA航空订票系统计算机毕业设计源码+数据库+lw文档+系统+部署
  2. 如何用VS2019编写C语言程序
  3. 星起航:社交媒体电商带货为什么这么受欢迎?
  4. 一站式电商是什么?如何绘制一站式电商流程
  5. 西电分布式系统考试复习
  6. 磨金石教育科技摄影技能干货分享|艺术摄影的本源是创作,核心是表达
  7. SolidWorks Flow Simulation 2017流体分析视频教程
  8. 【JavaSE学习】03面向对象Java语法
  9. Python基于周立功盒子的二次开发的准备工作
  10. c语言词法分析程序设计,C语言词法分析器设计与实现.doc