====================================================
拼图程序流程图:使用在线迅捷画图绘制
将bmp图片系列函数封装成库,将触摸函数也封装成库,结合两者实现拼图程序
如何截长图:解决迅捷画图中需要vip才可以导出图片
1.获取所需FastStone工具提取码: hdv7
2.打开压缩包里的 FSCapture.exe 文件
3.点击捕获滚动窗口:
4.方法一:单击鼠标左键选中窗口后,它自动会一直往下滚动,按Esc停止
5.方法二:按住Ctrl,点击鼠标左键选者区域,用鼠标滚轮慢慢滚动长图区域,按Esc停止。
演示样例:
MakeFile:添加了生成动态库
- 1.在命令行敲make shared 即可生成libxxx.so 在lib目录下
- 2.编译:
arm-linux-gcc ./src/LcdCutImage.c -o ./bin/LcdCutImagenlib -L./lib -lbmp -ltouch -I./inc
- 3.开发板运行时:首先临时配置库路径:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: $(pwd)/lib
TARGET =./bin/LcdCutImage
SRC =$(wildcard ./src/*.c)
OBJ =$(patsubst %.c, %.o, $(SRC))
CC =arm-linux-gcc
CONFIG =-I./inc
LIBPATHNAME =./lib/lib
LIB =$(patsubst %.o, %.so, $(OBJ))
$(TARGET):$(OBJ)
$(CC) $^ -o $@ $(CONFIG) -g
%.o:%.c
$(CC) $< -c -o $@ $(CONFIG)
shared:$(LIB)
%.so:%.o
$(CC) ./$< -o $(LIBPATHNAME)$(@F) $(CONFIG) -fPIC -shared
%.o:%.c
$(CC) ./$< -c -o ./$@ $(CONFIG) -fPIC
clean:
rm $(TARGET) $(OBJ)
所有程序文件如下:
File Name: bmp.h
Author: xiening
Mail: 1606598696@qq.com
Created Time: 2019年11月24日 星期日 09时58分34秒
#ifndef _BMP_H
#define _BMP_H
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <stdbool.h>
//BMP文件头部:(14位)
typedef struct BITMAPFILEHEADER{
short bfType;
unsigned bfSize;
short bfReserved1;
short bfReserved2;
unsigned bfOffBits;
}BitMapFileHeader;
//BMP文件信息:(40位)
typedef struct BITMAPINFOHEADER{
unsigned biSize;
unsigned biWidth;
unsigned biHeigh;
short biPlanes;
short biBitCount;
unsigned biCompression;
unsigned biSizeTmage;
int biXpelsPerMeter;
int biYpelsPerMeter;
unsigned biClrUsed;
unsigned biClrImportant;
}BitMapInfoHeader;
//bmp图片简单信息:
typedef struct BMPDATA{
unsigned Width;
unsigned Heigh;
short Type;
unsigned *Bmp; //用户存放位图数据
}BmpData;
//bmp分割后存储的结构体:
typedef struct BMPDIVDATA
{
unsigned Width;
unsigned Heigh;
int x, y;
int number;
int vnumber;
short Type;
unsigned *Bmp;
}BmpDivData;
//读取bmp图片信息至结构体BmpData
BmpData* ReadBmp(const char *filename);
//显示bmp图片
void ShowBmp(int x, int y, int Width, int Heigh, unsigned *Bmp);
//bmp图片大小转换
BmpData* ZoomBmp(int WidthScale, int HeighScale, BmpData *tem);
//bmp图片分割:
void BmpCut2N(int row, int col, BmpData *tem, BmpDivData *temdiv[]);
//设置随机数种子
void BmpRandom(BmpDivData *temdiv[], const int row, const int col);
//交换两张图片:
void ExchangeBmp(int num, int num1, int row, int col, BmpDivData *temdiv[]);
//判断是否拼图成功
bool IsBmpSucess(int row, int col, BmpDivData *temdiv[]);
//销毁bmp图片:
void DestoryBmp(BmpData *tem);
#endif
File Name: touch.h
Author: xiening
Mail: 1606598696@qq.com
Created Time: 2019年12月07日 星期六 19时34分47秒
#ifndef _TOUCH_H
#define _TOUCH_H
#include <stdio.h>
#include <linux/input.h>
//获取触摸屏坐标
void GetXY(int *x, int *y);
//判断第几张被选中
int WhichSelect(int x, int y, int row, int col);
#endif
File Name: bmp.c
Author: xiening
Mail: 1606598696@qq.com
Created Time: 2019年11月24日 星期日 10时40分53秒
#include "bmp.h"
//读取bmp图片信息至结构体BmpData
BmpData* ReadBmp(const char *filename)
{
//打开文件
FILE *fp = fopen(filename, "r+");
if(NULL == fp)
{
perror("fopen error\n");
return NULL;
}
//读BMP文件头部
BitMapFileHeader bmpheader;
int ret = fread(&bmpheader, 1, 14, fp);
if(14 != ret)
{
perror("fread error\n");
return NULL;
}
BitMapInfoHeader bmpinfo;
ret = fread(&bmpinfo, 1, 40, fp);
if(40 != ret)
{
perror("fread error\n");
return NULL;
}
//返回简单bmp信息
unsigned BmpSize = bmpinfo.biWidth*bmpinfo.biHeigh
*bmpinfo.biBitCount/8;
BmpData *tem = malloc(sizeof(BmpData));
tem->Width = bmpinfo.biWidth;
tem->Heigh = bmpinfo.biHeigh;
tem->Type = bmpinfo.biBitCount/8;
tem->Bmp = malloc(tem->Width*tem->Heigh*4);
char buf[BmpSize];
ret = fread(buf, 1, BmpSize, fp);
if(BmpSize != ret)
{
perror("fread error\n");
}
if(3 == tem->Type)
{
for(int i=0; i<tem->Heigh; i++)
{
for(int j=0; j<tem->Width; j++)
{
tem->Bmp[(tem->Heigh-1-i)*tem->Width+j]
= buf[(i*tem->Width+j)*3]
| buf[(i*tem->Width+j)*3+1] << 8
| buf[(i*tem->Width+j)*3+2] << 16;
}
}
}
if(4 == tem->Type)
{
for(int i=0; i<tem->Heigh; i++)
{
for(int j=0; j<tem->Width; j++)
{
tem->Bmp[(tem->Heigh-1-i)*tem->Width+j]
= (unsigned)buf[i*tem->Width+j];
}
}
}
return tem;
}
//显示bmp图片:
void ShowBmp(int x, int y, int Width, int Heigh, unsigned *Bmp)
{
//打开文件
FILE *fp = fopen("/dev/fb0", "r+");
if(NULL == fp)
{
perror("fopen error\n");
return;
}
int fd = fileno(fp);
//内存映射:
unsigned *buf = mmap(NULL, 480*800*4,
PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
for(int i=0; i<Heigh; i++)
{
for(int j=0; j<Width; j++)
{
memcpy(&buf[(y+i)*800+x+j], &Bmp[i*Width+j], 4);
}
}
//memcpy(buf, tem->Bmp, 480*800*4);
//解除映射
munmap(buf, 480*800*4);
fclose(fp);
fp = NULL;
}
//bmp图片大小转换
BmpData* ZoomBmp(int WidthScale, int HeighScale, BmpData *tem)
{
//赋值新信息
BmpData *tmp = malloc(sizeof(BmpData));
tmp->Width = WidthScale;
tmp->Heigh = HeighScale;
tmp->Type = tem->Type;
int BmpSize = WidthScale*HeighScale*4;
tmp->Bmp = malloc(BmpSize);
int wsc = tem->Width/(double)WidthScale*100;
int hsc = tem->Heigh/(double)HeighScale*100;
for(int i=0; i<HeighScale; i++)
{
for(int j=0; j<WidthScale; j++)
{
double number = (j*wsc)/100+tem->Width*((i*hsc)/100);
unsigned long num = j*tem->Heigh/WidthScale+i*tem->Width*tem->Heigh/HeighScale;
tmp->Bmp[i*WidthScale+j] = tem->Bmp[(int)number];
}
}
return tmp;
}
//bmp图片分割:
void BmpCut2N(int row, int col, BmpData *tem, BmpDivData *temdiv[])
{
//width=800,heigh=480
//一个row占480/row 一个col占800/col
int heigh = 480/row;
int width = 800/col;
for(int Hcount=0; Hcount<row; Hcount++)
{
for(int Wcount=0; Wcount<col; Wcount++)
{
temdiv[Wcount+Hcount*col]->Bmp = malloc(heigh*width*4);
temdiv[Wcount+Hcount*col]->number = Wcount+Hcount*col+1;
temdiv[Wcount+Hcount*col]->Width = width;
temdiv[Wcount+Hcount*col]->Heigh = heigh;
temdiv[Wcount+Hcount*col]->x = Wcount*width;
temdiv[Wcount+Hcount*col]->y = Hcount*heigh;
for(int i=0; i<heigh; i++)
{
for(int j=0; j<width; j++)
{
temdiv[Wcount+Hcount*col]->Bmp[i*width+j] = tem->Bmp[(i+Hcount*heigh)*800+Wcount*width+j];
}
}
}
}
}
//设置随机数种子
void BmpRandom(BmpDivData *temdiv[], const int row, const int col)
{
struct timeval t; //时间结构体
gettimeofday(&t,NULL); //获取系统时间
srandom(t.tv_usec); //设置随机数种子 时间微妙数
const int num = row*col;
int a[num];
int tem = rand()%num+1; //生成随机数
a[0] = tem;
for(int i=1; i<num; i++)
{
tem = rand()%num+1; //生成随机数
for(int j=0; j<i; j++)
{
if(a[j] == tem)
{
j = -1;
tem = rand()%num+1; //生成随机数
}
if(i-1 == j)
{
a[i] = tem;
}
}
}
for(int i=0; i<num; i++)
{
temdiv[i]->vnumber = a[i];
temdiv[i]->x = ((temdiv[i]->vnumber-1)%4)*800/col;
temdiv[i]->y = ((temdiv[i]->vnumber-1)/4)*480/row;
//printf("%d:[%d,%d]\n", temdiv[i]->vnumber, temdiv[i]->x, temdiv[i]->y);
}
}
//交换两张图片:
void ExchangeBmp(int num, int num1, int row, int col, BmpDivData *temdiv[])
{
int tem = temdiv[num]->vnumber;
temdiv[num]->vnumber = temdiv[num1]->vnumber;
temdiv[num]->x = ((temdiv[num]->vnumber-1)%4)*800/col;
temdiv[num]->y = ((temdiv[num]->vnumber-1)/4)*480/row;
temdiv[num1]->vnumber = tem;
temdiv[num1]->x = ((temdiv[num1]->vnumber-1)%4)*800/col;
temdiv[num1]->y = ((temdiv[num1]->vnumber-1)/4)*480/row;
}
//判断是否拼图成功
bool IsBmpSucceed(int row, int col, BmpDivData *temdiv[])
{
for(int i=0; i<row*col; i++)
{
if(temdiv[i]->number != temdiv[i]->vnumber)
{
return false;
}
}
return true;
}
//销毁bmp图片:
void DestoryBmp(BmpData *tem)
{
free(tem->Bmp);
free(tem);
tem = NULL;
}
File Name: touch.c
Author: xiening
Mail: 1606598696@qq.com
Created Time: 2019年12月07日 星期六 19时37分29秒
#include "touch.h"
//获取触摸屏坐标
void GetXY(int *x, int *y)
{
//打开触摸屏文件:
FILE *fp = fopen("/dev/input/event0", "r+");
if(NULL == fp)
{
perror("fopen error\n");
return ;
}
*x = 0;
*y = 0;
struct input_event data;
while(1)
{
fread(&data, 1, sizeof(data), fp);
if(data.type == 3 && data.code == 0)
{
*x = data.value*800/1024;
}
if(data.type == 3 && data.code == 1)
{
*y = data.value*480/600;
}
if(*x != 0 && *y !=0)
{
break;
}
}
printf("[%d,%d]\n", *x, *y);
}
//判断第几张被选中
int WhichSelect(int x, int y, int row, int col)
{
int width = 800/col;
int height = 480/row;
int WCount = x/width;
int HCount = y/height;
return WCount+HCount*col+1;
}
File Name: LcdCutImage.c
Author: xiening
Mail: 1606598696@qq.com
Created Time: 2019年12月07日 星期六 15时49分42秒
#include <stdio.h>
#include "bmp.h"
#include "touch.h"
int main(int argc, char const *argv[])
{
if(2 != argc)
{
perror("use:./LcdCutImage filename\n");
return -1;
}
//读取图片数据
BmpData *image1 = ReadBmp(argv[1]);
//bmp图片大小转换
BmpData *image = ZoomBmp(800, 480, image1);
//显示bmp图片:
//ShowBmp(0, 0, image1->Width, image1->Heigh, image1->Bmp);
//ShowBmp(200, 120, image->Width, image->Heigh, image->Bmp);
//bmp图片分割:
BmpDivData *temdiv[12];
for(int i=0; i<12; i++)
{
temdiv[i] = malloc(sizeof(BmpDivData));
}
BmpCut2N(3, 4, image, temdiv);
for(int i=0; i<12; i++)
{
ShowBmp(temdiv[i]->x, temdiv[i]->y,
temdiv[i]->Width, temdiv[i]->Heigh, temdiv[i]->Bmp);
}
sleep(3);
//设置随机数种子
BmpRandom(temdiv, 3, 4);
for(int i=0; i<12; i++)
{
ShowBmp(temdiv[i]->x, temdiv[i]->y,
temdiv[i]->Width, temdiv[i]->Heigh, temdiv[i]->Bmp);
printf("%d:[%d,%d]\n", temdiv[i]->vnumber, temdiv[i]->x, temdiv[i]->y);
}
int x,y;
int num,num1;
while(1)
{
GetXY(&x, &y);
num = WhichSelect(x, y, 3, 4);
//printf(" The %d image is be selected\n", num);
for(int i=0; i<12; i++)
{
if(num == temdiv[i]->vnumber)
{
num = i;
break;
}
}
while(1)
{
GetXY(&x, &y);
num1 = WhichSelect(x, y, 3, 4);
for(int i=0; i<12; i++)
{
if(num1 == temdiv[i]->vnumber)
{
num1 = i;
break;
}
}
if(num != num1)
{
break;
}
}
printf(" The %d image is be selected\n", temdiv[num]->vnumber);
printf(" The %d image is be selected\n", temdiv[num1]->vnumber);
ExchangeBmp(num, num1, 3, 4, temdiv);
ShowBmp(temdiv[num]->x, temdiv[num]->y,
temdiv[num]->Width, temdiv[num]->Heigh, temdiv[num]->Bmp);
ShowBmp(temdiv[num1]->x, temdiv[num1]->y,
temdiv[num1]->Width, temdiv[num1]->Heigh, temdiv[num1]->Bmp);
if(IsBmpSucceed(3, 4, temdiv))
{
printf("You have completed the bmp, finish\n");
break;
}
}
//销毁图片
DestoryBmp(image);
//DestoryBmp(image1);
return 0 ;
}