Zigzag Scan

zigzag扫描

Zigzag Scan是一种扫描矩阵的方法, 类似的还有光栅扫描等。大多用到图像和视频编码中。

Zigzag Scan_第1张图片
snipaste_20180822_161737.png

H264CAVLC编码中,编码一个4x4子块的时候, 首先要对4x4子块进行扫描, 得到一个一维序列, 之后计算非零系数和拖尾系数等,
然后进行编码。

CAVLC中使用Zigzag Scan的原因在于:

4x4块在经过变换、量化之后, 非零系数主要在低频部分(左上角), 而高频部分(右下角)大都是0。
使用zigzag扫描可以将非零系数较为集中的排列在一维序列的左边,
这样可以减少Total ZerosRunBeforeZerosLeft的编码, 提高编码效率。

下面是我自己写的Zigzag Scan扫描程序

#include 
#include 

#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;
}

你可能感兴趣的:(Zigzag Scan)