diff options
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java')
-rw-r--r-- | awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java | 642 |
1 files changed, 0 insertions, 642 deletions
diff --git a/awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java b/awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java deleted file mode 100644 index 9594047..0000000 --- a/awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java +++ /dev/null @@ -1,642 +0,0 @@ -/* - * 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. - */ -/** - * @author Oleg V. Khaschansky - * @version $Revision$ - */ -package org.apache.harmony.awt.gl.color; - -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentSampleModel; -import java.awt.image.DataBuffer; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; -import java.util.ArrayList; - -import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor; -import org.apache.harmony.awt.internal.nls.Messages; - - -/** - * This class converts java color/sample models to the LCMS pixel formats. - * It also encapsulates all the information about the image format, which native CMM - * needs to have in order to read/write data. - * - * At present planar formats (multiple bands) are not supported - * and they are handled as a common (custom) case. - * Samples other than 1 - 7 bytes and multiple of 8 bits are - * also handled as custom (and won't be supported in the nearest future). - */ -class NativeImageFormat { - ////////////////////////////////////////////// - // LCMS Pixel types - private static final int PT_ANY = 0; // Don't check colorspace - // 1 & 2 are reserved - private static final int PT_GRAY = 3; - private static final int PT_RGB = 4; - // Skipping other since we don't use them here - /////////////////////////////////////////////// - - // Conversion of predefined BufferedImage formats to LCMS formats - private static final int INT_RGB_LCMS_FMT = - colorspaceSh(PT_RGB)| - extraSh(1)| - channelsSh(3)| - bytesSh(1)| - doswapSh(1)| - swapfirstSh(1); - - private static final int INT_ARGB_LCMS_FMT = INT_RGB_LCMS_FMT; - - private static final int INT_BGR_LCMS_FMT = - colorspaceSh(PT_RGB)| - extraSh(1)| - channelsSh(3)| - bytesSh(1); - - private static final int THREE_BYTE_BGR_LCMS_FMT = - colorspaceSh(PT_RGB)| - channelsSh(3)| - bytesSh(1)| - doswapSh(1); - - private static final int FOUR_BYTE_ABGR_LCMS_FMT = - colorspaceSh(PT_RGB)| - extraSh(1)| - channelsSh(3)| - bytesSh(1)| - doswapSh(1); - - private static final int BYTE_GRAY_LCMS_FMT = - colorspaceSh(PT_GRAY)| - channelsSh(1)| - bytesSh(1); - - private static final int USHORT_GRAY_LCMS_FMT = - colorspaceSh(PT_GRAY)| - channelsSh(1)| - bytesSh(2); - - // LCMS format packed into 32 bit value. For description - // of this format refer to LCMS documentation. - private int cmmFormat = 0; - - // Dimensions - private int rows = 0; - private int cols = 0; - - // Scanline may contain some padding in the end - private int scanlineStride = -1; - - private Object imageData; - // It's possible to have offset from the beginning of the array - private int dataOffset; - - // Has the image alpha channel? If has - here its band band offset goes - private int alphaOffset = -1; - - // initializes proper field IDs - private static native void initIDs(); - - static { - NativeCMM.loadCMM(); - initIDs(); - } - - //////////////////////////////////// - // LCMS image format encoders - //////////////////////////////////// - private static int colorspaceSh(int s) { - return (s << 16); - } - - private static int swapfirstSh(int s) { - return (s << 14); - } - - private static int flavorSh(int s) { - return (s << 13); - } - - private static int planarSh(int s) { - return (s << 12); - } - - private static int endianSh(int s) { - return (s << 11); - } - - private static int doswapSh(int s) { - return (s << 10); - } - - private static int extraSh(int s) { - return (s << 7); - } - - private static int channelsSh(int s) { - return (s << 3); - } - - private static int bytesSh(int s) { - return s; - } - //////////////////////////////////// - // End of LCMS image format encoders - //////////////////////////////////// - - // Accessors - Object getChannelData() { - return imageData; - } - - int getNumCols() { - return cols; - } - - int getNumRows() { - return rows; - } - - // Constructors - public NativeImageFormat() { - } - - /** - * Simple image layout for common case with - * not optimized workflow. - * - * For hifi colorspaces with 5+ color channels imgData - * should be <code>byte</code> array. - * - * For common colorspaces with up to 4 color channels it - * should be <code>short</code> array. - * - * Alpha channel is handled by caller, not by CMS. - * - * Color channels are in their natural order (not BGR but RGB). - * - * @param imgData - array of <code>byte</code> or <code>short</code> - * @param nChannels - number of channels - * @param nRows - number of scanlines in the image - * @param nCols - number of pixels in one row of the image - */ - public NativeImageFormat(Object imgData, int nChannels, int nRows, int nCols) { - if (imgData instanceof short[]) { - cmmFormat |= bytesSh(2); - } - else if (imgData instanceof byte[]) { - cmmFormat |= bytesSh(1); - } - else - // awt.47=First argument should be byte or short array - throw new IllegalArgumentException(Messages.getString("awt.47")); //$NON-NLS-1$ - - cmmFormat |= channelsSh(nChannels); - - rows = nRows; - cols = nCols; - - imageData = imgData; - - dataOffset = 0; - } - - /** - * Deduces image format from the buffered image type - * or color and sample models. - * @param bi - image - * @return image format object - */ - public static NativeImageFormat createNativeImageFormat(BufferedImage bi) { - NativeImageFormat fmt = new NativeImageFormat(); - - switch (bi.getType()) { - case BufferedImage.TYPE_INT_RGB: { - fmt.cmmFormat = INT_RGB_LCMS_FMT; - break; - } - - case BufferedImage.TYPE_INT_ARGB: - case BufferedImage.TYPE_INT_ARGB_PRE: { - fmt.cmmFormat = INT_ARGB_LCMS_FMT; - fmt.alphaOffset = 3; - break; - } - - case BufferedImage.TYPE_INT_BGR: { - fmt.cmmFormat = INT_BGR_LCMS_FMT; - break; - } - - case BufferedImage.TYPE_3BYTE_BGR: { - fmt.cmmFormat = THREE_BYTE_BGR_LCMS_FMT; - break; - } - - case BufferedImage.TYPE_4BYTE_ABGR_PRE: - case BufferedImage.TYPE_4BYTE_ABGR: { - fmt.cmmFormat = FOUR_BYTE_ABGR_LCMS_FMT; - fmt.alphaOffset = 0; - break; - } - - case BufferedImage.TYPE_BYTE_GRAY: { - fmt.cmmFormat = BYTE_GRAY_LCMS_FMT; - break; - } - - case BufferedImage.TYPE_USHORT_GRAY: { - fmt.cmmFormat = USHORT_GRAY_LCMS_FMT; - break; - } - - case BufferedImage.TYPE_BYTE_BINARY: - case BufferedImage.TYPE_USHORT_565_RGB: - case BufferedImage.TYPE_USHORT_555_RGB: - case BufferedImage.TYPE_BYTE_INDEXED: { - // A bunch of unsupported formats - return null; - } - - default: - break; // Try to look at sample model and color model - } - - - if (fmt.cmmFormat == 0) { - ColorModel cm = bi.getColorModel(); - SampleModel sm = bi.getSampleModel(); - - if (sm instanceof ComponentSampleModel) { - ComponentSampleModel csm = (ComponentSampleModel) sm; - fmt.cmmFormat = getFormatFromComponentModel(csm, cm.hasAlpha()); - fmt.scanlineStride = calculateScanlineStrideCSM(csm, bi.getRaster()); - } else if (sm instanceof SinglePixelPackedSampleModel) { - SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm; - fmt.cmmFormat = getFormatFromSPPSampleModel(sppsm, cm.hasAlpha()); - fmt.scanlineStride = calculateScanlineStrideSPPSM(sppsm, bi.getRaster()); - } - - if (cm.hasAlpha()) - fmt.alphaOffset = calculateAlphaOffset(sm, bi.getRaster()); - } - - if (fmt.cmmFormat == 0) - return null; - - if (!fmt.setImageData(bi.getRaster().getDataBuffer())) { - return null; - } - - fmt.rows = bi.getHeight(); - fmt.cols = bi.getWidth(); - - fmt.dataOffset = bi.getRaster().getDataBuffer().getOffset(); - - return fmt; - } - - /** - * Deduces image format from the raster sample model. - * @param r - raster - * @return image format object - */ - public static NativeImageFormat createNativeImageFormat(Raster r) { - NativeImageFormat fmt = new NativeImageFormat(); - SampleModel sm = r.getSampleModel(); - - // Assume that there's no alpha - if (sm instanceof ComponentSampleModel) { - ComponentSampleModel csm = (ComponentSampleModel) sm; - fmt.cmmFormat = getFormatFromComponentModel(csm, false); - fmt.scanlineStride = calculateScanlineStrideCSM(csm, r); - } else if (sm instanceof SinglePixelPackedSampleModel) { - SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm; - fmt.cmmFormat = getFormatFromSPPSampleModel(sppsm, false); - fmt.scanlineStride = calculateScanlineStrideSPPSM(sppsm, r); - } - - if (fmt.cmmFormat == 0) - return null; - - fmt.cols = r.getWidth(); - fmt.rows = r.getHeight(); - fmt.dataOffset = r.getDataBuffer().getOffset(); - - if (!fmt.setImageData(r.getDataBuffer())) - return null; - - return fmt; - } - - /** - * Obtains LCMS format from the component sample model - * @param sm - sample model - * @param hasAlpha - true if there's an alpha channel - * @return LCMS format - */ - private static int getFormatFromComponentModel(ComponentSampleModel sm, boolean hasAlpha) { - // Multiple data arrays (banks) not supported - int bankIndex = sm.getBankIndices()[0]; - for (int i=1; i < sm.getNumBands(); i++) { - if (sm.getBankIndices()[i] != bankIndex) { - return 0; - } - } - - int channels = hasAlpha ? sm.getNumBands()-1 : sm.getNumBands(); - int extra = hasAlpha ? 1 : 0; - int bytes = 1; - switch (sm.getDataType()) { - case DataBuffer.TYPE_BYTE: - bytes = 1; break; - case DataBuffer.TYPE_SHORT: - case DataBuffer.TYPE_USHORT: - bytes = 2; break; - case DataBuffer.TYPE_INT: - bytes = 4; break; - case DataBuffer.TYPE_DOUBLE: - bytes = 0; break; - default: - return 0; // Unsupported data type - } - - int doSwap = 0; - int swapFirst = 0; - boolean knownFormat = false; - - int i; - - // "RGBA" - for (i=0; i < sm.getNumBands(); i++) { - if (sm.getBandOffsets()[i] != i) break; - } - if (i == sm.getNumBands()) { // Ok, it is it - doSwap = 0; - swapFirst = 0; - knownFormat = true; - } - - // "ARGB" - if (!knownFormat) { - for (i=0; i < sm.getNumBands()-1; i++) { - if (sm.getBandOffsets()[i] != i+1) break; - } - if (sm.getBandOffsets()[i] == 0) i++; - if (i == sm.getNumBands()) { // Ok, it is it - doSwap = 0; - swapFirst = 1; - knownFormat = true; - } - } - - // "BGRA" - if (!knownFormat) { - for (i=0; i < sm.getNumBands()-1; i++) { - if (sm.getBandOffsets()[i] != sm.getNumBands() - 2 - i) break; - } - if (sm.getBandOffsets()[i] == sm.getNumBands()-1) i++; - if (i == sm.getNumBands()) { // Ok, it is it - doSwap = 1; - swapFirst = 1; - knownFormat = true; - } - } - - // "ABGR" - if (!knownFormat) { - for (i=0; i < sm.getNumBands(); i++) { - if (sm.getBandOffsets()[i] != sm.getNumBands() - 1 - i) break; - } - if (i == sm.getNumBands()) { // Ok, it is it - doSwap = 1; - swapFirst = 0; - knownFormat = true; - } - } - - // XXX - Planar formats are not supported yet - if (!knownFormat) - return 0; - - return - channelsSh(channels) | - bytesSh(bytes) | - extraSh(extra) | - doswapSh(doSwap) | - swapfirstSh(swapFirst); - } - - /** - * Obtains LCMS format from the single pixel packed sample model - * @param sm - sample model - * @param hasAlpha - true if there's an alpha channel - * @return LCMS format - */ - private static int getFormatFromSPPSampleModel(SinglePixelPackedSampleModel sm, - boolean hasAlpha) { - // Can we extract bytes? - int mask = sm.getBitMasks()[0] >>> sm.getBitOffsets()[0]; - if (!(mask == 0xFF || mask == 0xFFFF || mask == 0xFFFFFFFF)) - return 0; - - // All masks are same? - for (int i = 1; i < sm.getNumBands(); i++) { - if ((sm.getBitMasks()[i] >>> sm.getBitOffsets()[i]) != mask) - return 0; - } - - int pixelSize = 0; - // Check if data type is supported - if (sm.getDataType() == DataBuffer.TYPE_USHORT) - pixelSize = 2; - else if (sm.getDataType() == DataBuffer.TYPE_INT) - pixelSize = 4; - else - return 0; - - - int bytes = 0; - switch (mask) { - case 0xFF: - bytes = 1; - break; - case 0xFFFF: - bytes = 2; - break; - case 0xFFFFFFFF: - bytes = 4; - break; - default: return 0; - } - - - int channels = hasAlpha ? sm.getNumBands()-1 : sm.getNumBands(); - int extra = hasAlpha ? 1 : 0; - extra += pixelSize/bytes - sm.getNumBands(); // Unused bytes? - - // Form an ArrayList containing offset for each band - ArrayList<Integer> offsetsLst = new ArrayList<Integer>(); - for (int k=0; k < sm.getNumBands(); k++) { - offsetsLst.add(new Integer(sm.getBitOffsets()[k]/(bytes*8))); - } - - // Add offsets for unused space - for (int i=0; i<pixelSize/bytes; i++) { - if (offsetsLst.indexOf(new Integer(i)) < 0) - offsetsLst.add(new Integer(i)); - } - - int offsets[] = new int[pixelSize/bytes]; - for (int i=0; i<offsetsLst.size(); i++) { - offsets[i] = offsetsLst.get(i).intValue(); - } - - int doSwap = 0; - int swapFirst = 0; - boolean knownFormat = false; - - int i; - - // "RGBA" - for (i=0; i < pixelSize; i++) { - if (offsets[i] != i) break; - } - if (i == pixelSize) { // Ok, it is it - doSwap = 0; - swapFirst = 0; - knownFormat = true; - } - - // "ARGB" - if (!knownFormat) { - for (i=0; i < pixelSize-1; i++) { - if (offsets[i] != i+1) break; - } - if (offsets[i] == 0) i++; - if (i == pixelSize) { // Ok, it is it - doSwap = 0; - swapFirst = 1; - knownFormat = true; - } - } - - // "BGRA" - if (!knownFormat) { - for (i=0; i < pixelSize-1; i++) { - if (offsets[i] != pixelSize - 2 - i) break; - } - if (offsets[i] == pixelSize-1) i++; - if (i == pixelSize) { // Ok, it is it - doSwap = 1; - swapFirst = 1; - knownFormat = true; - } - } - - // "ABGR" - if (!knownFormat) { - for (i=0; i < pixelSize; i++) { - if (offsets[i] != pixelSize - 1 - i) break; - } - if (i == pixelSize) { // Ok, it is it - doSwap = 1; - swapFirst = 0; - knownFormat = true; - } - } - - // XXX - Planar formats are not supported yet - if (!knownFormat) - return 0; - - return - channelsSh(channels) | - bytesSh(bytes) | - extraSh(extra) | - doswapSh(doSwap) | - swapfirstSh(swapFirst); - } - - /** - * Obtains data array from the DataBuffer object - * @param db - data buffer - * @return - true if successful - */ - private boolean setImageData(DataBuffer db) { - AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance(); - try { - imageData = dbAccess.getData(db); - } catch (IllegalArgumentException e) { - return false; // Unknown data buffer type - } - - return true; - } - - /** - * Calculates scanline stride in bytes - * @param csm - component sample model - * @param r - raster - * @return scanline stride in bytes - */ - private static int calculateScanlineStrideCSM(ComponentSampleModel csm, Raster r) { - if (csm.getScanlineStride() != csm.getPixelStride()*csm.getWidth()) { - int dataTypeSize = DataBuffer.getDataTypeSize(r.getDataBuffer().getDataType()) / 8; - return csm.getScanlineStride()*dataTypeSize; - } - return -1; - } - - /** - * Calculates scanline stride in bytes - * @param sppsm - sample model - * @param r - raster - * @return scanline stride in bytes - */ - private static int calculateScanlineStrideSPPSM(SinglePixelPackedSampleModel sppsm, Raster r) { - if (sppsm.getScanlineStride() != sppsm.getWidth()) { - int dataTypeSize = DataBuffer.getDataTypeSize(r.getDataBuffer().getDataType()) / 8; - return sppsm.getScanlineStride()*dataTypeSize; - } - return -1; - } - - /** - * Calculates byte offset of the alpha channel from the beginning of the pixel data - * @param sm - sample model - * @param r - raster - * @return byte offset of the alpha channel - */ - private static int calculateAlphaOffset(SampleModel sm, Raster r) { - if (sm instanceof ComponentSampleModel) { - ComponentSampleModel csm = (ComponentSampleModel) sm; - int dataTypeSize = - DataBuffer.getDataTypeSize(r.getDataBuffer().getDataType()) / 8; - return - csm.getBandOffsets()[csm.getBandOffsets().length - 1] * dataTypeSize; - } else if (sm instanceof SinglePixelPackedSampleModel) { - SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm; - return sppsm.getBitOffsets()[sppsm.getBitOffsets().length - 1] / 8; - } else { - return -1; // No offset, don't copy alpha - } - } -} |