C语言 NOTE20

====================================================

拼图程序流程图:使用在线迅捷画图绘制

将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: [email protected]
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: [email protected]
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: [email protected]
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: [email protected]
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: [email protected]
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 ;
}
发布了52 篇原创文章 · 获赞 2 · 访问量 2014

猜你喜欢

转载自blog.csdn.net/weixin_42191545/article/details/103433521