Skip to content
Snippets Groups Projects
FlatBufferLoader.java 3.83 KiB
package azgracompress.io.loader;

import azgracompress.data.Range;
import azgracompress.data.V2i;
import azgracompress.data.V3i;
import azgracompress.io.FlatBufferInputData;
import azgracompress.utilities.TypeConverter;

import java.io.IOException;
import java.util.Arrays;

/**
 * This loader is used when the entire dataset is stored in single buffer (array).
 */
public class FlatBufferLoader extends BasicLoader implements IPlaneLoader {
    /**
     * Flat buffer information.
     */
    private final FlatBufferInputData bufferInputData;

    /**
     * Pixel count in single plane.
     */
    private final int planePixelCount;

    public FlatBufferLoader(final FlatBufferInputData bufferDataInfo) {
        super(bufferDataInfo.getDimensions());
        this.bufferInputData = bufferDataInfo;
        planePixelCount = dims.getX() * dims.getY();
    }

    @Override
    public boolean supportParallelLoading() {
        return true;
    }

    private void copyShortArrayIntoBuffer(short[] srcArray,
                                          final int srcOffset,
                                          int[] destBuffer,
                                          final int destOffset,
                                          final int copyLen) {
        for (int i = 0; i < copyLen; i++) {
            destBuffer[destOffset + i] = TypeConverter.shortToInt(srcArray[srcOffset + i]);
        }
    }

    @Override
    protected int valueAt(final int plane, final int offset) {
        return TypeConverter.shortToInt(((short[]) bufferInputData.getPixelBuffer())[(plane * planePixelCount) + offset]);
    }

    @Override
    public int[] loadPlaneData(final int plane) throws IOException {
        final short[] flatBuffer = ((short[]) bufferInputData.getPixelBuffer());
        final int offset = plane * planePixelCount;
        final int[] planeData = new int[planePixelCount];
        for (int i = 0; i < planePixelCount; i++) {
            planeData[i] = TypeConverter.shortToInt(flatBuffer[offset + i]);
        }
        return planeData;
    }

    @Override
    public int[] loadPlanesU16Data(final int[] planes) throws IOException {
        if (planes.length < 1) {
            return new int[0];
        } else if (planes.length == 1) {
            return loadPlaneData(planes[0]);
        } else if (planes.length == bufferInputData.getDimensions().getZ()) { // Maybe?
            return loadAllPlanesU16Data();
        }
        final long totalValueCount = (long) planePixelCount * (long) planes.length;
        if (totalValueCount > (long) Integer.MAX_VALUE) {
            throw new IOException("Unable to load image data for planes, file size is too big.");
        }

        Arrays.sort(planes);

        final short[] flatBuffer = (short[]) bufferInputData.getPixelBuffer();
        int[] destBuffer = new int[(int) totalValueCount];
        int destOffset = 0;
        for (final int planeIndex : planes) {
            final int planeOffset = planeIndex * planePixelCount;
            copyShortArrayIntoBuffer(flatBuffer, planeOffset, destBuffer, destOffset, planePixelCount);
            destOffset += planePixelCount;
        }
        return destBuffer;
    }

    @Override
    public int[] loadAllPlanesU16Data() {
        final short[] flatBuffer = (short[]) bufferInputData.getPixelBuffer();
        return TypeConverter.shortArrayToIntArray(flatBuffer);
    }

    @Override
    public int[][] loadRowVectors(final int vectorSize, final Range<Integer> planeRange) {
        return loadRowVectorsImplByValueAt(vectorSize, planeRange);
    }

    @Override
    public int[][] loadBlocks(final V2i blockDim, final Range<Integer> planeRange) {
        return loadBlocksImplByValueAt(blockDim, planeRange);
    }

    @Override
    public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) {
        return loadVoxelsImplByValueAt(voxelDim, planeRange);
    }
}