All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.batik.ext.awt.image.rendered.MultiplyAlphaRed Maven / Gradle / Ivy

There is a newer version: 1.2.2.1-jre17
Show newest version
/*

   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.batik.ext.awt.image.rendered;

import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.util.ArrayList;
import java.util.List;


/**
 * This implements a masking operation by multiply the alpha channel of
 * one image by a luminance image (the mask).
 *
 * @author Thomas DeWeese
 * @version $Id: MultiplyAlphaRed.java 1831630 2018-05-15 12:56:55Z ssteiner $ */
public class MultiplyAlphaRed extends AbstractRed {

    /**
     * Multiply the alpha of one image with a mask image.
     * The size of the resultant image is the intersection of the
     * two image bounds.  If you want the end image to be the size
     * of one or the other please use the PadRed operator.
     *
     * @param src   The image to convert to multiply the alpha of
     * @param alpha The mask image to multiply the alpha channel of src
     *              with.
     */
    public MultiplyAlphaRed(CachableRed src, CachableRed alpha) {
        super(makeList(src, alpha),
              makeBounds(src,alpha),
              fixColorModel(src),
              fixSampleModel(src),
              src.getTileGridXOffset(),
              src.getTileGridYOffset(),
              null);
    }

    public boolean is_INT_PACK_BYTE_COMP(SampleModel srcSM,
                                         SampleModel alpSM) {
          // Check SampleModel types DirectColorModel
        if(!(srcSM instanceof SinglePixelPackedSampleModel)) return false;
        if(!(alpSM instanceof ComponentSampleModel))         return false;

        // Check transfer types
        if(srcSM.getDataType() != DataBuffer.TYPE_INT)       return false;
        if(alpSM.getDataType() != DataBuffer.TYPE_BYTE)      return false;


        SinglePixelPackedSampleModel sppsm;
        sppsm = (SinglePixelPackedSampleModel)srcSM;

        int [] masks = sppsm.getBitMasks();
        if(masks.length != 4) return false;
        if(masks[0] != 0x00ff0000) return false;
        if(masks[1] != 0x0000ff00) return false;
        if(masks[2] != 0x000000ff) return false;
        if(masks[3] != 0xff000000) return false;

        ComponentSampleModel csm;
        csm = (ComponentSampleModel)alpSM;
        if (csm.getNumBands()    != 1) return false;
        if (csm.getPixelStride() != 1) return false;

        return true;
   }

    public WritableRaster INT_PACK_BYTE_COMP_Impl (WritableRaster wr) {
          // Get my source.
        CachableRed srcRed   = (CachableRed)getSources().get(0);
        CachableRed alphaRed = (CachableRed)getSources().get(1);

        // Already has alpha channel so we use it.
        srcRed.copyData(wr);

        Rectangle rgn = wr.getBounds();
        rgn = rgn.intersection(alphaRed.getBounds());

        Raster r = alphaRed.getData(rgn);

        ComponentSampleModel csm;
        csm = (ComponentSampleModel)r.getSampleModel();
        final int alpScanStride = csm.getScanlineStride();

        DataBufferByte alpDB   = (DataBufferByte)r.getDataBuffer();
        final int      alpBase
            = (alpDB.getOffset() +
               csm.getOffset(rgn.x-r.getSampleModelTranslateX(),
                             rgn.y-r.getSampleModelTranslateY()));


          // Access the pixel data array
        final byte[] alpPixels = alpDB.getBankData()[0];

        SinglePixelPackedSampleModel sppsm;
        sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
        final int srcScanStride = sppsm.getScanlineStride();

        DataBufferInt srcDB   = (DataBufferInt)wr.getDataBuffer();
        final int     srcBase
            = (srcDB.getOffset() +
               sppsm.getOffset(rgn.x-wr.getSampleModelTranslateX(),
                               rgn.y-wr.getSampleModelTranslateY()));

          // Access the pixel data array
        final int[] srcPixels = srcDB.getBankData()[0];

        ColorModel cm = srcRed.getColorModel();

        if (cm.isAlphaPremultiplied()) {
            // For alpha premult we need to multiply all comps.
            for (int y=0; y>>24)     ) *a)&0xFF00)<<16) |
                         (((((pix>>>16)&0xFF) *a)&0xFF00)<<8 ) |
                         (((((pix>>> 8)&0xFF) *a)&0xFF00)    ) |
                         (((((pix     )&0xFF) *a)&0xFF00)>>8 ));
                    sp++;
                }
            }

        } else {
              // For non-alpha premult we only need to multiply alpha.
            for (int y=0; y>>24;
                    srcPixels[sp] = ((((sa*a) & 0xFF00)<<16)|
                                     srcPixels[sp]&0x00FFFFFF);
                    sp++;
                }
            }
        }

        return wr;
    }

    public WritableRaster copyData(WritableRaster wr) {
        // Get my source.
        CachableRed srcRed   = (CachableRed)getSources().get(0);
        CachableRed alphaRed = (CachableRed)getSources().get(1);

        if (is_INT_PACK_BYTE_COMP(srcRed.getSampleModel(),
                                  alphaRed.getSampleModel()))
            return INT_PACK_BYTE_COMP_Impl(wr);

        ColorModel cm = srcRed.getColorModel();
        if (cm.hasAlpha()) {
            // Already has alpha channel so we use it.
            srcRed.copyData(wr);

            Rectangle rgn = wr.getBounds();
            if (rgn.intersects(alphaRed.getBounds()))
                rgn = rgn.intersection(alphaRed.getBounds());
            else
                return wr;

            int [] wrData    = null;
            int [] alphaData = null;

            Raster r = alphaRed.getData(rgn);
            int    w = rgn.width;

            final int bands = wr.getSampleModel().getNumBands();

            if (cm.isAlphaPremultiplied()) {
                for (int y=rgn.y; y> 8;
                            ++i;
                            wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                            ++i;
                        }
                        break;
                    case 4:
                        for (int anAlphaData1 : alphaData) {
                            a = anAlphaData1 & 0xFF;
                            wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                            ++i;
                            wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                            ++i;
                            wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                            ++i;
                            wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                            ++i;
                        }
                        break;
                    default:
                        for (int anAlphaData : alphaData) {
                            a = anAlphaData & 0xFF;
                            for (b = 0; b < bands; b++) {
                                wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
                                ++i;
                            }
                        }
                    }
                    wr.setPixels(rgn.x, y, w, 1, wrData);
                }
            } else {
                int b = srcRed.getSampleModel().getNumBands()-1;
                for (int y=rgn.y; y>8;
                    }
                    wr.setSamples(rgn.x, y, w, 1, b, wrData);
                }
            }

            return wr;
        }

        // No alpha in source, so we hide the alpha channel in wr and
        // have our source fill wr with color info...
        int [] bands = new int[wr.getNumBands()-1];
        for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy