FileDocCategorySizeDatePackage
LookupOp.javaAPI DocAndroid 1.5 API24387Wed May 06 22:41:54 BST 2009java.awt.image

LookupOp

public class LookupOp extends Object implements BufferedImageOp, RasterOp
The LookupOp class performs a lookup operation which transforms a source image by filtering each band using a table of data. The table may contain a single array or it may contain a different data array for each band of the image.
since
Android 1.0

Fields Summary
private final LookupTable
lut
The lut.
private RenderingHints
hints
The hints.
private final boolean
canUseIpp
The can use ipp.
private int[]
cachedLevels
The cached levels.
private int[]
cachedValues
The cached values.
private int
validForChannels
The valid for channels.
static int[]
levelInitializer
The level initializer.
Constructors Summary
public LookupOp(LookupTable lookup, RenderingHints hints)
Instantiates a new LookupOp object from the specified LookupTable object and a RenderingHints object.

param
lookup the specified LookupTable object.
param
hints the RenderingHints object or null.


     
        // TODO
        // System.loadLibrary("imageops");

        for (int i = 1; i <= 0x10000; i++) {
            levelInitializer[i - 1] = i;
        }
    
        if (lookup == null) {
            throw new NullPointerException(Messages.getString("awt.01", "lookup")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        lut = lookup;
        this.hints = hints;
        canUseIpp = lut instanceof ByteLookupTable || lut instanceof ShortLookupTable;
    
Methods Summary
private final voidcreateByteLevels(int channels, boolean skipAlpha, int[] levels, int[] values, int[] channelsOrder)
Creates the byte levels.

param
channels the channels.
param
skipAlpha the skip alpha.
param
levels the levels.
param
values the values.
param
channelsOrder the channels order.

        byte data[][] = ((ByteLookupTable)lut).getTable();
        int nLevels = data[0].length;
        int offset = lut.getOffset();

        // Use one data array for all channels or use several data arrays
        int dataIncrement = data.length > 1 ? 1 : 0;

        for (int ch = 0, dataIdx = 0; ch < channels; dataIdx += dataIncrement, ch++) {
            int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];
            int channelBase = nLevels * channelOffset;

            // Skip last channel if needed, zero values are OK -
            // no changes to the channel information will be done in IPP
            if ((channelOffset == channels - 1 && skipAlpha) || (dataIdx >= data.length)) {
                continue;
            }

            System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
            for (int from = 0, to = channelBase; from < nLevels; from++, to++) {
                values[to] = data[dataIdx][from] & 0xFF;
            }
        }
    
public java.awt.image.BufferedImagecreateCompatibleDestImage(java.awt.image.BufferedImage src, java.awt.image.ColorModel dstCM)

        if (dstCM == null) {
            dstCM = src.getColorModel();

            // Sync transfer type with LUT for component color model
            if (dstCM instanceof ComponentColorModel) {
                int transferType = dstCM.getTransferType();
                if (lut instanceof ByteLookupTable) {
                    transferType = DataBuffer.TYPE_BYTE;
                } else if (lut instanceof ShortLookupTable) {
                    transferType = DataBuffer.TYPE_SHORT;
                }

                dstCM = new ComponentColorModel(dstCM.cs, dstCM.hasAlpha(),
                        dstCM.isAlphaPremultiplied, dstCM.transparency, transferType);
            }
        }

        WritableRaster r = dstCM.isCompatibleSampleModel(src.getSampleModel()) ? src.getRaster()
                .createCompatibleWritableRaster(src.getWidth(), src.getHeight()) : dstCM
                .createCompatibleWritableRaster(src.getWidth(), src.getHeight());

        return new BufferedImage(dstCM, r, dstCM.isAlphaPremultiplied(), null);
    
public java.awt.image.WritableRastercreateCompatibleDestRaster(java.awt.image.Raster src)

        return src.createCompatibleWritableRaster();
    
private final voidcreateShortLevels(int channels, boolean skipAlpha, int[] levels, int[] values, int[] channelsOrder)
Creates the short levels.

param
channels the channels.
param
skipAlpha the skip alpha.
param
levels the levels.
param
values the values.
param
channelsOrder the channels order.

        short data[][] = ((ShortLookupTable)lut).getTable();
        int nLevels = data[0].length;
        int offset = lut.getOffset();

        // Use one data array for all channels or use several data arrays
        int dataIncrement = data.length > 1 ? 1 : 0;

        for (int ch = 0, dataIdx = 0; ch < channels; dataIdx += dataIncrement, ch++) {
            int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];

            // Skip last channel if needed, zero values are OK -
            // no changes to the channel information will be done in IPP
            if ((channelOffset == channels - 1 && skipAlpha) || (dataIdx >= data.length)) {
                continue;
            }

            int channelBase = nLevels * channelOffset;
            System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
            for (int from = 0, to = channelBase; from < nLevels; from++, to++) {
                values[to] = data[dataIdx][from] & 0xFFFF;
            }
        }
    
