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

org.monte.media.pgm.PGMImageReader Maven / Gradle / Ivy

The newest version!

package org.monte.media.pgm;

import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferShort;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;


public class PGMImageReader extends ImageReader {


    private int width = -1;

    private int height = -1;

    private int maxGray = -1;

    private int numImages = -1;

    private long dataOffset = -1;

    public PGMImageReader(PGMImageReaderSpi originatingProvider) {
        super(originatingProvider);
    }

    @Override
    public int getNumImages(boolean allowSearch) throws IOException {
        if (allowSearch && numImages == -1) {
            readHeader();

            ImageInputStream in = (ImageInputStream) getInput();
            in.seek(dataOffset);
            int dataSize = width * height * (maxGray > 255 ? 2 : 1);
            numImages = 0;
            while (in.skipBytes(dataSize) == dataSize) {
                numImages++;
            }
        }
        return numImages;
    }

    @Override
    public int getWidth(int imageIndex) throws IOException {
        readHeader();
        return width;
    }

    @Override
    public int getHeight(int imageIndex) throws IOException {
        readHeader();
        return height;
    }

    @Override
    public Iterator getImageTypes(int imageIndex) throws IOException {
        readHeader();
        LinkedList l = new LinkedList();
        ComponentColorModel ccm = new ComponentColorModel(
                new ICC_ColorSpace(ICC_Profile.getInstance(ColorSpace.CS_GRAY)),
                new int[]{maxGray > 255 ? 16 : 8},
                false, false, Transparency.OPAQUE,
                (maxGray > 255) ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_BYTE);
        l.add(new ImageTypeSpecifier(ccm, ccm.createCompatibleSampleModel(width, height)));
        return l.iterator();
    }

    @Override
    public IIOMetadata getStreamMetadata() throws IOException {
        return null;
    }

    @Override
    public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
        return null;
    }

    @Override
    public BufferedImage read(int imageIndex, ImageReadParam param)
            throws IOException {
        readHeader();

        if (imageIndex > 0) {
            throw new ArrayIndexOutOfBoundsException("imageIndex is " + imageIndex + " must be 0.");
        }

        ImageInputStream in = (ImageInputStream) getInput();
        in.seek(dataOffset + imageIndex * width * height * (maxGray > 255 ? 2 : 1));

        ComponentColorModel ccm = new ComponentColorModel(
                new ICC_ColorSpace(ICC_Profile.getInstance(ColorSpace.CS_GRAY)),
                new int[]{maxGray > 255 ? 16 : 8},
                false, false, Transparency.OPAQUE,
                (maxGray > 255) ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_BYTE);
        SampleModel sm = ccm.createCompatibleSampleModel(width, height);

        BufferedImage img;
        if (maxGray > 255) {
            DataBufferShort db = new DataBufferShort(width * height);
            in.readFully(db.getData(), 0, width * height);
            img = new BufferedImage(ccm, Raster.createWritableRaster(sm, db, new Point(0, 0)), false, new Hashtable());
        } else {
            DataBufferByte db = new DataBufferByte(width * height);
            in.readFully(db.getData(), 0, width * height);
            img = new BufferedImage(ccm, Raster.createWritableRaster(sm, db, new Point(0, 0)), false, new Hashtable());
        }

        return img;
    }


    private void readHeader() throws IOException {
        if (dataOffset == -1) {

            ImageInputStream in = (ImageInputStream) getInput();
            in.seek(0);


            if (in.readShort() != 0x5035) {
                in.reset();
                throw new IOException("Illegal magic number");
            }

            int b = in.readUnsignedByte();
            if (b != 0x20 && b != 0x09 && b != 0x0d && b != 0x0a) {
                throw new IOException("Whitespace missing after magic number");
            }

            width = readHeaderValue(in, "image width");
            if (width < 1) {
                throw new IOException("Illegal image width " + width);
            }
            height = readHeaderValue(in, "image height");
            if (height < 1) {
                throw new IOException("Illegal image width " + height);
            }
            maxGray = readHeaderValue(in, "maximum gray value");
            if (maxGray < 2 || maxGray > 65536) {
                throw new IOException("Illegal maximum gray value " + maxGray);
            }
            dataOffset = in.getStreamPosition();
        }
    }

    private int readHeaderValue(ImageInputStream in, String name) throws IOException {

        int b;
        do {
            b = in.readUnsignedByte();

            if (b == '#') {
                do {
                    b = in.readUnsignedByte();
                } while (b != 0x0d && b != 0x0a);
            }
        } while (b == 0x20 || b == 0x09 || b == 0x0d || b == 0x0a);


        if (b < 0x30 || b > 0x39) {
            throw new IOException(name + " missing");
        }
        int value = 0;
        do {
            if (value >= 100000) {
                throw new IOException(name + " is too large");
            }
            value = value * 10 + b - 0x30;
        } while ((b = in.readUnsignedByte()) >= 0x30 && b <= 0x39);
        if (b != 0x20 && b != 0x09 && b != 0x0d && b != 0x0a) {
            throw new IOException("Whitespace after " + name + " missing");
        }
        return value;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy