package org.example;

//
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;

public class ColorSpaceRecognition {

    private static Logger logger = Logger.getLogger("ColorSpaceRecognition");



    public static void main(String[] args) throws IOException {
        // exported from Gimp as grey 8bit, recognized correctly as Grey
        // printColorSpaceInfos("/test.grey.8bit.png");
        // magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png
        printColorSpaceInfos("/test.grey.converted-4bit.png");
    }

    private static void printColorSpaceInfos(String resourceName) throws IOException {
        printRawColorSpace(resourceName);
        printNonRawColorSpace(resourceName);
    }

    private static void printNonRawColorSpace(String resourceName) throws IOException {
        logger.log(Level.INFO,"ImageIO.read({0}) ",resourceName);
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(getResourceAsBytes(resourceName)));
        if (image == null) {
            throw new RuntimeException("image format not supported");
        }
        logger.log(Level.INFO," image.getColorModel().getColorSpace().getType(): {0} ({1}=RGB, {2}=GRAY, {3}=YCbCr)",
                new Integer[]{image.getColorModel().getColorSpace().getType(),ColorSpace.TYPE_RGB,ColorSpace.TYPE_GRAY,ColorSpace.TYPE_YCbCr});

        logger.log(Level.INFO," image.getType(): {0}",image.getType());
        logger.log(Level.INFO," image.getColorModel().getPixelSize(): {0}",
                image.getColorModel().getPixelSize());
        logger.log(Level.INFO," image.getColorModel().getNumColorComponents(): {0}",
                image.getColorModel().getNumColorComponents());
        logger.log(Level.INFO," image.getColorModel().getComponentSize().length: {0}",
                image.getColorModel().getComponentSize().length);
        for (int i = 0; i < image.getColorModel().getComponentSize().length; i++) {
            logger.log(Level.INFO," image.getColorModel().getComponentSize()[{0}]: {1}",new Integer[]{i,
                    image.getColorModel().getComponentSize()[i]});
        }
        logger.log(Level.INFO," image.getColorModel().getColorSpace().isCS_sRGB(): {0}",
                image.getColorModel().getColorSpace().isCS_sRGB());
        logger.log(Level.INFO," image.getSampleModel().getNumBands(): {0}",
                image.getSampleModel().getNumBands());
    }

    private static void printRawColorSpace(String resourceName) throws IOException {

        logger.log(Level.INFO,"ImageIO.createImageInputStream({0})", resourceName);
        try (ImageInputStream input
                     = ImageIO.createImageInputStream(new ByteArrayInputStream(getResourceAsBytes(resourceName)))) {
            Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
            if (!readers.hasNext()) {
                throw new RuntimeException("image format not supported");
            } else {
                ImageReader reader = readers.next();

                try {
                    reader.setInput(input);

                    ImageTypeSpecifier rawImageType = reader.getRawImageType(0);
                    if (rawImageType == null) {
                        logger.log(Level.INFO," rawImageType: null");
                    } else {
                        logger.log(Level.INFO," rawImageType.getColorModel().getColorSpace().getType(): {0} ({1}=RGB, {2}=GRAY, {3}=YCbCr)",
                                new Integer[]{rawImageType.getColorModel().getColorSpace().getType(), ColorSpace.TYPE_RGB, ColorSpace.TYPE_GRAY, ColorSpace.TYPE_YCbCr});
                        logger.log(Level.INFO," rawImageType.getColorModel().getPixelSize(): {0}",
                                rawImageType.getColorModel().getPixelSize());
                        logger.log(Level.INFO," rawImageType.getColorModel().getNumColorComponents(): {0}",
                                rawImageType.getColorModel().getNumColorComponents());
                        logger.log(Level.INFO," rawImageType.getColorModel().getComponentSize().length: {0}",
                                rawImageType.getColorModel().getComponentSize().length);
                        for (int i = 0; i < rawImageType.getColorModel().getComponentSize().length; i++) {
                            logger.log(Level.INFO," rawImageType.getColorModel().getComponentSize()[{0}]: {1}", new Integer[]{i,
                                    rawImageType.getColorModel().getComponentSize()[i]});
                        }
                        logger.log(Level.INFO," rawImageType.getColorModel().getColorSpace().isCS_sRGB(): {0}",
                                rawImageType.getColorModel().getColorSpace().isCS_sRGB());
                    }
                } finally {
                    reader.dispose();
                }
            }
        }
    }

    private static byte[] getResourceAsBytes(String resourceName) {
        return getResourceAsBytes(resourceName, ColorSpaceRecognition.class);
    }

    private static byte[] getResourceAsBytes(String resourceName, Class<?> clazz) {
        try (InputStream in = clazz.getResourceAsStream(resourceName)) {
            if (in == null) {
                throw new RuntimeException("Resource '" + resourceName
                        + "' could not be loaded with ClassLoader for " + clazz.getCanonicalName());
            }
            return in.readAllBytes();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}