/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.pdf;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.xmlgraphics.image.GraphicsUtil;

/**
 * PDFImage implementation for alpha channel "images".
 */
public class AlphaRasterImage implements PDFImage {

    private int bitsPerComponent;
    private PDFDeviceColorSpace colorSpace;
    private Raster alpha;
    private String key;

    /**
     * Create a alpha channel image.
     * Creates a new bitmap image with the given data.
     *
     * @param k the key to be used to lookup the image
     * @param alpha the alpha channel raster
     */
    public AlphaRasterImage(String k, Raster alpha) {
        this.key = k;
        //Enable the commented line below if 16-bit alpha channels are desired.
        //Otherwise, we compress the alpha channel to 8 bit which should be sufficient.
        //this.bitsPerComponent = alpha.getSampleModel().getSampleSize(0);
        this.bitsPerComponent = 8;
        this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_GRAY);
        if (alpha == null) {
            throw new NullPointerException("Parameter alpha must not be null");
        }
        this.alpha = alpha;
    }

    /**
     * Create a alpha channel image.
     * Extracts the alpha channel from the RenderedImage and creates a new bitmap image
     * with the given data.
     *
     * @param k the key to be used to lookup the image
     * @param image the image (must have an alpha channel)
     */
    public AlphaRasterImage(String k, RenderedImage image) {
        this(k, getAlphaRaster(image));
    }

    /**
     * Extracts the Alpha Raster for the given image.
     * Also works for {@link java.awt.image.IndexColorModel}.
     */
    private static Raster getAlphaRaster(RenderedImage image) {
        Raster alphaRaster = GraphicsUtil.getAlphaRaster(image);

        /*
         * {@link GraphicsUtil#getAlphaRaster} calls internally
         * {@link java.awt.image.BufferedImage#getAlphRaster} which
         * will return <code>null</code> according to Java API
         * documentation for {@link java.awt.image.IndexColorModel}.
         *
         * In that case we create the raster drawing a hidden
         * image. That code might be better placed in
         * {@link java.awt.image.BufferedImage#getAlphRaster}
         * but since this is a different project and a change
         * to the interface semantics, it might break consumers.
         */
        if (alphaRaster == null) {
            BufferedImage bufferedImage = (BufferedImage) image;
            int w = bufferedImage.getWidth();
            int h = bufferedImage.getHeight();
            int type = BufferedImage.TYPE_INT_ARGB;
            BufferedImage bia = new BufferedImage(w, h, type);
            Graphics2D g = bia.createGraphics();
            g.drawImage(bufferedImage, 0, 0, null);
            g.dispose();
            alphaRaster = GraphicsUtil.getAlphaRaster(bia);
        }
        return alphaRaster;
    }

    /** {@inheritDoc} */
    public void setup(PDFDocument doc) {
        //nop
    }

    /** {@inheritDoc} */
    public String getKey() {
        return key;
    }

    /** {@inheritDoc} */
    public int getWidth() {
        return alpha.getWidth();
    }

    /** {@inheritDoc} */
    public int getHeight() {
        return alpha.getHeight();
    }

    /** {@inheritDoc} */
    public PDFDeviceColorSpace getColorSpace() {
        return colorSpace;
    }

    /** {@inheritDoc} */
    public int getBitsPerComponent() {
        return bitsPerComponent;
    }

    /** {@inheritDoc} */
    public boolean isTransparent() {
        return false;
    }

    /** {@inheritDoc} */
    public PDFColor getTransparentColor() {
        return null;
    }

    /** {@inheritDoc} */
    public String getMask() {
        return null;
    }

    /** @return null (unless overridden) */
    public String getSoftMask() {
        return null;
    }

    /** {@inheritDoc} */
    public PDFReference getSoftMaskReference() {
        return null;
    }

    /** {@inheritDoc} */
    public boolean isInverted() {
        return false;
    }

    /** {@inheritDoc} */
    public void outputContents(OutputStream out) throws IOException {
        int w = getWidth();
        int h = getHeight();

        //Check Raster
        int nbands = alpha.getNumBands();
        if (nbands != 1) {
            throw new UnsupportedOperationException(
                    "Expected only one band/component for the alpha channel");
        }

        //...and write the Raster line by line with a reusable buffer
        int dataType = alpha.getDataBuffer().getDataType();
        if (dataType == DataBuffer.TYPE_BYTE) {
            byte[] line = new byte[nbands * w];
            for (int y = 0; y < h; y++) {
                alpha.getDataElements(0, y, w, 1, line);
                out.write(line);
            }
        } else if (dataType == DataBuffer.TYPE_USHORT) {
            short[] sline = new short[nbands * w];
            byte[] line = new byte[nbands * w];
            for (int y = 0; y < h; y++) {
                alpha.getDataElements(0, y, w, 1, sline);
                for (int i = 0; i < w; i++) {
                    //this compresses a 16-bit alpha channel to 8 bits!
                    //we probably don't ever need a 16-bit channel
                    line[i] = (byte)(sline[i] >> 8);
                }
                out.write(line);
            }
        } else if (dataType == DataBuffer.TYPE_INT) {
            //Is there an better way to get a 8bit raster from a TYPE_INT raster?
            int shift = 24;
            SampleModel sampleModel = alpha.getSampleModel();
            if (sampleModel instanceof SinglePixelPackedSampleModel) {
                SinglePixelPackedSampleModel m = (SinglePixelPackedSampleModel)sampleModel;
                shift = m.getBitOffsets()[0];
            }
            int[] iline = new int[nbands * w];
            byte[] line = new byte[nbands * w];
            for (int y = 0; y < h; y++) {
                alpha.getDataElements(0, y, w, 1, iline);
                for (int i = 0; i < w; i++) {
                    line[i] = (byte)(iline[i] >> shift);
                }
                out.write(line);
            }
        } else {
            throw new UnsupportedOperationException("Unsupported DataBuffer type: "
                    + alpha.getDataBuffer().getClass().getName());
        }

    }

    /** {@inheritDoc} */
    public void populateXObjectDictionary(PDFDictionary dict) {
        //nop
    }

    /** {@inheritDoc} */
    public PDFICCStream getICCStream() {
        return null;
    }

    /** {@inheritDoc} */
    public boolean isPS() {
        return false;
    }

    /** {@inheritDoc} */
    public String getFilterHint() {
        return PDFFilterList.IMAGE_FILTER;
    }

    /** {@inheritDoc} */
    public PDFFilter getPDFFilter() {
        return null;
    }

    /** {@inheritDoc} */
    public boolean multipleFiltersAllowed() {
        return true;
    }
}


