当前位置: 首页 > news >正文

文件IO(刷BMP格式图片、JPG格式图片)

一、BMP图的实现

练习1:
再实现一张BMP图

 

	//打开lcd
	int lcd = open("/dev/fb0",O_RDWR);
	if(lcd < 0)
	{
		perror("open error!\n");
		return -1;
	}
	
	//lcd映射
	//指针指向一个像素点
	int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	if(p == NULL)
	{
		perror("mmap fail!\n");
		return -1;
	}	
	//打开bmp图片
	int lcd_bmp = open("1.bmp",O_RDWR);
	if(lcd_bmp < 0)
	{
		printf("open bmp fail!\n");
		return -1;
	}
	
	//去除掉头54个字节
	lseek(lcd_bmp,54,SEEK_SET);

	//存储bmp图片的buffer:800*480*3
	char buf[800*480*3] = {0};
	
	//读bmp图片
	read(lcd_bmp,buf,800*480*3);
	
	//将buf数据通过指针p填充到LCD中	
	// int i;
	// for(i=0;i<800*480;i++)
	// {
		// *(p+i) = buf[3*i] |buf[3*i+1]<<8 |buf[3*i+2]<<16;
	// }

	//将buf数据通过指针p填充到LCD中
	int x;//x表示横轴
	int y;//y表示纵轴
	for(y=0;y<480;y++)
	{
		for(x=0;x<800;x++)
		{
			/*
				将buf[]里面的数据由BGR换成RGB
				将3个字节封装成4个字节
			*/
			*(p+((479-y)*800+x)) = (buf[3*(y*800+x)+0]) | (buf[3*(y*800+x)+1]<<8) | (buf[3*(y*800+x)+2]<<16);
				/* 
			        0    =  buf[0] | buf[1]<<8 | buf[2]<<16
					1    =  buf[3] | buf[4]<<8 | buf[5]<<16
					2    =  buf[6] | buf[7]<<8 | buf[8]<<16
					800    =  buf[800*3] | buf[800*3+1]<<8 | buf[800*3+2]<<16
				 */	
		}
	}

	
	//lcd映射释放
	munmap(p,800*480*4);
	
	//关闭lcd\bmp
	close(lcd);
	close(lcd_bmp);

练习2:
实现3张照片的轮流播放
sleep(1);//延时1秒
usleep(1); //延时微秒
推展:能否将你实现bmp照片的代码封装成一个函数

int show_pic(int *p,char *bmp_path)
{
		//打开bmp图片
	int bmp = open(bmp_path,O_RDWR);
	if(bmp < 0)
	{
		printf("open bmp fail!\n");
		return -1;
	}
	
	//去除掉头54个字节
	lseek(bmp,54,SEEK_SET);
	
	//存储bmp图片的buffer:800*480*3
	char buf[800*480*3] = {0};

	int ret1 = read(bmp,buf,800*480*3);		
		sleep(1);
		//读bmp图片
		//将buf数据通过指针p填充到LCD中
		
	int x;//x表示横轴
	int y;//y表示纵轴
	for(y=0;y<480;y++)
	{
		for(x=0;x<800;x++)
		{
			/*
				将buf[]里面的数据由BGR换成RGB
				将3个字节封装成4个字节
			*/
			*(p+((479-y)*800+x)) = (buf[3*(y*800+x)+0]) | (buf[3*(y*800+x)+1]<<8) | (buf[3*(y*800+x)+2]<<16);
				/* 
					0    =  buf[0] | buf[1]<<8 | buf[2]<<16
					1    =  buf[3] | buf[4]<<8 | buf[5]<<16
					2    =  buf[6] | buf[7]<<8 | buf[8]<<16
					800    =  buf[800*3] | buf[800*3+1]<<8 | buf[800*3+2]<<16
				 */	
		}
	}
	close(bmp);
	
	return 0;
}


int main(int argc,char *argv[])
{
	//打开lcd
	int lcd = open("/dev/fb0",O_RDWR);
	if(lcd < 0)
	{
		perror("open lcd error!\n");
		return -1;
	}
	
	//lcd映射
	//指针指向一个像素点
	int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	if(p == NULL)
	{
		perror("mmap fail!\n");
		return -1;
	}
	
	//指针数组存储字符串
	char *bmp_path[] = {"1.bmp","zhao.bmp","guo.bmp","curry.bmp"};
	int n = 4;
	int i =0 ;
	
	while(1)
	{
		for(i=0;i<4;i++)
		{
			show_pic(p,bmp_path[i]);
			sleep(1);
		}
	}
		
	//lcd映射释放
	munmap(p,800*480*4);
	
	//关闭lcd\bmp
	close(lcd);
	
	
	return 0;
}

