home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / image / MultiPixelPackedSampleModel.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  15.4 KB  |  468 lines

  1. /*
  2.  * @(#)MultiPixelPackedSampleModel.java    1.12 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. /* ****************************************************************
  16.  ******************************************************************
  17.  ******************************************************************
  18.  *** COPYRIGHT (c) Eastman Kodak Company, 1997
  19.  *** As  an unpublished  work pursuant to Title 17 of the United
  20.  *** States Code.  All rights reserved.
  21.  ******************************************************************
  22.  ******************************************************************
  23.  ******************************************************************/
  24.  
  25. package java.awt.image;
  26.  
  27. /**
  28.  * This class extends SampleModel.  It only stores one-banded images,
  29.  * but it can pack multiple one-sample pixels into one data element.
  30.  * Note that pixels are not allowed to span data element.  In addition,
  31.  * each pixel must be a power of 2 number of bits and a power of 2
  32.  * number of pixels must fit exactly in one data element.  Pixel bit stride
  33.  * is equal to the number of bits per pixel.  Scanline stride is in
  34.  * data elements so the last data element may be padded with unused pixels.
  35.  * Data bit offset must be a multiple of pixel bit stride.
  36.  */
  37.  
  38. public class MultiPixelPackedSampleModel extends SampleModel
  39. {
  40.     /** The number of bits from one pixel to the next. */
  41.     int pixelBitStride;
  42.  
  43.     /** Bitmask that extracts the rightmost pixel of a data element. */
  44.     int bitMask;
  45.  
  46.     /** 
  47.       * The number of pixels that fit in a data Element.  Also used 
  48.       * as the number of bits per pixel.
  49.       */
  50.     int pixelsPerDataElement;    
  51.  
  52.     /** The size of a data element in bits. */
  53.     int dataElementSize;
  54.  
  55.     /** The bitOffset into the dataArray where the first pixel begins. */
  56.     int dataBitOffset;
  57.  
  58.     /** ScanlineStride of the data buffer described in data array elements. */
  59.     int scanlineStride;
  60.  
  61.     /**
  62.      * Constructs a MultiPixelPackedSampleModel with the given data type, 
  63.      * width, height and number of bits per pixel.
  64.      * @param dataType  The data type for storing samples.
  65.      * @param w     The width (in pixels) of the region of
  66.      * image data described.
  67.      * @param h     The height (in pixels) of the region of
  68.      * image data described.
  69.      * @param numofBits The pixelBitStride for  the region of image data
  70.      * described.    
  71.      */
  72.     public MultiPixelPackedSampleModel(int dataType, 
  73.                                        int w, 
  74.                                        int h, 
  75.                                        int numberOfBits) {
  76.         this(dataType,w,h,
  77.              numberOfBits,
  78.             (w*numberOfBits+DataBuffer.sizeOf(dataType)-1)/
  79.                 DataBuffer.sizeOf(dataType),
  80.              0);
  81.     }
  82.  
  83.     /**
  84.      * Constructs a MultiPixelPackedSampleModel with given data type, width,
  85.      * height, number of bits per pixel, scanline stride and data bit
  86.      * offset.
  87.      * @param dataType  The data type for storing samples. 
  88.      * @param w     The width (in pixels) of the region of
  89.      * image data described.
  90.      * @param h     The height (in pixels) of the region of
  91.      * image data described.
  92.      * @param pixelBitStride  The pixelBitStride of the region of image data
  93.      * described.    
  94.      * @param scanlineStride The line stride of the region of the
  95.      * image data described.
  96.      * @param dataBitOffset The data bit offset for the region of image
  97.      * data described.
  98.      */
  99.     public MultiPixelPackedSampleModel(int dataType, int w, int h, 
  100.                                        int pixelBitStride, 
  101.                                        int scanlineStride,
  102.                                        int dataBitOffset) {
  103.         super(dataType, w, h, 1);
  104.         this.dataType = dataType;
  105.         this.pixelBitStride = pixelBitStride;
  106.         this.scanlineStride = scanlineStride;
  107.         this.dataBitOffset = dataBitOffset;
  108.         this.dataElementSize = DataBuffer.sizeOf(dataType);
  109.         this.pixelsPerDataElement = dataElementSize/pixelBitStride;
  110.         if (pixelsPerDataElement*pixelBitStride != dataElementSize) {
  111.            throw new RasterFormatException("MultiPixelPackedSampleModel " + 
  112.                                              "does not allow pixels to " +
  113.                                              "span byte boundaries");
  114.         }
  115.         this.bitMask = (1 << pixelBitStride) - 1;
  116.     }
  117.  
  118.  
  119.     /**
  120.      * Creates a new SinglePackedSampleModel with the requested 
  121.      * width and height.
  122.      */
  123.     public SampleModel createCompatibleSampleModel(int w, int h) {
  124.       SampleModel sampleModel = 
  125.             new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
  126.       return sampleModel;
  127.     }
  128.     
  129.     /** 
  130.      * Creates a DataBuffer of the correct type big enough to hold all 
  131.      * pixels described by this MultiPixelPackedSampleModel.
  132.      */
  133.     public DataBuffer createCompatibleDataBuffer() {
  134.     DataBuffer dataBuffer = null;
  135.  
  136.     int size = (int)scanlineStride*height;
  137.     switch (dataType) {
  138.     case DataBuffer.BYTE_DATA:
  139.         dataBuffer = new DataBufferByte(size);
  140.         break;
  141.     case DataBuffer.SHORT_DATA:
  142.         dataBuffer = new DataBufferShort(size);
  143.         break;
  144.     case DataBuffer.INT_DATA:
  145.         dataBuffer = new DataBufferInt(size);
  146.         break;      
  147.     }
  148.     return dataBuffer;
  149.     }
  150.  
  151.     /** 
  152.      * Creates a DataBuffer of the correct type big enough to hold all 
  153.      * pixels described by this MultiPixelPackedSampleModel with
  154.      * the desired height and width.
  155.      */
  156.     public DataBuffer createCompatibleDataBuffer(int desiredWidth,
  157.                                                  int desiredHeight) {
  158.        DataBuffer dataBuffer = null;
  159.  
  160.         int size = (int)(desiredWidth*desiredHeight*numBands);
  161.         switch (dataType) {
  162.         case DataBuffer.BYTE_DATA:
  163.             dataBuffer = new DataBufferByte(size);
  164.             break;
  165.         case DataBuffer.SHORT_DATA:
  166.             dataBuffer = new DataBufferShort(size);
  167.             break;
  168.         case DataBuffer.INT_DATA:
  169.             dataBuffer = new DataBufferInt(size);
  170.             break;
  171.         }
  172.         return dataBuffer;
  173.     }
  174.  
  175.  
  176.     /** Returns the size of a pixel in bits.  This is equal to the
  177.       * pixel bit stride. 
  178.       */
  179.     public int getPixelBitSize() {
  180.     int bitSize = 0;
  181.     int sampleSize[] = getSampleSize();
  182.     for (int i=0; i<sampleSize.length; i++) {
  183.         bitSize += sampleSize[i];
  184.     }
  185.  
  186.     return bitSize;
  187.     }
  188.  
  189.     /** Returns the number of data elements required to store one pixel. */ 
  190.     public int getNumDataElements() {
  191.     return 1;
  192.     }
  193.     
  194.     /** Returns the size of all bands in bits. */
  195.     public int[] getSampleSize() {
  196.         int sampleSize[] = {pixelBitStride};
  197.     return sampleSize;
  198.     }
  199.  
  200.     /** Returns the size of the requested bands in bits. */
  201.     public int getSampleSize(int band) {
  202.     return pixelBitStride;
  203.     }
  204.  
  205.     /** Returns the offset (in data array elements) of pixel (x,y). */
  206.     public long getOffset(int x, int y) {
  207.     long offset = y * scanlineStride;
  208.         offset +=  (x*pixelBitStride+dataBitOffset)/dataElementSize;
  209.     return offset;
  210.     }
  211.  
  212.     /**
  213.      *  Returns offset in bits of the xth pixel of a scanline into the
  214.      *  data element in which it's stored.
  215.      */
  216.     public int getBitOffset(int x){
  217.        return  (x*pixelBitStride+dataBitOffset)%dataElementSize;
  218.     }
  219.  
  220.     /** Returns the scanline stride. */ 
  221.     public int getScanlineStride() {
  222.         return scanlineStride;
  223.     }
  224.  
  225.     /** Returns the pixel bit stride in bits.  Same as pixel bit size. */ 
  226.     public int getPixelBitStride() {
  227.         return pixelBitStride;
  228.     }
  229.  
  230.     /** Returns the data bit offset in bits. */
  231.     public int getDataBitOffset() {
  232.         return dataBitOffset;
  233.     }
  234.  
  235.     /** Returns the tranfer type of the data */
  236.     public int getTransferType() {
  237.     if (pixelBitStride > 16)
  238.         return DataBuffer.INT_DATA;
  239.     else if (pixelBitStride > 8)
  240.         return DataBuffer.SHORT_DATA;
  241.     else
  242.         return DataBuffer.BYTE_DATA;
  243.     }
  244.  
  245.     /**
  246.      * This creates a new SampleModel with the requested physical
  247.      * width and height and with a subset of the components of this
  248.      * SampleModel.
  249.      */
  250.     public SampleModel createSubsetSampleModel(int w, int h, int bands[]) {
  251.         if (bands != null) {
  252.        if (bands.length != 1)
  253.         throw new RasterFormatException("MultiPixelPackedSampleModel has "
  254.                         + "only one band.");
  255.         }
  256.     SampleModel sm = createCompatibleSampleModel(w, h);
  257.     return sm;
  258.     }
  259.  
  260.     /** 
  261.      * Returns the sample in a specified band for a pixel as an int.
  262.      * @param x     The X coordinate of the pixel location
  263.      * @param y     The Y coordinate of the pixel location
  264.      * @param b     The band to return (assumed to be 0)
  265.      * @param data      The DataBuffer where image data is stored.
  266.      */
  267.     public int getSample(int x, int y, int b, DataBuffer data) {
  268.         int bitnum = dataBitOffset + x*pixelBitStride;
  269.         int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
  270.         int shift = dataElementSize - (bitnum & (dataElementSize-1)) 
  271.                     - pixelBitStride;
  272.         return (element >> shift) & bitMask;
  273.     }
  274.  
  275.     /** 
  276.      * Sets a sample in the DataBuffer using an int for input.
  277.      * @param x     The X coordinate of the pixel location
  278.      * @param y     The Y coordinate of the pixel location
  279.      * @param b     The band to return (assumed to be 0)
  280.      * @param s     The input sample as an int
  281.      * @param data     The DataBuffer where image data is stored
  282.      */
  283.     public void setSample(int x, int y, int b, int s,
  284.               DataBuffer data) {
  285.         int bitnum = dataBitOffset + x * pixelBitStride;
  286.         int index = y * scanlineStride + (bitnum / dataElementSize);
  287.         int shift = dataElementSize - (bitnum & (dataElementSize-1))
  288.                     - pixelBitStride;
  289.         int element = data.getElem(index);
  290.         element &= ~(bitMask << shift);
  291.         element |= (s & bitMask) << shift;
  292.         data.setElem(index,element);
  293.     }
  294.  
  295.     /** 
  296.      * Returns the pixel data in an array of primitives that can be byte,
  297.      * short or int. Which primitive type is returned depends on
  298.      * the transfer type. Data is returned in the packed format,
  299.      * thus increasing efficiency for data transfers. Generally, obj
  300.      * should be passed in as null, so that the Object will be created
  301.      * automatically and will be of the right primitive data type.
  302.      * <pre>
  303.      *          MultiPixelPackedSampleModel mppsm1, mppsm2;
  304.      *         DataBufferInt db1, db2;
  305.      *          mppsm2.setPixelData(x, y, mppsm1.getPixelData(x, y, null, db1), db2);
  306.      * </pre>
  307.      * @param x     The X coordinate of the pixel location.
  308.      * @param y     The Y coordinate of the pixel location.
  309.      * @param obj       If non-null, returns the primitive array in this object.
  310.      * @param data      The DataBuffer containing the image data.
  311.      */
  312.     public Object getPixelData(int x, int y, Object obj, DataBuffer data) {
  313.  
  314.     int type = getTransferType();
  315.     int bitnum = dataBitOffset + x*pixelBitStride;
  316.     int shift = dataElementSize - (bitnum & (dataElementSize-1))
  317.                     - pixelBitStride;
  318.     int element = 0;
  319.     
  320.     switch(type) {
  321.  
  322.     case DataBuffer.BYTE_DATA:
  323.  
  324.         byte[] bdata;
  325.         
  326.         if (obj == null)
  327.         bdata = new byte[1];
  328.         else
  329.         bdata = (byte[])obj;
  330.  
  331.         element = data.getElem(y*scanlineStride +
  332.                     bitnum/dataElementSize);
  333.         bdata[0] = (byte)((element >> shift) & bitMask);
  334.  
  335.         obj = (Object)bdata;
  336.         break;
  337.  
  338.     case DataBuffer.SHORT_DATA:
  339.  
  340.         short[] sdata;
  341.         
  342.         if (obj == null)
  343.         sdata = new short[1];
  344.         else
  345.         sdata = (short[])obj;
  346.  
  347.         element = data.getElem(y*scanlineStride +
  348.                    bitnum/dataElementSize);
  349.         sdata[0] = (short)((element >> shift) & bitMask);
  350.         
  351.         obj = (Object)sdata;
  352.         break;
  353.  
  354.     case DataBuffer.INT_DATA:
  355.  
  356.         int[] idata;
  357.         
  358.         if (obj == null)
  359.         idata = new int[1];
  360.         else
  361.         idata = (int[])obj;
  362.  
  363.         element = data.getElem(y*scanlineStride +
  364.                    bitnum/dataElementSize);
  365.         idata[0] = (element >> shift) & bitMask;
  366.  
  367.         obj = (Object)idata;
  368.         break;
  369.     }
  370.  
  371.     return obj;
  372.     }
  373.  
  374.     /**
  375.      * Returns the requested pixel as an int.
  376.      * @param x     The X coordinate of the pixel location.
  377.      * @param y     The Y coordinate of the pixel location.
  378.      * @param data     The DataBuffer where image data is stored.
  379.      */
  380.     public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
  381.         int pixels[];
  382.         if (iArray != null) {
  383.            pixels = iArray;
  384.         } else {
  385.            pixels = new int [numBands];
  386.         }
  387.         int bitnum = dataBitOffset + x*pixelBitStride;
  388.         int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
  389.         int shift = dataElementSize - (bitnum & (dataElementSize-1))
  390.                     - pixelBitStride;
  391.         pixels[0] = (element >> shift) & bitMask;
  392.         return pixels;
  393.     }
  394.  
  395.     /** 
  396.      * Puts the pixel data from an Object that contains an
  397.      * array of primitives that can be byte,
  398.      * short or int. Which primitive type it contains depends on
  399.      * the transfer type. Data in the Object is in the packed format,
  400.      * thus increasing efficiency for data transfers.
  401.      * <pre>
  402.      *          MultiPixelPackedSampleModel mppsm1, mppsm2;
  403.      *         DataBufferInt db1, db2;
  404.      *          mppsm2.setPixelData(x, y, mppsm1.getPixelData(x, y, null, db1), db2);
  405.      * </pre>
  406.      * @param x     The X coordinate of the pixel location.
  407.      * @param y     The Y coordinate of the pixel location.
  408.      * @param obj       If non-null, returns the primitive array in this object.
  409.      * @param data      The DataBuffer containing the image data.
  410.      */
  411.     public void setPixelData(int x, int y, Object obj, DataBuffer data) {
  412.  
  413.     int type = getTransferType();
  414.     int bitnum = dataBitOffset + x * pixelBitStride;
  415.     int index = y * scanlineStride + (bitnum / dataElementSize);
  416.     int shift = dataElementSize - (bitnum & (dataElementSize-1))
  417.                     - pixelBitStride;
  418.         int element = data.getElem(index);
  419.     element &= ~(bitMask << shift);
  420.     
  421.     switch(type) {
  422.  
  423.     case DataBuffer.BYTE_DATA:
  424.  
  425.         byte[] barray = (byte[])obj;
  426.         element |= ( ((int)(barray[0])&0xff) & bitMask) << shift;
  427.         data.setElem(index, element);
  428.         break;
  429.  
  430.     case DataBuffer.SHORT_DATA:
  431.  
  432.         short[] sarray = (short[])obj;
  433.         element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift;
  434.         data.setElem(index, element);
  435.         break;
  436.         
  437.     case DataBuffer.INT_DATA:    
  438.         
  439.         int[] iarray = (int[])obj;
  440.         element |= (iarray[0] & bitMask) << shift;
  441.         data.setElem(index, element);
  442.         break;
  443.     }
  444.     }
  445.     
  446.     /**
  447.      * Sets a pixel in the DataBuffer using an int for input.
  448.      * @param x     The X coordinate of the pixel location
  449.      * @param y     The Y coordinate of the pixel location
  450.      * @param s     The input sample as an int
  451.      * @param data     The DataBuffer where image data is stored
  452.      */
  453.     public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
  454.         int bitnum = dataBitOffset + x * pixelBitStride;
  455.         int index = y * scanlineStride + (bitnum / dataElementSize);
  456.         int shift = dataElementSize - (bitnum & (dataElementSize-1))
  457.                     - pixelBitStride;
  458.         int element = data.getElem(index);
  459.         element &= ~(bitMask << shift);
  460.         element |= (iArray[0] & bitMask) << shift;
  461.         data.setElem(index,element);
  462.     }
  463.  
  464.  
  465. }
  466.  
  467.  
  468.