2021SC@SDUSC
目录
一、convert.c 分析
1.以NULL结尾的已知格式列表,按优先顺序排列
平面YUV格式
fourcc('4','2','2','P'),
fourcc('I','4','2','0'),
fourcc('Y','U','1','2'),
fourcc('Y','V','1','2'),
fourcc('4','1','1','P'),
平面Y+压缩UV平面
fourcc('N','V','1','2'),
fourcc('N','V','2','1'),
压缩YUV格式
fourcc('Y','U','Y','V'),
fourcc('U','Y','V','Y'),
fourcc('Y','U','Y','2'),
fourcc('Y','U','V','4'),
压缩rgb格式
fourcc('R','G','B','3'),
fourcc( 3 , 0 , 0 , 0 ),
fourcc('B','G','R','3'),
fourcc('R','G','B','4'),
fourcc('B','G','R','4'),
fourcc('R','G','B','P'),
fourcc('R','G','B','O'),
fourcc('R','G','B','R'),
fourcc('R','G','B','Q'),
fourcc('Y','U','V','9'),
fourcc('Y','V','U','9'),
基本灰度格式
fourcc('G','R','E','Y'),
fourcc('Y','8','0','0'),
fourcc('Y','8',' ',' '),
fourcc('Y','8', 0 , 0 ),
低质量RGB格式
fourcc('R','G','B','1'),
fourcc('R','4','4','4'),
fourcc('B','A','8','1'),
不支持的压缩YUV格式
fourcc('Y','4','1','P'),
fourcc('Y','4','4','4'),
fourcc('Y','U','V','O'),
fourcc('H','M','1','2'),
不支持的压缩RGB格式
fourcc('H','I','2','4'),
不支持的压缩格式
fourcc('J','P','E','G'),
fourcc('M','J','P','G'),
fourcc('M','P','E','G'),
2.函数分析
static inline int verify_format_sort (void)
{
int i;
for(i = 0; i < num_format_defs; i++) {
int j = i * 2 + 1;
if((j < num_format_defs &&
format_defs[i].format < format_defs[j].format) ||
(j + 1 < num_format_defs &&
format_defs[j + 1].format < format_defs[i].format))
break;
}
if(i == num_format_defs)
return(0);
验证格式列表是否符合所需的排序顺序
fprintf(stderr, "ERROR: image format list is not sorted!?\n");
#ifdef DEBUG_CONVERT
assert(num_format_defs);
uint32_t sorted[num_format_defs];
uint32_t ordered[num_format_defs];
for(i = 0; i < num_format_defs; i++)
sorted[i] = format_defs[i].format;
qsort(sorted, num_format_defs, sizeof(uint32_t), intsort);
for(i = 0; i < num_format_defs; i = i << 1 | 1);
i = (i - 1) / 2;
ordered[i] = sorted[0];
int j, k;
for(j = 1; j < num_format_defs; j++) {
k = i * 2 + 2;
if(k < num_format_defs) {
i = k;
for(k = k * 2 + 1; k < num_format_defs; k = k * 2 + 1)
i = k;
}
else {
for(k = (i - 1) / 2; i != k * 2 + 1; k = (i - 1) / 2) {
assert(i);
i = k;
}
i = k;
}
ordered[i] = sorted[j];
}
fprintf(stderr, "correct sort order is:");
for(i = 0; i < num_format_defs; i++)
fprintf(stderr, " %4.4s", (char*)&ordered[i]);
fprintf(stderr, "\n");
#endif
return(-1);
}
发出正确的修复顺序。
static void cleanup_ref (zbar_image_t *img)
{
if(img->next)
_zbar_image_refcnt(img->next, -1);
}
通过取消引用清理链接图像。
static inline void convert_y_resize (zbar_image_t *dst,
const zbar_format_def_t *dstfmt,
const zbar_image_t *src,
const zbar_format_def_t *srcfmt,
size_t n)
{
uint8_t *psrc, *pdst;
unsigned width, height, xpad, y;
if(dst->width == src->width && dst->height == src->height) {
memcpy((void*)dst->data, src->data, n);
return;
}
psrc = (void*)src->data;
pdst = (void*)dst->data;
width = (dst->width > src->width) ? src->width : dst->width;
xpad = (dst->width > src->width) ? dst->width - src->width : 0;
height = (dst->height > src->height) ? src->height : dst->height;
for(y = 0; y < height; y++) {
memcpy(pdst, psrc, width);
pdst += width;
psrc += src->width;
if(xpad) {
memset(pdst, *(psrc - 1), xpad);
pdst += xpad;
}
}
psrc -= src->width;
for(; y < dst->height; y++) {
memcpy(pdst, psrc, width);
pdst += width;
if(xpad) {
memset(pdst, *(psrc - 1), xpad);
pdst += xpad;
}
}
}
调整y平面的大小,从右/底部删除额外的列/行,或复制最后一列/行以填充缺失的数据。
static void convert_copy (zbar_image_t *dst,
const zbar_format_def_t *dstfmt,
const zbar_image_t *src,
const zbar_format_def_t *srcfmt)
{
if(src->width == dst->width &&
src->height == dst->height) {
zbar_image_t *s = (zbar_image_t*)src;
dst->data = src->data;
dst->datalen = src->datalen;
dst->cleanup = cleanup_ref;
dst->next = s;
_zbar_image_refcnt(s, 1);
}
else
convert_y_resize(dst, dstfmt, src, srcfmt, dst->width * dst->height);
}
参照相同的图像数据制作新图像。
static void convert_uvp_append (zbar_image_t *dst,
const zbar_format_def_t *dstfmt,
const zbar_image_t *src,
const zbar_format_def_t *srcfmt)
{
unsigned long n;
uv_roundup(dst, dstfmt);
dst->datalen = uvp_size(dst, dstfmt) * 2;
n = dst->width * dst->height;
dst->datalen += n;
assert(src->datalen >= src->width * src->height);
zprintf(24, "dst=%dx%d (%lx) %lx src=%dx%d %lx\n",
dst->width, dst->height, n, dst->datalen,
src->width, src->height, src->datalen);
dst->data = malloc(dst->datalen);
if(!dst->data) return;
convert_y_resize(dst, dstfmt, src, srcfmt, n);
memset((uint8_t*)dst->data + n, 0x80, dst->datalen - n);
}
将中性UV平面附加到灰度图像。
static void convert_uvp_resample (zbar_image_t *dst,
const zbar_format_def_t *dstfmt,
const zbar_image_t *src,
const zbar_format_def_t *srcfmt)
{
unsigned long dstn, dstm2;
uv_roundup(dst, dstfmt);
dstn = dst->width * dst->height;
dstm2 = uvp_size(dst, dstfmt) * 2;
dst->datalen = dstn + dstm2;
dst->data = malloc(dst->datalen);
if(!dst->data) return;
convert_y_resize(dst, dstfmt, src, srcfmt, dstn);
if(dstm2)
memset((uint8_t*)dst->data + dstn, 0x80, dstm2);
}
重采样和调整UV平面大小FIXME当前忽略图像的颜色和灰度。