命名规则:
1.windows里面的命名
以大写字母开头来区分与单词之间
ShowBmp

2. linux里面的命名
以"_"来区分与单词之间
show_bmp

3.驼峰命名法
1)小驼峰:
int myStudentCount;
变量myStudentCount第一个单词是全部小写,后面的单词首字母大写。

2)大驼峰
public class DataBaseUser
相比小驼峰法,大驼峰法(即帕斯卡命名法)把第一个单词的首字母也大写了

4.具体用什么方法来命名
由老板来决定

二、计算bmp图片的宽度和高度
通过bmp图片的头54个字节来计算bmp图片的高度和宽度


那如果是一张800*480的图片,那么他的
int hight = 480
int width = 800
lseek(fd_bmp,18,SEEK_SET); //光标是在18位置
read(fd_bmp,&width,4); //光标是在22位置
read(fd_bmp,&hight,4);
printf("width=%d hight=%d\n",width,hight);

 

	int bmp_fd = open(argv[1], O_RDWR);
	if (bmp_fd == -1) {
		printf("打开失败\n");
		return -1;
	}

	char header[54]; //储存头文件数据
	read(bmp_fd, header, 54); //读取头文件数据
	
	int w, h; //定义宽、高变量
	
	lseek(bmp_fd,18,SEEK_SET);
	read(bmp_fd,&w,4);
	read(bmp_fd,&h,4);
	printf("h:%d  w:%d\n",h,w);
	
	close(bmp_fd);	

二、如何使用jpg图片


bmp图片:优点:读取数据方便,实现一张800*480代码比较简单;缺点:图片太大,要增加硬件成本
jpg图片:优点:图片小便于存储;缺点:要解压图片代码比较复杂

 

 

1.如何使用第三方库来解压jpg图片
1)如何使用第三方库(别人开发的库文件--外库)----->移植
三大神步骤
配置  ./configure
编译 make 
安装 make install

2)如何来移植一个jpeg库
移植成功之后开发板的操作:
[root@GEC6818 /IOT/bling]#chmod 777 main
[root@GEC6818 /IOT/bling]#
[root@GEC6818 /IOT/bling]#./main (没移植库前会出现如下错误)
./main: error while loading shared libraries: libjpeg.so.9: cannot open shared object file: No such file or directory
[root@GEC6818 /IOT/bling]#chmod 777 libjpeg.so.9(一定要修改库的权限) 
[root@GEC6818 /IOT/bling]#
[root@GEC6818 /IOT/bling]#cp libjpeg.so.9 /lib/

三、安装小工具
如何开火车和养猫
sudo apt-get install sl   //火车  sl --help
sudo apt-get install oneko   //hellokitty  猫  oneko --help
oneko -bg red 给猫一个红色
说明:
(前提需要ubuntu联外网)
sudo apt-get update //更新软件源

作业1:
实现4张照片的轮流播放
2张bmp(800*480)
2张jpg(400*240)这两张放同一平面上

lcdjpg.c

#include <stdio.h>   	
#include <fcntl.h>		 	 
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "lcdjpg.h"
#include "jpeglib.h"
#include <sys/stat.h>

static char g_color_buf[FB_SIZE]={0};

static int  g_fb_fd;
static int *g_pfb_memory;

/* video_chat.c ?-?D?-??ê?μ?×?±ê */
volatile int g_jpg_in_jpg_x;
volatile int g_jpg_in_jpg_y;

unsigned long file_size_get(const char *pfile_path)
{
	unsigned long filesize = -1;	
	struct stat statbuff;
	
	if(stat(pfile_path, &statbuff) < 0)
	{
		return filesize;
	}
	else
	{
		filesize = statbuff.st_size;
	}
	
	return filesize;
}
//LCD?-μ?
void lcd_draw_point(unsigned int x,unsigned int y, unsigned int color)
{
	*(g_pfb_memory+y*800+x)=color;
}

int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half)  
{
	//3?ê??ˉLCD
	g_fb_fd = open("/dev/fb0", O_RDWR);
	
	if(g_fb_fd<0)
	{
			printf("open lcd error\n");
			return -1;
	}

	g_pfb_memory  = (int *)mmap(	NULL, 				//ó3é???μ??aê?μ??·£?éè???aNULLê±±íê?óé?μí3???¨ó3é???μ??eê?μ??·
									FB_SIZE, 				//ó3é???μ?3¤?è
									PROT_READ|PROT_WRITE, 	//?úèY?éò?±??áè?oíD′è?
									MAP_SHARED,				//12?í?ú′?
									g_fb_fd, 				//óDD§μ????t?èê?′ê
									0						//±?ó3é????ó?úèYμ??eμ?
								);
	
	/*?¨ò??a?????ó£?′í?ó′|àí???ó*/
	struct 	jpeg_decompress_struct 	cinfo;
	struct 	jpeg_error_mgr 			jerr;	
	
	char *pcolor_buf = g_color_buf;
	char 	*pjpg;
	
	unsigned int 	i=0;
	unsigned int	color =0;
	unsigned int	count =0;
	
	unsigned int 	x_s = x;
	unsigned int 	x_e ;	
	unsigned int 	y_e ;
	
			 int	jpg_fd;
	unsigned int 	jpg_size;
	
	unsigned int 	jpg_width;
	unsigned int 	jpg_height;
	
	if(pjpg_path!=NULL)
	{
		/* éê??jpg×ê?′£?è¨?T?é?á?éD′ */	
		jpg_fd=open(pjpg_path,O_RDWR);
		
		if(jpg_fd == -1)
		{
		   printf("open %s error\n",pjpg_path);
		   
		   return -1;	
		}	
		
		/* ??è?jpg???tμ?′óD? */
		jpg_size=file_size_get(pjpg_path);	

		/* ?ajpg???téê???ú′????? */	
		pjpg = malloc(jpg_size);

		/* ?áè?jpg???t?ùóD?úèYμ??ú′? */		
		read(jpg_fd,pjpg,jpg_size);
	}
	else
	{
		jpg_size = jpg_buf_size;
		
		pjpg = pjpg_buf;
	}

	/*×¢2á3?′í′|àí*/
	cinfo.err = jpeg_std_error(&jerr);

	/*′′?¨?a??*/
	jpeg_create_decompress(&cinfo);

	/*?±?ó?a???ú′?êy?Y*/		
	jpeg_mem_src(&cinfo,pjpg,jpg_size);
	
	/*?á???tí·*/
	jpeg_read_header(&cinfo, TRUE);

	/*?aê??a??*/
	jpeg_start_decompress(&cinfo);		
	if(jpg_half)
	{
		x_e	= x_s+(cinfo.output_width/2);
		y_e	= y  +(cinfo.output_height/2);		
		
		/*?á?a??êy?Y*/
		while(cinfo.output_scanline < cinfo.output_height)
		{		
			pcolor_buf = g_color_buf;
			
			/* ?áè?jpgò?DDμ?rgb?μ */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);			
			
			/* ?ù?áè?jpgò?DDμ?rgb?μ */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);

			for(i=0; i<(cinfo.output_width/2); i++)
			{
				/* ??è?rgb?μ */
				color = 		*(pcolor_buf+2);
				color = color | *(pcolor_buf+1)<<8;
				color = color | *(pcolor_buf)<<16;
				
				/* ??ê?????μ? */
				lcd_draw_point(x,y,color);			
				pcolor_buf +=6;			
				x++;
			}		
			/* ??DD */
			y++;						
			x = x_s;			
		}
	}
	else
	{
		x_e	= x_s+cinfo.output_width;
		y_e	= y  +cinfo.output_height;	

		/*?á?a??êy?Y*/
		while(cinfo.output_scanline < cinfo.output_height )
		{		
			pcolor_buf = g_color_buf;
			
			/* ?áè?jpgò?DDμ?rgb?μ */
			jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
			
			for(i=0; i<cinfo.output_width; i++)
			{
				/* ??è?rgb?μ */
				color = 		*(pcolor_buf+2);
				color = color | *(pcolor_buf+1)<<8;
				color = color | *(pcolor_buf)<<16;
				
				/* ??ê?????μ? */
				lcd_draw_point(x,y,color);				
				pcolor_buf +=3;				
				x++;
			}			
			/* ??DD */
			y++;						
			x = x_s;			
		}		
	}
	
	/*?a??íê3é*/
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	if(pjpg_path!=NULL)
	{
		/* 1?±?jpg???t */
		close(jpg_fd);	
		
		/* êí·?jpg???t?ú′????? */
		free(pjpg);		
	}
	//LCD1?±?
	/* è????ú′?ó3é? */
	munmap(g_pfb_memory, FB_SIZE);
	
	/* 1?±?LCDéè±? */
	close(g_fb_fd);
	return 0;
}

lcdjpg.h

#ifndef __LCDJPG_H__
#define __LCDJPG_H__

#define LCD_WIDTH  			800
#define LCD_HEIGHT 			480
#define FB_SIZE				(LCD_WIDTH * LCD_HEIGHT * 4)

//my_head.h
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>

int show_pic(int *p,char *bmp_path);

