# JPEGD功能及约束说明


#### 功能说明

JPEGD（JPEG Decoder）实现.jpg、.jpeg、.JPG、.JPEG图片文件的解码。

- JPEGD在解码图片时，支持对图片进行旋转。
  如果输入图片的码流中包含Orientation信息（代表捕获图像时摄像机相对于场景的方向），则JPEGD在解码时会解析Orientation信息，将图片进行90度、180度、270度或镜像旋转。旋转后输出图片的宽stride、高stride、输出内存仍需满足图片格式、宽高对齐、内存约束中的要求。如果输入图片的码流异常，导致JPEGD解码时无法读取Orientation信息，则不能实现图片旋转的功能。

  Atlas 200/500 A2推理产品上，JPEGD 422格式旋转图片，若原图高为奇数，并且旋转方式为宽高对换，则旋转后宽存在黑边，建议用户将宽向下对齐到偶数使用（即去除黑边），比如原图为200*101，若旋转后为101*200，则建议用户实际使用区域为100*200。 Atlas 200/500 A2推理产品上，JPEGD 440格式旋转图片，若原图宽为奇数，并且旋转方式为宽高对换，则旋转后高存在黑边，建议用户将高向下对齐到偶数使用（即去除黑边），比如原图为201*101，若旋转后为100*201，则建议用户实际使用区域为100*200。 JPEGD 422格式旋转图片，若原图高为奇数，并且旋转方式为宽高对换，则旋转后宽存在黑边，建议用户将宽向下对齐到偶数使用（即去除黑边），比如原图为200*101，若旋转后为101*200，则建议用户实际使用区域为100*200。 JPEGD 440格式旋转图片，若原图宽为奇数，并且旋转方式为宽高对换，则旋转后高存在黑边，建议用户将高向下对齐到偶数使用（即去除黑边），比如原图为201*101，若旋转后为100*201，则建议用户实际使用区域为100*200。

- JPEGD在解码图片时，支持按源图片格式解码。
源图片格式解码是指解码前后图片的编码格式保持一致，例如解码前输入图片为jpeg(440)，解码后输出图片为YUV440SP V在前U在后或YUV440SP U在前V在后。
使用源图片格式解码，有以下方式：

  - 在调用JPEGD解码接口时，直接将输出图片格式配置为HI_PIXEL_FORMAT_UNKNOWN，输出格式默认按源图片格式输出、且是V在前U在后的Semi-Planar格式。例如，JPEG源图片格式为jpeg(440)，输出图片格式配置为HI_PIXEL_FORMAT_UNKNOWN，JPEGD解码后，实际输出图片格式为YUV440SP V在前U在后。
    此种方式，由于不知道输出图片格式，因此需要用户申请尽量大的内存或调用hi_mpi_dvpp_get_image_info接口获取解码输出内存大小，防止内存不够，无法存放输出图片。

  - 先调用    hi_mpi_dvpp_get_image_info
接口根据传入的jpeg源图片，获取按源图解码时的输出图片的宽、高、宽stride、高stride、解码输出内存大小、图片格式等信息后，再调用JPEGD解码接口，使用通过    hi_mpi_dvpp_get_image_info
接口获取的图片格式来设置输出图片格式。
JPEGD解码后的输出图片，如果要直接作为模型推理的输入，建议将输出图片格式配置为HI_PIXEL_FORMAT_UNKNOWN，这时JPEGD使用源图片格式解码（但这里要确保解码后的图片格式模型是支持的），保证模型推理的精度。

JPEGD解码后的输出图片，如果直接作为VPC的输入，该场景下若使用源图片格式解码时，则需要关注解码后的输出图片格式VPC是否支持（VPC输入图片的格式请参见约束说明），如果VPC不支持，则用户需按VPC支持的情况指定JPEGD的输出图片格式。


#### 图片分辨率约束

- 输入图片分辨率| 版本 | 分辨率范围 |
| --- | --- |
| Atlas 200/500 A2推理产品 | 最大分辨率：16384\*16384，最小分辨率：32\*32。 |


- 输出图片分辨率
  JPEGD只对图片解码，不会改变图片分辨率，因此输出与输入的图片分辨率保持一致。


#### 内存申请/释放接口说明

输入内存的大小就是指实际的输入图片所占用的大小，输出内存的大小参见表1中的计算公式。

