/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.imaging;

import java.awt.RenderingHints;
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.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImagingOpException;
import java.io.File;
import java.io.IOException;

/**
 * This class is a mess and needs to be cleaned up.
 */
public class ColorTools {

    public BufferedImage correctImage(BufferedImage src, File file)
            throws ImageReadException, IOException {
        ICC_Profile icc = Sanselan.getICCProfile(file);
        if (icc == null)
            return src;

        ICC_ColorSpace cs = new ICC_ColorSpace(icc);

        BufferedImage dst = convertFromColorSpace(src, cs);
        return dst;
    }

    public BufferedImage relabelColorSpace(BufferedImage bi, ICC_Profile profile)
            throws ImagingOpException {
        ICC_ColorSpace cs = new ICC_ColorSpace(profile);

        return relabelColorSpace(bi, cs);
    }

    public BufferedImage relabelColorSpace(BufferedImage bi, ColorSpace cs)
            throws ImagingOpException {
        // This does not do the conversion. It tries to relabel the
        // BufferedImage
        // with its actual (presumably correct) Colorspace.
        // use this when the image is mislabeled, presumably having been
        // wrongly assumed to be sRGB

        ColorModel cm = deriveColorModel(bi, cs);

        return relabelColorSpace(bi, cm);

    }

    public BufferedImage relabelColorSpace(BufferedImage bi, ColorModel cm)
            throws ImagingOpException {
        // This does not do the conversion. It tries to relabel the
        // BufferedImage
        // with its actual (presumably correct) Colorspace.
        // use this when the image is mislabeled, presumably having been
        // wrongly assumed to be sRGB

        BufferedImage result = new BufferedImage(cm, bi.getRaster(), false,
                null);

        return result;
    }

    public ColorModel deriveColorModel(BufferedImage bi, ColorSpace cs)
            throws ImagingOpException {
        // boolean hasAlpha = (bi.getAlphaRaster() != null);
        return deriveColorModel(bi, cs, false);
    }

    public ColorModel deriveColorModel(BufferedImage bi, ColorSpace cs,
            boolean force_no_alpha) throws ImagingOpException {
        return deriveColorModel(bi.getColorModel(), cs, force_no_alpha);
    }

    public ColorModel deriveColorModel(ColorModel old_cm, ColorSpace cs,
            boolean force_no_alpha) throws ImagingOpException {

        if (old_cm instanceof ComponentColorModel) {
            ComponentColorModel ccm = (ComponentColorModel) old_cm;
            // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
            if (force_no_alpha)
                return new ComponentColorModel(cs, false, false,
                        ComponentColorModel.OPAQUE, ccm.getTransferType());
            else
                return new ComponentColorModel(cs, ccm.hasAlpha(), ccm
                        .isAlphaPremultiplied(), ccm.getTransparency(), ccm
                        .getTransferType());
        } else if (old_cm instanceof DirectColorModel) {
            DirectColorModel dcm = (DirectColorModel) old_cm;

            int old_mask = dcm.getRedMask() | dcm.getGreenMask()
                    | dcm.getBlueMask() | dcm.getAlphaMask();

            int old_bits = count_bits_in_mask(old_mask);

            return new DirectColorModel(cs, old_bits, dcm.getRedMask(), dcm
                    .getGreenMask(), dcm.getBlueMask(), dcm.getAlphaMask(), dcm
                    .isAlphaPremultiplied(), dcm.getTransferType());
        }
        // else if (old_cm instanceof PackedColorModel)
        // {
        // PackedColorModel pcm = (PackedColorModel) old_cm;
        //
        // // int old_mask = dcm.getRedMask() | dcm.getGreenMask()
        // // | dcm.getBlueMask() | dcm.getAlphaMask();
        //
        // int old_masks[] = pcm.getMasks();
        // // System.out.println("old_mask: " + old_mask);
        // int old_bits = count_bits_in_mask(old_masks);
        // // System.out.println("old_bits: " + old_bits);
        //
        // // PackedColorModel(ColorSpace space, int bits, int rmask, int gmask,
        // int bmask, int amask, boolean isAlphaPremultiplied, int trans, int
        // transferType)
        // cm = new PackedColorModel(cs, old_bits, pcm.getMasks(),
        //
        // pcm.isAlphaPremultiplied(), pcm.getTransparency(), pcm
        // .getTransferType());
        // }

        throw new ImagingOpException("Could not clone unknown ColorModel Type.");
    }

    private int count_bits_in_mask(int i) {
        int count = 0;
        while (i != 0) {
            count += (i & 1);
            // uses the unsigned version of java's right shift operator,
            // so that left hand bits are zeroed.
            i >>>= 1;
        }
        return count;
    }

    public BufferedImage convertToColorSpace(BufferedImage bi, ColorSpace to) {
        ColorSpace from = bi.getColorModel().getColorSpace();

        RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);

        ColorConvertOp op = new ColorConvertOp(from, to, hints);

        BufferedImage result = op.filter(bi, null);

        result = relabelColorSpace(result, to);

        return result;
    }

    public BufferedImage convertTosRGB(BufferedImage bi) {
        ColorSpace cs_sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);

        ColorModel srgbCM = ColorModel.getRGBdefault();
        cs_sRGB = srgbCM.getColorSpace();

        return convertToColorSpace(bi, cs_sRGB);
    }

    protected BufferedImage convertFromColorSpace(BufferedImage bi,
            ColorSpace from) {
        ColorSpace cs_sRGB;

        ColorModel srgbCM = ColorModel.getRGBdefault();
        cs_sRGB = srgbCM.getColorSpace();

        return convertBetweenColorSpaces(bi, from, cs_sRGB);

    }

    public BufferedImage convertBetweenICCProfiles(BufferedImage bi,
            ICC_Profile from, ICC_Profile to) {
        ICC_ColorSpace cs_from = new ICC_ColorSpace(from);
        ICC_ColorSpace cs_to = new ICC_ColorSpace(to);

        return convertBetweenColorSpaces(bi, cs_from, cs_to);
    }

    public BufferedImage convertToICCProfile(BufferedImage bi, ICC_Profile to) {
        ICC_ColorSpace cs_to = new ICC_ColorSpace(to);

        return convertToColorSpace(bi, cs_to);
    }

    public BufferedImage convertBetweenColorSpacesX2(BufferedImage bi,
            ColorSpace from, ColorSpace to) {
        RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);

        // bi = relabelColorSpace(bi, cs);
        // dumpColorSpace("\tcs_sRGB", cs_sRGB);
        // dumpColorSpace("\tColorModel.getRGBdefaultc",
        // ColorModel.getRGBdefault().getColorSpace());

        bi = relabelColorSpace(bi, from);
        ColorConvertOp op = new ColorConvertOp(from, to, hints);
        bi = op.filter(bi, null);

        bi = relabelColorSpace(bi, from);

        bi = op.filter(bi, null);

        bi = relabelColorSpace(bi, to);

        return bi;

    }

    public BufferedImage convertBetweenColorSpaces(BufferedImage bi,
            ColorSpace from, ColorSpace to) {
        RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);

        ColorConvertOp op = new ColorConvertOp(from, to, hints);

        bi = relabelColorSpace(bi, from);

        BufferedImage result = op.filter(bi, null);

        result = relabelColorSpace(result, to);

        return result;
    }

}