All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mreutegg.laszip4j.laszip.IntegerCompressor Maven / Gradle / Ivy

/*
 * Copyright 2007-2014, martin isenburg, rapidlasso - fast tools to catch reality
 *
 * This is free software; you can redistribute and/or modify it under the
 * terms of the GNU Lesser General Licence as published by the Free Software
 * Foundation. See the LICENSE.txt file for more information.
 *
 * This software is distributed WITHOUT ANY WARRANTY and without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
package com.github.mreutegg.laszip4j.laszip;

import static java.lang.Integer.compareUnsigned;

public class IntegerCompressor {

    private int u_k;

    private int u_contexts;
    private int u_bits_high;

    private int u_bits;
    private int u_range;

    private int u_corr_bits;
    private int u_corr_range;
    private int corr_min;
    private int corr_max;

    private ArithmeticEncoder enc;
    private ArithmeticDecoder dec;

    private ArithmeticModel[] mBits;

    private ArithmeticBitModel mCorrector0;
    private ArithmeticModel[] mCorrector;

    private int[][] corr_histogram;

    public IntegerCompressor(ArithmeticEncoder enc, int u_bits) {
        this(enc, u_bits, 1, 8, 0);
    }

    public IntegerCompressor(ArithmeticEncoder enc, int u_bits, int u_contexts) {
        this(enc, u_bits, u_contexts, 8, 0);
    }

    IntegerCompressor(ArithmeticEncoder enc, int u_bits, int u_contexts, int u_bits_high, int u_range)
    {
        assert(enc != null);
        this.enc = enc;
        this.dec = null;
        this.u_bits = u_bits;
        this.u_contexts = u_contexts;
        this.u_bits_high = u_bits_high;
        this.u_range = u_range;

        if (u_range != 0) // the corrector's significant bits and range
        {
            u_corr_bits = 0;
            u_corr_range = u_range;
            while (u_range != 0)
            {
                u_range = u_range >>> 1;
                u_corr_bits++;
            }
            if (u_corr_range == (1 << (u_corr_bits -1)))
            {
                u_corr_bits--;
            }
            // the corrector must fall into this interval
            corr_min = -(Integer.divideUnsigned(u_corr_range, 2));
            corr_max = corr_min + u_corr_range - 1;
        }
        else if (u_bits != 0 && compareUnsigned(u_bits, 32) < 0)
        {
            u_corr_bits = u_bits;
            u_corr_range = 1 << u_bits;
            // the corrector must fall into this interval
            corr_min = -(Integer.divideUnsigned(u_corr_range, 2));
            corr_max = corr_min + u_corr_range - 1;
        }
        else
        {
            u_corr_bits = 32;
            u_corr_range = 0;
            // the corrector must fall into this interval
            corr_min = Integer.MIN_VALUE;
            corr_max = Integer.MAX_VALUE;
        }

        u_k = 0;

        mBits = null;
        mCorrector = null;
    }

    public IntegerCompressor(ArithmeticDecoder dec, int u_bits) {
        this(dec, u_bits, 1);
    }

    IntegerCompressor(ArithmeticDecoder dec, int u_bits, int u_contexts, int u_bits_high, int u_range)
    {
        assert(dec != null);
        this.enc = null;
        this.dec = dec;
        this.u_bits = u_bits;
        this.u_contexts = u_contexts;
        this.u_bits_high = u_bits_high;
        this.u_range = u_range;

        if (u_range != 0) // the corrector's significant bits and range
        {
            u_corr_bits = 0;
            u_corr_range = u_range;
            while (u_range != 0)
            {
                u_range = u_range >>> 1;
                u_corr_bits++;
            }
            if (u_corr_range == (1 << (u_corr_bits -1)))
            {
                u_corr_bits--;
            }
            // the corrector must fall into this interval
            corr_min = -(Integer.divideUnsigned(u_corr_range, 2));
            corr_max = corr_min + u_corr_range - 1;
        }
        else if (u_bits != 0 && compareUnsigned(u_bits, 32) < 0)
        {
            u_corr_bits = u_bits;
            u_corr_range = 1 << u_bits;
            // the corrector must fall into this interval
            corr_min = -(Integer.divideUnsigned(u_corr_range, 2));
            corr_max = corr_min + u_corr_range - 1;
        }
        else
        {
            u_corr_bits = 32;
            u_corr_range = 0;
            // the corrector must fall into this interval
            corr_min = Integer.MIN_VALUE;
            corr_max = Integer.MAX_VALUE;
        }

        u_k = 0;

        mBits = null;
        mCorrector = null;
    }

    public IntegerCompressor(ArithmeticDecoder dec, int u_bits, int u_contexts) {
        this(dec, u_bits, u_contexts, 8, 0);
    }

    public int getK() {
        return u_k;
    }

    public void initCompressor()
    {
        int u_i;

        assert(enc != null);

        // maybe create the models
        if (mBits == null)
        {
            mBits = new ArithmeticModel[u_contexts];
            for (u_i = 0; u_i < u_contexts; u_i++)
            {
                mBits[u_i] = enc.createSymbolModel(u_corr_bits +1);
            }
            mCorrector = new ArithmeticModel[u_corr_bits +1];
            mCorrector0 = enc.createBitModel();
            for (u_i = 1; u_i <= u_corr_bits; u_i++)
            {
                if (u_i <= u_bits_high)
                {
                    mCorrector[u_i] = enc.createSymbolModel(1< corr_max) corr -= u_corr_range;
        writeCorrector(corr, mBits[u_context]);
    }

    public void initDecompressor()
    {
        int u_i;

        assert(dec != null);

        // maybe create the models
        if (mBits == null)
        {
            mBits = new ArithmeticModel[u_contexts];
            for (u_i = 0; u_i < u_contexts; u_i++)
            {
                mBits[u_i] = dec.createSymbolModel(u_corr_bits +1);
            }
            mCorrector = new ArithmeticModel[u_corr_bits +1];
            mCorrector0 = dec.createBitModel();
            for (u_i = 1; u_i <= u_corr_bits; u_i++)
            {
                if (u_i <= u_bits_high)
                {
                    mCorrector[u_i] = dec.createSymbolModel(1<= 0) real -= u_corr_range;
        return real;
    }

    void writeCorrector(int c, ArithmeticModel mBits) {
        int u_c1;

        // find the tighest interval [ - (2^k - 1)  ...  + (2^k) ] that contains c

        u_k = 0;

        // do this by checking the absolute value of c (adjusted for the case that c is 2^k)

        u_c1 = (c <= 0 ? -c : c-1);

        // this loop could be replaced with more efficient code

        while (u_c1 != 0)
        {
            u_c1 = u_c1 >>> 1;
            u_k = u_k + 1;
        }

        // the number k is between 0 and corr_bits and describes the interval the corrector falls into
        // we can compress the exact location of c within this interval using k bits

        enc.encodeSymbol(mBits, u_k);

        if (u_k != 0) // then c is either smaller than 0 or bigger than 1
        {
            assert((c != 0) && (c != 1));
            if (compareUnsigned(u_k, 32) < 0)
            {
                // translate the corrector c into the k-bit interval [ 0 ... 2^k - 1 ]
                if (c < 0) // then c is in the interval [ - (2^k - 1)  ...  - (2^(k-1)) ]
                {
                    // so we translate c into the interval [ 0 ...  + 2^(k-1) - 1 ] by adding (2^k - 1)
                    c += ((1<< u_k) - 1);
                }
                else // then c is in the interval [ 2^(k-1) + 1  ...  2^k ]
                {
                    // so we translate c into the interval [ 2^(k-1) ...  + 2^k - 1 ] by subtracting 1
                    c -= 1;
                }
                if (u_k <= u_bits_high) // for small k we code the interval in one step
                {
                    // compress c with the range coder
                    enc.encodeSymbol(mCorrector[u_k], c);
                }
                else // for larger k we need to code the interval in two steps
                {
                    // figure out how many lower bits there are
                    int k1 = u_k - u_bits_high;
                    // c1 represents the lowest k-bits_high+1 bits
                    u_c1 = c & ((1<> k1;
                    // compress the higher bits using a context table
                    enc.encodeSymbol(mCorrector[u_k], c);
                    // store the lower k1 bits raw
                    enc.writeBits(k1, u_c1);
                }
            }
        }
        else // then c is 0 or 1
        {
            assert((c == 0) || (c == 1));
            enc.encodeBit(mCorrector0,c);
        }
    }

    int readCorrector(ArithmeticModel mBits)
    {
        int c;

        // decode within which interval the corrector is falling

        u_k = dec.decodeSymbol(mBits);

        // decode the exact location of the corrector within the interval

        // TODO: original code: if (k)
        // TODO: how can k be zero or one?
        if (u_k != 0) // then c is either smaller than 0 or bigger than 1
        {
            if (compareUnsigned(u_k, 32) < 0)
            {
                if (compareUnsigned(u_k, u_bits_high) <= 0) // for small k we can do this in one step
                {
                    // decompress c with the range coder
                    c = dec.decodeSymbol(mCorrector[u_k]);
                }
                else
                {
                    // for larger k we need to do this in two steps
                    int k1 = u_k - u_bits_high;
                    // decompress higher bits with table
                    c = dec.decodeSymbol(mCorrector[u_k]);
                    // read lower bits raw
                    int c1 = dec.readBits(k1);
                    // put the corrector back together
                    c = (c << k1) | c1;
                }
                // translate c back into its correct interval
                if (c >= (1<<(u_k -1))) // if c is in the interval [ 2^(k-1)  ...  + 2^k - 1 ]
                {
                    // so we translate c back into the interval [ 2^(k-1) + 1  ...  2^k ] by adding 1
                    c += 1;
                }
                else // otherwise c is in the interval [ 0 ...  + 2^(k-1) - 1 ]
                {
                    // so we translate c back into the interval [ - (2^k - 1)  ...  - (2^(k-1)) ] by subtracting (2^k - 1)
                    c -= ((1<< u_k) - 1);
                }
            }
            else
            {
                c = corr_min;
            }
        }
        else // then c is either 0 or 1
        {
            c = dec.decodeBit(mCorrector0);
        }

        return c;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy