
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.*;
import javax.imageio.metadata.*;

import javax.imageio.stream.*;
import javax.imageio.plugins.tiff.*;


public class ReadParamTest {

    private final static int SZ = 50;
    private final static Color C = Color.RED;

    private final static String EXIF_DATA[] = {"2000:00:00 00:00:00"};
    private final static int N_EXIF = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL;

    private final static short FAX_DATA =
        FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED;
    private final static int N_FAX = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA;

    private final static String GPS_DATA[] =
        {ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS};
    private final static int N_GPS = ExifGPSTagSet.TAG_GPS_STATUS;

    private final boolean ignoreMetadata;

    public ReadParamTest(boolean ignoreMetadata) {
        this.ignoreMetadata = ignoreMetadata;
    }

    private ImageWriter getTIFFWriter() {

        java.util.Iterator<ImageWriter> writers =
            ImageIO.getImageWritersByFormatName("TIFF");
        if (!writers.hasNext()) {
            throw new RuntimeException("No writers available for TIFF format");
        }
        return writers.next();
    }

    private ImageReader getTIFFReader() {

        java.util.Iterator<ImageReader> readers =
            ImageIO.getImageReadersByFormatName("TIFF");
        if (!readers.hasNext()) {
            throw new RuntimeException("No readers available for TIFF format");
        }
        return readers.next();
    }


    private void writeImage() throws Exception {

        String fn = "test-" + ignoreMetadata + ".tiff";
        OutputStream s = new BufferedOutputStream(new FileOutputStream(fn));
        try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {

            ImageWriter writer = getTIFFWriter();
            writer.setOutput(ios);

            BufferedImage img = new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB);
            Graphics g = img.getGraphics();
            g.setColor(C);
            g.fillRect(0, 0, SZ, SZ);
            g.dispose();

            ImageWriteParam param = writer.getDefaultWriteParam();

            IIOMetadata md = writer.getDefaultImageMetadata(
                    new ImageTypeSpecifier(img), param);

            TIFFDirectory dir = TIFFDirectory.createFromMetadata(md);

            int ascii = TIFFTag.TIFF_ASCII;

            TIFFTag exifTag = new TIFFTag("DateTimeOriginal", N_EXIF, 1 << ascii);
            dir.addTIFFField(new TIFFField(exifTag, ascii, 1, EXIF_DATA));

            TIFFTag faxTag = new TIFFTag("CleanFaxData", N_FAX, 1 << TIFFTag.TIFF_SHORT);
            dir.addTIFFField(new TIFFField(faxTag, FAX_DATA));

            TIFFTag gpsTag = new TIFFTag("GPSStatus", N_GPS, 1 << ascii);
            dir.addTIFFField(new TIFFField(gpsTag, ascii, 1, GPS_DATA));

            writer.write(new IIOImage(img, null, dir.getAsMetadata()));

            ios.flush();
            writer.dispose();
        }
        s.close();
    }

    private void readAndCheckImage() throws Exception {

        ImageReader reader = getTIFFReader();

        String fn = "test-" + ignoreMetadata + ".tiff";
        ImageInputStream s = ImageIO.createImageInputStream(new File(fn));

        reader.setInput(s, false, ignoreMetadata);

        int ni = reader.getNumImages(true);
        check(ni == 1, "invalid number of images");


        TIFFImageReadParam param = new TIFFImageReadParam();
        // fax data are allowed by default
        param.removeAllowedTagSet(FaxTIFFTagSet.getInstance());
        // add non-default data
        param.addAllowedTagSet(ExifGPSTagSet.getInstance());


        // read images and metadata
        IIOImage i = reader.readAll(0, param);
        BufferedImage bi = (BufferedImage) i.getRenderedImage();

        check(bi.getWidth()  == SZ, "invalid width");
        check(bi.getHeight() == SZ, "invalid height");
        Color c = new Color(bi.getRGB(SZ / 2, SZ / 2));
        check(c.equals(C), "invalid color");

        TIFFDirectory dir =
            TIFFDirectory.createFromMetadata(i.getMetadata());

        System.out.println("EXIF: " + dir.containsTIFFField(N_EXIF));
        System.out.println("Fax : " + dir.containsTIFFField(N_FAX));
        System.out.println("GPS : " + dir.containsTIFFField(N_GPS));
    }

    public void run() {

        try {
            writeImage();
            readAndCheckImage();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void check(boolean ok, String msg) {
        if (!ok) { throw new RuntimeException(msg); }
    }

    public static void main(String[] args) {
        System.out.println("ignore = true:");
        (new ReadParamTest(true)).run();
        System.out.println("\nignore = false:");
        (new ReadParamTest(false)).run();
    }
}
