数据排序转换

最近在做RK平台的相关东东,RK内存的数据排序如下图(以12bit为例):


图1 大端存储(高地址,低字节)

如图1所示,在RK内存中,(个人认为)以大端存储,像素的高字节数据(11~4bit)保存在内存的低地址中。以代码中打印的数据为例,P0像素的数据为0x7F(内存低地址,11~4bit),0xE0(内存高地址,3~0bit,0000),P1像素的数据为0x7E(内存低地址,11~4bit),0x30(内存高地址,0000)。

随后,在RK平台使用fwrite()函数保存文件(例如RAW_1)到SD卡中,(个人认为),RAW_1文件起始的16位数据存储为0x7FE0,如图2所示(好吧,其实和图1差不多微笑)。

ps:这个0x7FE0是指如果我们在其他的大端机上用fread函数读取RAW_1文件,则读取到的数据也是0x7FE0。


                                                                                                图2

之后,将SD卡中的文件RAW_1拷贝到PC机中,在PC机里是小端存储(高地址,高字节),如果使用fread函数读出来,则读取到的数据是0xE07F,如图3所示。

ps:(个人猜测)文件RAW_1在由大端机上向小端机上拷贝的过程中发生了存储方式的改变

        另外,要记住,这些文件其实本质上存储的事宜ASCII码值。


                                                                                      图3 小端存储(低地址,低字节)

但是,我们希望保存下来的数据在PC机上显示是高字节4位无数据,也就是如图4所示(图越来越渣了吐舌头


                                                                                      图4 小端存储(高字节4bit无数据)

所以这就要求保存在SD卡中的文件,或者说在RK内存(大端)中的数据排序应该如图5所示


图5

所以希望在保存数据前进行内存中数据排序的转换,写了一个不咋地的小程序,但是总算可以实现想要的功能。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned short exchange(char *buffer_hi,char *buffer_lo)
{
	unsigned short value_hi=((unsigned short)*buffer_hi<<8)&0xff00;
	unsigned short value_lo=(unsigned short)*buffer_lo&0xff;

	unsigned short temp1=((value_hi|value_lo)&0x000f)<<12&0xf000;
	unsigned short temp2=(value_hi|value_lo)>>4&0x0fff;

	unsigned short value_out=temp1|temp2;

	return value_out;
}

int main()
{
	char buffer[6];	
	buffer[0]=0xC3;	//1100 0011
	buffer[1]=0x61;	//1000 0001
	buffer[2]=0x42;	//0100 0010
	buffer[3]=0x51;	//0101 0001
	buffer[4]=0x21;	//0010 0001
	buffer[5]=0x50;	//0101 0000
	
	for(int i=0;i<6;i++)
	{
		printf("buffer[%d] is %x\n",i,buffer[i]);
	}
	
	char *p=NULL;
	p=(char *)malloc(sizeof(char)*6);
	if(p)  
		printf("Memory Allocated at: %x\n",p);  
	else  
		printf("Not Enough Memory!\n"); 
		
	char *p1=p;
		
	memcpy(p,&buffer[0],sizeof(buffer));
	
	unsigned short buffer_out[3];
	memset(buffer_out,0,sizeof(unsigned short)*3);
	
	printf("开始转换\n");
	
	for(int k=0;k<3;k++)
	{
		char temp1=*p;
		char temp2=*(++p);
		printf("temp1 is %x, temp2 is %x\n",temp1,temp2);
		buffer_out[k]=exchange(&temp1,&temp2);
		p++;
	}
		
	printf("转换结束\n");
	
	p=p1;             //p指针已经偏移,要free一定要指回来 
	free(p);
	p=NULL;           //置NULL 
	p1=NULL;
	
	for(int m=0;m<3;m++)
	{
		printf("buffer_out[%d] is %x\n",m,buffer_out[m]);
	}
	
	return 0;
}

运行结果为:

buffer[0] is ffffffc3
buffer[1] is 61
buffer[2] is 42
buffer[3] is 51
buffer[4] is 21
buffer[5] is 50
Memory Allocated at: 780f30
开始转换
temp1 is ffffffc3, temp2 is 61
temp1 is 42, temp2 is 51
temp1 is 21, temp2 is 50
转换结束
buffer_out[0] is 1c36
buffer_out[1] is 1425
buffer_out[2] is 215
请按任意键继续. . .

在后续的开发过程中发现大量的数据转换耗时真的太长,以RK1108来说,转换224*172*9这么大的数据(也就是上面代码的循环次数k<224*179*9),总共需要大概20.6ms,于是想着怎么优化,先想到一条,不调用exchange函数,直接在循环里进行转换,这样可以减少出战入栈的时间,运行了一下,现在转换一次,大概需要13.9ms,提升了35%。后面继续优化,想到再来添加。


说真的,不到用的时候真的不算深入了解这些知识,以前对大小端的认识只是停留在概念,经过这次后,理解加深了很多。


后续附上一个关于大小端的网址,感觉这个说的挺全面的。

http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_14837.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值