jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java
changeset 16900 5e0400ee2917
parent 15974 91b0e63e6e83
parent 16899 666a37b19844
child 18255 3bad8692f61c
equal deleted inserted replaced
16898:b321dfd1163f 16900:5e0400ee2917
    83      * image is processed scan by scan.
    83      * image is processed scan by scan.
    84      */
    84      */
    85     private boolean imageAtOnce = false;
    85     private boolean imageAtOnce = false;
    86     Object dataArray;
    86     Object dataArray;
    87 
    87 
    88     private LCMSImageLayout(int np, int pixelType, int pixelSize) {
    88     private int dataArrayLength; /* in bytes */
       
    89 
       
    90     private LCMSImageLayout(int np, int pixelType, int pixelSize)
       
    91             throws ImageLayoutException
       
    92     {
    89         this.pixelType = pixelType;
    93         this.pixelType = pixelType;
    90         width = np;
    94         width = np;
    91         height = 1;
    95         height = 1;
    92         nextRowOffset = np * pixelSize;
    96         nextRowOffset = safeMult(pixelSize, np);
    93         offset = 0;
    97         offset = 0;
    94     }
    98     }
    95 
    99 
    96     private LCMSImageLayout(int width, int height, int pixelType,
   100     private LCMSImageLayout(int width, int height, int pixelType,
    97             int pixelSize) {
   101                             int pixelSize)
       
   102             throws ImageLayoutException
       
   103     {
    98         this.pixelType = pixelType;
   104         this.pixelType = pixelType;
    99         this.width = width;
   105         this.width = width;
   100         this.height = height;
   106         this.height = height;
   101         nextRowOffset = width * pixelSize;
   107         nextRowOffset = safeMult(pixelSize, width);
   102         offset = 0;
   108         offset = 0;
   103     }
   109     }
   104 
   110 
   105     public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
   111 
       
   112     public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize)
       
   113             throws ImageLayoutException
       
   114     {
   106         this(np, pixelType, pixelSize);
   115         this(np, pixelType, pixelSize);
   107         dataType = DT_BYTE;
   116         dataType = DT_BYTE;
   108         dataArray = data;
   117         dataArray = data;
   109     }
   118         dataArrayLength = data.length;
   110 
   119 
   111     public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) {
   120         verify();
       
   121     }
       
   122 
       
   123     public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize)
       
   124             throws ImageLayoutException
       
   125     {
   112         this(np, pixelType, pixelSize);
   126         this(np, pixelType, pixelSize);
   113         dataType = DT_SHORT;
   127         dataType = DT_SHORT;
   114         dataArray = data;
   128         dataArray = data;
   115     }
   129         dataArrayLength = 2 * data.length;
   116 
   130 
   117     public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) {
   131         verify();
       
   132     }
       
   133 
       
   134     public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize)
       
   135             throws ImageLayoutException
       
   136     {
   118         this(np, pixelType, pixelSize);
   137         this(np, pixelType, pixelSize);
   119         dataType = DT_INT;
   138         dataType = DT_INT;
   120         dataArray = data;
   139         dataArray = data;
   121     }
   140         dataArrayLength = 4 * data.length;
   122 
   141 
   123     public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) {
   142         verify();
       
   143     }
       
   144 
       
   145     public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
       
   146             throws ImageLayoutException
       
   147     {
   124         this(np, pixelType, pixelSize);
   148         this(np, pixelType, pixelSize);
   125         dataType = DT_DOUBLE;
   149         dataType = DT_DOUBLE;
   126         dataArray = data;
   150         dataArray = data;
       
   151         dataArrayLength = 8 * data.length;
       
   152 
       
   153         verify();
   127     }
   154     }
   128 
   155 
   129     private LCMSImageLayout() {
   156     private LCMSImageLayout() {
   130     }
   157     }
   131 
   158 
   132     /* This method creates a layout object for given image.
   159     /* This method creates a layout object for given image.
   133      * Returns null if the image is not supported by current implementation.
   160      * Returns null if the image is not supported by current implementation.
   134      */
   161      */
   135     public static LCMSImageLayout createImageLayout(BufferedImage image) {
   162     public static LCMSImageLayout createImageLayout(BufferedImage image) throws ImageLayoutException {
   136         LCMSImageLayout l = new LCMSImageLayout();
   163         LCMSImageLayout l = new LCMSImageLayout();
   137 
   164 
   138         switch (image.getType()) {
   165         switch (image.getType()) {
   139             case BufferedImage.TYPE_INT_RGB:
   166             case BufferedImage.TYPE_INT_RGB:
   140                 l.pixelType = PT_ARGB_8;
   167                 l.pixelType = PT_ARGB_8;
   191             case BufferedImage.TYPE_INT_ARGB:
   218             case BufferedImage.TYPE_INT_ARGB:
   192             case BufferedImage.TYPE_INT_BGR:
   219             case BufferedImage.TYPE_INT_BGR:
   193                 do {
   220                 do {
   194                     IntegerComponentRaster intRaster = (IntegerComponentRaster)
   221                     IntegerComponentRaster intRaster = (IntegerComponentRaster)
   195                             image.getRaster();
   222                             image.getRaster();
   196                     l.nextRowOffset = intRaster.getScanlineStride() * 4;
   223                     l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
   197                     l.offset = intRaster.getDataOffset(0) * 4;
   224                     l.offset = safeMult(4, intRaster.getDataOffset(0));
   198                     l.dataArray = intRaster.getDataStorage();
   225                     l.dataArray = intRaster.getDataStorage();
       
   226                     l.dataArrayLength = 4 * intRaster.getDataStorage().length;
   199                     l.dataType = DT_INT;
   227                     l.dataType = DT_INT;
   200 
   228 
   201                     if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
   229                     if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
   202                         l.imageAtOnce = true;
   230                         l.imageAtOnce = true;
   203                     }
   231                     }
   211                             image.getRaster();
   239                             image.getRaster();
   212                     l.nextRowOffset = byteRaster.getScanlineStride();
   240                     l.nextRowOffset = byteRaster.getScanlineStride();
   213                     int firstBand = image.getSampleModel().getNumBands() - 1;
   241                     int firstBand = image.getSampleModel().getNumBands() - 1;
   214                     l.offset = byteRaster.getDataOffset(firstBand);
   242                     l.offset = byteRaster.getDataOffset(firstBand);
   215                     l.dataArray = byteRaster.getDataStorage();
   243                     l.dataArray = byteRaster.getDataStorage();
       
   244                     l.dataArrayLength = byteRaster.getDataStorage().length;
   216                     l.dataType = DT_BYTE;
   245                     l.dataType = DT_BYTE;
   217                     if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
   246                     if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
   218                         l.imageAtOnce = true;
   247                         l.imageAtOnce = true;
   219                     }
   248                     }
   220                 } while (false);
   249                 } while (false);
   223             case BufferedImage.TYPE_BYTE_GRAY:
   252             case BufferedImage.TYPE_BYTE_GRAY:
   224                 do {
   253                 do {
   225                     ByteComponentRaster byteRaster = (ByteComponentRaster)
   254                     ByteComponentRaster byteRaster = (ByteComponentRaster)
   226                             image.getRaster();
   255                             image.getRaster();
   227                     l.nextRowOffset = byteRaster.getScanlineStride();
   256                     l.nextRowOffset = byteRaster.getScanlineStride();
       
   257                     l.dataArrayLength = byteRaster.getDataStorage().length;
   228                     l.offset = byteRaster.getDataOffset(0);
   258                     l.offset = byteRaster.getDataOffset(0);
   229                     l.dataArray = byteRaster.getDataStorage();
   259                     l.dataArray = byteRaster.getDataStorage();
   230                     l.dataType = DT_BYTE;
   260                     l.dataType = DT_BYTE;
   231 
   261 
   232                     if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
   262                     if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
   237 
   267 
   238             case BufferedImage.TYPE_USHORT_GRAY:
   268             case BufferedImage.TYPE_USHORT_GRAY:
   239                 do {
   269                 do {
   240                     ShortComponentRaster shortRaster = (ShortComponentRaster)
   270                     ShortComponentRaster shortRaster = (ShortComponentRaster)
   241                             image.getRaster();
   271                             image.getRaster();
   242                     l.nextRowOffset = shortRaster.getScanlineStride() * 2;
   272                     l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
   243                     l.offset = shortRaster.getDataOffset(0) * 2;
   273                     l.offset = safeMult(2, shortRaster.getDataOffset(0));
   244                     l.dataArray = shortRaster.getDataStorage();
   274                     l.dataArray = shortRaster.getDataStorage();
       
   275                     l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
   245                     l.dataType = DT_SHORT;
   276                     l.dataType = DT_SHORT;
   246 
   277 
   247                     if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
   278                     if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
   248                         l.imageAtOnce = true;
   279                         l.imageAtOnce = true;
   249                     }
   280                     }
   250                 } while (false);
   281                 } while (false);
   251                 break;
   282                 break;
   252             default:
   283             default:
   253                 return null;
   284                 return null;
   254         }
   285         }
       
   286         l.verify();
   255         return l;
   287         return l;
   256     }
   288     }
   257 
   289 
   258     private static enum BandOrder {
   290     private static enum BandOrder {
   259         DIRECT,
   291         DIRECT,
   291             }
   323             }
   292             return order;
   324             return order;
   293         }
   325         }
   294     }
   326     }
   295 
   327 
       
   328     private void verify() throws ImageLayoutException {
       
   329 
       
   330         if (offset < 0 || offset >= dataArrayLength) {
       
   331             throw new ImageLayoutException("Invalid image layout");
       
   332         }
       
   333 
       
   334         int lastPixelOffset = safeMult(nextRowOffset, (height - 1));
       
   335 
       
   336         lastPixelOffset = safeAdd(lastPixelOffset, (width - 1));
       
   337 
       
   338         int off = safeAdd(offset, lastPixelOffset);
       
   339 
       
   340         if (off < 0 || off >= dataArrayLength) {
       
   341             throw new ImageLayoutException("Invalid image layout");
       
   342         }
       
   343     }
       
   344 
       
   345     static int safeAdd(int a, int b) throws ImageLayoutException {
       
   346         long res = a;
       
   347         res += b;
       
   348         if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
       
   349             throw new ImageLayoutException("Invalid image layout");
       
   350         }
       
   351         return (int)res;
       
   352     }
       
   353 
       
   354     static int safeMult(int a, int b) throws ImageLayoutException {
       
   355         long res = a;
       
   356         res *= b;
       
   357         if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
       
   358             throw new ImageLayoutException("Invalid image layout");
       
   359         }
       
   360         return (int)res;
       
   361     }
       
   362 
       
   363     public static class ImageLayoutException extends Exception {
       
   364         public ImageLayoutException(String message) {
       
   365             super(message);
       
   366         }
       
   367     }
   296     public static LCMSImageLayout createImageLayout(Raster r) {
   368     public static LCMSImageLayout createImageLayout(Raster r) {
   297         LCMSImageLayout l = new LCMSImageLayout();
   369         LCMSImageLayout l = new LCMSImageLayout();
   298         if (r instanceof ByteComponentRaster) {
   370         if (r instanceof ByteComponentRaster) {
   299             ByteComponentRaster br = (ByteComponentRaster)r;
   371             ByteComponentRaster br = (ByteComponentRaster)r;
   300 
   372