001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object; 016 017import java.util.Iterator; 018import java.util.List; 019import java.util.Vector; 020 021/** 022 * A scalar dataset is a multiple dimension array of scalar points. The Datatype of a scalar dataset must be an atomic 023 * datatype. Common datatypes of scalar datasets include char, byte, short, int, long, float, double and string. 024 * <p> 025 * A ScalarDS can be an image or spreadsheet data. ScalarDS defines few methods to deal with both images and 026 * spreadsheets. 027 * <p> 028 * ScalarDS is an abstract class. Current implementing classes are the H4SDS, H5GRImage and H5ScalarDS. 029 * 030 * @version 1.1 9/4/2007 031 * @author Peter X. Cao 032 */ 033public abstract class ScalarDS extends Dataset { 034 /** 035 * 036 */ 037 private static final long serialVersionUID = 8925371455928203981L; 038 039 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScalarDS.class); 040 041 // The following constant strings are copied from 042 // http://hdf.uiuc.edu/HDF5/doc/ADGuide/ImageSpec.html 043 // to make the definition consistent with the image specs. 044 /** 045 * Indicates that the pixel RGB values are contiguous. 046 */ 047 public final static int INTERLACE_PIXEL = 0; 048 049 /** Indicates that each pixel component of RGB is stored as a scan line. */ 050 public static final int INTERLACE_LINE = 1; 051 052 /** Indicates that each pixel component of RGB is stored as a plane. */ 053 public final static int INTERLACE_PLANE = 2; 054 055 /** 056 * The interlace mode of the stored raster image data. Valid values are INTERLACE_PIXEL, INTERLACE_LINE and 057 * INTERLACE_PLANE. 058 */ 059 protected int interlace; 060 061 /** 062 * The min-max range of image data values. For example, [0, 255] indicates the min is 0, and the max is 255. 063 */ 064 protected double[] imageDataRange; 065 066 /** 067 * The indexed RGB color model with 256 colors. 068 * <p> 069 * The palette values are stored in a two-dimensional byte array and arrange by color components of red, green and 070 * blue. palette[][] = byte[3][256], where, palette[0][], palette[1][] and palette[2][] are the red, green and blue 071 * components respectively. 072 */ 073 protected byte[][] palette; 074 075 /** 076 * True if this dataset is an image. 077 */ 078 protected boolean isImage; 079 080 /** 081 * True if this dataset is a true color image. 082 */ 083 protected boolean isTrueColor; 084 085 /** 086 * True if this dataset is ASCII text. 087 */ 088 protected boolean isText; 089 090 /** 091 * Flag to indicate if the original C data is unsigned integer. 092 */ 093 protected boolean isUnsigned; 094 095 /** 096 * Flag to indicate is the original unsigned C data is converted. 097 */ 098 protected boolean unsignedConverted; 099 100 /** The fill value of the dataset. */ 101 protected Object fillValue = null; 102 103 private List<Number> filteredImageValues; 104 105 /** Flag to indicate if the dataset is displayed as an image */ 106 protected boolean isImageDisplay; 107 108 /** 109 * Flag to indicate if the dataset is displayed as an image with default order of dimensions 110 */ 111 protected boolean isDefaultImageOrder; 112 113 /** 114 * Flag to indicate if the FillValue is converted from unsigned C. 115 */ 116 public boolean isFillValueConverted; 117 118 /** 119 * Constructs an instance of a ScalarDS with specific name and path. An HDF data object must have a name. The path 120 * is the group path starting from the root. 121 * <p> 122 * For example, in H5ScalarDS(h5file, "dset", "/arrays/"), "dset" is the name of the dataset, "/arrays" is the group 123 * path of the dataset. 124 * 125 * @param theFile 126 * the file that contains the data object. 127 * @param theName 128 * the name of the data object, e.g. "dset". 129 * @param thePath 130 * the full path of the data object, e.g. "/arrays/". 131 */ 132 public ScalarDS(FileFormat theFile, String theName, String thePath) { 133 this(theFile, theName, thePath, null); 134 } 135 136 /** 137 * @deprecated Not for public use in the future.<br> 138 * Using {@link #ScalarDS(FileFormat, String, String)} 139 * 140 * @param theFile 141 * the file that contains the data object. 142 * @param theName 143 * the name of the data object, e.g. "dset". 144 * @param thePath 145 * the full path of the data object, e.g. "/arrays/". 146 * @param oid 147 * the v of the data object. 148 */ 149 @Deprecated 150 public ScalarDS(FileFormat theFile, String theName, String thePath, long[] oid) { 151 super(theFile, theName, thePath, oid); 152 153 palette = null; 154 isImage = false; 155 isTrueColor = false; 156 isText = false; 157 isUnsigned = false; 158 interlace = -1; 159 datatype = null; 160 imageDataRange = null; 161 isImageDisplay = false; 162 isDefaultImageOrder = true; 163 isFillValueConverted = false; 164 filteredImageValues = new Vector<Number>(); 165 } 166 167 /* 168 * (non-Javadoc) 169 * 170 * @see hdf.object.Dataset#clearData() 171 */ 172 @Override 173 public void clearData() { 174 super.clearData(); 175 unsignedConverted = false; 176 } 177 178 /** 179 * Converts the data values of this dataset to appropriate Java integer if they are unsigned integers. 180 * 181 * @see hdf.object.Dataset#convertToUnsignedC(Object) 182 * @see hdf.object.Dataset#convertFromUnsignedC(Object, Object) 183 * 184 * @return the converted data buffer. 185 */ 186 public Object convertFromUnsignedC() { 187 // keep a copy of original buffer and the converted buffer 188 // so that they can be reused later to save memory 189 log.trace("convertFromUnsignedC: start"); 190 if ((data != null) && isUnsigned && !unsignedConverted) { 191 log.trace("convertFromUnsignedC: convert"); 192 originalBuf = data; 193 convertedBuf = convertFromUnsignedC(originalBuf, convertedBuf); 194 data = convertedBuf; 195 unsignedConverted = true; 196 197 if (fillValue != null) { 198 if (!isFillValueConverted) { 199 fillValue = convertFromUnsignedC(fillValue, null); 200 isFillValueConverted = true; 201 } 202 } 203 204 } 205 206 log.trace("convertFromUnsignedC: finish"); 207 return data; 208 } 209 210 /** 211 * Converts Java integer data of this dataset back to unsigned C-type integer data if they are unsigned integers. 212 * 213 * @see hdf.object.Dataset#convertToUnsignedC(Object) 214 * @see hdf.object.Dataset#convertToUnsignedC(Object, Object) 215 * @see #convertFromUnsignedC(Object data_in) 216 * 217 * @return the converted data buffer. 218 */ 219 public Object convertToUnsignedC() { 220 // keep a copy of original buffer and the converted buffer 221 // so that they can be reused later to save memory 222 if ((data != null) && isUnsigned) { 223 convertedBuf = data; 224 originalBuf = convertToUnsignedC(convertedBuf, originalBuf); 225 data = originalBuf; 226 } 227 228 return data; 229 } 230 231 /** 232 * Returns the palette of this scalar dataset or null if palette does not exist. 233 * <p> 234 * Scalar dataset can be displayed as spreadsheet data or image. When a scalar dataset is chosen to display as an 235 * image, the palette or color table may be needed to translate a pixel value to color components (for example, red, 236 * green, and blue). Some scalar datasets have no palette and some datasets have one or more than one palettes. If 237 * an associated palette exists but not loaded, this interface retrieves the palette from the file and returns the 238 * palette. If the palette is loaded, it returnd the palette. It returns null if there is no palette assciated with 239 * the dataset. 240 * <p> 241 * Current implementation only supports palette model of indexed RGB with 256 colors. Other models such as 242 * YUV", "CMY", "CMYK", "YCbCr", "HSV will be supported in the future. 243 * <p> 244 * The palette values are stored in a two-dimensional byte array and arrange by color components of red, green and 245 * blue. palette[][] = byte[3][256], where, palette[0][], palette[1][] and palette[2][] are the red, green and blue 246 * components respectively. 247 * <p> 248 * Sub-classes have to implement this interface. HDF4 and HDF5 images use different libraries to retrieve the 249 * associated palette. 250 * 251 * @return the 2D palette byte array. 252 */ 253 public abstract byte[][] getPalette(); 254 255 /** 256 * Sets the palette for this dataset. 257 * 258 * @param pal 259 * the 2D palette byte array. 260 */ 261 public final void setPalette(byte[][] pal) { 262 palette = pal; 263 } 264 265 /** 266 * Reads a specific image palette from file. 267 * <p> 268 * A scalar dataset may have multiple palettes attached to it. readPalette(int idx) returns a specific palette 269 * identified by its index. 270 * 271 * @param idx 272 * the index of the palette to read. 273 * 274 * @return the image palette 275 */ 276 public abstract byte[][] readPalette(int idx); 277 278 /** 279 * Get the name of a specific image palette from file. 280 * <p> 281 * A scalar dataset may have multiple palettes attached to it. getPaletteName(int idx) returns the name of a 282 * specific palette identified by its index. 283 * 284 * @param idx 285 * the index of the palette to retrieve the name. 286 * 287 * @return The name of the palette 288 */ 289 public String getPaletteName(int idx) { 290 String paletteName = "Default "; 291 if (idx != 0) 292 paletteName = "Default " + idx; 293 return paletteName; 294 } 295 296 /** 297 * Returns the byte array of palette refs. 298 * <p> 299 * A palette reference is an object reference that points to the palette dataset. 300 * <p> 301 * For example, Dataset "Iceberg" has an attribute of object reference "Palette". The arrtibute "Palette" has value 302 * "2538" that is the object reference of the palette data set "Iceberg Palette". 303 * 304 * @return null if there is no palette attribute attached to this dataset. 305 */ 306 public abstract byte[] getPaletteRefs(); 307 308 /** 309 * Returns true if this dataset is an image. 310 * <p> 311 * For all Images, they must have an attribute called "CLASS". The value of this attribute is "IMAGE". For more 312 * details, read <a href="http://hdfgroup.org/HDF5/doc/ADGuide/ImageSpec.html"> HDF5 Image and Palette Specification 313 * </a> 314 * 315 * @return true if the dataset is an image; otherwise, returns false. 316 */ 317 public final boolean isImage() { 318 return isImage; 319 } 320 321 /** 322 * Returns true if this dataset is displayed as an image. 323 * <p> 324 * A ScalarDS can be displayed as an image or table. 325 * 326 * @return true if this dataset is displayed as an image; otherwise, returns false. 327 */ 328 public final boolean isImageDisplay() { 329 330 return isImageDisplay; 331 } 332 333 /** 334 * Returns true if this dataset is displayed as an image with default image order. 335 * <p> 336 * A ScalarDS can be displayed as an image with different orders of dimensions. 337 * 338 * @return true if this dataset is displayed as an image with default image order; otherwise, returns false. 339 */ 340 public final boolean isDefaultImageOrder() { 341 return isDefaultImageOrder; 342 } 343 344 /** 345 * Sets the flag to display the dataset as an image. 346 * 347 * @param b 348 * if b is true, display the dataset as an image 349 */ 350 public final void setIsImageDisplay(boolean b) { 351 isImageDisplay = b; 352 353 if (isImageDisplay) { 354 enumConverted = false; 355 } 356 } 357 358 /** 359 * Sets the flag to indicate this dataset is an image. 360 * 361 * @param b 362 * if b is true, the dataset is an image. 363 */ 364 public final void setIsImage(boolean b) { 365 isImage = b; 366 367 if (isImage) { 368 enumConverted = false; 369 } 370 } 371 372 /** 373 * Sets data range for an image. 374 * 375 * @param min 376 * the data range start. 377 * @param max 378 * the data range end. 379 */ 380 public final void setImageDataRange(double min, double max) { 381 if (max <= min) 382 return; 383 384 if (imageDataRange == null) 385 imageDataRange = new double[2]; 386 387 imageDataRange[0] = min; 388 imageDataRange[1] = max; 389 } 390 391 /** 392 * Add a value that will be filtered out in image 393 * 394 * @param x 395 * value to be filtered 396 */ 397 public void addFilteredImageValue(Number x) { 398 399 Iterator<Number> it = filteredImageValues.iterator(); 400 while (it.hasNext()) { 401 if (it.next().toString().equals(x.toString())) 402 return; 403 } 404 405 filteredImageValues.add(x); 406 } 407 408 /** 409 * get a list of values that will be filtered out in image 410 * 411 * @return the list of Image values 412 */ 413 public List<Number> getFilteredImageValues() { 414 return filteredImageValues; 415 } 416 417 /** 418 * @return true if this dataset is a true color image. 419 * 420 */ 421 422 public final boolean isTrueColor() { 423 return isTrueColor; 424 } 425 426 /** 427 * Returns true if this dataset is ASCII text. 428 * 429 * @return true if this dataset is ASCII text. 430 */ 431 public final boolean isText() { 432 return isText; 433 } 434 435 /** 436 * Returns the interlace mode of a true color image (RGB). 437 * 438 * Valid values: 439 * 440 * <pre> 441 * INTERLACE_PIXEL -- RGB components are contiguous, i.e. rgb, rgb, rgb, ... 442 * INTERLACE_LINE -- each RGB component is stored as a scan line 443 * INTERLACE_PLANE -- each RGB component is stored as a plane 444 * </pre> 445 * 446 * @return the interlace mode of a true color image (RGB). 447 */ 448 public final int getInterlace() { 449 return interlace; 450 } 451 452 /** 453 * Returns true if the original C data are unsigned integers. 454 * 455 * @return true if the original C data are unsigned integers. 456 */ 457 public final boolean isUnsigned() { 458 return isUnsigned; 459 } 460 461 /** 462 * Returns the (min, max) pair of image data range. 463 * 464 * @return the (min, max) pair of image data range. 465 */ 466 public double[] getImageDataRange() { 467 return imageDataRange; 468 } 469 470 /** 471 * Returns the fill values for the dataset. 472 * 473 * @return the fill values for the dataset. 474 */ 475 public final Object getFillValue() { 476 return fillValue; 477 } 478 479}