/* video_chat.c 画中画显示的坐标 */
extern volatile int g_jpg_in_jpg_x;
extern volatile int g_jpg_in_jpg_y;

void lcd_draw_point(unsigned int x,unsigned int y, unsigned int color);
int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half);
#endif

main.c

#include <stdio.h>
#include "lcdjpg.h"

/*
参数说明:
0:x坐标
0:y坐标
./2.jpg:图片的名字
NULL:pjpg_buf
0:jpg_buf_size
0:jpg_half
编译:
	arm-linux-gcc *.c -o main -I./libjpeg -L./libjpeg -ljpeg 

*/

int main(void)
{
	
	//打开lcd
	int lcd = open("/dev/fb0",O_RDWR);
	if(lcd < 0)
	{
		perror("open lcd error!\n");
		return -1;
	}
	
	//lcd映射
	//指针指向一个像素点
	int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	if(p == NULL)
	{
		perror("mmap fail!\n");
		return -1;
	}
	
	//指针数组存储字符串
	char *bmp_path[] = {"zhao.bmp","guo.bmp"};
	int n = 2;
	int i =0 ;
	
	while(1)
	{
		for(i=0;i<2;i++)
		{
			show_pic(p,bmp_path[i]);
			sleep(1);
			lcd_draw_jpg(0,0,"./curry.jpg",NULL,0,0);
			sleep(1);
			lcd_draw_jpg(400,0,"./tom.jpg",NULL,0,0);
			sleep(1);
			lcd_draw_jpg(0,240,"./james.jpg",NULL,0,0);
			sleep(1);
			lcd_draw_jpg(400,240,"./jr.jpg",NULL,0,0);
			sleep(1);
		}
	}
		
	//lcd映射释放
	munmap(p,800*480*4);
	
	//关闭lcd\bmp
	close(lcd);
	return 0;
}

show_pic_fun.c

#include "my_head.h"

int show_pic(int *p,char *bmp_path)
{
		//打开bmp图片
	int bmp = open(bmp_path,O_RDWR);
	if(bmp < 0)
	{
		printf("open bmp fail!\n");
		return -1;
	}
	
	//去除掉头54个字节
	lseek(bmp,54,SEEK_SET);
	
	//存储bmp图片的buffer:800*480*3
	char buf[800*480*3] = {0};

	int ret1 = read(bmp,buf,800*480*3);		
		sleep(1);
		//读bmp图片
		//将buf数据通过指针p填充到LCD中
		
	int x;//x表示横轴
	int y;//y表示纵轴
	for(y=0;y<480;y++)
	{
		for(x=0;x<800;x++)
		{
			/*
				将buf[]里面的数据由BGR换成RGB
				将3个字节封装成4个字节
			*/
			*(p+((479-y)*800+x)) = (buf[3*(y*800+x)+0]) | (buf[3*(y*800+x)+1]<<8) | (buf[3*(y*800+x)+2]<<16);
				/* 
					0    =  buf[0] | buf[1]<<8 | buf[2]<<16
					1    =  buf[3] | buf[4]<<8 | buf[5]<<16
					2    =  buf[6] | buf[7]<<8 | buf[8]<<16
					800    =  buf[800*3] | buf[800*3+1]<<8 | buf[800*3+2]<<16
				 */	
		}
	}
	close(bmp);
	
	return 0;
}

编译:
    arm-linux-gcc *.c -o main -I./libjpeg -L./libjpeg -ljpeg  


附加题:(前提条件小于800*480)
通过读取bmp图片的高度和宽度来实现任意一张任意大小的bmp图片