| 版本 | 内存申请接口 |
| --- | --- |
| Atlas 200/500 A2推理产品 | JPEGD图片解码时，支持以下两种内存申请接口： 调用aclrtMalloc\aclrtFree接口申请\释放Device上的输入、输出内存，这部分内存的生命周期由用户自行管理。 调用hi\_mpi\_dvpp\_malloc\hi\_mpi\_dvpp\_free接口申请\释放Device上的输入、输出内存，这部分内存的生命周期由用户自行管理。 注意：调用hi\_mpi\_dvpp\_malloc接口申请的内存为媒体数据处理的专用内存，但专用内存的地址空间有限，若关注内存规划或内存资源有限时，建议调用aclrtMalloc接口申请内存。 |


#### 图片格式、宽高对齐、内存约束

实现JPEGD图片解码功能时，仅支持Huffman编码，压缩前的原图像色彩空间为YUV，像素的各分量比例为4:4:4或4:2:2或4:2:0或4:0:0或4:4:0，不支持算术编码、不支持渐进JPEG格式、不支持JPEG2000格式。

输出图片格式的定义请参见hi_pixel_format，宽stride、高stride等概念请参见基本概念。


**表1 图片格式、宽高对齐、内存大小约束**

| 输入图片格式（YUV分量比例） | 输出图片格式 | 输出图片宽、高对齐要求 | 输出图片宽stride、高stride、内存大小要求 |
| --- | --- | --- | --- |
| jpeg(444) | YVU444SP 8bit | 无对齐要求 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3 |
| jpeg(444) | YUV444SP 8bit | 无对齐要求 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3 |
| jpeg(444) | YUV420SP NV12 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(444) | YUV420SP NV21 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(422) | YVU422SP 8bit | 宽2对齐 高无对齐要求 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 2 |
| jpeg(422) | YUV422SP 8bit | 宽2对齐 高无对齐要求 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 2 |
| jpeg(422) | YUV420SP NV12 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(422) | YUV420SP NV21 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(420) | YUV420SP NV12 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(420) | YUV420SP NV21 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(400) | YUV420SP NV12 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(400) | YUV420SP NV21 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(400) | YUV400 8bit | 无对齐要求 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride |
| jpeg(440) | YVU440SP 8bit | 宽无对齐要求 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 2 |
| jpeg(440) | YUV440SP 8bit | 宽无对齐要求 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 2 |
| jpeg(440) | YUV420SP NV12 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |
| jpeg(440) | YUV420SP NV21 8bit | 宽2对齐 高2对齐 | 宽stride为宽64对齐后的值。 高stride为高16对齐后的值。 内存大小（单位Byte）≥ 宽stride \* 高stride \* 3/2 |


#### 软、硬件约束

- 硬件约束：

  - 最多支持4张Huffman表，其中包括2 张DC（Direct Current）（直流）表和2 张AC（Alternating Current）（交流）表；
  - 最多支持3张量化表；
  - 只支持8bit采样精度；
  - 只支持对顺序式编码的图片进行解码；
  - 只支持基于DCT（Discrete Cosine Transform）变换的JPEG 格式解码；
  - 只支持一个SOS（Start of Scan）标志的图片解码。
- 软件约束：

  - 支持3个SOS标志的图片解码；
  - 支持mcu（Minimum Coded Unit）数据不足的异常图片解码。


#### 精度相关约束

JPEGD+VPC串联使用时，由于JPEGD解码后的输出图片的宽stride*高stride有64*16对齐的约束，因此解码后的输出图片的宽、高有一些补边的无效数据，所以在执行VPC功能时（例如缩放时），需在输入图片的hi_vpc_pic_info.picture_width、hi_vpc_pic_info.picture_height参数处正确设置输入图片的原图宽高，这样VPC在缩放图片前会先根据原图宽高自行抠图，目的是去除无效数据对图像精度的影响。


#### 其它注意事项

若图片内EOI（End Of Image，标记代码为0XFFD9）之后，还有用户自定义的数据，则JPEGD在对图片进行解码时，会直接清零EOI之后的8字节数据，若用户需要保留这些自定义的数据，则将图片数据读入内存之后，需要提前备份这部分数据，再传给JPEGD处理。

若需要查看图片内EOI之后是否存在自定义数据，可以使用二进制查看工具打开图片查看，例如下图中的FFD9标记符之后就存在自定义数据。
