1 /*
   2  * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.java2d.cmm.lcms;
  27 
  28 import java.awt.Graphics2D;
  29 import java.awt.image.BufferedImage;
  30 import java.awt.image.ComponentColorModel;
  31 import java.awt.image.Raster;
  32 import java.awt.image.WritableRaster;
  33 import java.awt.image.SinglePixelPackedSampleModel;
  34 import java.awt.image.ComponentSampleModel;
  35 import java.awt.image.DataBuffer;
  36 import java.awt.image.DataBufferByte;
  37 import java.awt.image.DataBufferUShort;
  38 import java.awt.image.DataBufferInt;
  39 import java.awt.image.ColorModel;
  40 import sun.awt.image.ByteComponentRaster;
  41 import sun.awt.image.ShortComponentRaster;
  42 import sun.awt.image.IntegerComponentRaster;
  43 
  44 
  45 class LCMSImageLayout {
  46 
  47     public static int BYTES_SH(int x) {
  48         return x;
  49     }
  50 
  51     public static int EXTRA_SH(int x) {
  52         return x<<7;
  53     }
  54 
  55     public static int CHANNELS_SH(int x) {
  56         return x<<3;
  57     }
  58 
  59     public static final int SWAPFIRST   = 1<<14;
  60 
  61     public static final int DOSWAP      = 1<<10;
  62 
  63     public static final int PT_RGB_8 =
  64         CHANNELS_SH(3) | BYTES_SH(1);
  65 
  66     public static final int PT_GRAY_8 =
  67         CHANNELS_SH(1) | BYTES_SH(1);
  68 
  69     public static final int PT_GRAY_16 =
  70         CHANNELS_SH(1) | BYTES_SH(2);
  71 
  72     public static final int PT_RGBA_8 =
  73         EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
  74 
  75     public static final int PT_ARGB_8 =
  76         EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST;
  77 
  78     public static final int PT_BGR_8 =
  79         DOSWAP | CHANNELS_SH(3) | BYTES_SH(1);
  80 
  81     public static final int PT_ABGR_8 =
  82         DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
  83 
  84     public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) |
  85         BYTES_SH(1) | DOSWAP | SWAPFIRST;
  86 
  87     public static final int DT_BYTE     = 0;
  88     public static final int DT_SHORT    = 1;
  89     public static final int DT_INT      = 2;
  90     public static final int DT_DOUBLE   = 3;
  91 
  92 
  93     boolean isIntPacked = false;
  94     int pixelType;
  95     int dataType;
  96     int width;
  97     int height;
  98     int nextRowOffset;
  99     int offset;
 100 
 101     Object dataArray;
 102     private LCMSImageLayout(int np, int pixelType, int pixelSize) {
 103         this.pixelType = pixelType;
 104         width = np;
 105         height = 1;
 106         nextRowOffset = np*pixelSize;
 107         offset = 0;
 108     }
 109 
 110     private LCMSImageLayout(int width, int height, int pixelType,
 111                             int pixelSize) {
 112         this.pixelType = pixelType;
 113         this.width = width;
 114         this.height = height;
 115         nextRowOffset = width*pixelSize;
 116         offset = 0;
 117     }
 118 
 119 
 120     public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
 121         this(np, pixelType, pixelSize);
 122         dataType = DT_BYTE;
 123         dataArray = data;
 124     }
 125 
 126     public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) {
 127         this(np, pixelType, pixelSize);
 128         dataType = DT_SHORT;
 129         dataArray = data;
 130     }
 131 
 132     public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) {
 133         this(np, pixelType, pixelSize);
 134         dataType = DT_INT;
 135         dataArray = data;
 136     }
 137 
 138     public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
 139     {
 140         this(np, pixelType, pixelSize);
 141         dataType = DT_DOUBLE;
 142         dataArray = data;
 143     }
 144 
 145     public LCMSImageLayout(BufferedImage image) {
 146         ShortComponentRaster shortRaster;
 147         IntegerComponentRaster intRaster;
 148         ByteComponentRaster byteRaster;
 149         switch (image.getType()) {
 150             case BufferedImage.TYPE_INT_RGB:
 151                 pixelType = PT_ARGB_8;
 152                 isIntPacked = true;
 153                 break;
 154             case BufferedImage.TYPE_INT_ARGB:
 155                 pixelType = PT_ARGB_8;
 156                 isIntPacked = true;
 157                 break;
 158             case BufferedImage.TYPE_INT_BGR:
 159                 pixelType = PT_ABGR_8;
 160                 isIntPacked = true;
 161                 break;
 162             case BufferedImage.TYPE_3BYTE_BGR:
 163                 pixelType = PT_BGR_8;
 164                 break;
 165             case BufferedImage.TYPE_4BYTE_ABGR:
 166                 pixelType = PT_ABGR_8;
 167                 break;
 168             case BufferedImage.TYPE_BYTE_GRAY:
 169                 pixelType = PT_GRAY_8;
 170                 break;
 171             case BufferedImage.TYPE_USHORT_GRAY:
 172                 pixelType = PT_GRAY_16;
 173                 break;
 174             default:
 175             // TODO: Add support for some images having
 176             // SinglePixelPackedModel and ComponentSampleModel
 177                 throw new IllegalArgumentException(
 178                     "CMMImageLayout - bad image type passed to constructor");
 179         }
 180 
 181         width = image.getWidth();
 182         height = image.getHeight();
 183 
 184         switch (image.getType()) {
 185             case BufferedImage.TYPE_INT_RGB:
 186             case BufferedImage.TYPE_INT_ARGB:
 187             case BufferedImage.TYPE_INT_BGR:
 188                 intRaster = (IntegerComponentRaster)image.getRaster();
 189                 nextRowOffset = intRaster.getScanlineStride()*4;
 190                 offset = intRaster.getDataOffset(0)*4;
 191                 dataArray = intRaster.getDataStorage();
 192                 dataType = DT_INT;
 193                 break;
 194 
 195             case BufferedImage.TYPE_3BYTE_BGR:
 196             case BufferedImage.TYPE_4BYTE_ABGR:
 197                 byteRaster = (ByteComponentRaster)image.getRaster();
 198                 nextRowOffset = byteRaster.getScanlineStride();
 199                 int firstBand = image.getSampleModel().getNumBands() - 1;
 200                 offset = byteRaster.getDataOffset(firstBand);
 201                 dataArray = byteRaster.getDataStorage();
 202                 dataType = DT_BYTE;
 203                 break;
 204 
 205             case BufferedImage.TYPE_BYTE_GRAY:
 206                 byteRaster = (ByteComponentRaster)image.getRaster();
 207                 nextRowOffset = byteRaster.getScanlineStride();
 208                 offset = byteRaster.getDataOffset(0);
 209                 dataArray = byteRaster.getDataStorage();
 210                 dataType = DT_BYTE;
 211                 break;
 212 
 213             case BufferedImage.TYPE_USHORT_GRAY:
 214                 shortRaster = (ShortComponentRaster)image.getRaster();
 215                 nextRowOffset = shortRaster.getScanlineStride()*2;
 216                 offset = shortRaster.getDataOffset(0) * 2;
 217                 dataArray = shortRaster.getDataStorage();
 218                 dataType = DT_SHORT;
 219                 break;
 220         }
 221     }
 222 
 223     public static boolean isSupported(BufferedImage image) {
 224         switch (image.getType()) {
 225             case BufferedImage.TYPE_INT_RGB:
 226             case BufferedImage.TYPE_INT_ARGB:
 227             case BufferedImage.TYPE_INT_BGR:
 228             case BufferedImage.TYPE_3BYTE_BGR:
 229             case BufferedImage.TYPE_4BYTE_ABGR:
 230             case BufferedImage.TYPE_BYTE_GRAY:
 231             case BufferedImage.TYPE_USHORT_GRAY:
 232                 return true;
 233         }
 234         return false;
 235     }
 236 }