Home » openjdk-7 » java » awt » image » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2010, 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   /* ****************************************************************
   27    ******************************************************************
   28    ******************************************************************
   29    *** COPYRIGHT (c) Eastman Kodak Company, 1997
   30    *** As  an unpublished  work pursuant to Title 17 of the United
   31    *** States Code.  All rights reserved.
   32    ******************************************************************
   33    ******************************************************************
   34    ******************************************************************/
   35   
   36   package java.awt.image;
   37   
   38   import java.util.Arrays;
   39   
   40   /**
   41    *  This class represents pixel data packed such that the N samples which make
   42    *  up a single pixel are stored in a single data array element, and each data
   43    *  data array element holds samples for only one pixel.
   44    *  This class supports
   45    *  {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
   46    *  {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
   47    *  {@link DataBuffer#TYPE_INT TYPE_INT} data types.
   48    *  All data array elements reside
   49    *  in the first bank of a DataBuffer.  Accessor methods are provided so
   50    *  that the image data can be manipulated directly. Scanline stride is the
   51    *  number of data array elements between a given sample and the corresponding
   52    *  sample in the same column of the next scanline. Bit masks are the masks
   53    *  required to extract the samples representing the bands of the pixel.
   54    *  Bit offsets are the offsets in bits into the data array
   55    *  element of the samples representing the bands of the pixel.
   56    * <p>
   57    * The following code illustrates extracting the bits of the sample
   58    * representing band <code>b</code> for pixel <code>x,y</code>
   59    * from DataBuffer <code>data</code>:
   60    * <pre>
   61    *      int sample = data.getElem(y * scanlineStride + x);
   62    *      sample = (sample & bitMasks[b]) >>> bitOffsets[b];
   63    * </pre>
   64    */
   65   
   66   public class SinglePixelPackedSampleModel extends SampleModel
   67   {
   68       /** Bit masks for all bands of the image data. */
   69       private int bitMasks[];
   70   
   71       /** Bit Offsets for all bands of the image data. */
   72       private int bitOffsets[];
   73   
   74       /** Bit sizes for all the bands of the image data. */
   75       private int bitSizes[];
   76   
   77       /** Maximum bit size. */
   78       private int maxBitSize;
   79   
   80       /** Line stride of the region of image data described by this
   81        *  SinglePixelPackedSampleModel.
   82        */
   83       private int scanlineStride;
   84   
   85       private static native void initIDs();
   86       static {
   87           ColorModel.loadLibraries();
   88           initIDs();
   89       }
   90   
   91       /**
   92        * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
   93        * Each sample is stored in a data array element in the position of
   94        * its corresponding bit mask.  Each bit mask must be contiguous and
   95        * masks must not overlap. Bit masks exceeding data type capacity are
   96        * truncated.
   97        * @param dataType  The data type for storing samples.
   98        * @param w         The width (in pixels) of the region of the
   99        *                  image data described.
  100        * @param h         The height (in pixels) of the region of the
  101        *                  image data described.
  102        * @param bitMasks  The bit masks for all bands.
  103        * @throws IllegalArgumentException if <code>dataType</code> is not
  104        *         either <code>DataBuffer.TYPE_BYTE</code>,
  105        *         <code>DataBuffer.TYPE_USHORT</code>, or
  106        *         <code>DataBuffer.TYPE_INT</code>
  107        */
  108       public SinglePixelPackedSampleModel(int dataType, int w, int h,
  109                                      int bitMasks[]) {
  110           this(dataType, w, h, w, bitMasks);
  111           if (dataType != DataBuffer.TYPE_BYTE &&
  112               dataType != DataBuffer.TYPE_USHORT &&
  113               dataType != DataBuffer.TYPE_INT) {
  114               throw new IllegalArgumentException("Unsupported data type "+
  115                                                  dataType);
  116           }
  117       }
  118   
  119       /**
  120        * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
  121        * and a scanline stride equal to scanlineStride data array elements.
  122        * Each sample is stored in a data array element in the position of
  123        * its corresponding bit mask.  Each bit mask must be contiguous and
  124        * masks must not overlap. Bit masks exceeding data type capacity are
  125        * truncated.
  126        * @param dataType  The data type for storing samples.
  127        * @param w         The width (in pixels) of the region of
  128        *                  image data described.
  129        * @param h         The height (in pixels) of the region of
  130        *                  image data described.
  131        * @param scanlineStride The line stride of the image data.
  132        * @param bitMasks The bit masks for all bands.
  133        * @throws IllegalArgumentException if <code>w</code> or
  134        *         <code>h</code> is not greater than 0
  135        * @throws IllegalArgumentException if any mask in
  136        *         <code>bitMask</code> is not contiguous
  137        * @throws IllegalArgumentException if <code>dataType</code> is not
  138        *         either <code>DataBuffer.TYPE_BYTE</code>,
  139        *         <code>DataBuffer.TYPE_USHORT</code>, or
  140        *         <code>DataBuffer.TYPE_INT</code>
  141        */
  142       public SinglePixelPackedSampleModel(int dataType, int w, int h,
  143                                      int scanlineStride, int bitMasks[]) {
  144           super(dataType, w, h, bitMasks.length);
  145           if (dataType != DataBuffer.TYPE_BYTE &&
  146               dataType != DataBuffer.TYPE_USHORT &&
  147               dataType != DataBuffer.TYPE_INT) {
  148               throw new IllegalArgumentException("Unsupported data type "+
  149                                                  dataType);
  150           }
  151           this.dataType = dataType;
  152           this.bitMasks = (int[]) bitMasks.clone();
  153           this.scanlineStride = scanlineStride;
  154   
  155           this.bitOffsets = new int[numBands];
  156           this.bitSizes = new int[numBands];
  157   
  158           int maxMask = (int)((1L << DataBuffer.getDataTypeSize(dataType)) - 1);
  159   
  160           this.maxBitSize = 0;
  161           for (int i=0; i<numBands; i++) {
  162               int bitOffset = 0, bitSize = 0, mask;
  163               this.bitMasks[i] &= maxMask;
  164               mask = this.bitMasks[i];
  165               if (mask != 0) {
  166                   while ((mask & 1) == 0) {
  167                       mask = mask >>> 1;
  168                       bitOffset++;
  169                   }
  170                   while ((mask & 1) == 1) {
  171                       mask = mask >>> 1;
  172                       bitSize++;
  173                   }
  174                   if (mask != 0) {
  175                       throw new IllegalArgumentException("Mask "+bitMasks[i]+
  176                                                          " must be contiguous");
  177                   }
  178               }
  179               bitOffsets[i] = bitOffset;
  180               bitSizes[i] = bitSize;
  181               if (bitSize > maxBitSize) {
  182                   maxBitSize = bitSize;
  183               }
  184           }
  185       }
  186   
  187       /**
  188        * Returns the number of data elements needed to transfer one pixel
  189        * via the getDataElements and setDataElements methods.
  190        * For a SinglePixelPackedSampleModel, this is one.
  191        */
  192       public int getNumDataElements() {
  193           return 1;
  194       }
  195   
  196       /**
  197        * Returns the size of the buffer (in data array elements)
  198        * needed for a data buffer that matches this
  199        * SinglePixelPackedSampleModel.
  200        */
  201       private long getBufferSize() {
  202         long size = scanlineStride * (height-1) + width;
  203         return size;
  204       }
  205   
  206       /**
  207        * Creates a new SinglePixelPackedSampleModel with the specified
  208        * width and height.  The new SinglePixelPackedSampleModel will have the
  209        * same storage data type and bit masks as this
  210        * SinglePixelPackedSampleModel.
  211        * @param w the width of the resulting <code>SampleModel</code>
  212        * @param h the height of the resulting <code>SampleModel</code>
  213        * @return a <code>SinglePixelPackedSampleModel</code> with the
  214        *         specified width and height.
  215        * @throws IllegalArgumentException if <code>w</code> or
  216        *         <code>h</code> is not greater than 0
  217        */
  218       public SampleModel createCompatibleSampleModel(int w, int h) {
  219         SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
  220                                                                 bitMasks);
  221         return sampleModel;
  222       }
  223   
  224       /**
  225        * Creates a DataBuffer that corresponds to this
  226        * SinglePixelPackedSampleModel.  The DataBuffer's data type and size
  227        * will be consistent with this SinglePixelPackedSampleModel.  The
  228        * DataBuffer will have a single bank.
  229        */
  230       public DataBuffer createDataBuffer() {
  231           DataBuffer dataBuffer = null;
  232   
  233           int size = (int)getBufferSize();
  234           switch (dataType) {
  235           case DataBuffer.TYPE_BYTE:
  236               dataBuffer = new DataBufferByte(size);
  237               break;
  238           case DataBuffer.TYPE_USHORT:
  239               dataBuffer = new DataBufferUShort(size);
  240               break;
  241           case DataBuffer.TYPE_INT:
  242               dataBuffer = new DataBufferInt(size);
  243               break;
  244           }
  245           return dataBuffer;
  246       }
  247   
  248       /** Returns the number of bits per sample for all bands. */
  249       public int[] getSampleSize() {
  250           return bitSizes.clone();
  251       }
  252   
  253       /** Returns the number of bits per sample for the specified band. */
  254       public int getSampleSize(int band) {
  255           return bitSizes[band];
  256       }
  257   
  258       /** Returns the offset (in data array elements) of pixel (x,y).
  259        *  The data element containing pixel <code>x,y</code>
  260        *  can be retrieved from a DataBuffer <code>data</code> with a
  261        *  SinglePixelPackedSampleModel <code>sppsm</code> as:
  262        * <pre>
  263        *        data.getElem(sppsm.getOffset(x, y));
  264        * </pre>
  265        * @param x the X coordinate of the specified pixel
  266        * @param y the Y coordinate of the specified pixel
  267        * @return the offset of the specified pixel.
  268        */
  269       public int getOffset(int x, int y) {
  270           int offset = y * scanlineStride + x;
  271           return offset;
  272       }
  273   
  274       /** Returns the bit offsets into the data array element representing
  275        *  a pixel for all bands.
  276        *  @return the bit offsets representing a pixel for all bands.
  277        */
  278       public int [] getBitOffsets() {
  279         return (int[])bitOffsets.clone();
  280       }
  281   
  282       /** Returns the bit masks for all bands.
  283        *  @return the bit masks for all bands.
  284        */
  285       public int [] getBitMasks() {
  286         return (int[])bitMasks.clone();
  287       }
  288   
  289       /** Returns the scanline stride of this SinglePixelPackedSampleModel.
  290        *  @return the scanline stride of this
  291        *          <code>SinglePixelPackedSampleModel</code>.
  292        */
  293       public int getScanlineStride() {
  294         return scanlineStride;
  295       }
  296   
  297       /**
  298        * This creates a new SinglePixelPackedSampleModel with a subset of the
  299        * bands of this SinglePixelPackedSampleModel.  The new
  300        * SinglePixelPackedSampleModel can be used with any DataBuffer that the
  301        * existing SinglePixelPackedSampleModel can be used with.  The new
  302        * SinglePixelPackedSampleModel/DataBuffer combination will represent
  303        * an image with a subset of the bands of the original
  304        * SinglePixelPackedSampleModel/DataBuffer combination.
  305        * @exception RasterFormatException if the length of the bands argument is
  306        *                                  greater than the number of bands in
  307        *                                  the sample model.
  308        */
  309       public SampleModel createSubsetSampleModel(int bands[]) {
  310           if (bands.length > numBands)
  311               throw new RasterFormatException("There are only " +
  312                                               numBands +
  313                                               " bands");
  314           int newBitMasks[] = new int[bands.length];
  315           for (int i=0; i<bands.length; i++)
  316               newBitMasks[i] = bitMasks[bands[i]];
  317   
  318           return new SinglePixelPackedSampleModel(this.dataType, width, height,
  319                                              this.scanlineStride, newBitMasks);
  320       }
  321   
  322       /**
  323        * Returns data for a single pixel in a primitive array of type
  324        * TransferType.  For a SinglePixelPackedSampleModel, the array will
  325        * have one element, and the type will be the same as the storage
  326        * data type.  Generally, obj
  327        * should be passed in as null, so that the Object will be created
  328        * automatically and will be of the right primitive data type.
  329        * <p>
  330        * The following code illustrates transferring data for one pixel from
  331        * DataBuffer <code>db1</code>, whose storage layout is described by
  332        * SinglePixelPackedSampleModel <code>sppsm1</code>, to
  333        * DataBuffer <code>db2</code>, whose storage layout is described by
  334        * SinglePixelPackedSampleModel <code>sppsm2</code>.
  335        * The transfer will generally be more efficient than using
  336        * getPixel/setPixel.
  337        * <pre>
  338        *       SinglePixelPackedSampleModel sppsm1, sppsm2;
  339        *       DataBufferInt db1, db2;
  340        *       sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  341        *                              db1), db2);
  342        * </pre>
  343        * Using getDataElements/setDataElements to transfer between two
  344        * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  345        * the same number of bands, corresponding bands have the same number of
  346        * bits per sample, and the TransferTypes are the same.
  347        * <p>
  348        * If obj is non-null, it should be a primitive array of type TransferType.
  349        * Otherwise, a ClassCastException is thrown.  An
  350        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  351        * not in bounds, or if obj is non-null and is not large enough to hold
  352        * the pixel data.
  353        * @param x         The X coordinate of the pixel location.
  354        * @param y         The Y coordinate of the pixel location.
  355        * @param obj       If non-null, a primitive array in which to return
  356        *                  the pixel data.
  357        * @param data      The DataBuffer containing the image data.
  358        * @return the data for the specified pixel.
  359        * @see #setDataElements(int, int, Object, DataBuffer)
  360        */
  361       public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
  362           // Bounds check for 'b' will be performed automatically
  363           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  364               throw new ArrayIndexOutOfBoundsException
  365                   ("Coordinate out of bounds!");
  366           }
  367   
  368           int type = getTransferType();
  369   
  370           switch(type) {
  371   
  372           case DataBuffer.TYPE_BYTE:
  373   
  374               byte[] bdata;
  375   
  376               if (obj == null)
  377                   bdata = new byte[1];
  378               else
  379                   bdata = (byte[])obj;
  380   
  381               bdata[0] = (byte)data.getElem(y * scanlineStride + x);
  382   
  383               obj = (Object)bdata;
  384               break;
  385   
  386           case DataBuffer.TYPE_USHORT:
  387   
  388               short[] sdata;
  389   
  390               if (obj == null)
  391                   sdata = new short[1];
  392               else
  393                   sdata = (short[])obj;
  394   
  395               sdata[0] = (short)data.getElem(y * scanlineStride + x);
  396   
  397               obj = (Object)sdata;
  398               break;
  399   
  400           case DataBuffer.TYPE_INT:
  401   
  402               int[] idata;
  403   
  404               if (obj == null)
  405                   idata = new int[1];
  406               else
  407                   idata = (int[])obj;
  408   
  409               idata[0] = data.getElem(y * scanlineStride + x);
  410   
  411               obj = (Object)idata;
  412               break;
  413           }
  414   
  415           return obj;
  416       }
  417   
  418       /**
  419        * Returns all samples in for the specified pixel in an int array.
  420        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  421        * not in bounds.
  422        * @param x         The X coordinate of the pixel location.
  423        * @param y         The Y coordinate of the pixel location.
  424        * @param iArray    If non-null, returns the samples in this array
  425        * @param data      The DataBuffer containing the image data.
  426        * @return all samples for the specified pixel.
  427        * @see #setPixel(int, int, int[], DataBuffer)
  428        */
  429       public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
  430           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  431               throw new ArrayIndexOutOfBoundsException
  432                   ("Coordinate out of bounds!");
  433           }
  434           int pixels[];
  435           if (iArray == null) {
  436               pixels = new int [numBands];
  437           } else {
  438               pixels = iArray;
  439           }
  440   
  441           int value = data.getElem(y * scanlineStride + x);
  442           for (int i=0; i<numBands; i++) {
  443               pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
  444           }
  445           return pixels;
  446       }
  447   
  448       /**
  449        * Returns all samples for the specified rectangle of pixels in
  450        * an int array, one sample per array element.
  451        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  452        * not in bounds.
  453        * @param x         The X coordinate of the upper left pixel location.
  454        * @param y         The Y coordinate of the upper left pixel location.
  455        * @param w         The width of the pixel rectangle.
  456        * @param h         The height of the pixel rectangle.
  457        * @param iArray    If non-null, returns the samples in this array.
  458        * @param data      The DataBuffer containing the image data.
  459        * @return all samples for the specified region of pixels.
  460        * @see #setPixels(int, int, int, int, int[], DataBuffer)
  461        */
  462       public int[] getPixels(int x, int y, int w, int h,
  463                              int iArray[], DataBuffer data) {
  464           int x1 = x + w;
  465           int y1 = y + h;
  466   
  467           if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
  468               y < 0 || y >= height || h > height || y1 < 0 || y1 >  height)
  469           {
  470               throw new ArrayIndexOutOfBoundsException
  471                   ("Coordinate out of bounds!");
  472           }
  473           int pixels[];
  474           if (iArray != null) {
  475              pixels = iArray;
  476           } else {
  477              pixels = new int [w*h*numBands];
  478           }
  479           int lineOffset = y*scanlineStride + x;
  480           int dstOffset = 0;
  481   
  482           for (int i = 0; i < h; i++) {
  483              for (int j = 0; j < w; j++) {
  484                 int value = data.getElem(lineOffset+j);
  485                 for (int k=0; k < numBands; k++) {
  486                     pixels[dstOffset++] =
  487                        ((value & bitMasks[k]) >>> bitOffsets[k]);
  488                 }
  489              }
  490              lineOffset += scanlineStride;
  491           }
  492           return pixels;
  493       }
  494   
  495       /**
  496        * Returns as int the sample in a specified band for the pixel
  497        * located at (x,y).
  498        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  499        * not in bounds.
  500        * @param x         The X coordinate of the pixel location.
  501        * @param y         The Y coordinate of the pixel location.
  502        * @param b         The band to return.
  503        * @param data      The DataBuffer containing the image data.
  504        * @return the sample in a specified band for the specified
  505        *         pixel.
  506        * @see #setSample(int, int, int, int, DataBuffer)
  507        */
  508       public int getSample(int x, int y, int b, DataBuffer data) {
  509           // Bounds check for 'b' will be performed automatically
  510           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  511               throw new ArrayIndexOutOfBoundsException
  512                   ("Coordinate out of bounds!");
  513           }
  514           int sample = data.getElem(y * scanlineStride + x);
  515           return ((sample & bitMasks[b]) >>> bitOffsets[b]);
  516       }
  517   
  518       /**
  519        * Returns the samples for a specified band for the specified rectangle
  520        * of pixels in an int array, one sample per array element.
  521        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  522        * not in bounds.
  523        * @param x         The X coordinate of the upper left pixel location.
  524        * @param y         The Y coordinate of the upper left pixel location.
  525        * @param w         The width of the pixel rectangle.
  526        * @param h         The height of the pixel rectangle.
  527        * @param b         The band to return.
  528        * @param iArray    If non-null, returns the samples in this array.
  529        * @param data      The DataBuffer containing the image data.
  530        * @return the samples for the specified band for the specified
  531        *         region of pixels.
  532        * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
  533        */
  534       public int[] getSamples(int x, int y, int w, int h, int b,
  535                              int iArray[], DataBuffer data) {
  536           // Bounds check for 'b' will be performed automatically
  537           if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  538               throw new ArrayIndexOutOfBoundsException
  539                   ("Coordinate out of bounds!");
  540           }
  541           int samples[];
  542           if (iArray != null) {
  543              samples = iArray;
  544           } else {
  545              samples = new int [w*h];
  546           }
  547           int lineOffset = y*scanlineStride + x;
  548           int dstOffset = 0;
  549   
  550           for (int i = 0; i < h; i++) {
  551              for (int j = 0; j < w; j++) {
  552                 int value = data.getElem(lineOffset+j);
  553                 samples[dstOffset++] =
  554                    ((value & bitMasks[b]) >>> bitOffsets[b]);
  555              }
  556              lineOffset += scanlineStride;
  557           }
  558           return samples;
  559       }
  560   
  561       /**
  562        * Sets the data for a single pixel in the specified DataBuffer from a
  563        * primitive array of type TransferType.  For a
  564        * SinglePixelPackedSampleModel, only the first element of the array
  565        * will hold valid data, and the type of the array must be the same as
  566        * the storage data type of the SinglePixelPackedSampleModel.
  567        * <p>
  568        * The following code illustrates transferring data for one pixel from
  569        * DataBuffer <code>db1</code>, whose storage layout is described by
  570        * SinglePixelPackedSampleModel <code>sppsm1</code>,
  571        * to DataBuffer <code>db2</code>, whose storage layout is described by
  572        * SinglePixelPackedSampleModel <code>sppsm2</code>.
  573        * The transfer will generally be more efficient than using
  574        * getPixel/setPixel.
  575        * <pre>
  576        *       SinglePixelPackedSampleModel sppsm1, sppsm2;
  577        *       DataBufferInt db1, db2;
  578        *       sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
  579        *                              db1), db2);
  580        * </pre>
  581        * Using getDataElements/setDataElements to transfer between two
  582        * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
  583        * the same number of bands, corresponding bands have the same number of
  584        * bits per sample, and the TransferTypes are the same.
  585        * <p>
  586        * obj must be a primitive array of type TransferType.  Otherwise,
  587        * a ClassCastException is thrown.  An
  588        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  589        * not in bounds, or if obj is not large enough to hold the pixel data.
  590        * @param x         The X coordinate of the pixel location.
  591        * @param y         The Y coordinate of the pixel location.
  592        * @param obj       A primitive array containing pixel data.
  593        * @param data      The DataBuffer containing the image data.
  594        * @see #getDataElements(int, int, Object, DataBuffer)
  595        */
  596       public void setDataElements(int x, int y, Object obj, DataBuffer data) {
  597           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  598               throw new ArrayIndexOutOfBoundsException
  599                   ("Coordinate out of bounds!");
  600           }
  601   
  602           int type = getTransferType();
  603   
  604           switch(type) {
  605   
  606           case DataBuffer.TYPE_BYTE:
  607   
  608               byte[] barray = (byte[])obj;
  609               data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
  610               break;
  611   
  612           case DataBuffer.TYPE_USHORT:
  613   
  614               short[] sarray = (short[])obj;
  615               data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
  616               break;
  617   
  618           case DataBuffer.TYPE_INT:
  619   
  620               int[] iarray = (int[])obj;
  621               data.setElem(y*scanlineStride+x, iarray[0]);
  622               break;
  623           }
  624       }
  625   
  626       /**
  627        * Sets a pixel in the DataBuffer using an int array of samples for input.
  628        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  629        * not in bounds.
  630        * @param x         The X coordinate of the pixel location.
  631        * @param y         The Y coordinate of the pixel location.
  632        * @param iArray    The input samples in an int array.
  633        * @param data      The DataBuffer containing the image data.
  634        * @see #getPixel(int, int, int[], DataBuffer)
  635        */
  636       public void setPixel(int x, int y,
  637                            int iArray[],
  638                            DataBuffer data) {
  639           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  640               throw new ArrayIndexOutOfBoundsException
  641                   ("Coordinate out of bounds!");
  642           }
  643           int lineOffset = y * scanlineStride + x;
  644           int value = data.getElem(lineOffset);
  645           for (int i=0; i < numBands; i++) {
  646               value &= ~bitMasks[i];
  647               value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
  648           }
  649           data.setElem(lineOffset, value);
  650       }
  651   
  652       /**
  653        * Sets all samples for a rectangle of pixels from an int array containing
  654        * one sample per array element.
  655        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  656        * not in bounds.
  657        * @param x         The X coordinate of the upper left pixel location.
  658        * @param y         The Y coordinate of the upper left pixel location.
  659        * @param w         The width of the pixel rectangle.
  660        * @param h         The height of the pixel rectangle.
  661        * @param iArray    The input samples in an int array.
  662        * @param data      The DataBuffer containing the image data.
  663        * @see #getPixels(int, int, int, int, int[], DataBuffer)
  664        */
  665       public void setPixels(int x, int y, int w, int h,
  666                             int iArray[], DataBuffer data) {
  667           int x1 = x + w;
  668           int y1 = y + h;
  669   
  670           if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
  671               y < 0 || y >= height || h > height || y1 < 0 || y1 >  height)
  672           {
  673               throw new ArrayIndexOutOfBoundsException
  674                   ("Coordinate out of bounds!");
  675           }
  676   
  677           int lineOffset = y*scanlineStride + x;
  678           int srcOffset = 0;
  679   
  680           for (int i = 0; i < h; i++) {
  681              for (int j = 0; j < w; j++) {
  682                  int value = data.getElem(lineOffset+j);
  683                  for (int k=0; k < numBands; k++) {
  684                      value &= ~bitMasks[k];
  685                      int srcValue = iArray[srcOffset++];
  686                      value |= ((srcValue << bitOffsets[k])
  687                                & bitMasks[k]);
  688                  }
  689                  data.setElem(lineOffset+j, value);
  690              }
  691              lineOffset += scanlineStride;
  692           }
  693       }
  694   
  695       /**
  696        * Sets a sample in the specified band for the pixel located at (x,y)
  697        * in the DataBuffer using an int for input.
  698        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  699        * not in bounds.
  700        * @param x         The X coordinate of the pixel location.
  701        * @param y         The Y coordinate of the pixel location.
  702        * @param b         The band to set.
  703        * @param s         The input sample as an int.
  704        * @param data      The DataBuffer containing the image data.
  705        * @see #getSample(int, int, int, DataBuffer)
  706        */
  707       public void setSample(int x, int y, int b, int s,
  708                             DataBuffer data) {
  709           // Bounds check for 'b' will be performed automatically
  710           if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
  711               throw new ArrayIndexOutOfBoundsException
  712                   ("Coordinate out of bounds!");
  713           }
  714           int value = data.getElem(y*scanlineStride + x);
  715           value &= ~bitMasks[b];
  716           value |= (s << bitOffsets[b]) & bitMasks[b];
  717           data.setElem(y*scanlineStride + x,value);
  718       }
  719   
  720       /**
  721        * Sets the samples in the specified band for the specified rectangle
  722        * of pixels from an int array containing one sample per array element.
  723        * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
  724        * not in bounds.
  725        * @param x         The X coordinate of the upper left pixel location.
  726        * @param y         The Y coordinate of the upper left pixel location.
  727        * @param w         The width of the pixel rectangle.
  728        * @param h         The height of the pixel rectangle.
  729        * @param b         The band to set.
  730        * @param iArray    The input samples in an int array.
  731        * @param data      The DataBuffer containing the image data.
  732        * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
  733        */
  734       public void setSamples(int x, int y, int w, int h, int b,
  735                             int iArray[], DataBuffer data) {
  736           // Bounds check for 'b' will be performed automatically
  737           if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
  738               throw new ArrayIndexOutOfBoundsException
  739                   ("Coordinate out of bounds!");
  740           }
  741           int lineOffset = y*scanlineStride + x;
  742           int srcOffset = 0;
  743   
  744           for (int i = 0; i < h; i++) {
  745              for (int j = 0; j < w; j++) {
  746                 int value = data.getElem(lineOffset+j);
  747                 value &= ~bitMasks[b];
  748                 int sample = iArray[srcOffset++];
  749                 value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
  750                 data.setElem(lineOffset+j,value);
  751              }
  752              lineOffset += scanlineStride;
  753           }
  754       }
  755   
  756       public boolean equals(Object o) {
  757           if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
  758               return false;
  759           }
  760   
  761           SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o;
  762           return this.width == that.width &&
  763               this.height == that.height &&
  764               this.numBands == that.numBands &&
  765               this.dataType == that.dataType &&
  766               Arrays.equals(this.bitMasks, that.bitMasks) &&
  767               Arrays.equals(this.bitOffsets, that.bitOffsets) &&
  768               Arrays.equals(this.bitSizes, that.bitSizes) &&
  769               this.maxBitSize == that.maxBitSize &&
  770               this.scanlineStride == that.scanlineStride;
  771       }
  772   
  773       // If we implement equals() we must also implement hashCode
  774       public int hashCode() {
  775           int hash = 0;
  776           hash = width;
  777           hash <<= 8;
  778           hash ^= height;
  779           hash <<= 8;
  780           hash ^= numBands;
  781           hash <<= 8;
  782           hash ^= dataType;
  783           hash <<= 8;
  784           for (int i = 0; i < bitMasks.length; i++) {
  785               hash ^= bitMasks[i];
  786               hash <<= 8;
  787           }
  788           for (int i = 0; i < bitOffsets.length; i++) {
  789               hash ^= bitOffsets[i];
  790               hash <<= 8;
  791           }
  792           for (int i = 0; i < bitSizes.length; i++) {
  793               hash ^= bitSizes[i];
  794               hash <<= 8;
  795           }
  796           hash ^= maxBitSize;
  797           hash <<= 8;
  798           hash ^= scanlineStride;
  799           return hash;
  800       }
  801   }

Home » openjdk-7 » java » awt » image » [javadoc | source]