c MJPG

yuv格式的照片是纯yuv的数据,如果不告诉图片查看程序此数据流的长与宽,是无法显示图片的。

MJPG是由多帧jpg图片组成。jpg图片有文件头,里面就有必须的长,宽数据。jpg的图片数据是yuv压缩后的数据。所以jpg解码后的数据也是yuv,也必须转为RGB32显示器才能显示。

1.   查看文件头字节:

     

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <stdlib.h>int main(void)
{FILE *f=fopen("/home/wzpc/Pictures/my.jpg","rb");if(f==NULL){puts("file error");exit(1);}fseek(f,0,SEEK_END);int len=ftell(f);fseek(f,0,SEEK_SET);int ft=fileno(f);char *fb=mmap(NULL,len,PROT_READ,MAP_SHARED,ft,0);unsigned char (*c)[16]=(unsigned char (*)[16])fb;for(int a=0;a<40;a++){for(int b=0;b<16;b++){printf("%x  ",c[a][b]);}puts("");}return 0;
}

 

3.c摄像头 生成jpg图片

ff  d8  ff  db  0  43  0  5  3  3  4  3  3  5  4  3                    ff d8:jpg 开始    ff db 0 43 0:量化表1开始  64字节   8*8 
4  5  5  5  5  7  c  8  7  6  6  7  f  a  b  8  
c  12  f  12  12  11  f  11  10  14  16  1c  18  14  15  1a  
15  10  11  19  21  19  1a  1d  1e  1f  20  1f  13  17  23  25               
23  1f  25  1c  1f  1f  1e  ff  db  0  43  1  5  5  5  7               ff db 0 43 1: 量化表2开始       64字节   8*8
6  7  e  8  8  e  1e  14  11  14  1e  1e  1e  1e  1e  1e  
1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  
1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  
1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  1e  ff  c0  0  11           ff c0:量化表后面有一个“开始帧(SOF)”,由“FFC0”等标记表示。据说图像的大小是在SOF中定义的。
8  2  d0  5  0  3  1  21  0  2  11  1  3  11  1  ff                     ff c4:以标记“FFC4”开头的“霍夫曼表”是一步压缩数据的霍夫曼编码
c4  0  1f  0  0  1  5  1  1  1  1  1  1  0  0  0                        ff c4 0 1f:  0x1f=31=29+2   所以数据长度为29个
0  0  0  0  0  1  2  3  4  5  6  7  8  9  a  b  
ff  c4  0  b5  10  0  2  1  3  3  2  4  3  5  5  4                      ff c4 0 b5:  0xb5=16*11+5=181=179+2   数据长度为179
 0  0  1  7d  1  2  3  0  4  11  5  12  21  31  41  
6  13  51  61  7  22  71  14  32  81  91  a1  8  23  42  b1  
c1  15  52  d1  f0  24  33  62  72  82  9  a  16  17  18  19  
1a  25  26  27  28  29  2a  34  35  36  37  38  39  3a  43  44  
45  46  47  48  49  4a  53  54  55  56  57  58  59  5a  63  64        
6  67  68  69  6a  73  74  75  76  77  78  79  7a  83  84  
85  86  87  88  89  8a  92  93  94  95  96  97  98  99  9a  a2  
a3  a4  a5  a6  a7  a8  a9  aa  b2  b3  b4  b5  b6  b7  b8  b9  
ba  c2  c3  c4  c5  c6  c7  c8  c9  ca  d2  d3  d4  d5  d6  d7  
d8  d9  da  e1  e2  e3  e4  e5  e6  e7  e8  e9  ea  f1  f2  f3  
f4  f5  f6  f7  f8  f9  fa  ff  c4  0  1f  1  0  3  1  1               ff c4 0 1f:
  1  1  1  1  1  0  0  0  0  0  0  1  2  3                 
4  5  6  7  8  9  a  b  ff  c4  0  b5  11  0  2  1                      ff c4 0 b5:
4  4  3  4  7  5  4  4  0  1  2  77  0  1  2  

