c jpeg YUV图片帧分割成 8*8 块 ,与逆向把8*8还原为帧

2023-12-14 00:27:29

1.? 正向分割为若干8*8 块

? ? ?下面的程序为通用程序,可以分割任意块


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>  //v4l2 头文件
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>

int main(void){
	char i[]={1, 2, 3, 4,   5, 6, 7, 8,
	          9,10,11,12,   13,14,15,16,
		      17,18,19,20,  21,22,23,24,
		      25,26,27,28,  29,30,31,32,
		
		      33,34,35,36,  37,38,39,40,
			  41,42,43,44,  45,46,47,48,
		      49,50,51,52,  53,54,55,56,
		      57,58,59,60,  61,62,63,64
	       };
	
	int width=8;              //被分割数据宽度
	int heigth=8;             //被分割数据高度
	                   
	int fwidth=4;             //分割块的宽度     分割成4×2块
	int fheigth=2;            //分割块的高度
	
	
	char o[width*heigth];     //分割后的数据
	int t=0;

		for(int c=0;c<heigth/fheigth;c++){
		 
		  for(int b=c*width*fheigth;b<width+c*fheigth*width;b=b+fwidth){
			
			for(int a=0;a<fheigth;a++){
			    memcpy(&o[t],&i[a*width+b],fwidth);
			    t=t+fwidth;
			
			}
		  }
		}
//--------------------------------------------------------------	
	char (*p1)[2][4]=(char (*)[2][4])o;   //显示4×2 块
	
	for(int a=0;a<8;a++){
		for(int b=0;b<2;b++){
			for(int c=0;c<4;c++){
				printf("%d  ",p1[a][b][c]);
			}
			printf("\n");
		}
		puts("-----------");
		
	}


	return 0;
}

2. 8*8 块逆向 转化为帧


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>  //v4l2 头文件
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>

int main(void){
/*	char i[]={1, 2, 3, 4,   5, 6, 7, 8,
	          9,10,11,12,   13,14,15,16,
		      17,18,19,20,  21,22,23,24,
		      25,26,27,28,  29,30,31,32,
		
		      33,34,35,36,  37,38,39,40,
			  41,42,43,44,  45,46,47,48,
		      49,50,51,52,  53,54,55,56,
		      57,58,59,60,  61,62,63,64
	};*/
	
    char io[]={
		1,  2,  3,  4,  
		9,  10,  11,  12,  
		17,  18,  19,  20,  
		25,  26,  27,  28,  
		
		5,  6,  7,  8,  
		13,  14,  15,  16,  
		21,  22,  23,  24,  
		29,  30,  31,  32,  
		
		33,  34,  35,  36,  
		41,  42,  43,  44,  
		49,  50,  51,  52,  
		57,  58,  59,  60,  
		
		37,  38,  39,  40,  
		45,  46,  47,  48,  
		53,  54,  55,  56,  
		61,  62,  63,  64
	};
	
	int width=8;              //被分割数据宽度
	int heigth=8;             //被分割数据高度
	                   
	int fwidth=4;             //分割块的宽度     
	int fheigth=4;            //分割块的高度
	
/*	
	char o[width*heigth];     //分割后的数据
	int t=0;

		for(int c=0;c<heigth/fheigth;c++){
		 		
		   for(int b=c*width*fheigth;b<width+c*fheigth*width;b=b+fwidth){
				for(int a=0;a<fheigth;a++){   
			
			    memcpy(&o[t],&i[a*width+b],fwidth);
			    t=t+fwidth;
			
			}
		  }
		}
*/	
	char oo[width*heigth];    
	int ot=0;
	
	for(int c=0;c<heigth/fheigth;c++){
		for(int a=0;a<fheigth;a++){
	    	for(int b=0;b<width/fwidth;b++){
			
				memcpy(&oo[ot],&io[b*fwidth*fheigth+a*fwidth+c*fheigth*fwidth*width/fwidth],fwidth);
				ot=ot+fwidth;
				
			}
		}
	}
//--------------------------------------------------------------	
	char (*p1)[4][4]=(char (*)[4][4])oo;   //显示
	
	for(int a=0;a<4;a++){
		for(int b=0;b<4;b++){
			for(int c=0;c<4;c++){
				printf("%d,  ",p1[a][b][c]);
			}
			printf("\n");
		}
		puts("-----------");
		
	}


	return 0;
}

实话头都绕晕了,看能不能再想一个好理解的方法。查表法简单,但数据大了就不实用了,如果要程序生成大数据的表,感觉又多了一个环节。而且也不容易

但Z 型排列可以用查表法。

3.用4×4块模拟生成一维的帧

//模拟4×4的块横向拼接成一个16×4的一个大块

下面的拼接思路为:先确定要拼接的输出数组每行总宽度width, 再确定这个总宽度要几个被转换的块,再取出每一个块的第一行组成输出数组的第一行,取每个块的第二行组成输出数组的第二行,直到fheigth结束。


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>  //v4l2 头文件
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>

int main(void){
/*	char i[]={1, 2,3, 4,    5, 6, 7, 8,
	          9,10,11,12,   13,14,15,16,
		      17,18,19,20,  21,22,23,24,
		      25,26,27,28,  29,30,31,32,
		
		      33,34,35,36,  37,38,39,40,
			  41,42,43,44,  45,46,47,48,
		      49,50,51,52,  53,54,55,56,
		      57,58,59,60,  61,62,63,64
	};
*/
	char i1[]={              //模拟4×4的块横向拼接成一个16×4的一个大块
		1, 2,3, 4,    
		9,10,11,12,   
		17,18,19,20, 
		25,26,27,28,
	};
	
	char (*p1)[4]=(char (*)[4])i1;
	
	char i2[]={
		 5, 6, 7, 8,
         13,14,15,16,
	     21,22,23,24,
		 29,30,31,32,
	};
	char (*p2)[4]=(char (*)[4])i2;
	char i3[]={
		33,34,35,36,  
		41,42,43,44,  
		49,50,51,52,  
		57,58,59,60,  
	};
	char (*p3)[4]=(char (*)[4])i3;
	char i4[]={
		 37,38,39,40,
		45,46,47,48,
		53,54,55,56,
		61,62,63,64
	};
	char (*p4)[4]=(char (*)[4])i4;
	
	char i[64];             //4个块合成在一起,相当于逆向余弦后的8×8数据合成一数组
	memcpy(i,i1,16);
	memcpy(&i[16],i2,16);
	memcpy(&i[32],i3,16);
	memcpy(&i[48],i4,16);
	

    int n=4;
	char o[64];             //正常的帧排列
	int fwidth=4;
	int fheigth=4;
	int width=n*fwidth;
	int heigth=4;
	
	char (*po)[width]=(char (*)[width])o;
	char (*ii)[fheigth][fwidth]=(char (*)[fheigth][fwidth])i;	//把要转换的数据转成n个fwidth*fheigth的块,用n的id来代表这些块
//--------------------------------------------------	
	for(int a=0;a<heigth;a++){
		for(int b=0;b<width;b++){            
			
			int k=b/fwidth;                  //这两句非常重要,k=块id
		    po[a][b]=ii[k][a][b-fwidth*k];   //b-fwidth*k 等于每一个块的fwidth
			
		}
		
	}
//-------------------------------------------------	
	for(int t=0;t<64;t++){                  //显示
		printf("%d  ,",o[t]);
	}
	

	return 0;
}

?

?

?

?

文章来源:https://blog.csdn.net/m0_59802969/article/details/134876068
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。