Package org.apache.pdfbox.pdmodel.graphics.blend

Source Code of org.apache.pdfbox.pdmodel.graphics.blend.BlendComposite$BlendCompositeContext

/*
* 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.pdfbox.pdmodel.graphics.blend;

import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.RenderingHints;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* AWT composite for blend modes.
*
* @author K�hn & Weyh Software, GmbH
*/
public final class BlendComposite implements Composite
{
    /**
     * Log instance.
     */
    private static final Log LOG = LogFactory.getLog(BlendComposite.class);

    /**
     * Creates a blend composite
     *
     * @param blendMode Desired blend mode
     * @param constantAlpha Constant alpha, must be in the inclusive range
     * [0.0,�1.0] or it will be clipped.
     */
    public static Composite getInstance(BlendMode blendMode, float constantAlpha)
    {
        if (blendMode == BlendMode.NORMAL)
        {
            if (constantAlpha < 0)
            {
                LOG.warn("using 0 instead of incorrect Alpha " + constantAlpha);
                constantAlpha = 0;
            }
            else if (constantAlpha > 1)
            {
                LOG.warn("using 1 instead of incorrect Alpha " + constantAlpha);
                constantAlpha = 1;
            }
            return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, constantAlpha);
        }
        else
        {
            return new BlendComposite(blendMode, constantAlpha);
        }
    }

    // TODO - non-separable blending modes

    private final BlendMode blendMode;
    private final float constantAlpha;

    private BlendComposite(BlendMode blendMode, float constantAlpha)
    {
        super();
        this.blendMode = blendMode;
        this.constantAlpha = constantAlpha;
    }

    @Override
    public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel,
            RenderingHints hints)
    {
        return new BlendCompositeContext(srcColorModel, dstColorModel, hints);
    }

    class BlendCompositeContext implements CompositeContext
    {
        private final ColorModel srcColorModel;
        private final ColorModel dstColorModel;
        private final RenderingHints hints;

        BlendCompositeContext(ColorModel srcColorModel, ColorModel dstColorModel,
                RenderingHints hints)
        {
            this.srcColorModel = srcColorModel;
            this.dstColorModel = dstColorModel;
            this.hints = hints;
        }

        @Override
        public void dispose()
        {
            // nothing needed
        }

        @Override
        public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
        {
            int x0 = src.getMinX();
            int y0 = src.getMinY();
            int width = Math.min(Math.min(src.getWidth(), dstIn.getWidth()), dstOut.getWidth());
            int height = Math.min(Math.min(src.getHeight(), dstIn.getHeight()), dstOut.getHeight());
            int x1 = x0 + width;
            int y1 = y0 + height;
            int dstInXShift = dstIn.getMinX() - x0;
            int dstInYShift = dstIn.getMinY() - y0;
            int dstOutXShift = dstOut.getMinX() - x0;
            int dstOutYShift = dstOut.getMinY() - y0;

            ColorSpace srcColorSpace = srcColorModel.getColorSpace();
            int numSrcColorComponents = srcColorModel.getNumColorComponents();
            int numSrcComponents = src.getNumBands();
            boolean srcHasAlpha = (numSrcComponents > numSrcColorComponents);
            ColorSpace dstColorSpace = dstColorModel.getColorSpace();
            int numDstColorComponents = dstColorModel.getNumColorComponents();
            int numDstComponents = dstIn.getNumBands();
            boolean dstHasAlpha = (numDstComponents > numDstColorComponents);

            int colorSpaceType = dstColorSpace.getType();
            boolean subtractive = (colorSpaceType != ColorSpace.TYPE_RGB)
                    && (colorSpaceType != ColorSpace.TYPE_GRAY);

            boolean blendModeIsSeparable = blendMode instanceof SeparableBlendMode;
            SeparableBlendMode separableBlendMode = blendModeIsSeparable ?
                    (SeparableBlendMode) blendMode : null;

            boolean needsColorConversion = !srcColorSpace.equals(dstColorSpace);

            Object srcPixel = null;
            Object dstPixel = null;
            float[] srcComponents = new float[numSrcComponents];
            float[] dstComponents = new float[numDstComponents];

            float[] srcColor = new float[numSrcColorComponents];
            float[] srcConverted;

            for (int y = y0; y < y1; y++)
            {
                for (int x = x0; x < x1; x++)
                {
                    srcPixel = src.getDataElements(x, y, srcPixel);
                    dstPixel = dstIn.getDataElements(dstInXShift + x, dstInYShift + y, dstPixel);

                    srcComponents = srcColorModel.getNormalizedComponents(srcPixel, srcComponents,
                            0);
                    dstComponents = dstColorModel.getNormalizedComponents(dstPixel, dstComponents,
                            0);

                    float srcAlpha = srcHasAlpha ? srcComponents[numSrcColorComponents] : 1.0f;
                    float dstAlpha = dstHasAlpha ? dstComponents[numDstColorComponents] : 1.0f;

                    srcAlpha = srcAlpha * constantAlpha;

                    float resultAlpha = dstAlpha + srcAlpha - srcAlpha * dstAlpha;
                    float srcAlphaRatio = (resultAlpha > 0) ? srcAlpha / resultAlpha : 0;

                    // convert color
                    System.arraycopy(srcComponents, 0, srcColor, 0, numSrcColorComponents);
                    if (needsColorConversion)
                    {
                        // TODO - very very slow - Hash results???
                        float[] cieXYZ = srcColorSpace.toCIEXYZ(srcColor);
                        srcConverted = dstColorSpace.fromCIEXYZ(cieXYZ);
                    }
                    else
                    {
                        srcConverted = srcColor;
                    }

                    if (separableBlendMode != null)
                    {
                        for (int k = 0; k < numDstColorComponents; k++)
                        {
                            float srcValue = srcConverted[k];
                            float dstValue = dstComponents[k];

                            if (subtractive)
                            {
                                srcValue = 1 - srcValue;
                                dstValue = 1 - dstValue;
                            }

                            float value = separableBlendMode.blendChannel(srcValue, dstValue);
                            value = srcValue + dstAlpha * (value - srcValue);
                            value = dstValue + srcAlphaRatio * (value - dstValue);

                            if (subtractive)
                            {
                                value = 1 - value;
                            }

                            dstComponents[k] = value;
                        }
                    }
                    else
                    {
                        // TODO - nonseparable modes
                    }

                    if (dstHasAlpha)
                    {
                        dstComponents[numDstColorComponents] = resultAlpha;
                    }

                    dstPixel = dstColorModel.getDataElements(dstComponents, 0, dstPixel);
                    dstOut.setDataElements(dstOutXShift + x, dstOutYShift + y, dstPixel);
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.pdfbox.pdmodel.graphics.blend.BlendComposite$BlendCompositeContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.