zoukankan      html  css  js  c++  java
  • TIFF6 Packbit algorithm

    “Packbits” from ISO 12369

    参考TIFF 6.0 Specification,点击TIFF, Version 6.0

    @Section 9: PackBits Compression

    > This section describes TIFF compression type 32773, a simple byte-oriented runlength scheme.

    描述[摘录]

    In choosing a simple byte-oriented run-length compression scheme, we arbitrarily chose the Apple Macintosh PackBits scheme. It has a good worst case behavior
    (at most 1 extra byte for every 128 input bytes). For Macintosh users, the toolbox utilities PackBits and UnPackBits will do the work for you, but it is easy to implement your own routines.
    A pseudo code fragment to unpack might look like this:

    Loop until you get the number of unpacked bytes you are expecting:
    Read the next source byte into n.
    If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
    Else if n is between -127 and -1 inclusive, copy the next byte -n+1
    times.
    Else if n is -128, noop.
    Endloop


    In the inverse routine, it is best to encode a 2-byte repeat run as a replicate run except when preceded and followed by a literal run. In that case, it is best to merge
    the three runs into one literal run. Always encode 3-byte repeats as replicate runs.
    That is the essence of the algorithm. Here are some additional rules:
    • Pack each row separately. Do not compress across row boundaries.
    • The number of uncompressed bytes per row is defined to be (ImageWidth + 7)/8. If the uncompressed bitmap is required to have an even number of bytes per
    row, decompress into word-aligned buffers.
    • If a run is larger than 128 bytes, encode the remainder of the run as one or more additional replicate runs.
    When PackBits data is decompressed, the result should be interpreted as per compression type 1 (no compression).

    Coding

    function declaration

    // Packbit algorithm, make sure the _countof(Pack[*]) >= (count + count/128 +2);
    // return _countof(Pack[*]) actual count
    // AVC_FMAC
    int  tiff6_PackBits(unsigned char array[], int count, unsigned char Pack[]);
    // return _countof(array[*]);
    // AVC_FMAC
    int  tiff6_unPackBits(char Pack[], int count, unsigned char array[] /*= NULL*/);

    implementation

    static signed char* Pack_init(unsigned char Pack[], unsigned char Byte);
    static signed char* Pack_byte(signed char* Count, unsigned char Byte);
    static unsigned char* End_byte(signed char* Count);
    int  tiff6_PackBits(unsigned char array[], int count, unsigned char Pack[])
    {
        int i = 0;
        signed char* Count = Pack_init(Pack, array[i]); i++;
        for (; i < count; i++) Count = Pack_byte(Count, array[i]);
        unsigned char* End = End_byte(Count); *End = '';
        return (End - Pack);
    }
    static int unPack_count(char Pack[], int count);
    int  tiff6_unPackBits(char Pack[], int count, unsigned char array[] /*= NULL*/)
    {
        if (!array) return unPack_count(Pack, count);
        int nRes = 0;
        signed char* Count = (signed char*)Pack;
        while ((char*)Count < (Pack+count))
        {
            int c = *Count;
            if (c<0)
            {
                int n = (1-c);
                memset(&(array[nRes]), Count[1], n);
                nRes += n;
            }
            else
            {
                int n = (1+c);
                memcpy(&(array[nRes]), &Count[1], n);
                nRes += n;
            }
            Count = (signed char*)End_byte(Count);
        }
        return nRes;
    }
    
    int unPack_count(char Pack[], int count)
    {
        int nRes = 0;
        signed char* Count = (signed char*)Pack;
        while ((char*)Count < (Pack+count))
        {
            int c = *Count;
            if (c<0)
                nRes += (1-c);
            else
                nRes += (1+c);
            Count = (signed char*)End_byte(Count);
        }
        return nRes;
    }
    signed char* Pack_init( unsigned char Pack[], unsigned char Byte )
    {
        signed char* Cnt = (signed char*)Pack;
        *Cnt = 0; Pack[1] = Byte;
        return Cnt;
    }
    unsigned char* End_byte( signed char* Count )
    {
        unsigned char* Pack = (unsigned char*)(Count+1);
        signed char c = *Count;
        if (c >0)
             Pack = &(Pack[c+1]);
        else Pack = &(Pack[1]);
        return Pack;
    }
    signed char* Pack_byte( signed char* Count, unsigned char Byte )
    {
        signed char c = *Count;
        unsigned char* End = End_byte(Count);
        if (127 == c || c == -127)
            return Pack_init(End, Byte);
        else
        {
            unsigned char* Pack = End-1;
            if (*(Pack) == Byte)
            {
                if (c >0)
                {
                    (*Count) = c-1;
                    Count = Pack_byte(Pack_init(Pack, Byte), Byte);
                }
                else (*Count)--;
            }
            else
            {
                if (c >= 0)
                {
                    *End = Byte;
                    (*Count)++;
                }
                else Count = Pack_init(End, Byte);
            }
        }
        return Count;
    }


    另,本文明确使用了signed修饰char, 因为有些编译环境下char默认是有符号的,但是笔者也曾遇到默认无符号的环境,因此为了使代码在其中编译能正确使用,则指明符号修饰。

  • 相关阅读:
    laravel吐槽系列之一
    每日晨读_20140924
    技术晨读_2014_9_1
    大话胖model和瘦model
    大话PHP缓存头
    vim黏贴自动增加tab的毛病
    Laravel学习
    郑捷2017年电子工业出版社出版的图书《NLP汉语自然语言处理原理与实践》
    delete
    NLP知识结构概述
  • 原文地址:https://www.cnblogs.com/qianwen36/p/3965116.html
Copyright © 2011-2022 走看看