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