游程长度编码

  

图1:原始栅格数据

游程长度编码(run-length code)

  游程长度编码是栅格数据压缩的重要编码方法,它的基本思路是:对于一幅栅格图像,常常有行(或列)方向上相邻的若干点具有相同的属性代码,因而可采取某种方法压缩那些重复的记录内容。其编码方案是,只在各行(或列)数据的代码发生变化时依次记录该代码以及相同代码重复的个数,从而实现数据的压缩。
  例如对图1所示的栅格数据,可沿行方向进行如下游程长度编码:
  (9,4),(0,4),(9,3),(0,5),(0,1)(9,2),(0,1),(7,2),(0,2),(0,4),(7,2),(0,2),(0,4),(7,4),(0,4),(7,4) ,(0,4),(7,4) ,(0,4),(7,4)
  游程长度编码对图3-6(a)只用了40个整数就可以表示,而如果用前述的直接编码却需要64个整数表示,可见游程长度编码压缩数据是十分有效又简便的。事实上,压缩比的大小是与图的复杂程度成反比的,在变化多的部分,游程数就多,变化少的部分游程数就少,图件越简单,压缩效率就越高。
  游程长度编码在栅格加密时,数据量没有明显增加,压缩效率较高,且易于检索,叠加合并等操作,运算简单,适用于机器存贮容量小,数据需大量压缩,而又要避免复杂的编码解码运算增加处理和操作时间的情况。
  [font id="zoom" class="zoom"]游程长度RL (Run—Length),简称游程或游长,指的是由字符(或信号取样值)构成的数据流中各个字符重复出现而形成的字符的长度.如果给出了形成申的字符,申的长度及申的位置,就能恢复出原来的数据流,游程长度编码(RLC)就是用二进制码字给出这些信息的一类方法。游程长度编码的主要思想是将一个相同值的连续申用其值和申长(重复的个数)的数对二元组来替代.例如,在图像编码中,可以定义沿特定方向上具有相同灰度值的相邻像素为一轮,其延续的长度称之为延续的行程,即游程.游程终点位置由前一游程终点的相对距离确定,这样就可以由灰度游程串来表示图像数据.例如,若沿水平方向有一申M 个像素具有相同的灰度N,则按游程长度编码后,只传递两个值(N,M )就可以代替这M个像素的M个灰度值N。简单来说,游程长度编码的主要任务是统计连续相同字符的个数,解码时要根据字符及连续相同字符的个数,恢复原来的数据.在多媒体信息量激增、网络特性和速度都飞速提高的今天,游程长度编码是一种十分简单的压缩方法,编码/解码的速度也非常快,可广泛应用于多媒体信息的存储,传输。
/***********************************************************************************************************
 RLE.c
本演示程序提供了游程长度编码法的压缩和解压缩函数,并实现了对图象
文件的压缩和解压缩
**********************************************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LEN          (0x7f)       /* maximum length for runs or sequences    */
#define MAX_RUN_HEADER  (0xff)       /* bit 7 == 1 : run follows                */
                                  /* bit 6 - 0  : length of run              */
#define MAX_SEQ_HEADER (0x7f)         /* bit 7 == 0 : unencode sequence follows  */
                                  /* bit 6 - 0  : length of sequence         */
#define RUN (0x80)                    /* bit 7 == 1 : run follows                */
#define SEQ (0x00)                    /* bit 7 == 0 : unencoded sequence follows */
/* 函数原型 */
int RLE_Compression(char * infile_name, char * outfile_name);
int RLE_Decompression(char * infile_name, char * outfile_name);
/* 主程序 */
void main(int argc, char *argv[])
{
 printf("RLE compression and decompression utility/n");
 if (4 != argc)
 {
  printf("/nUsage : rle -c|d sourcefilename targetfilename/n");
  exit(0);
 }
 if (! strcmp(argv[1], "-c"))
 {
  printf("/nCompress...");
  RLE_Compression(argv[2], argv[3]);
 }
 else if (! strcmp(argv[1], "-d"))
 {
  printf("/nDecompress...");
  RLE_Decompression(argv[2], argv[3]);
 }
 else
  printf("/nUnknow command./n");
}
/**************************************************************************
 RLE_Compression ()
 本函数用RLE算法对文件进行压缩
 **************************************************************************/
