Changeset 3265


Ignore:
Timestamp:
10/11/07 12:23:08 (12 years ago)
Author:
curtis
Message:

Clean up and debug image construction methods.

Location:
trunk/loci/formats
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/DataTools.java

    r3253 r3265  
    395395  } 
    396396 
     397  /** 
     398   * Convert a byte array to the appropriate primitive type array. 
     399   * @param b Byte array to convert. 
     400   * @param bpp Denotes the number of bytes in the returned primitive type 
     401   *   (e.g. if bpp == 2, we should return an array of type short). 
     402   * @param fp If set and bpp == 4 or bpp == 8, then return floats or doubles. 
     403   * @param little Whether byte array is in little-endian order. 
     404   */ 
     405  public static Object makeDataArray(byte[] b, 
     406    int bpp, boolean fp, boolean little) 
     407  { 
     408    if (bpp == 1) return b; 
     409    else if (bpp == 2) { 
     410      short[] s = new short[b.length / 2]; 
     411      for (int i=0; i<s.length; i++) { 
     412        s[i] = bytesToShort(b, i*2, 2, little); 
     413      } 
     414      return s; 
     415    } 
     416    else if (bpp == 4 && fp) { 
     417      float[] f = new float[b.length / 4]; 
     418      for (int i=0; i<f.length; i++) { 
     419        f[i] = Float.intBitsToFloat(bytesToInt(b, i*4, 4, little)); 
     420      } 
     421      return f; 
     422    } 
     423    else if (bpp == 4) { 
     424      int[] i = new int[b.length / 4]; 
     425      for (int j=0; j<i.length; j++) { 
     426        i[j] = bytesToInt(b, j*4, 4, little); 
     427      } 
     428      return i; 
     429    } 
     430    else if (bpp == 8 && fp) { 
     431      double[] d = new double[b.length / 8]; 
     432      for (int i=0; i<d.length; i++) { 
     433        d[i] = Double.longBitsToDouble(bytesToLong(b, i*8, 8, little)); 
     434      } 
     435      return d; 
     436    } 
     437    else if (bpp == 8) { 
     438      long[] l = new long[b.length / 8]; 
     439      for (int i=0; i<l.length; i++) { 
     440        l[i] = bytesToLong(b, i*8, 8, little); 
     441      } 
     442      return l; 
     443    } 
     444    return null; 
     445  } 
     446 
    397447  // -- Byte swapping -- 
    398448 
     
    447497 
    448498  /** 
    449    * Convert a byte array to the appropriate primitive type array. 
    450    * The 'bpp' parameter denotes the number of bytes in the returned primitive 
    451    * type (e.g. if bpp == 2, we should return an array of type short). 
    452    * If 'fp' is set and bpp == 4 or bpp == 8, then return floats or doubles. 
    453    */ 
    454   public static Object makeDataArray(byte[] b, int bpp, boolean fp, 
    455     boolean little) 
    456   { 
    457     if (bpp == 1) return b; 
    458     else if (bpp == 2) { 
    459       short[] s = new short[b.length / 2]; 
    460       for (int i=0; i<s.length; i++) { 
    461         s[i] = bytesToShort(b, i*2, 2, little); 
    462       } 
    463       return s; 
    464     } 
    465     else if (bpp == 4 && fp) { 
    466       float[] f = new float[b.length / 4]; 
    467       for (int i=0; i<f.length; i++) { 
    468         f[i] = Float.intBitsToFloat(bytesToInt(b, i*4, 4, little)); 
    469       } 
    470       return f; 
    471     } 
    472     else if (bpp == 4) { 
    473       int[] i = new int[b.length / 4]; 
    474       for (int j=0; j<i.length; j++) { 
    475         i[j] = bytesToInt(b, j*4, 4, little); 
    476       } 
    477       return i; 
    478     } 
    479     else if (bpp == 8 && fp) { 
    480       double[] d = new double[b.length / 8]; 
    481       for (int i=0; i<d.length; i++) { 
    482         d[i] = Double.longBitsToDouble(bytesToLong(b, i*8, 8, little)); 
    483       } 
    484       return d; 
    485     } 
    486     else if (bpp == 8) { 
    487       long[] l = new long[b.length / 8]; 
    488       for (int i=0; i<l.length; i++) { 
    489         l[i] = bytesToLong(b, i*8, 8, little); 
    490       } 
    491       return l; 
    492     } 
    493     return null; 
    494   } 
    495  
    496   /** 
    497499   * Normalize the given float array so that the minimum value maps to 0.0 
    498500   * and the maximum value maps to 1.0. 
  • trunk/loci/formats/ImageTools.java

    r3257 r3265  
    5353  private ImageTools() { } 
    5454 
    55   // -- Image construction -- 
    56  
    57   /** 
    58    * Creates an image from the given data, performing type conversions as 
    59    * necessary. 
    60    * If the interleaved flag is set, the channels are assumed to be 
    61    * interleaved; otherwise they are assumed to be sequential. 
    62    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    63    * while "RRR...GGG...BBB..." is sequential. 
    64    */ 
    65   public static BufferedImage makeImage(byte[] data, int w, int h, int c, 
    66     boolean interleaved, int bps, boolean little) 
    67   { 
    68     Object pixels = DataTools.makeDataArray(data, bps % 3 == 0 ? bps / 3 : bps, 
    69       false, little); 
    70  
    71     if (pixels instanceof byte[]) { 
    72       return makeImage((byte[]) pixels, w, h, c, interleaved); 
    73     } 
    74     else if (pixels instanceof short[]) { 
    75       return makeImage((short[]) pixels, w, h, c, interleaved); 
    76     } 
    77     else if (pixels instanceof int[]) { 
    78       return makeImage((int[]) pixels, w, h, c, interleaved); 
    79     } 
    80     else if (pixels instanceof float[]) { 
    81       return makeImage((float[]) pixels, w, h, c, interleaved); 
    82     } 
    83     else if (pixels instanceof double[]) { 
    84       return makeImage((double[]) pixels, w, h, c, interleaved); 
    85     } 
    86     return null; 
    87   } 
     55  // -- Image construction - from 1D (single channel) data arrays -- 
     56 
     57  /** 
     58   * Creates an image from the given single-channel unsigned byte data. 
     59   * @param data Array containing image data. 
     60   * @param w Width of image plane. 
     61   * @param h Height of image plane. 
     62   */ 
     63  public static BufferedImage makeImage(byte[] data, int w, int h) { 
     64    return makeImage(new byte[][] {data}, w, h); 
     65  } 
     66 
     67  /** 
     68   * Creates an image from the given single-channel unsigned short data. 
     69   * @param data Array containing image data. 
     70   * @param w Width of image plane. 
     71   * @param h Height of image plane. 
     72   */ 
     73  public static BufferedImage makeImage(short[] data, int w, int h) { 
     74    return makeImage(new short[][] {data}, w, h); 
     75  } 
     76 
     77  /** 
     78   * Creates an image from the given single-channel signed int data. 
     79   * @param data Array containing image data. 
     80   * @param w Width of image plane. 
     81   * @param h Height of image plane. 
     82   */ 
     83  public static BufferedImage makeImage(int[] data, int w, int h) { 
     84    return makeImage(new int[][] {data}, w, h); 
     85  } 
     86 
     87  /** 
     88   * Creates an image from the given single-channel float data. 
     89   * @param data Array containing image data. 
     90   * @param w Width of image plane. 
     91   * @param h Height of image plane. 
     92   */ 
     93  public static BufferedImage makeImage(float[] data, int w, int h) { 
     94    return makeImage(new float[][] {data}, w, h); 
     95  } 
     96 
     97  /** 
     98   * Creates an image from the given single-channel double data. 
     99   * @param data Array containing image data. 
     100   * @param w Width of image plane. 
     101   * @param h Height of image plane. 
     102   */ 
     103  public static BufferedImage makeImage(double[] data, int w, int h) { 
     104    return makeImage(new double[][] {data}, w, h); 
     105  } 
     106 
     107  // -- Image construction - from 1D (interleaved or banded) data arrays -- 
    88108 
    89109  /** 
    90110   * Creates an image from the given unsigned byte data. 
    91    * If the interleaved flag is set, the channels are assumed to be 
    92    * interleaved; otherwise they are assumed to be sequential. 
    93    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    94    * while "RRR...GGG...BBB..." is sequential. 
     111   * @param data Array containing image data. 
     112   * @param w Width of image plane. 
     113   * @param h Height of image plane. 
     114   * @param c Number of channels. 
     115   * @param interleaved If set, the channels are assumed to be interleaved; 
     116   *   otherwise they are assumed to be sequential. 
     117   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     118   *   while "RRR...GGG...BBB..." is sequential. 
    95119   */ 
    96120  public static BufferedImage makeImage(byte[] data, 
     
    112136    } 
    113137    DataBuffer buffer = new DataBufferByte(data, c * w * h); 
    114     return constructImage(c, dataType, w, h, interleaved, buffer); 
     138    return constructImage(c, dataType, w, h, interleaved, false, buffer); 
    115139  } 
    116140 
    117141  /** 
    118142   * Creates an image from the given unsigned short data. 
    119    * If the interleaved flag is set, the channels are assumed to be 
    120    * interleaved; otherwise they are assumed to be sequential. 
    121    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    122    * while "RRR...GGG...BBB..." is sequential. 
     143   * @param data Array containing image data. 
     144   * @param w Width of image plane. 
     145   * @param h Height of image plane. 
     146   * @param c Number of channels. 
     147   * @param interleaved If set, the channels are assumed to be interleaved; 
     148   *   otherwise they are assumed to be sequential. 
     149   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     150   *   while "RRR...GGG...BBB..." is sequential. 
    123151   */ 
    124152  public static BufferedImage makeImage(short[] data, 
     
    140168    } 
    141169    DataBuffer buffer = new DataBufferUShort(data, c * w * h); 
    142     return constructImage(c, dataType, w, h, interleaved, buffer); 
     170    return constructImage(c, dataType, w, h, interleaved, false, buffer); 
    143171  } 
    144172 
    145173  /** 
    146174   * Creates an image from the given signed int data. 
    147    * If the interleaved flag is set, the channels are assumed to be 
    148    * interleaved; otherwise they are assumed to be sequential. 
    149    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    150    * while "RRR...GGG...BBB..." is sequential. 
     175   * @param data Array containing image data. 
     176   * @param w Width of image plane. 
     177   * @param h Height of image plane. 
     178   * @param c Number of channels. 
     179   * @param interleaved If set, the channels are assumed to be interleaved; 
     180   *   otherwise they are assumed to be sequential. 
     181   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     182   *   while "RRR...GGG...BBB..." is sequential. 
    151183   */ 
    152184  public static BufferedImage makeImage(int[] data, 
     
    168200    } 
    169201    DataBuffer buffer = new DataBufferInt(data, c * w * h); 
    170     return constructImage(c, dataType, w, h, interleaved, buffer); 
     202    return constructImage(c, dataType, w, h, interleaved, false, buffer); 
    171203  } 
    172204 
    173205  /** 
    174206   * Creates an image from the given float data. 
    175    * If the interleaved flag is set, the channels are assumed to be 
    176    * interleaved; otherwise they are assumed to be sequential. 
    177    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    178    * while "RRR...GGG...BBB..." is sequential. 
     207   * @param data Array containing image data. 
     208   * @param w Width of image plane. 
     209   * @param h Height of image plane. 
     210   * @param c Number of channels. 
     211   * @param interleaved If set, the channels are assumed to be interleaved; 
     212   *   otherwise they are assumed to be sequential. 
     213   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     214   *   while "RRR...GGG...BBB..." is sequential. 
    179215   */ 
    180216  public static BufferedImage makeImage(float[] data, 
     
    196232    } 
    197233    DataBuffer buffer = new DataBufferFloat(data, c * w * h); 
    198     return constructImage(c, dataType, w, h, interleaved, buffer); 
     234    return constructImage(c, dataType, w, h, interleaved, false, buffer); 
    199235  } 
    200236 
    201237  /** 
    202238   * Creates an image from the given double data. 
    203    * If the interleaved flag is set, the channels are assumed to be 
    204    * interleaved; otherwise they are assumed to be sequential. 
    205    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    206    * while "RRR...GGG...BBB..." is sequential. 
     239   * @param data Array containing image data. 
     240   * @param w Width of image plane. 
     241   * @param h Height of image plane. 
     242   * @param c Number of channels. 
     243   * @param interleaved If set, the channels are assumed to be interleaved; 
     244   *   otherwise they are assumed to be sequential. 
     245   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     246   *   while "RRR...GGG...BBB..." is sequential. 
    207247   */ 
    208248  public static BufferedImage makeImage(double[] data, 
     
    224264    } 
    225265    DataBuffer buffer = new DataBufferDouble(data, c * w * h); 
    226     return constructImage(c, dataType, w, h, interleaved, buffer); 
    227   } 
    228  
    229   /** 
    230    * Creates an image from the given data, performing type conversions as 
    231    * necessary. 
    232    * If the interleaved flag is set, the channels are assumed to be 
    233    * interleaved; otherwise they are assumed to be sequential. 
    234    * For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
    235    * while "RRR...GGG...BBB..." is sequential. 
    236    */ 
    237   public static BufferedImage makeImage(byte[][] data, int w, int h, 
    238     int bps, boolean little) 
    239   { 
    240     if (bps == 1) return makeImage(data, w, h); 
    241     else if (bps == 2) { 
    242       short[][] shorts = new short[data.length][data[0].length / bps]; 
    243       for (int i=0; i<shorts.length; i++) { 
    244         for (int j=0; j<shorts[0].length; j++) { 
    245           shorts[i][j] = DataTools.bytesToShort(data[i], j*2, 2, little); 
    246         } 
    247       } 
    248       return makeImage(shorts, w, h); 
    249     } 
    250     else if (bps == 4) { 
    251       float[][] floats = new float[data.length][data[0].length / bps]; 
    252       for (int i=0; i<floats.length; i++) { 
    253         floats[i] = 
    254           (float[]) DataTools.makeDataArray(data[i], bps, true, little); 
    255       } 
    256       return makeImage(floats, w, h); 
    257     } 
    258     else { 
    259       double[][] doubles = new double[data.length][data[0].length / bps]; 
    260       for (int i=0; i<doubles.length; i++) { 
    261         for (int j=0; j<doubles[0].length; j++) { 
    262           doubles[i][j] = Double.longBitsToDouble( 
    263             DataTools.bytesToLong(data[i], j*bps, bps, little)); 
    264         } 
    265       } 
    266       return makeImage(doubles, w, h); 
    267     } 
    268   } 
     266    return constructImage(c, dataType, w, h, interleaved, false, buffer); 
     267  } 
     268 
     269  // -- Image construction - from 2D (banded) data arrays -- 
    269270 
    270271  /** 
    271272   * Creates an image from the given unsigned byte data. 
    272    * It is assumed that each channel corresponds to one element of the array. 
    273    * For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     273   * @param data Array containing image data. 
     274   *   It is assumed that each channel corresponds to one element of the array. 
     275   *   For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     276   * @param w Width of image plane. 
     277   * @param h Height of image plane. 
    274278   */ 
    275279  public static BufferedImage makeImage(byte[][] data, int w, int h) { 
    276280    int dataType = DataBuffer.TYPE_BYTE; 
    277     ColorModel colorModel = makeColorModel(data.length, dataType); 
    278     if (colorModel == null) return null; 
    279     SampleModel model = new BandedSampleModel(dataType, w, h, data.length); 
    280281    DataBuffer buffer = new DataBufferByte(data, data[0].length); 
    281     WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
    282     return new BufferedImage(colorModel, raster, false, null); 
     282    return constructImage(data.length, dataType, w, h, false, true, buffer); 
    283283  } 
    284284 
    285285  /** 
    286286   * Creates an image from the given unsigned short data. 
    287    * It is assumed that each channel corresponds to one element of the array. 
    288    * For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     287   * @param data Array containing image data. 
     288   *   It is assumed that each channel corresponds to one element of the array. 
     289   *   For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     290   * @param w Width of image plane. 
     291   * @param h Height of image plane. 
    289292   */ 
    290293  public static BufferedImage makeImage(short[][] data, int w, int h) { 
    291294    int dataType = DataBuffer.TYPE_USHORT; 
    292     ColorModel colorModel = makeColorModel(data.length, dataType); 
    293     if (colorModel == null) return null; 
    294     SampleModel model = new BandedSampleModel(dataType, w, h, data.length); 
    295295    DataBuffer buffer = new DataBufferUShort(data, data[0].length); 
    296     WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
    297     return new BufferedImage(colorModel, raster, false, null); 
     296    return constructImage(data.length, dataType, w, h, false, true, buffer); 
    298297  } 
    299298 
    300299  /** 
    301300   * Creates an image from the given signed int data. 
    302    * It is assumed that each channel corresponds to one element of the array. 
    303    * For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     301   * @param data Array containing image data. 
     302   *   It is assumed that each channel corresponds to one element of the array. 
     303   *   For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     304   * @param w Width of image plane. 
     305   * @param h Height of image plane. 
    304306   */ 
    305307  public static BufferedImage makeImage(int[][] data, int w, int h) { 
    306308    int dataType = DataBuffer.TYPE_INT; 
    307     ColorModel colorModel = makeColorModel(data.length, dataType); 
    308     if (colorModel == null) return null; 
    309     SampleModel model = new BandedSampleModel(dataType, w, h, data.length); 
    310309    DataBuffer buffer = new DataBufferInt(data, data[0].length); 
    311     WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
    312     return new BufferedImage(colorModel, raster, false, null); 
     310    return constructImage(data.length, dataType, w, h, false, true, buffer); 
    313311  } 
    314312 
    315313  /** 
    316314   * Creates an image from the given single-precision floating point data. 
    317    * It is assumed that each channel corresponds to one element of the array. 
    318    * For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     315   * @param data Array containing image data. 
     316   *   It is assumed that each channel corresponds to one element of the array. 
     317   *   For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     318   * @param w Width of image plane. 
     319   * @param h Height of image plane. 
    319320   */ 
    320321  public static BufferedImage makeImage(float[][] data, int w, int h) { 
    321322    int dataType = DataBuffer.TYPE_FLOAT; 
    322     ColorModel colorModel = makeColorModel(data.length, dataType); 
    323     if (colorModel == null) return null; 
    324     SampleModel model = new BandedSampleModel(dataType, w, h, data.length); 
    325323    DataBuffer buffer = new DataBufferFloat(data, data[0].length); 
    326     WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
    327     return new BufferedImage(colorModel, raster, false, null); 
     324    return constructImage(data.length, dataType, w, h, false, true, buffer); 
    328325  } 
    329326 
    330327  /** 
    331328   * Creates an image from the given double-precision floating point data. 
    332    * It is assumed that each channel corresponds to one element of the array. 
    333    * For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     329   * @param data Array containing image data. 
     330   *   It is assumed that each channel corresponds to one element of the array. 
     331   *   For example, for RGB data, data[0] is R, data[1] is G, and data[2] is B. 
     332   * @param w Width of image plane. 
     333   * @param h Height of image plane. 
    334334   */ 
    335335  public static BufferedImage makeImage(double[][] data, int w, int h) { 
    336336    int dataType = DataBuffer.TYPE_DOUBLE; 
    337     ColorModel colorModel = makeColorModel(data.length, dataType); 
    338     if (colorModel == null) return null; 
    339     SampleModel model = new BandedSampleModel(dataType, w, h, data.length); 
    340337    DataBuffer buffer = new DataBufferDouble(data, data[0].length); 
    341     WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
    342     return new BufferedImage(colorModel, raster, false, null); 
    343   } 
    344  
    345   /** Creates an image from the given single-channel unsigned byte data. */ 
    346   public static BufferedImage makeImage(byte[] data, int w, int h) { 
    347     return makeImage(new byte[][] {data}, w, h); 
    348   } 
    349  
    350   /** Creates an image from the given single-channel unsigned short data. */ 
    351   public static BufferedImage makeImage(short[] data, int w, int h) { 
    352     return makeImage(new short[][] {data}, w, h); 
    353   } 
    354  
    355   /** Creates an image from the given single-channel signed int data. */ 
    356   public static BufferedImage makeImage(int[] data, int w, int h) { 
    357     return makeImage(new int[][] {data}, w, h); 
    358   } 
    359  
    360   /** Creates an image from the given single-channel float data. */ 
    361   public static BufferedImage makeImage(float[] data, int w, int h) { 
    362     return makeImage(new float[][] {data}, w, h); 
    363   } 
    364  
    365   /** Creates an image from the given single-channel double data. */ 
    366   public static BufferedImage makeImage(double[] data, int w, int h) { 
    367     return makeImage(new double[][] {data}, w, h); 
    368   } 
    369  
    370   /** Create a blank image with the given dimensions and transfer type. */ 
     338    return constructImage(data.length, dataType, w, h, false, true, buffer); 
     339  } 
     340 
     341  // -- Image construction - with type conversion -- 
     342 
     343  /** 
     344   * Creates an image from the given data, 
     345   * performing type conversions as necessary. 
     346   * @param data Array containing image data. 
     347   * @param w Width of image plane. 
     348   * @param h Height of image plane. 
     349   * @param c Number of channels. 
     350   * @param interleaved If set, the channels are assumed to be interleaved; 
     351   *   otherwise they are assumed to be sequential. 
     352   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     353   *   while "RRR...GGG...BBB..." is sequential. 
     354   * @param bpp Denotes the number of bytes in the returned primitive type 
     355   *   (e.g. if bpp == 2, we should return an array of type short). 
     356   * @param little Whether byte array is in little-endian order. 
     357   */ 
     358  public static BufferedImage makeImage(byte[] data, int w, int h, int c, 
     359    boolean interleaved, int bpp, boolean little) 
     360  { 
     361    return makeImage(data, w, h, c, interleaved, bpp, false, little); 
     362  } 
     363 
     364  /** 
     365   * Creates an image from the given data, 
     366   * performing type conversions as necessary. 
     367   * @param data Array containing image data. 
     368   * @param w Width of image plane. 
     369   * @param h Height of image plane. 
     370   * @param c Number of channels. 
     371   * @param interleaved If set, the channels are assumed to be interleaved; 
     372   *   otherwise they are assumed to be sequential. 
     373   *   For example, for RGB data, the pattern "RGBRGBRGB..." is interleaved, 
     374   *   while "RRR...GGG...BBB..." is sequential. 
     375   * @param bpp Denotes the number of bytes in the returned primitive type 
     376   *   (e.g. if bpp == 2, we should return an array of type short). 
     377   * @param fp If set and bpp == 4 or bpp == 8, then return floats or doubles. 
     378   * @param little Whether byte array is in little-endian order. 
     379   */ 
     380  public static BufferedImage makeImage(byte[] data, int w, int h, int c, 
     381    boolean interleaved, int bpp, boolean fp, boolean little) 
     382  { 
     383    Object pixels = DataTools.makeDataArray(data, 
     384      bpp % 3 == 0 ? bpp / 3 : bpp, fp, little); 
     385 
     386    if (pixels instanceof byte[]) { 
     387      return makeImage((byte[]) pixels, w, h, c, interleaved); 
     388    } 
     389    else if (pixels instanceof short[]) { 
     390      return makeImage((short[]) pixels, w, h, c, interleaved); 
     391    } 
     392    else if (pixels instanceof int[]) { 
     393      return makeImage((int[]) pixels, w, h, c, interleaved); 
     394    } 
     395    else if (pixels instanceof float[]) { 
     396      return makeImage((float[]) pixels, w, h, c, interleaved); 
     397    } 
     398    else if (pixels instanceof double[]) { 
     399      return makeImage((double[]) pixels, w, h, c, interleaved); 
     400    } 
     401    return null; 
     402  } 
     403 
     404  /** 
     405   * Creates an image from the given data, 
     406   * performing type conversions as necessary. 
     407   * @param data Array containing image data, one channel per element. 
     408   * @param w Width of image plane. 
     409   * @param h Height of image plane. 
     410   * @param bpp Denotes the number of bytes in the returned primitive type 
     411   *   (e.g. if bpp == 2, we should return an array of type short). 
     412   * @param little Whether byte array is in little-endian order. 
     413   */ 
     414  public static BufferedImage makeImage(byte[][] data, 
     415    int w, int h, int bpp, boolean little) 
     416  { 
     417    return makeImage(data, w, h, bpp, false, little); 
     418  } 
     419 
     420  /** 
     421   * Creates an image from the given data, 
     422   * performing type conversions as necessary. 
     423   * @param data Array containing image data, one channel per element. 
     424   * @param w Width of image plane. 
     425   * @param h Height of image plane. 
     426   * @param bpp Denotes the number of bytes in the returned primitive type 
     427   *   (e.g. if bpp == 2, we should return an array of type short). 
     428   * @param fp If set and bpp == 4 or bpp == 8, then return floats or doubles. 
     429   * @param little Whether byte array is in little-endian order. 
     430   */ 
     431  public static BufferedImage makeImage(byte[][] data, 
     432    int w, int h, int bpp, boolean fp, boolean little) 
     433  { 
     434    int c = data.length; 
     435    Object v = null; 
     436    for (int i=0; i<c; i++) { 
     437      Object pixels = DataTools.makeDataArray(data[i], 
     438        bpp % 3 == 0 ? bpp / 3 : bpp, fp, little); 
     439      if (pixels instanceof byte[]) { 
     440        if (v == null) v = new byte[c][]; 
     441        ((byte[][]) v)[i] = (byte[]) pixels; 
     442      } 
     443      else if (pixels instanceof short[]) { 
     444        if (v == null) v = new short[c][]; 
     445        ((short[][]) v)[i] = (short[]) pixels; 
     446      } 
     447      else if (pixels instanceof int[]) { 
     448        if (v == null) v = new int[c][]; 
     449        ((int[][]) v)[i] = (int[]) pixels; 
     450      } 
     451      else if (pixels instanceof float[]) { 
     452        if (v == null) v = new float[c][]; 
     453        ((float[][]) v)[i] = (float[]) pixels; 
     454      } 
     455      else if (pixels instanceof double[]) { 
     456        if (v == null) v = new double[c][]; 
     457        ((double[][]) v)[i] = (double[]) pixels; 
     458      } 
     459    } 
     460    if (v instanceof byte[][]) return makeImage((byte[][]) v, w, h); 
     461    else if (v instanceof short[][]) return makeImage((short[][]) v, w, h); 
     462    else if (v instanceof int[][]) return makeImage((int[][]) v, w, h); 
     463    else if (v instanceof float[][]) return makeImage((float[][]) v, w, h); 
     464    else if (v instanceof double[][]) return makeImage((double[][]) v, w, h); 
     465    return null; 
     466  } 
     467 
     468  // -- Image construction - miscellaneous -- 
     469 
     470  /** 
     471   * Creates a blank image with the given dimensions and transfer type. 
     472   * @param w Width of image plane. 
     473   * @param h Height of image plane. 
     474   * @param c Number of channels. 
     475   * @param type One of the following types:<ul> 
     476   *   <li>FormatReader.INT8</li> 
     477   *   <li>FormatReader.UINT8</li> 
     478   *   <li>FormatReader.INT16</li> 
     479   *   <li>FormatReader.UINT16</li> 
     480   *   <li>FormatReader.INT32</li> 
     481   *   <li>FormatReader.UINT32</li> 
     482   *   <li>FormatReader.FLOAT</li> 
     483   *   <li>FormatReader.DOUBLE</li> 
     484   * </ul> 
     485   */ 
    371486  public static BufferedImage blankImage(int w, int h, int c, int type) { 
    372     int tt = 0; 
    373     DataBuffer buffer = null; 
    374487    switch (type) { 
    375488      case FormatTools.INT8: 
    376489      case FormatTools.UINT8: 
    377         tt = DataBuffer.TYPE_BYTE; 
    378         buffer = new DataBufferByte(new byte[c * w * h], c * w * h); 
    379         break; 
     490        return makeImage(new byte[c][w * h], w, h); 
    380491      case FormatTools.INT16: 
    381492      case FormatTools.UINT16: 
    382         tt = DataBuffer.TYPE_USHORT; 
    383         buffer = new DataBufferUShort(new short[c * w * h], c * w * h); 
    384         break; 
     493        return makeImage(new short[c][w * h], w, h); 
    385494      case FormatTools.INT32: 
    386495      case FormatTools.UINT32: 
    387         tt = DataBuffer.TYPE_INT; 
    388         buffer = new DataBufferInt(new int[c * w * h], c * w * h); 
    389         break; 
     496        return makeImage(new int[c][w * h], w, h); 
    390497      case FormatTools.FLOAT: 
    391         tt = DataBuffer.TYPE_FLOAT; 
    392         buffer = new DataBufferFloat(new float[c * w * h], c * w * h); 
    393         break; 
     498        return makeImage(new float[c][w * h], w, h); 
    394499      case FormatTools.DOUBLE: 
    395         tt = DataBuffer.TYPE_DOUBLE; 
    396         buffer = new DataBufferDouble(new double[c * w * h], c * w * h); 
    397         break; 
    398     } 
    399  
    400     return constructImage(c, tt, w, h, true, buffer); 
    401   } 
    402  
    403   /** Create an image with the given DataBuffer. */ 
     500        return makeImage(new double[c][w * h], w, h); 
     501    } 
     502    return null; 
     503  } 
     504 
     505  /** Creates an image with the given DataBuffer. */ 
    404506  private static BufferedImage constructImage(int c, int type, int w, 
    405     int h, boolean interleaved, DataBuffer buffer) 
     507    int h, boolean interleaved, boolean banded, DataBuffer buffer) 
    406508  { 
    407509    ColorModel colorModel = makeColorModel(c, type); 
     
    409511 
    410512    SampleModel model; 
    411     if (interleaved) { 
     513    if (banded) model = new BandedSampleModel(type, w, h, c); 
     514    else if (interleaved) { 
    412515      int[] bandOffsets = new int[c]; 
    413516      for (int i=0; i<c; i++) bandOffsets[i] = i; 
     
    415518        w, h, c, c * w, bandOffsets); 
    416519    } 
    417     else model = new BandedSampleModel(type, w, h, c); 
     520    else { 
     521      int[] bandOffsets = new int[c]; 
     522      for (int i=0; i<c; i++) bandOffsets[i] = i * w * h; 
     523      model = new ComponentSampleModel(type, w, h, 1, w, bandOffsets); 
     524    } 
    418525 
    419526    WritableRaster raster = Raster.createWritableRaster(model, buffer, null); 
     
    679786  // in case we decide to explore this issue any further in the future. 
    680787 
    681 //  /** Copies the given image into a result with the specified data type. */ 
    682 //  public static BufferedImage makeType(BufferedImage image, int type) { 
    683 //    WritableRaster r = image.getRaster(); 
    684 //    int w = image.getWidth(), h = image.getHeight(), c = r.getNumBands(); 
    685 //    ColorModel colorModel = makeColorModel(c, type); 
    686 //    if (colorModel == null) return null; 
    687 // 
    688 //    int s = w * h; 
    689 //    DataBuffer buf = null; 
    690 //    if (type == DataBuffer.TYPE_BYTE) buf = new DataBufferByte(s, c); 
    691 //    else if (type == DataBuffer.TYPE_USHORT) buf = new DataBufferUShort(s, c); 
    692 //    else if (type == DataBuffer.TYPE_INT) buf = new DataBufferInt(s, c); 
    693 //    else if (type == DataBuffer.TYPE_SHORT) buf = new DataBufferShort(s, c); 
    694 //    else if (type == DataBuffer.TYPE_FLOAT) buf = new DataBufferFloat(s, c); 
    695 //    else if (type == DataBuffer.TYPE_DOUBLE) buf = new DataBufferDouble(s, c); 
    696 //    if (buf == null) return null; 
    697 // 
    698 //    SampleModel model = new BandedSampleModel(type, w, h, c); 
    699 //    WritableRaster raster = Raster.createWritableRaster(model, buf, null); 
    700 //    BufferedImage target = new BufferedImage(colorModel, raster, false, null); 
    701 //    Graphics2D g2 = target.createGraphics(); 
    702 //    g2.drawRenderedImage(image, null); 
    703 //    g2.dispose(); 
    704 //    return target; 
    705 //  } 
     788  ///** Copies the given image into a result with the specified data type. */ 
     789  //public static BufferedImage makeType(BufferedImage image, int type) { 
     790  //  WritableRaster r = image.getRaster(); 
     791  //  int w = image.getWidth(), h = image.getHeight(), c = r.getNumBands(); 
     792  //  ColorModel colorModel = makeColorModel(c, type); 
     793  //  if (colorModel == null) return null; 
     794  // 
     795  //  int s = w * h; 
     796  //  DataBuffer buf = null; 
     797  //  if (type == DataBuffer.TYPE_BYTE) buf = new DataBufferByte(s, c); 
     798  //  else if (type == DataBuffer.TYPE_USHORT) buf = new DataBufferUShort(s, c); 
     799  //  else if (type == DataBuffer.TYPE_INT) buf = new DataBufferInt(s, c); 
     800  //  else if (type == DataBuffer.TYPE_SHORT) buf = new DataBufferShort(s, c); 
     801  //  else if (type == DataBuffer.TYPE_FLOAT) buf = new DataBufferFloat(s, c); 
     802  //  else if (type == DataBuffer.TYPE_DOUBLE) buf = new DataBufferDouble(s, c); 
     803  //  if (buf == null) return null; 
     804  // 
     805  //  SampleModel model = new BandedSampleModel(type, w, h, c); 
     806  //  WritableRaster raster = Raster.createWritableRaster(model, buf, null); 
     807  //  BufferedImage target = new BufferedImage(colorModel, raster, false, null); 
     808  //  Graphics2D g2 = target.createGraphics(); 
     809  //  g2.drawRenderedImage(image, null); 
     810  //  g2.dispose(); 
     811  //  return target; 
     812  //} 
    706813 
    707814  /** Get the bytes from an image, merging the channels as necessary. */ 
Note: See TracChangeset for help on using the changeset viewer.