4. SOF (ff c0) 帧开始的定义
    标记代码(2字节)   0xffc0
       数据长度   2      sof 长度
       精度      1      每个样本数据的位数 ,通常是8
       图像高度   2      单位是像素点
       图像宽度   2       单位是像素点
       颜色分级   1       YCbCr 3
       颜色分量信息  颜色分量数X3(一般为9字节)     每个颜色分量: 1字节分量id  1字节水平垂直采样因子  1字节分量使用的量化表id

      ff  c0   0   11   8   2  d0   5   0   3   1   21   0   2   11   1  3    11   1 
      sof数据`长度  0x11=17-2=15个字节
      图像高度  [2][d0]=2*256+13*16=720
      图像高度  [5][0]=5*256+0=1280
      颜色分级  3: YCbCr
      分量信息:
                   id          采样因子         使用的量化表id
        Y  :        1           21                0 
        Cb          2           11                1
        Cr          3           11                1
         
5.
标记名字        标记识别符              说明
SOI            0xd8                jpg图像开始
APP0           0xe0               JFIF应用领域
               0xe1-0xef          其他APP细分市场
              0xdb                量化表
              0xc0                 帧开始
              0xc4                霍夫曼表
              0xda                 扫描行开始
              0xd9                jpg图片结束
到这里基本上就得到了jpg图片的基本数据,剩下的就是用代码把它解码还原成YCbCr。

文件头最重要必须的数据结构有3种类型:4张向量表,SOF 帧数据,多个霍夫曼编码数据。得到这三种类型数据后,就可把编码数据解码成YUV格式数据了。

//----------------------------------------------------------------

摄像头生成的jpg文件结构如下:

0xff d8   开始

0xff db

oxff db      两张量化表

0xff c0       帧全局参数

0x ff   c4

0xff    c4

0xff   c4

0xff  c4     4张范式霍夫曼表

0xff   dd     差分编码累计复位间隔

0x ff   da     扫描数据开始

0xff   d9       结束

----------------------------------------------------------

开始从 范式霍夫曼解码开始下手。

下面是4张霍夫曼表数据

  ff  c4  0  1f  0  0  1  5  1  1  1  1  1  1  0  0  0  0  0  0  0  0  1  2  3  4  5  6  7  8  9  a  b    

        ff  c4  0  b5  10  0  2  1  3  3  2  4  3  5  5  4  4  0  0  1  7d  1  2  3  0  4  11  5  12  21  31  41  
6  13  51  61  7  22  71  14  32  81  91  a1  8  23  42  b1  c1  15  52  d1  f0  24  33  62  72  82  9  a  16  17  18  19  
1a  25  26  27  28  29  2a  34  35  36  37  38  39  3a  43  44  45  46  47  48  49  4a  53  54  55  56  57  58  59  5a  63  64  
65  66  67  68  69  6a  73  74  75  76  77  78  79  7a  83  84  85  86  87  88  89  8a  92  93  94  95  96  97  98  99  9a  a2  
a3  a4  a5  a6  a7  a8  a9  aa  b2  b3  b4  b5  b6  b7  b8  b9  ba  c2  c3  c4  c5  c6  c7  c8  c9  ca  d2  d3  d4  d5  d6  d7  
d8  d9  da  e1  e2  e3  e4  e5  e6  e7  e8  e9  ea  f1  f2  f3  f4  f5  f6  f7  f8  f9  fa 

        ff  c4  0  1f  1  0  3  1  1  
1  1  1  1  1  1  1  0  0  0  0  0  0  1  2  3  4  5  6  7  8  9  a  b 

         ff  c4  0  b5  11  0  2  1  
2  4  4  3  4  7  5  4  4  0  1  2  77  0  1  2  3  11  4  5  21  31  6  12  41  51  7  61  71  13  22  32  
81  8  14  42  91  a1  b1  c1  9  23  33  52  f0  15  62  72  d1  a  16  24  34  e1  25  f1  17  18  19  1a  26  27  28  29  
2a  35  36  37  38  39  3a  43  44  45  46  47  48  49  4a  53  54  55  56  57  58  59  5a  63  64  65  66  67  68  69  6a  73  
74  75  76  77  78  79  7a  82  83  84  85  86  87  88  89  8a  92  93  94  95  96  97  98  99  9a  a2  a3  a4  a5  a6  a7  a8  
a9  aa  b2  b3  b4  b5  b6  b7  b8  b9  ba  c2  c3  c4  c5  c6  c7  c8  c9  ca  d2  d3  d4  d5  d6  d7  d8  d9  da  e2  e3  e4  
e5  e6  e7  e8  e9  ea  f2  f3  f4  f5  f6  f7  f8  f9  fa

--------------------------------------------------------------------

ff  c4  0  1f  0  0  1  5  1  1  1  1  1  1  0  0  0  0  0  0  0  0  1  2  3  4  5  6  7  8  9  a  b                // ff c4  0  1f  0   (ff c4  0)固定,1f 长度  0:表id

 n0  n1  n2  n3  n4  n5   n6  n7  n8  n9  n10  n11  n12  n13  n14  n15         //生成编码长度 1-16位

  0      1    5   1    1    1     1    1    1    0     0      0      0     0      0       0             0  1  2  3  4  5  6  7  8

 9  a  b  (从0-b)是要被编的字符 总共12个

 

范式霍夫曼三个规则:

最小编码长度的第一个编码必须从0开始。
相同长度编码必须是连续的。
编码长度为 j 的第一个符号可以从编码长度为 j − 1 的最后一个符号所得知,即 c( j) = 2 ∗ ( c (j − 1) + 1 ) 


        编码位数     被编码个数        生成范式霍夫曼编码 (括号内是被编码数)
n0: 0   表示1位      0个           
n1: 1   表示2位      1个               00(0)
n2: 5   表示3位      5个               010(1) , 011(2),100(3),101(4),110(5)
n3: 1     4         1                1110 (6)
n4: 1     5         1                11110 (7)
n5: 1     6         1                111110 (8)
N6: 1     7         1                1111110(9)
n7: 1     8         1                11111110(a)
n8: 1     9         1                111111110(b)

 

现在就体会了压缩的好处:平时如果是char,存储0要用8bit位,现在只用2个bit位00  就行了。

现在有一个问题,用这种位数不同的编码怎样存入内存,程序又是怎样区分哪几位是代表0,哪几位是代表1  难道不同位数之间又要加分隔符号?

下面的这段话似乎解释了上面的问题。

霍夫曼编码后,二进制位数据是连续的,中间没有分隔符。需要保证各个符号编码不会冲突,也就是说,不会存在某一个编码是另一个编码的前缀。

把霍夫曼码流解码的方法是:从2bit位开始,先读两位bit位,去比对范式霍夫曼编码表中二位的编码,如有,就确定,如没有,就再读一bit位,再去比对3位码表查找,,,,依次循环,直到读到真实唯一的被编码数。所以不存在用分隔符的问题。

所以解码的过程就是依次+1bit读取被编码流去对比码表的过程。

 

现在正考虑怎样进行bit位操作,因为霍夫曼编码是变长位的数据,c中除了一个位字段操作以外,就没有任何对位数据的操作了。我在想如果有一个办法把扫描的霍夫曼编码流全部转为bit流,那操作就容易多了。(现在我们用的mmap操作的是字节流,如有办法能用mmap操作bit流就完美了)。

利用位字段把整数转为二进制

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>int main(void) {unsigned char t=201;typedef	struct {unsigned char b0:1;unsigned char b1:1;unsigned char b2:1;unsigned char b3:1;unsigned char b4:1;unsigned char b5:1;unsigned char b6:1;unsigned char b7:1;} bit;bit ss;memcpy(&ss,&t,1);printf("%d\n",ss.b0);printf("%d\n",ss.b1);printf("%d\n",ss.b2);printf("%d\n",ss.b3);printf("%d\n",ss.b4);printf("%d\n",ss.b5);printf("%d\n",ss.b6);printf("%d\n",ss.b7);return 0;
}

利用位字段把连续的字节流转为比特流

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>int main(void) {typedef	struct {unsigned char b0:1;unsigned char b1:1;unsigned char b2:1;unsigned char b3:1;unsigned char b4:1;unsigned char b5:1;unsigned char b6:1;unsigned char b7:1;} bit;bit ss;unsigned char p[3]={254,254,254};   //内存中连续存储的以字节为单位的数据unsigned char o[30]={0};           //以字节为单位用来存储一个比特的数据unsigned char *sp=o;               //数组o 中的数据就是p 的连续的比特数for(int n=0;n<3;n++){              
//	 memset(&ss,0,1);memcpy(&ss,p+n,1);              //把一个字节的数据赋值给struct bit*(sp+8*n+0)=ss.b7;               //把位赋值给字节存储*(sp+8*n+1)=ss.b6;               //反序排列的*(sp+8*n+2)=ss.b5;           *(sp+8*n+3)=ss.b4;*(sp+8*n+4)=ss.b3;*(sp+8*n+5)=ss.b2;*(sp+8*n+6)=ss.b1;*(sp+8*n+7)=ss.b0;}for(int c=0;c<24;c++){printf("%d ",o[c]);  //1 1 1 1 1 1 1 0    1 1 1 1 1 1 1 0    1 1 1 1 1 1 1 0 }return 0;
}

此比特流只能用于判断,因为现在是用8位的char 代替一位的bit数据。只有一个好处,可以用指针连续跟踪查询比特数据。省去几位bit数据在两个或多个字节中的拼接。

如果想把此char还原成一位的真实比特流,应该可以采用移位,再8位与运算拼接成一个字节的数据。

还有一个问题,因为c 的数组下标是有大小限制的,所以如遇到大数据,最好用动态分配内存malloc。

到目的为止,就可以用上面的程序把霍夫曼编码流转化为连续的比特流(用一个char表示一位bit)。按照霍夫曼的编码循环读取查询还原出真实的z字扫描数据。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/188024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器安全是什么

容器安全是当前面临的重要挑战之一&#xff0c;但通过采取有效的应对策略&#xff0c;我们可以有效地保护容器的安全。在应对容器安全挑战时&#xff0c;我们需要综合考虑镜像安全、网络安全和数据安全等多个方面&#xff0c;并采取相应的措施来确保容器的安全性。 德迅蜂巢原…

Clion+Ubuntu(WSL)+MySQL8.0开发环境搭建

1. 下载 MySQL 源码 访问 MySQL 官方网站&#xff08;MySQL :: Download MySQL Community Server&#xff09;并下载 MySQL 8.0 的源码包&#xff08;mysql-boost-8.0.31.tar.gz&#xff09;。 2. 安装编译依赖 1&#xff09;更换镜像源 参考&#xff1a;Linux Ubuntu 修改…

java开发之个微群聊自动添加好友

请求URL&#xff1a; http://域名/addRoomMemberFriend 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是String登录实例标识chatRoom…

20 Go的命令行参数

概述 在上一节的内容中&#xff0c;我们介绍了Go的时间日期&#xff0c;包括&#xff1a;time包、格式化日期、日期字符串解析、计算日期差、时区操作、定时任务等。在本节中&#xff0c;我们将介绍Go的命令行参数。命令行参数在程序设计中扮演着重要的角色&#xff0c;它允许用…

4个Pycharm高效插件

大家好&#xff0c;Pycharm是Python最受欢迎的集成开发环境之一&#xff0c;它具有良好的代码助手、漂亮的主题和快捷方式&#xff0c;使编写代码变得简单快捷。话虽如此&#xff0c;开发者仍可以通过使用一些插件来提高在Pycharm中编写Python代码的效率和乐趣&#xff0c;在市…

【【FPGA 之Micro Blaze的串口中断实验】】

FPGA 之Micro Blaze的串口中断实验 我们在使用 MicroBlaze 进行嵌入式系统设计的时候&#xff0c;通常会用到 AXI Uartlite IP 核与外部设备通信。AXI UART IP 核实现了 RS-232 通讯协议&#xff0c;并使得大家可以设置串口通信相关的波特率、奇偶校验位、停止位和数据位等参数…

前端OFD文件预览(vue案例cafe-ofd)

0、提示 下面只有vue的使用示例demo &#xff0c;官文档参考 cafe-ofd - npm 其他平台可以参考 ofd - npm 官方线上demo: ofd 1、安装包 npm install cafe-ofd --save 2、引入 import cafeOfd from cafe-ofd import cafe-ofd/package/index.css Vue.use(cafeOfd) 3、使…

数据可视化工具APITable:实现强大的多维表格功能并随时随地远程访问

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

kubectl系列(五)-kubectl scale 命令最佳实践

1 概述 kubectl scale命令通过调整正在运行的容器的数量来立即缩放应用程序。这是增加部署副本数量的最快、最简单的方法&#xff0c;可用于应对服务高峰以及日常维护变更。 在本文中将了解如何使用kubectl scale来扩展一个简单的Kubernetes Deployment&#xff0c;同时还将更…

kobs-ng 烧写nand中的uboot

如何获取kobs-ng 我是使用buildroot自动编译的imx-kobs&#xff0c;生成了kobs-ng可执行文件。 使用 kobs-ng 烧写 u-boot 1. flash_erase /dev/mtd0 0 0 //擦除uboot所在分区 2. 挂载 debugfs mount -t debugfs debugfs /sys/kernel/debug 如果不挂载为报以下错误&#x…

Java中的synchronized关键字

目录 1、synchronized是什么 2、synchronized的用法 synchronized可以用在方法或者代码块上&#xff0c;分别称为同步方法和同步代码块。 用法理解 3、synchronized的实现原理 ⭐synchronized锁的对比 4、synchronized的优缺点 ⭐扩展&#xff1a;synchronized 和 vola…

nvm安装管理nodejs版本

1&#xff1a;如果之前先安装了nodejs先卸载nodejs 2&#xff1a;下载nvm&#xff0c;点击下载路径https://github.com/coreybutler/nvm-windows/releases&#xff0c;选择相应环境下载&#xff0c;如下window环境下载 下载成功后&#xff0c;选择NVM安装在哪个文件目录下&…

IDEA之Eclipse Code Formatter插件的安装与使用

概述 Eclipse、Intellij idea格式化结果不同&#xff0c;之前由于没有Eclipse Code Formatter插件&#xff0c;所以公司统一用eclipse做开发&#xff0c;但是我们都知道IDEA是非常强大、也非常的方便&#xff0c;很多功能是eclipse不具备的&#xff0c;只是我们公司统一用&…

【隐私计算】VOLE (Vector Oblivious Linear Evaluation)学习笔记

近年来&#xff0c;VOLE&#xff08;向量不经意线性评估&#xff09;被用于构造各种高效安全多方计算协议&#xff0c;具有较低的通信复杂度。最近的CipherGPT则是基于VOLE对线性层进行计算。 1 VOLE总体设计 VOLE的功能如下&#xff0c;VOLE发送 Δ \Delta Δ和 b b b给send…

【论文阅读笔记】InstructDiffusion: A Generalist Modeling Interface for Vision Tasks

【论文阅读笔记】StyleAvatar3D: Leveraging Image-Text Diffusion Models for High-Fidelity 3D Avatar Generation 论文阅读笔记论文信息引言动机挑战 方法结果 关键发现相关工作1. 视觉语言基础模型2. 视觉通用模型 方法/模型视觉任务的统一说明训练数据构建网络结构 实验设…

全网最新最全面的Jmeter接口测试:jmeter模拟http请求实战

1、get请求 http://www.hnxmxit.com/ 2、带参数的get请求 微信公众号获取token请求 3、自定义头部信息的请求 百度搜索请求 https://www.baidu.com/s?wd猫 4、post请求 微信公众号添加用户标签请求 注&#xff1a;post请求中如果body中的数据为json,一定要在信息头管理器中…

编译原理头歌实验:实验1《词法分析程序设计与实现》(C语言版)

任务描述 本关任务&#xff1a;加深对词法分析器的工作过程的理解&#xff1b;加强对词法分析方法的掌握&#xff1b;能够采用一种编程语言实现简单的词法分析程序&#xff1b;能够使用自己编写的分析程序对简单的程序段进行词法分析。 相关知识 为了完成本关任务&#xff0…

Qt应用开发--国产工业开发板全志T113-i的部署教程

Qt在工业上的使用场景包括工业自动化、嵌入式系统、汽车行业、航空航天、医疗设备、制造业和物联网应用。Qt被用来开发工业设备的用户界面、控制系统、嵌入式应用和其他工业应用&#xff0c;因其跨平台性和丰富的功能而备受青睐。 Qt能够为工业领域带来什么好处&#xff1a; -…

袋鼠云产品功能更新报告08期|近百项全新功能和优化,你要的都在这里!

欢迎来到袋鼠云08期产品功能更新报告&#xff01;在瞬息万变的市场环境中&#xff0c;我们深知客户的需求与期待&#xff0c;因此&#xff0c;我们及时推出袋鼠云最新产品更新及优化&#xff0c;包括数据治理中心、Hive SQL 性能优化、新插件等&#xff0c;助力企业在数字世界中…

Golang分布式事务

引言 在分布式系统中&#xff0c;事务管理是一项非常重要的任务。分布式事务涉及到多个事务参与者之间的协调和一致性保证&#xff0c;同时还要解决网络延迟、故障恢复等问题。Golang作为一门强大的编程语言&#xff0c;提供了一些工具和框架来帮助开发人员实现分布式事务。本…