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

darwin.jopenctm.io.CtmInputStream Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 Daniel Heinrich
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * (version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see  
 * or write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301  USA.
 */
package darwin.jopenctm.io;

import java.io.*;

import lzma.sdk.lzma.Decoder;
import org.cservenak.streams.Coder;

/**
 *
 * @author daniel
 */
public class CtmInputStream extends DataInputStream {

    public CtmInputStream(InputStream in) {
        super(in);
    }

    public String readString() throws IOException {
        int len = readLittleInt();
        if (len > 0) {
            byte[] values = new byte[len];
            if (read(values) == -1) {
                throw new IOException("End of file reached while parsing the file!");
            }
            return new String(values);
        } else {
            return "";
        }
    }

    /**
     * reads a single integer value, in little endian order
     *
     * @return read integer value
     * @throws IOException see {@link InputStream#read()}
     */
    public int readLittleInt() throws IOException {
        int ch1 = read();
        int ch2 = read();
        int ch3 = read();
        int ch4 = read();
        if ((ch1 | ch2 | ch3 | ch4) < 0) {
            throw new EOFException();
        }
        return (ch1 + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));
    }

    public int[] readLittleIntArray(int count) throws IOException {
        int[] array = new int[count];
        for (int i = 0; i < count; i++) {
            array[i] = readLittleInt();
        }
        return array;
    }

    /**
     * Reads floating point number stored in little endian
     *
     * @return read float value
     * @throws IOException see {@link InputStream#read()}
     * @see CtmInputStream#readFloat()
     */
    public final float readLittleFloat() throws IOException {
        return Float.intBitsToFloat(readLittleInt());
    }

    public float[] readLittleFloatArray(int count) throws IOException {
        float[] array = new float[count];
        for (int i = 0; i < count; i++) {
            array[i] = readLittleFloat();
        }
        return array;
    }

    public int[] readPackedInts(int count, int size, boolean signed) throws IOException {
        int[] data = new int[count * size];
        byte[] tmp = readCompressedData(count * size * 4);//a Integer is 4 bytes
        // Convert interleaved array to integers
        for (int i = 0; i < count; ++i) {
            for (int k = 0; k < size; ++k) {
                int value = interleavedRetrieve(tmp, i + k * count, count * size);
                if (signed) {
                    long x = ((long) value) & 0xFFFFFFFFL;//not sure if correct
                    value = (x & 1) != 0 ? -(int) ((x + 1) >> 1) : (int) (x >> 1);
                }
                data[i * size + k] = value;
            }
        }
        return data;
    }

    public float[] readPackedFloats(int count, int size) throws IOException {
        float[] data = new float[count * size];
        byte[] tmp = readCompressedData(count * size * 4);//a Float is 4 bytes
        // Convert interleaved array to floats
        for (int i = 0; i < count; ++i) {
            for (int k = 0; k < size; ++k) {
                int value = interleavedRetrieve(tmp, i + k * count, count * size);
                data[i * size + k] = Float.intBitsToFloat(value);
            }
        }

        return data;
    }

    public byte[] readCompressedData(int size) throws IOException {
        int packedSize = readLittleInt();
        byte[] packed = new byte[packedSize + 5];//lzma properties are 5 bytes big
        if (read(packed) == -1) {
            throw new IOException("End of file reached while reading!");
        }
        
        ByteArrayOutputStream bout = new ByteArrayOutputStream(size);
        
        CustomCoder coder = new CustomCoder(size);
        coder.code(new ByteArrayInputStream(packed), bout);
                
        byte[] data = bout.toByteArray();
        assert data.length == size;
        
        return data;
    }

    public static int interleavedRetrieve(byte[] data, int offset, int stride) {
        byte b1 = data[offset + 3 * stride];
        byte b2 = data[offset + 2 * stride];
        byte b3 = data[offset + 1 * stride];
        byte b4 = data[offset];

        int i1 = ((int) b1) & 0xff;
        int i2 = ((int) b2) & 0xff;
        int i3 = ((int) b3) & 0xff;
        int i4 = ((int) b4) & 0xff;

        return i1 | (i2 << 8) | (i3 << 16) | (i4 << 24);
    }

    private static class CustomCoder implements Coder {

        private final Decoder d;
        private final int len;

        public CustomCoder(int packedLength) {
            d = new Decoder();
            len = packedLength;
        }

        @Override
        public void code(final InputStream in, final OutputStream out)
                throws IOException {

            byte[] properties = new byte[5];
            if (in.read(properties) != 5) {
                throw new IOException("LZMA file has no header!");
            }

            if (!d.setDecoderProperties(properties)) {
                throw new IOException("Decoder properties cannot be set!");
            }

            if (!d.code(in, out, len)) {
                throw new IOException("Decoding unsuccessful!");
            }            
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy