summaryrefslogtreecommitdiffstats
path: root/awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java')
-rw-r--r--awt/org/apache/harmony/awt/gl/color/NativeImageFormat.java642
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
- }
- }
-}