/*
	说明:
		图片的宽度一定要是4的倍数,如果不是4的倍数,需要做像素点补偿(专业)
		所以我们自己制作bmp图片,宽度要做成4的倍数
		
		图片的大小和你的偏移量合起来不能超过整个屏幕
*/
int show_bmp_size(int *p,char *bmp_path,int offset_x,int offset_y)
{
	//打开bmp图片
	int lcd_bmp = open(bmp_path,O_RDWR);//800*480的图片
	if(lcd_bmp < 0)
	{
		printf("open bmp fail!\n");
		return -1;
	}
	
	int wide=0,hight=0;
	lseek(lcd_bmp,18,SEEK_SET);
	read(lcd_bmp,&wide,4);
	read(lcd_bmp,&hight,4);
	printf("hight:%d  wideZ:%d\n",hight,wide);
	//去除掉头54个字节
	lseek(lcd_bmp,54,SEEK_SET);

	//存储bmp图片的buffer:800*480*3
	char buf[wide*hight*3];
	
	//读bmp图片
	read(lcd_bmp,buf,wide*hight*3);
	
	// int offset_x = 100;//图片x起始位置
	// int offset_y = 100;//图片y起始位置
	printf("offset_x:%d  offset_y:%d\n",offset_x,offset_y);
	
	
	//将buf数据通过指针p填充到LCD中	
	int x;//x表示横轴
	int y;//y表示纵轴
	for(y=0;y<hight;y++)
	{
		for(x=0;x<wide;x++)
		{
			/*
				屏幕的起始坐标值应该从偏移量开始
				offset_y+hight 是最后一行起始点的纵轴坐标
				offset_x是最后一行起始点横轴坐标
			*/
			*(p+(offset_y+hight-1-y)*800+offset_x+x) = (buf[3*(y*wide+x)+0])
												| (buf[3*(y*wide+x)+1]<<8)
												| (buf[3*(y*wide+x)+2]<<16);
				/* 
			        0    =  buf[0] | buf[1]<<8 | buf[2]<<16
					1    =  buf[3] | buf[4]<<8 | buf[5]<<16
					2    =  buf[6] | buf[7]<<8 | buf[8]<<16
					800    =  buf[800*3] | buf[800*3+1]<<8 | buf[800*3+2]<<16
				 */	
		}
	}
	
	close(lcd_bmp);
	
	return 0;
}

int main(int argc,char *argv[])
{
	
	if(argc !=4)
	{
		printf("./a.out <bmp_path> <offset_x> <offset_y>");
		return -1;
	}
	//打开lcd
	int lcd = open("/dev/fb0",O_RDWR);
	if(lcd < 0)
	{
		perror("open error!\n");
		return -1;
	}
	
	//lcd映射
	//指针指向一个像素点
	int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	if(p == NULL)
	{
		perror("mmap fail!\n");
		return -1;
	}	
	
	//argv[1]照片名字
	//atoiargv[2]照片x轴起始位置
	//atoiargv[3]照片y轴起始位置
	show_bmp_size(p,argv[1],atoi(argv[2]),atoi(argv[3]));
	
	//lcd映射释放
	munmap(p,800*480*4);
	
	//关闭lcd\bmp
	close(lcd);

	return 0;
}

相关文章:

  • 矩阵顺时针反转
  • arm-2d移植到OneOS上的使用
  • 文章说明86145B安捷伦光学分析仪86145B
  • 网课答案查题功能调用接口
  • 『Halcon与C#混合编程』012_迈德威视工业相机SDK入门
  • 以太坊合并可能会引发的雪崩
  • 记一次Prometheus监控下的“内存飙升”事件
  • Linux——进程操作之创建
  • 葡聚糖-聚乙烯亚胺Dextran-PEI,聚乙烯亚胺修饰纤维二糖/香菇多糖/辣根过氧化氢酶/溶菌酶
  • 浙大MBA网上报名关键信息点提醒,选错一个,回头重来
  • 本地git操作-之分支合并与回滚
  • Three 之 three.js (webgl)物体描边效果(outline)三种实现方式的简单整理(后期渲染/MeshBasicMaterial/法线扩展)
  • nginx平滑升级、nginx支持的kill信号
  • Golang中进行Url编码,再也不怕奇奇怪怪的参数格式了
  • Linux机器时钟同步
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • E-HPC支持多队列管理和自动伸缩
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • ESLint简单操作
  • Gradle 5.0 正式版发布
  • JavaScript的使用你知道几种?(上)
  • java中具有继承关系的类及其对象初始化顺序
  • Laravel 实践之路: 数据库迁移与数据填充
  • October CMS - 快速入门 9 Images And Galleries
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 从输入URL到页面加载发生了什么
  • 二维平面内的碰撞检测【一】
  • 关于 Cirru Editor 存储格式
  • 关于for循环的简单归纳
  • 记一次和乔布斯合作最难忘的经历
  • 设计模式(12)迭代器模式(讲解+应用)
  • 设计模式走一遍---观察者模式
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 数据仓库的几种建模方法
  • 通过npm或yarn自动生成vue组件
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 昨天1024程序员节,我故意写了个死循环~
  • # C++之functional库用法整理
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (1)SpringCloud 整合Python
  • (安卓)跳转应用市场APP详情页的方式
  • (二)正点原子I.MX6ULL u-boot移植
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (一)WLAN定义和基本架构转
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • [CSS]CSS 字体属性
  • [LeetCode]-Pascal's Triangle III 杨辉三角问题
  • [NAND Flash 6.2] NAND 初始化常用命令:复位 (Reset) 和 Read ID 和 Read UID 操作和代码实现
  • [NSSRound#16 Basic]RCE但是没有完全RCE