zigzag扫描
Zigzag Scan
是一种扫描矩阵的方法, 类似的还有光栅扫描等。大多用到图像和视频编码中。
H264
中CAVLC编码中,编码一个4x4子块的时候, 首先要对4x4子块进行扫描, 得到一个一维序列, 之后计算非零系数和拖尾系数等,
然后进行编码。
CAVLC
中使用Zigzag Scan
的原因在于:
4x4块在经过变换、量化之后, 非零系数主要在低频部分(左上角), 而高频部分(右下角)大都是0。
使用zigzag扫描可以将非零系数较为集中的排列在一维序列的左边,
这样可以减少Total Zeros、RunBefore、ZerosLeft的编码, 提高编码效率。
下面是我自己写的Zigzag Scan
扫描程序
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 128
typedef enum {
MOVE_DOWN,
MOVE_RIGHT,
MOVE_RIGHT_UP,
MOVE_LEFT_DOWN,
} MOVE_DIRECTION;
int zigzag_scan(int matrix[MAX_NUM][MAX_NUM], int x, int y, int *res)
{
int i, j;
int move_dir = MOVE_RIGHT_UP;
int *result = res;
if (!result) {
return 0;
}
i = j = 0;
while (i < x && j < y) {
*result = matrix[i][j];
result ++;
if (i == 0 && j < y -1) {
move_dir = move_dir == MOVE_RIGHT_UP ? MOVE_RIGHT : MOVE_LEFT_DOWN;
} else if (i == x-1 && j < y -1) {
move_dir = move_dir == MOVE_LEFT_DOWN ? MOVE_RIGHT : MOVE_RIGHT_UP;
}else if (j == 0 && i < x - 1) {
move_dir = move_dir == MOVE_LEFT_DOWN ? MOVE_DOWN : MOVE_RIGHT_UP;
} else if (j == y-1 && i < x-1) {
move_dir = move_dir == MOVE_RIGHT_UP ? MOVE_DOWN : MOVE_LEFT_DOWN;
}
switch (move_dir) {
case MOVE_DOWN:
i ++;
break;
case MOVE_RIGHT:
j ++;
break;
case MOVE_RIGHT_UP:
i --;
j ++;
break;
case MOVE_LEFT_DOWN:
j --;
i ++;
break;
default:
break;
}
}
return 1;
}
int main(int argc, char **argv)
{
int matrix[MAX_NUM][MAX_NUM] = {{0, 3, 1, 0, 1},
{0, -1, 1, 0, 2},
{1, 0, 2, 0, 3},
{0, 1, 0, 1, 4}};
int i;
int *res = (int *)malloc(100 * sizeof(int));
zigzag_scan(matrix, 4, 4, res);
printf("print result ... ");
for (i = 0; i < 20; i++) {
printf("%d ", res[i]);
}
printf("\n");
return 0;
}