public final java.awt.image.BufferedImagefilter(java.awt.image.BufferedImage src, java.awt.image.BufferedImage dst)

        ColorModel srcCM = src.getColorModel();

        if (srcCM instanceof IndexColorModel) {
            // awt.220=Source should not have IndexColorModel
            throw new IllegalArgumentException(Messages.getString("awt.220")); //$NON-NLS-1$
        }

        // Check if the number of scaling factors matches the number of bands
        int nComponents = srcCM.getNumComponents();
        int nLUTComponents = lut.getNumComponents();
        boolean skipAlpha;
        if (srcCM.hasAlpha()) {
            if (nLUTComponents == 1 || nLUTComponents == nComponents - 1) {
                skipAlpha = true;
            } else if (nLUTComponents == nComponents) {
                skipAlpha = false;
            } else {
                // awt.229=Number of components in the LUT does not match the
                // number of bands
                throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
            }
        } else if (nLUTComponents == 1 || nLUTComponents == nComponents) {
            skipAlpha = false;
        } else {
            // awt.229=Number of components in the LUT does not match the number
            // of bands
            throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
        }

        BufferedImage finalDst = null;
        if (dst == null) {
            finalDst = dst;
            dst = createCompatibleDestImage(src, null);
        } else {
            if (src.getWidth() != dst.getWidth()) {
                throw new IllegalArgumentException(Messages.getString("awt.291")); //$NON-NLS-1$
            }

            if (src.getHeight() != dst.getHeight()) {
                throw new IllegalArgumentException(Messages.getString("awt.292")); //$NON-NLS-1$
            }

            if (!srcCM.equals(dst.getColorModel())) {
                // Treat BufferedImage.TYPE_INT_RGB and
                // BufferedImage.TYPE_INT_ARGB as same
                if (!((src.getType() == BufferedImage.TYPE_INT_RGB || src.getType() == BufferedImage.TYPE_INT_ARGB) && (dst
                        .getType() == BufferedImage.TYPE_INT_RGB || dst.getType() == BufferedImage.TYPE_INT_ARGB))) {
                    finalDst = dst;
                    dst = createCompatibleDestImage(src, null);
                }
            }
        }

        // TODO
        // if (!canUseIpp || ippFilter(src.getRaster(), dst.getRaster(),
        // src.getType(), skipAlpha) != 0)
        if (slowFilter(src.getRaster(), dst.getRaster(), skipAlpha) != 0) {
            // awt.21F=Unable to transform source
            throw new ImagingOpException(Messages.getString("awt.21F")); //$NON-NLS-1$
        }

        if (finalDst != null) {
            Graphics2D g = finalDst.createGraphics();
            g.setComposite(AlphaComposite.Src);
            g.drawImage(dst, 0, 0, null);
        } else {
            finalDst = dst;
        }

        return dst;
    
public final java.awt.image.WritableRasterfilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst)

        if (dst == null) {
            dst = createCompatibleDestRaster(src);
        } else {
            if (src.getNumBands() != dst.getNumBands()) {
                throw new IllegalArgumentException(Messages.getString("awt.237")); //$NON-NLS-1$            }
            }
            if (src.getWidth() != dst.getWidth()) {
                throw new IllegalArgumentException(Messages.getString("awt.28F")); //$NON-NLS-1$            }
            }
            if (src.getHeight() != dst.getHeight()) {
                throw new IllegalArgumentException(Messages.getString("awt.290")); //$NON-NLS-1$            }
            }
        }

        if (lut.getNumComponents() != 1 && lut.getNumComponents() != src.getNumBands()) {
            // awt.238=The number of arrays in the LookupTable does not meet the
            // restrictions
            throw new IllegalArgumentException(Messages.getString("awt.238")); //$NON-NLS-1$
        }

        // TODO
        // if (!canUseIpp || ippFilter(src, dst, BufferedImage.TYPE_CUSTOM,
        // false) != 0)
        if (slowFilter(src, dst, false) != 0) {
            // awt.21F=Unable to transform source
            throw new ImagingOpException(Messages.getString("awt.21F")); //$NON-NLS-1$
        }

        return dst;
    
public final java.awt.geom.Rectangle2DgetBounds2D(java.awt.image.Raster src)

        return src.getBounds();
    
public final java.awt.geom.Rectangle2DgetBounds2D(java.awt.image.BufferedImage src)

        return getBounds2D(src.getRaster());
    
public final java.awt.geom.Point2DgetPoint2D(java.awt.geom.Point2D srcPt, java.awt.geom.Point2D dstPt)

        if (dstPt == null) {
            dstPt = new Point2D.Float();
        }

        dstPt.setLocation(srcPt);
        return dstPt;
    
public final java.awt.RenderingHintsgetRenderingHints()

        return hints;
    
public final java.awt.image.LookupTablegetTable()
Gets the LookupTable of the specified Object.

return
the LookupTable of the specified Object.

        return lut;
    
private final intippFilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst, int imageType, boolean skipAlpha)
Ipp filter.

param
src the src.
param
dst the dst.
param
imageType the image type.
param
skipAlpha the skip alpha.
return
the int.

        int res;

        int srcStride, dstStride;
        int channels;
        int offsets[] = null;
        int channelsOrder[] = null;

        switch (imageType) {
            case BufferedImage.TYPE_INT_ARGB:
            case BufferedImage.TYPE_INT_ARGB_PRE:
            case BufferedImage.TYPE_INT_RGB: {
                channels = 4;
                srcStride = src.getWidth() * 4;
                dstStride = dst.getWidth() * 4;
                channelsOrder = new int[] {
                        2, 1, 0, 3
                };
                break;
            }

            case BufferedImage.TYPE_4BYTE_ABGR:
            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
            case BufferedImage.TYPE_INT_BGR: {
                channels = 4;
                srcStride = src.getWidth() * 4;
                dstStride = dst.getWidth() * 4;
                break;
            }

            case BufferedImage.TYPE_BYTE_GRAY: {
                channels = 1;
                srcStride = src.getWidth();
                dstStride = dst.getWidth();
                break;
            }

            case BufferedImage.TYPE_3BYTE_BGR: {
                channels = 3;
                srcStride = src.getWidth() * 3;
                dstStride = dst.getWidth() * 3;
                channelsOrder = new int[] {
                        2, 1, 0
                };
                break;
            }

            case BufferedImage.TYPE_USHORT_GRAY:
            case BufferedImage.TYPE_USHORT_565_RGB:
            case BufferedImage.TYPE_USHORT_555_RGB:
            case BufferedImage.TYPE_BYTE_BINARY: {
                return slowFilter(src, dst, skipAlpha);
            }

            default: {
                SampleModel srcSM = src.getSampleModel();
                SampleModel dstSM = dst.getSampleModel();

                if (srcSM instanceof PixelInterleavedSampleModel
                        && dstSM instanceof PixelInterleavedSampleModel) {
                    // Check PixelInterleavedSampleModel
                    if (srcSM.getDataType() != DataBuffer.TYPE_BYTE
                            || dstSM.getDataType() != DataBuffer.TYPE_BYTE) {
                        return slowFilter(src, dst, skipAlpha);
                    }

                    // Have IPP functions for 1, 3 and 4 channels
                    channels = srcSM.getNumBands();
                    if (!(channels == 1 || channels == 3 || channels == 4)) {
                        return slowFilter(src, dst, skipAlpha);
                    }

                    srcStride = ((ComponentSampleModel)srcSM).getScanlineStride();
                    dstStride = ((ComponentSampleModel)dstSM).getScanlineStride();

                    channelsOrder = ((ComponentSampleModel)srcSM).getBandOffsets();
                } else if (srcSM instanceof SinglePixelPackedSampleModel
                        && dstSM instanceof SinglePixelPackedSampleModel) {
                    // Check SinglePixelPackedSampleModel
                    SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel)srcSM;
                    SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel)dstSM;

                    channels = sppsm1.getNumBands();

                    // TYPE_INT_RGB, TYPE_INT_ARGB...
                    if (sppsm1.getDataType() != DataBuffer.TYPE_INT
                            || sppsm2.getDataType() != DataBuffer.TYPE_INT
                            || !(channels == 3 || channels == 4)) {
                        return slowFilter(src, dst, skipAlpha);
                    }

                    // Check compatibility of sample models
                    if (!Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets())
                            || !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())) {
                        return slowFilter(src, dst, skipAlpha);
                    }

                    for (int i = 0; i < channels; i++) {
                        if (sppsm1.getSampleSize(i) != 8) {
                            return slowFilter(src, dst, skipAlpha);
                        }
                    }

                    channelsOrder = new int[channels];
                    int bitOffsets[] = sppsm1.getBitOffsets();
                    for (int i = 0; i < channels; i++) {
                        channelsOrder[i] = bitOffsets[i] / 8;
                    }

                    if (channels == 3) { // Don't skip channel now, could be
                        // optimized
                        channels = 4;
                    }

                    srcStride = sppsm1.getScanlineStride() * 4;
                    dstStride = sppsm2.getScanlineStride() * 4;
                } else {
                    return slowFilter(src, dst, skipAlpha);
                }

                // Fill offsets if there's a child raster
                if (src.getParent() != null || dst.getParent() != null) {
                    if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0
                            || dst.getSampleModelTranslateX() != 0
                            || dst.getSampleModelTranslateY() != 0) {
                        offsets = new int[4];
                        offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
                        offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
                        offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
                        offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
                    }
                }
            }
        }

        int levels[] = null, values[] = null;
        int channelMultiplier = skipAlpha ? -1 : 1;
        if (channelMultiplier * channels == validForChannels) { // use existing
            // levels/values
            levels = cachedLevels;
            values = cachedValues;
        } else { // create new levels/values
            if (lut instanceof ByteLookupTable) {
                byte data[][] = ((ByteLookupTable)lut).getTable();
                levels = new int[channels * data[0].length];
                values = new int[channels * data[0].length];
                createByteLevels(channels, skipAlpha, levels, values, channelsOrder);
            } else if (lut instanceof ShortLookupTable) {
                short data[][] = ((ShortLookupTable)lut).getTable();
                levels = new int[channels * data[0].length];
                values = new int[channels * data[0].length];
                createShortLevels(channels, skipAlpha, levels, values, channelsOrder);
            }

            // cache levels/values
            validForChannels = channelMultiplier * channels;
            cachedLevels = levels;
            cachedValues = values;
        }

        Object srcData, dstData;
        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
        try {
            srcData = dbAccess.getData(src.getDataBuffer());
            dstData = dbAccess.getData(dst.getDataBuffer());
        } catch (IllegalArgumentException e) {
            return -1; // Unknown data buffer type
        }

        res = ippLUT(srcData, src.getWidth(), src.getHeight(), srcStride, dstData, dst.getWidth(),
                dst.getHeight(), dstStride, levels, values, channels, offsets, false);

        return res;
    
static final native intippLUT(java.lang.Object src, int srcWidth, int srcHeight, int srcStride, java.lang.Object dst, int dstWidth, int dstHeight, int dstStride, int[] levels, int[] values, int channels, int[] offsets, boolean linear)
Ipp lut.

param
src the src.
param
srcWidth the src width.
param
srcHeight the src height.
param
srcStride the src stride.
param
dst the dst.
param
dstWidth the dst width.
param
dstHeight the dst height.
param
dstStride the dst stride.
param
levels the levels.
param
values the values.
param
channels the channels.
param
offsets the offsets.
param
linear the linear.
return
the int.

private final intslowFilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst, boolean skipAlpha)
Slow filter.

param
src the src.
param
dst the dst.
param
skipAlpha the skip alpha.
return
the int.

        int minSrcX = src.getMinX();
        int minDstX = dst.getMinX();
        int minSrcY = src.getMinY();
        int minDstY = dst.getMinY();

        int skippingChannels = skipAlpha ? 1 : 0;
        int numBands2Process = src.getNumBands() - skippingChannels;

        int numBands = src.getNumBands();
        int srcHeight = src.getHeight();
        int srcWidth = src.getWidth();

        int[] pixels = null;
        int offset = lut.getOffset();

        if (lut instanceof ByteLookupTable) {
            byte[][] byteData = ((ByteLookupTable)lut).getTable();
            pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);

            if (lut.getNumComponents() != 1) {
                for (int i = 0; i < pixels.length; i += numBands) {
                    for (int b = 0; b < numBands2Process; b++) {
                        pixels[i + b] = byteData[b][pixels[i + b] - offset] & 0xFF;
                    }
                }
            } else {
                for (int i = 0; i < pixels.length; i += numBands) {
                    for (int b = 0; b < numBands2Process; b++) {
                        pixels[i + b] = byteData[0][pixels[i + b] - offset] & 0xFF;
                    }
                }
            }

            dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
        } else if (lut instanceof ShortLookupTable) {
            short[][] shortData = ((ShortLookupTable)lut).getTable();
            pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);

            if (lut.getNumComponents() != 1) {
                for (int i = 0; i < pixels.length; i += numBands) {
                    for (int b = 0; b < numBands2Process; b++) {
                        pixels[i + b] = shortData[b][pixels[i + b] - offset] & 0xFFFF;
                    }
                }
            } else {
                for (int i = 0; i < pixels.length; i += numBands) {
                    for (int b = 0; b < numBands2Process; b++) {
                        pixels[i + b] = shortData[0][pixels[i + b] - offset] & 0xFFFF;
                    }
                }
            }

            dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
        } else {
            int pixel[] = new int[src.getNumBands()];
            int maxY = minSrcY + srcHeight;
            int maxX = minSrcX + srcWidth;
            for (int srcY = minSrcY, dstY = minDstY; srcY < maxY; srcY++, dstY++) {
                for (int srcX = minSrcX, dstX = minDstX; srcX < maxX; srcX++, dstX++) {
                    src.getPixel(srcX, srcY, pixel);
                    lut.lookupPixel(pixel, pixel);
                    dst.setPixel(dstX, dstY, pixel);
                }
            }
        }

        return 0;