int RLE_Compression(char * infile_name, char * outfile_name)
{
    register int cur_char;                /* a character                    */
    register unsigned int i;              /* generic index variable         */
    register unsigned short run_len = 0;  /* length of character run so far */
    int run_char;                         /* which char run is of           */
    unsigned int j;                       /* another index variable         */
    unsigned short seq_len=0;             /* length of non-run sequence     */
    char scratch_space[256];              /* string scratch space           */
    char seq[MAX_LEN];                    /* buffer for uncompressible data */
    FILE *infile;                           /* file ptr to input file (uncompressed)    */
    FILE *outfile;                          /* file ptr to output file (compressed)     */

    if ((infile=fopen(infile_name, "rb")) == NULL)
    {
        strcpy(scratch_space, "Uable to open ");
        strcat(scratch_space, infile_name);
        puts(scratch_space);
        return 1;
    }
    if ((outfile=fopen(outfile_name, "wb")) == NULL)
    {
        strcpy(scratch_space, "Uable to open ");
        strcat(scratch_space, outfile_name);
        puts(scratch_space);
        return 1;
    }
    while (!feof(infile))
    {
        cur_char = fgetc(infile);
        if (feof(infile))
            continue;
        if (seq_len ==0)                /* haven't got a sequence yet   */
        {
            if (run_len == 0)           /* start a new run              */
            {
                run_char = cur_char;
                ++run_len;
                continue;
            }
            if (run_char == cur_char)   /* got another char in the run  */
                if (++run_len == MAX_LEN)
                {
                    fputc((int)MAX_RUN_HEADER, outfile);
                    fputc((int) run_char, outfile);
                    run_len = 0;
                    continue;
                }
                                   /* got a different character     */
                                   /* than the run we were building */
            if (run_len > 2)       /* so write out the run and      */
                                   /* start a new one of the new    */
                                   /* character.                    */
            {
                fputc((int)(RUN | run_len), outfile);
                fputc((int)run_char, outfile);
                run_len = 1;
                run_char   = cur_char;
                continue;
            }
            /* run was only one or two chars, make a seq out of it instead       */
            for (j = 0; j < run_len; j++);    /* copy 1 or 2 char run to seq[]   */
            {
                seq[seq_len] = run_char;
                ++seq_len;
                if (seq_len == MAX_LEN)       /* if seq[] is full, write to disk */
                {
                    fputc((int)MAX_SEQ_HEADER, outfile);
                    for (i = 0; i < seq_len; i++)
                        fputc((int)seq[i], outfile);
                    seq_len = 0;
                }
            }
            run_len = 0;
            seq[seq_len++] = cur_char;
            if (seq_len == MAX_LEN)        /* if seq[] is full, write to disk */
            {
                fputc((int)MAX_SEQ_HEADER, outfile);
                for (i = 0; i < seq_len; i++)
                    fputc((int)seq[i], outfile);
                seq_len = 0;
            }
        }
        else    /* a sequence exists */
        {
            if (run_len != 0)           /* if a run exists */
            {
                if (cur_char == run_char )  /* add to run!  Yay.  */
                {
                    ++run_len;
                    if (run_len == MAX_LEN)  /* if run is full */
                    {
                        /* write sequence that precedes run */
                        fputc((int)(SEQ | seq_len), outfile);
                        for (i = 0; i < seq_len; i++)
                            fputc((int)seq[i], outfile);
                        /* write run                        */
                        fputc((int)(RUN | run_len), outfile);
                        fputc((int)run_char, outfile);
                        /* and start out fresh              */
                        seq_len = run_len = 0;
                    }  /* end write full run with existing sequence */
                    continue;
                }  /* end add to run for sequence exists */
                /* we couldn't add to the run, and a preceding sequence */
                /* exists, so write the sequence and the run, and       */
                /* try starting a new run with the current character.   */
                /* write sequence that precedes run */
                fputc((int)(SEQ | seq_len), outfile);
                for (i = 0; i < seq_len; i++)
                    fputc((int)seq[i], outfile);
                /* write run                        */
                fputc((int)(RUN | run_len), outfile);
                fputc((int)run_char, outfile);
                /* and start a new run w/ cur_char  */
                seq_len = 0;
                run_len = 1;
                run_char = cur_char;
                continue;
            }    /* end can't add to existing run, and preceding seq exists */
            /* no run exists, but a sequences does.  Try to create a run    */
            /* by looking at cur_char and the last char of the sequence.    */
            /* if that fails, add the char to the sequence.                 */
            /* if the sequence is full, write it to disk.  (Slightly non    */
            /* optimal; we could wait one more char.  A small thing to fix  */
            /* if someone gets the urge...                                  */
            if (seq[seq_len - 1] == cur_char)       /* if we can make a run */
            {
                run_char = cur_char;
                run_len = 2;
                --seq_len;
                continue;
            }
            /* couldn't make a run, add char to seq.  Maybe next time       */
            /* around...                                                    */
            seq[seq_len++] = cur_char;
            if (seq_len == MAX_LEN) /* if the sequence is full, write out   */
            {
                fputc((int)MAX_SEQ_HEADER, outfile);
                for (i = 0; i < MAX_LEN; i++)
                    fputc((int)seq[i], outfile);
                seq_len = 0;
            }
        }  /* end branch on sequence exists */
    } /* done with whole file */
    /* there may be stuff left that hasn't been written yet; if so, write it */
    if (seq_len != 0)  /* write sequence that precedes run */
    {
        fputc((int)(SEQ | seq_len), outfile);
        for (i = 0; i < seq_len; i++)
            fputc((int)seq[i], outfile);
    }
    if (run_len != 0)  /* write run */
    {
        fputc((int)(RUN | run_len), outfile);
        fputc((int)run_char, outfile);
    }
    fclose(infile);
    fclose (outfile);
    return 0;
}  /* end RLE_Compression() */

/**************************************************************************
 RLE_Decompression ()
 本函数用RLE算法对文件进行解压缩
 **************************************************************************/
int RLE_Decompression(char * infile_name, char * outfile_name)
{
    register int byte;
    register unsigned short i;
    register unsigned short length;
    int packet_hdr;
    char scratch_space[134];
    FILE *infile, *outfile;
    if ((infile=fopen(infile_name, "rb")) == NULL)
    {
        strcpy(scratch_space, "Unable to open ");
        strcat(scratch_space, infile_name);
        puts(scratch_space);
        return 1;
    }
    if ((outfile=fopen(outfile_name, "wb")) == NULL)
    {
        strcpy(scratch_space, "Unable to open ");
        strcat(scratch_space, outfile_name);
        puts(scratch_space);
        return 1;
    }
    while (!feof(infile))
    {
        packet_hdr = fgetc(infile);
        if (feof(infile))
            continue;
        length = MAX_LEN & packet_hdr;
        if (packet_hdr & RUN)  /* if it's a run... */
        {
            byte = fgetc(infile);
            for (i = 0; i < length; i++)
                if (fputc(byte, outfile)== EOF)
                {
                    strcpy(scratch_space, "Error writing to ");
                    strcat(scratch_space, outfile_name);
                    puts(scratch_space);
                    fclose(infile);
                    fclose(outfile);
                    return 1;
                }
        }
        else /* it's a sequence */
            for (i = 0; i < length; i++)
                if (fputc(fgetc(infile), outfile)==EOF)
                {
                    strcpy(scratch_space, "Error writing to ");
                    strcat(scratch_space, outfile_name);
                    puts(scratch_space);
                    fclose(infile);
                    fclose(outfile);
                    return 1;
                }
    }
    fclose(infile);
    fclose(outfile);
    return 0;
}  /* end RLE_Uncompression() */
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值