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 / SinglePixelPackedSampleModel.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  19.1 KB  |  600 lines

  1. /*
  2.  * @(#)SinglePixelPackedSampleModel.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 stores (packs) the N samples which make
  29.  *  up a single pixel in 1 data array element.  All data array elements reside
  30.  *  in the first bank of a DataBuffer.  Accessor methods are provided so
  31.  *  that the image data can be manipulated directly. Scanlinestride is the
  32.  *  number of data array elements between a given sample and the sample in
  33.  *  the same column of the next scanline. Bit Masks are the masks required
  34.  *  to extract the samples representing the bands of the pixel.
  35.  */
  36.  
  37. public class SinglePixelPackedSampleModel extends SampleModel
  38. {
  39.     /** Bit masks for all bands of the image data. */
  40.     private int bitMasks[];
  41.  
  42.     /** Bit Offsets for all bands of the image data. */
  43.     private int bitOffsets[];
  44.  
  45.     /** Bit sizes for all the bands of the image data. */
  46.     private int bitSizes[];
  47.  
  48.     /** Total bit size. */
  49.     private int totalBitSize;
  50.  
  51.     /** Line stride of the region of image data described by this
  52.      *  SinglePixelPackedSampleModel.
  53.      */
  54.     private int scanlineStride;
  55.  
  56.     /**
  57.      * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
  58.      * Each sample is stored in a data array element in the position of
  59.      * its corresponding bit mask.  Bit masks should be contiguous and
  60.      * should not overlap.
  61.      * @param dataType     The data type for storing samples.
  62.      * @param w     The width (in pixels) of the region of the
  63.      * image data described.
  64.      * @param h     The height (in pixels) of the region of the
  65.      * image data described.
  66.      * @param bitMasks  The bit masks for various bands.
  67.      */
  68.     public SinglePixelPackedSampleModel(int dataType, int w, int h, 
  69.                    int bitMasks[]) {
  70.         this(dataType, w, h, w, bitMasks);
  71.     }
  72.  
  73.     /**
  74.      * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
  75.      * and a scanline stride equal to scanlineStride data array elements.
  76.      * Each sample is stored in a data array element in the position of 
  77.      * its corresponding bit mask.  Bit masks should be contiguous and
  78.      * should not overlap.  
  79.      * @param dataType     The data type for storing samples.
  80.      * @param w     The width (in pixels) of the region of
  81.      * image data described.
  82.      * @param h     The height (in pixels) of the region of
  83.      * image data described.
  84.      * @param scanlineStride The line stride of the region of image
  85.      * data described. 
  86.      * @param bitMasks The bit masks for various bands.
  87.      */
  88.     public SinglePixelPackedSampleModel(int dataType, int w, int h, 
  89.                                    int scanlineStride, int bitMasks[]) {
  90.         super(dataType, w, h, bitMasks.length);
  91.         this.dataType = dataType;
  92.         this.bitMasks = bitMasks;
  93.         this.scanlineStride = scanlineStride;
  94.  
  95.         this.bitOffsets = new int[numBands];
  96.         this.bitSizes = new int[numBands];
  97.  
  98.         this.totalBitSize = 0; 
  99.         for (int i=0; i<numBands; i++) {
  100.             int bitOffset = 0, bitSize = 0, mask;
  101.             mask = bitMasks[i];
  102.  
  103.             if (mask != 0) {
  104.                 while ((mask & 1) == 0) {
  105.                     mask = mask >>> 1;
  106.                     bitOffset++;
  107.                 }
  108.                 while ((mask & 1) == 1) {
  109.                     mask = mask >>> 1;
  110.                     bitSize++;
  111.                 }
  112.             }
  113.             bitOffsets[i] = bitOffset;
  114.             bitSizes[i] = bitSize;
  115.             totalBitSize += bitSize;
  116.         }
  117.     }
  118.  
  119.     /**
  120.      * Returns the number of data elements that are required to store
  121.      * one pixel. For a SinglePixelPackedSampleModel, this is always one.
  122.      */
  123.     public int getNumDataElements() {
  124.     return 1;
  125.     }
  126.     
  127.     /**
  128.      * Returns the size of the buffer (in data array elements)
  129.      * needed for a data buffer that matches this
  130.      * SinglePixelPackedSampleModel.
  131.      */
  132.     private long getBufferSize() {
  133.       long size = width * height;
  134.       return size;
  135.     }
  136.  
  137.     /**
  138.      * This creates a new SinglePixelPackedSampleModel with the specified
  139.      * width and height.  
  140.      */
  141.     public SampleModel createCompatibleSampleModel(int w, int h) {
  142.       SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
  143.                                   bitMasks);
  144.       return sampleModel;
  145.     }
  146.     
  147.     /** 
  148.      * Creates a DataBuffer that corresponds to this SinglePixelPackedSampleModel.
  149.      * The DataBuffer's width and height will match this
  150.      * SinglePixelPackedSampleModel's.
  151.      */
  152.     public DataBuffer createCompatibleDataBuffer() {
  153.     DataBuffer dataBuffer = null;
  154.  
  155.     int size = (int)getBufferSize();
  156.     switch (dataType) {
  157.     case DataBuffer.BYTE_DATA:
  158.         dataBuffer = new DataBufferByte(size);
  159.         break;
  160.     case DataBuffer.SHORT_DATA:
  161.         dataBuffer = new DataBufferShort(size);
  162.         break;
  163.     case DataBuffer.INT_DATA:
  164.         dataBuffer = new DataBufferInt(size);
  165.         break;      
  166.     }
  167.     return dataBuffer;
  168.     }
  169.  
  170.     /**
  171.      * Creates a DataBuffer that corresponds to this SinglePixelPackedSampleModel,
  172.      * with a different width and height.    
  173.      */
  174.     public DataBuffer createCompatibleDataBuffer(int desiredWidth,
  175.                                                  int desiredHeight) {
  176.        DataBuffer dataBuffer = null;
  177.  
  178.         int size = (int)(desiredWidth*desiredHeight*numBands);
  179.         switch (dataType) {
  180.         case DataBuffer.BYTE_DATA:
  181.             dataBuffer = new DataBufferByte(size);
  182.             break;
  183.         case DataBuffer.SHORT_DATA:
  184.             dataBuffer = new DataBufferShort(size);
  185.             break;
  186.         case DataBuffer.INT_DATA:
  187.             dataBuffer = new DataBufferInt(size);
  188.             break;
  189.         }
  190.         return dataBuffer;
  191.     }
  192.  
  193.  
  194.     /** Returns the size of a pixel in bits. */
  195.     public int getPixelBitSize() {
  196.     int bitSize = 0;
  197.     int sampleSize[] = getSampleSize();
  198.     for (int i=0; i<sampleSize.length; i++) {
  199.         bitSize += sampleSize[i];
  200.     }
  201.  
  202.     return bitSize;
  203.     }
  204.  
  205.     /** Returns the size in bits of samples for all bands. */
  206.     public int[] getSampleSize() {
  207.     int mask;
  208.     int sampleSize[] = new int [numBands];
  209.     for (int i=0; i<numBands; i++) {
  210.         sampleSize[i] = 0;
  211.         mask = bitMasks[i] >>> bitOffsets[i];
  212.         while ((mask & 1) != 0) {
  213.         sampleSize[i] ++;
  214.         mask = mask >>> 1;
  215.         }
  216.     }
  217.  
  218.     return sampleSize;
  219.     }
  220.  
  221.     /** Returns the size in bits of samples for the specified band. */
  222.     public int getSampleSize(int band) {
  223.     int sampleSize = 0;
  224.     int mask = bitMasks[band] >>> bitOffsets[band];
  225.     while ((mask & 1) != 0) {
  226.         sampleSize ++;
  227.         mask = mask >>> 1;
  228.     }
  229.       
  230.     return sampleSize;
  231.     }
  232.  
  233.     /** Returns the offset (in data array elements) of pixel (x,y).
  234.      *  A sample of the first band can be retrieved from a dataBuffer
  235.      *  data with a SinglePixelPackedSampleModel sppsm as
  236.      * <pre>
  237.      *        data.getElem(sppsm.getOffset(x, y));
  238.      * </pre>
  239.      */
  240.     public long getOffset(int x, int y) {
  241.     long offset = y * scanlineStride + x;
  242.     return offset;
  243.     }
  244.  
  245.     /** Returns the bit offset into the data array element representing
  246.      *  a pixel for each band. */
  247.     public int [] getBitOffsets() {
  248.       return (int[])bitOffsets.clone();
  249.     }
  250.  
  251.     /** Returns the size in bits of each band. */
  252.     public int [] getBitSizes() {
  253.       return (int[])bitSizes.clone();
  254.     }
  255.  
  256.     /** Returns the bit masks for each band. */
  257.     public int [] getBitMasks() {
  258.       return (int[])bitMasks.clone();
  259.     }
  260.  
  261.     /** Returns the scanline stride of this SinglePixelPackedSampleModel. */ 
  262.     public int getScanlineStride() {
  263.       return scanlineStride;
  264.     }
  265.  
  266.     /** Returns the transfer type of the data */
  267.     public int getTransferType() {
  268.     return dataType;
  269.     }
  270.     
  271.     /**
  272.      * This creates a new SinglePixelPackedSampleModel with the specified
  273.      * width and height and with a subset of the bands of this
  274.      * SinglePixelPackedSampleModel.
  275.      */
  276.     public SampleModel createSubsetSampleModel(int w, int h, int bands[]) {
  277.     if (bands.length > numBands)
  278.         throw new RasterFormatException("There are only " +
  279.                         numBands +
  280.                         " bands");
  281.     int newBitMasks[] = new int[bands.length];
  282.     for (int i=0; i<bands.length; i++)
  283.         newBitMasks[i] = bitMasks[bands[i]]; 
  284.     
  285.         return new SinglePixelPackedSampleModel(this.dataType, w, h,
  286.                        this.scanlineStride, newBitMasks);
  287.     }
  288.  
  289.     /** 
  290.      * Returns the pixel data in an array of primitives that can be byte,
  291.      * short or int. Which primitive type is returned depends on
  292.      * the transfer type. Data is returned in the packed format,
  293.      * thus increasing efficiency for data transfers. Generally, obj
  294.      * should be passed in as null, so that the Object will be created
  295.      * automatically and will be of the right primitive data type.
  296.      * <pre>
  297.      *          SinglePixelPackedSampleModel sppsm1, sppsm2;
  298.      *         DataBufferInt db1, db2;
  299.      *          sppsm2.setPixelData(x, y, sppsm1.getPixelData(x, y, null, db1), db2);
  300.      * </pre>
  301.      * @param x     The X coordinate of the pixel location.
  302.      * @param y     The Y coordinate of the pixel location.
  303.      * @param obj       If non-null, returns the primitive array in this object.
  304.      * @param data      The DataBuffer containing the image data.
  305.      */
  306.     public Object getPixelData(int x, int y, Object obj, DataBuffer data) {
  307.  
  308.     int type = getTransferType();
  309.  
  310.     switch(type) {
  311.  
  312.     case DataBuffer.BYTE_DATA:
  313.  
  314.         byte[] bdata;
  315.     
  316.         if (obj == null)
  317.         bdata = new byte[1];
  318.         else
  319.         bdata = (byte[])obj;
  320.         
  321.         bdata[0] = (byte)data.getElem(y * scanlineStride + x);
  322.         
  323.         obj = (Object)bdata;
  324.         break;
  325.         
  326.     case DataBuffer.SHORT_DATA:
  327.         
  328.         short[] sdata;
  329.         
  330.         if (obj == null)
  331.         sdata = new short[1];
  332.         else
  333.         sdata = (short[])obj;
  334.  
  335.         sdata[0] = (short)data.getElem(y * scanlineStride + x);
  336.         
  337.         obj = (Object)sdata;
  338.         break;
  339.  
  340.     case DataBuffer.INT_DATA:
  341.         
  342.         int[] idata;
  343.         
  344.         if (obj == null)
  345.         idata = new int[1];
  346.         else
  347.         idata = (int[])obj;
  348.  
  349.         idata[0] = data.getElem(y * scanlineStride + x);
  350.         
  351.         obj = (Object)idata;
  352.         break;
  353.     }
  354.     
  355.     return obj;
  356.     }
  357.  
  358.     /** 
  359.      * Returns all samples in for the specified pixel in an int array.
  360.      * @param x     The X coordinate of the pixel location.
  361.      * @param y     The Y coordinate of the pixel location.
  362.      * @param iArray    If non-null, returns the samples in this array
  363.      * @param data     The DataBuffer containing the image data.
  364.      */
  365.     public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
  366.         int pixels[];
  367.     if (iArray == null) {
  368.         pixels = new int [numBands];
  369.         } else {
  370.             pixels = iArray;
  371.         }
  372.     
  373.     int value = data.getElem(y * scanlineStride + x);
  374.     for (int i=0; i<numBands; i++) {
  375.         pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
  376.     }
  377.     return pixels;
  378.     }
  379.  
  380.     /**
  381.      * Returns all samples for the specified rectangle of pixels in
  382.      * an int array, one sample per array element.
  383.      * @param x     The X coordinate of the upper left pixel location.
  384.      * @param y     The Y coordinate of the upper left pixel location.
  385.      * @param w     The width of the pixel rectangle.
  386.      * @param h     The height of the pixel rectangle.
  387.      * @param iArray    If non-null, returns the samples in this array.
  388.      * @param data     The DataBuffer containing the image data.
  389.      */
  390.     public int[] getPixel(int x, int y, int w, int h,
  391.               int iArray[], DataBuffer data) {
  392.         int pixels[];
  393.         if (iArray != null) {
  394.            pixels = iArray;
  395.         } else {
  396.            pixels = new int [w*h*numBands];
  397.         }
  398.         int lineOffset = y*scanlineStride + x;
  399.         int dstOffset = 0;
  400.          
  401.         for (int i = 0; i < h; i++) {
  402.            for (int j = 0; j < w; j++) { 
  403.               int value = data.getElem(lineOffset+j);
  404.               for (int k=0; k < numBands; k++) {
  405.                   pixels[dstOffset++] =  
  406.                      ((value & bitMasks[k]) >>> bitOffsets[k]);
  407.               }
  408.            }
  409.            lineOffset += scanlineStride;
  410.         }
  411.         return pixels;
  412.     }
  413.  
  414.     /** 
  415.      * Returns as int the sample in a specified band for the pixel
  416.      * located at (x,y).
  417.      * @param x     The X coordinate of the pixel location.
  418.      * @param y     The Y coordinate of the pixel location.
  419.      * @param b     The band to return.
  420.      * @param data     The DataBuffer containing the image data.
  421.      */
  422.     public int getSample(int x, int y, int b, DataBuffer data) {
  423.     int sample = data.getElem(y * scanlineStride + x);
  424.     return ((sample & bitMasks[b]) >>> bitOffsets[b]);
  425.     }
  426.     
  427.     /**
  428.      * Returns the samples in a specified band for the specified rectangle
  429.      * of pixels in an int array, one sample per data array element.
  430.      * @param x     The X coordinate of the upper left pixel location.
  431.      * @param y     The Y coordinate of the upper left pixel location.
  432.      * @param w     The width of the pixel rectangle.
  433.      * @param h     The height of the pixel rectangle.
  434.      * @param b     The band to return.
  435.      * @param iArray    If non-null, returns the samples in this array.
  436.      * @param data     The DataBuffer containing the image data.
  437.      */
  438.     public int[] getSample(int x, int y, int w, int h, int b,
  439.                int iArray[], DataBuffer data) {
  440.         int samples[];
  441.         if (iArray != null) {
  442.            samples = iArray;
  443.         } else {
  444.            samples = new int [w*h];
  445.         }
  446.         int lineOffset = y*scanlineStride + x;
  447.         int dstOffset = 0;
  448.  
  449.         for (int i = 0; i < h; i++) {
  450.            for (int j = 0; j < w; j++) {
  451.               int value = data.getElem(lineOffset+j);
  452.               samples[dstOffset++] =
  453.                  ((value & bitMasks[b]) >>> bitOffsets[b]);
  454.            }
  455.            lineOffset += scanlineStride;
  456.         }
  457.         return samples;
  458.     }
  459.  
  460.     /** 
  461.      * Puts the pixel data from an Object that contains an
  462.      * array of primitives that can be byte,
  463.      * short or int. Which primitive type it contains depends on
  464.      * the transfer type. Data in the Object is in the packed format,
  465.      * thus increasing efficiency for data transfers.
  466.      * <pre>
  467.      *          SinglePixelPackedSampleModel sppsm1, sppsm2;
  468.      *         DataBufferInt db1, db2;
  469.      *          sppsm2.setPixelData(x, y, sppsm1.getPixelData(x, y, null, db1), db2);
  470.      * </pre>
  471.      * @param x     The X coordinate of the pixel location.
  472.      * @param y     The Y coordinate of the pixel location.
  473.      * @param obj       If non-null, returns the primitive array in this object.
  474.      * @param data      The DataBuffer containing the image data.
  475.      */
  476.     public void setPixelData(int x, int y, Object obj, DataBuffer data) {
  477.  
  478.     int type = getTransferType();
  479.  
  480.     switch(type) {
  481.  
  482.     case DataBuffer.BYTE_DATA:
  483.  
  484.         byte[] barray = (byte[])obj;
  485.         data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
  486.         break;
  487.  
  488.     case DataBuffer.SHORT_DATA:
  489.  
  490.         short[] sarray = (short[])obj;
  491.         data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
  492.         break;
  493.  
  494.     case DataBuffer.INT_DATA:    
  495.         
  496.         int[] iarray = (int[])obj;
  497.         data.setElem(y*scanlineStride+x, iarray[0]);
  498.         break;
  499.     }
  500.     }
  501.  
  502.     /** 
  503.      * Sets a pixel in the DataBuffer using an int array of samples for input.
  504.      * @param x     The X coordinate of the pixel location.
  505.      * @param y     The Y coordinate of the pixel location.
  506.      * @param iArray     The input samples in an int array.
  507.      * @param data     The DataBuffer containing the image data.
  508.      */
  509.     public void setPixel(int x, int y, 
  510.              int iArray[],
  511.              DataBuffer data) {
  512.         int value = 0; 
  513.         for (int i=0; i < numBands; i++) {
  514.             value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
  515.         }
  516.         data.setElem(y*scanlineStride+x, value);
  517.     }
  518.     
  519.     /**
  520.      * Sets all samples for a rectangle of pixels from an int array containing
  521.      * one sample per data array element.
  522.      * @param x     The X coordinate of the upper left pixel location.
  523.      * @param y     The Y coordinate of the upper left pixel location.
  524.      * @param w     The width of the pixel rectangle.
  525.      * @param h     The height of the pixel rectangle.
  526.      * @param iArray     The input samples in an int array.
  527.      * @param data     The DataBuffer containing the image data.
  528.      */
  529.     public void setPixel(int x, int y, int w, int h,
  530.              int iArray[], DataBuffer data) {
  531.  
  532.         int lineOffset = y*scanlineStride + x;
  533.     int srcOffset = 0;
  534.     
  535.         for (int i = 0; i < h; i++) {
  536.            for (int j = 0; j < w; j++) {
  537.               int value = 0;
  538.               for (int k=0; k < numBands; k++) {
  539.                  value |= ((iArray[srcOffset++] << bitOffsets[k])
  540.                & bitMasks[k]);
  541.               }
  542.               data.setElem(lineOffset+j,value);
  543.            }
  544.            lineOffset += scanlineStride;
  545.         }
  546.     }
  547.  
  548.     /** 
  549.      * Sets a sample in the specified band for the pixel located at (x,y)
  550.      * in the DataBuffer using an int for input.
  551.      * @param x     The X coordinate of the pixel location.
  552.      * @param y     The Y coordinate of the pixel location.
  553.      * @param b     The band to set.
  554.      * @param s     The input sample as an int.
  555.      * @param data     The DataBuffer containing the image data.
  556.      */
  557.     public void setSample(int x, int y, int b, int s,
  558.               DataBuffer data) {
  559.         int value = data.getElem(y*scanlineStride + x);
  560.         value &= ~bitMasks[b];
  561.         value |= (s << bitOffsets[b]) & bitMasks[b];
  562.         data.setElem(y*scanlineStride + x,value);
  563.     }
  564.  
  565.     /**
  566.      * Sets the samples in the specified band for the specified rectangle
  567.      * of pixels from an int array containing one sample per data array element.
  568.      * @param x     The X coordinate of the upper left pixel location.
  569.      * @param y     The Y coordinate of the upper left pixel location.
  570.      * @param w     The width of the pixel rectangle.
  571.      * @param h     The height of the pixel rectangle.
  572.      * @param b     The band to set.
  573.      * @param iArray     The input samples in an int array.
  574.      * @param data     The DataBuffer containing the image data.
  575.      */
  576.     public void setSample(int x, int y, int w, int h, int b,
  577.               int iArray[], DataBuffer data) {
  578.         int lineOffset = y*scanlineStride + x;
  579.         int srcOffset = 0;
  580.  
  581.         for (int i = 0; i < h; i++) {
  582.            for (int j = 0; j < w; j++) {
  583.               int value = data.getElem(lineOffset+j);
  584.               value &= ~bitMasks[b];
  585.               int sample = iArray[srcOffset++];
  586.               value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
  587.               data.setElem(lineOffset+j,value);
  588.            }
  589.            lineOffset += scanlineStride;
  590.         }
  591.     }
  592.  
  593. }
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.