001/*- 002 ******************************************************************************* 003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Peter Chang - initial API and implementation and/or initial documentation 011 *******************************************************************************/ 012 013package org.eclipse.january.dataset; 014 015import java.util.Arrays; 016 017import org.slf4j.Logger; 018import org.slf4j.LoggerFactory; 019 020/** 021 * Class to hold colour datasets as red, green, blue tuples of short integers 022 */ 023public class RGBDataset extends CompoundShortDataset implements Cloneable { 024 // pin UID to base class 025 private static final long serialVersionUID = Dataset.serialVersionUID; 026 027 private static final Logger logger = LoggerFactory.getLogger(RGBDataset.class); 028 029 private static final int ISIZE = 3; // number of elements per item 030 031 /** 032 * Create a null dataset 033 */ 034 public RGBDataset() { 035 super(ISIZE); 036 } 037 038 /** 039 * @param shape output shape 040 */ 041 public RGBDataset(final int... shape) { 042 super(ISIZE, shape); 043 } 044 045 /** 046 * @param data interleaved RGB values 047 * @param shape output shape 048 */ 049 public RGBDataset(final short[] data, final int... shape) { 050 super(ISIZE, data, shape); 051 } 052 053 /** 054 * Copy a dataset 055 * @param dataset to clone 056 */ 057 public RGBDataset(final RGBDataset dataset) { 058 super(dataset); 059 } 060 061 @Override 062 public RGBDataset clone() { 063 return new RGBDataset(this); 064 } 065 066 /** 067 * Create a dataset using given data (red, green and blue parts are given separately) 068 * @param redData data for red 069 * @param greenData data for green 070 * @param blueData data for blue 071 * @param shape (can be null to create 1D dataset) 072 */ 073 public RGBDataset(final int[] redData, final int[] greenData, final int[] blueData, int... shape) { 074 int dsize = redData.length > greenData.length ? greenData.length : redData.length; 075 dsize = dsize > blueData.length ? blueData.length : dsize; 076 if (shape == null || shape.length == 0) { 077 shape = new int[] {dsize}; 078 } 079 isize = ISIZE; 080 size = ShapeUtils.calcSize(shape); 081 if (size != dsize) { 082 logger.error("Shape is not compatible with size of data array"); 083 throw new IllegalArgumentException("Shape is not compatible with size of data array"); 084 } 085 this.shape = shape.clone(); 086 087 try { 088 odata = data = createArray(size); 089 } catch (Throwable t) { 090 logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t); 091 throw new IllegalArgumentException(t); 092 } 093 094 for (int i = 0, n = 0; i < size; i++) { 095 data[n++] = (short) redData[i]; 096 data[n++] = (short) greenData[i]; 097 data[n++] = (short) blueData[i]; 098 } 099 } 100 101 /** 102 * Create a dataset using given data (red, green and blue parts are given separately) 103 * @param redData data for red 104 * @param greenData data for green 105 * @param blueData data for blue 106 * @param shape (can be null to create 1D dataset) 107 */ 108 public RGBDataset(final short[] redData, final short[] greenData, final short[] blueData, int... shape) { 109 int dsize = redData.length > greenData.length ? greenData.length : redData.length; 110 dsize = dsize > blueData.length ? blueData.length : dsize; 111 if (shape == null || shape.length == 0) { 112 shape = new int[] {dsize}; 113 } 114 isize = ISIZE; 115 size = ShapeUtils.calcSize(shape); 116 if (size != dsize) { 117 logger.error("Shape is not compatible with size of data array"); 118 throw new IllegalArgumentException("Shape is not compatible with size of data array"); 119 } 120 this.shape = shape.clone(); 121 122 try { 123 odata = data = createArray(size); 124 } catch (Throwable t) { 125 logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t); 126 throw new IllegalArgumentException(t); 127 } 128 129 for (int i = 0, n = 0; i < size; i++) { 130 data[n++] = redData[i]; 131 data[n++] = greenData[i]; 132 data[n++] = blueData[i]; 133 } 134 } 135 136 /** 137 * Create a dataset using given data (red, green and blue parts are given separately) 138 * @param redData data for red 139 * @param greenData data for green 140 * @param blueData data for blue 141 * @param shape (can be null to create 1D dataset) 142 */ 143 public RGBDataset(final byte[] redData, final byte[] greenData, final byte[] blueData, int... shape) { 144 int dsize = redData.length > greenData.length ? greenData.length : redData.length; 145 dsize = dsize > blueData.length ? blueData.length : dsize; 146 if (shape == null || shape.length == 0) { 147 shape = new int[] {dsize}; 148 } 149 isize = ISIZE; 150 size = ShapeUtils.calcSize(shape); 151 if (size != dsize) { 152 logger.error("Shape is not compatible with size of data array"); 153 throw new IllegalArgumentException("Shape is not compatible with size of data array"); 154 } 155 this.shape = shape.clone(); 156 157 try { 158 odata = data = createArray(size); 159 } catch (Throwable t) { 160 logger.error("Could not create a dataset of shape {}", Arrays.toString(shape), t); 161 throw new IllegalArgumentException(t); 162 } 163 164 for (int i = 0, n = 0; i < size; i++) { 165 data[n++] = (short) (0xff & redData[i]); 166 data[n++] = (short) (0xff & greenData[i]); 167 data[n++] = (short) (0xff & blueData[i]); 168 } 169 } 170 171 /** 172 * Create a dataset using given colour data (colour components are given separately) 173 * @param red dataset 174 * @param green dataset 175 * @param blue dataset 176 */ 177 public RGBDataset(final Dataset red, final Dataset green, final Dataset blue) { 178 super(ISIZE, red.getShapeRef()); 179 red.checkCompatibility(green); 180 red.checkCompatibility(blue); 181 182 if (red.max().doubleValue() > Short.MAX_VALUE || red.min().doubleValue() < Short.MIN_VALUE || 183 green.max().doubleValue() > Short.MAX_VALUE || green.min().doubleValue() < Short.MIN_VALUE || 184 blue.max().doubleValue() > Short.MAX_VALUE || blue.min().doubleValue() < Short.MIN_VALUE) { 185 logger.warn("Some values are out of range and will be truncated"); 186 } 187 188 IndexIterator riter = red.getIterator(); 189 IndexIterator giter = green.getIterator(); 190 IndexIterator biter = blue.getIterator(); 191 192 for (int i = 0; riter.hasNext() && giter.hasNext() && biter.hasNext();) { 193 data[i++] = (short) red.getElementLongAbs(riter.index); 194 data[i++] = (short) green.getElementLongAbs(giter.index); 195 data[i++] = (short) blue.getElementLongAbs(biter.index); 196 } 197 } 198 199 /** 200 * Create a dataset using given grey data 201 * @param grey dataset 202 */ 203 public RGBDataset(final Dataset grey) { 204 super(ISIZE, grey.getShapeRef()); 205 206 IndexIterator giter = grey.getIterator(); 207 208 for (int i = 0; giter.hasNext();) { 209 final short g = (short) grey.getElementLongAbs(giter.index); 210 data[i++] = g; 211 data[i++] = g; 212 data[i++] = g; 213 } 214 } 215 216 /** 217 * Create a dataset using given compound data 218 * @param colour dataset with colour data 219 * @since 2.3 220 */ 221 public RGBDataset(final CompoundDataset colour) { 222 super(ISIZE, colour.getShapeRef()); 223 224 if (colour.getElementsPerItem() != 3) { 225 throw new IllegalArgumentException("Compound dataset must have three elements per item"); 226 } 227 228 final IndexIterator it = colour.getIterator(); 229 for (int i = 0; it.hasNext();) { 230 data[i++] = (short) colour.getElementLongAbs(it.index); 231 data[i++] = (short) colour.getElementLongAbs(it.index + 1); 232 data[i++] = (short) colour.getElementLongAbs(it.index + 2); 233 } 234 } 235 /** 236 * Create a RGB dataset from an object which could be a Java list, array (of arrays...) or Number. Ragged 237 * sequences or arrays are padded with zeros. The item size is the last dimension of the corresponding 238 * elemental dataset 239 * 240 * @param obj object 241 * @return dataset with contents given by input 242 */ 243 public static RGBDataset createFromObject(final Object obj) { 244 CompoundShortDataset result = (CompoundShortDataset) DatasetUtils.createCompoundDataset(ShortDataset.createFromObject(obj), ISIZE); 245 return new RGBDataset(result.data, result.shape); 246 } 247 248 /** 249 * Create a RGB dataset from a compound dataset (no normalisation performed) 250 * @param a dataset 251 * @return RGB dataset (grey if input dataset has less than 3 elements per item) 252 */ 253 public static RGBDataset createFromCompoundDataset(final CompoundDataset a) { 254 if (a instanceof RGBDataset) 255 return (RGBDataset) a; 256 final int is = a.getElementsPerItem(); 257 if (is < 3) { 258 return new RGBDataset((Dataset) a); 259 } 260 261 if (a instanceof CompoundShortDataset && is == 3) { 262 return new RGBDataset((short[]) a.getBuffer(), a.getShapeRef()); 263 } 264 265 final RGBDataset rgb = new RGBDataset(a.getShapeRef()); 266 final IndexIterator it = a.getIterator(); 267 268 int n = 0; 269 while (it.hasNext()) { 270 rgb.data[n++] = (short) a.getElementLongAbs(it.index); 271 rgb.data[n++] = (short) a.getElementLongAbs(it.index + 1); 272 rgb.data[n++] = (short) a.getElementLongAbs(it.index + 2); 273 } 274 275 return rgb; 276 } 277 278 /** 279 * Create a RGB dataset from hue, saturation and value dataset 280 * @param hue (in degrees from -360 to 360) 281 * @param saturation (from 0 to 1), can be null to denote 1 282 * @param value (from 0 to 1) 283 * @return RGB dataset 284 */ 285 public static RGBDataset createFromHSV(final Dataset hue, final Dataset saturation, final Dataset value) { 286 if ((saturation != null && !hue.isCompatibleWith(saturation)) || !hue.isCompatibleWith(value)) { 287 throw new IllegalArgumentException("Hue, saturation and value datasets must have the same shape"); 288 } 289 290 RGBDataset result = new RGBDataset(hue.getShapeRef()); 291 IndexIterator it = result.getIterator(true); 292 int[] pos = it.getPos(); 293 short[] rgb = new short[3]; 294 295 if (saturation == null) { 296 while (it.hasNext()) { 297 convertHSVToRGB(hue.getDouble(pos), 1, value.getDouble(pos), rgb); 298 result.setAbs(it.index, rgb); 299 } 300 } else { 301 while (it.hasNext()) { 302 convertHSVToRGB(hue.getDouble(pos), saturation.getDouble(pos), value.getDouble(pos), rgb); 303 result.setAbs(it.index, rgb); 304 } 305 } 306 307 return result; 308 } 309 310 /** 311 * Create a RGB dataset from hue, saturation and lightness dataset 312 * @param hue (in degrees from -360 to 360) 313 * @param saturation (from 0 to 1), can be null to denote 1 314 * @param lightness (from 0 to 1) 315 * @return RGB dataset 316 */ 317 public static RGBDataset createFromHSL(final Dataset hue, final Dataset saturation, final Dataset lightness) { 318 if ((saturation != null && !hue.isCompatibleWith(saturation)) || !hue.isCompatibleWith(lightness)) { 319 throw new IllegalArgumentException("Hue, saturation and lightness datasets must have the same shape"); 320 } 321 322 RGBDataset result = new RGBDataset(hue.getShapeRef()); 323 IndexIterator it = result.getIterator(true); 324 int[] pos = it.getPos(); 325 short[] rgb = new short[3]; 326 327 if (saturation == null) { 328 while (it.hasNext()) { 329 convertHSLToRGB(hue.getDouble(pos), 1, lightness.getDouble(pos), rgb); 330 result.setAbs(it.index, rgb); 331 } 332 } else { 333 while (it.hasNext()) { 334 convertHSLToRGB(hue.getDouble(pos), saturation.getDouble(pos), lightness.getDouble(pos), rgb); 335 result.setAbs(it.index, rgb); 336 } 337 } 338 339 return result; 340 } 341 342 private static void convertHSVToRGB(double h, double s, double v, short[] rgb) { 343 double m = 255 * v; 344 double chroma = s * m; 345 m -= chroma; 346 double hprime = h / 60.; 347 if (hprime < 0) { 348 hprime += 6; 349 } 350 short sx = (short) (chroma * (1 - Math.abs((hprime % 2) - 1)) + m); 351 short sc = (short) (chroma + m); 352 short sm = (short) m; 353 354 if (hprime < 1) { 355 rgb[0] = sc; 356 rgb[1] = sx; 357 rgb[2] = sm; 358 } else if (hprime < 2) { 359 rgb[0] = sx; 360 rgb[1] = sc; 361 rgb[2] = sm; 362 } else if (hprime < 3) { 363 rgb[0] = sm; 364 rgb[1] = sc; 365 rgb[2] = sx; 366 } else if (hprime < 4) { 367 rgb[0] = sm; 368 rgb[1] = sx; 369 rgb[2] = sc; 370 } else if (hprime < 5) { 371 rgb[0] = sx; 372 rgb[1] = sm; 373 rgb[2] = sc; 374 } else if (hprime < 6) { 375 rgb[0] = sc; 376 rgb[1] = sm; 377 rgb[2] = sx; 378 } else { // if hue is outside domain 379 rgb[0] = sm; 380 rgb[1] = sm; 381 rgb[2] = sm; 382 } 383 } 384 385 private static void convertHSLToRGB(double h, double s, double l, short[] rgb) { 386 double m = l; 387 double chroma = s * (1 - Math.abs(2 * m - 1)); 388 m -= chroma * 0.5; 389 m *= 255; 390 chroma *= 255; 391 double hprime = h / 60.; 392 if (hprime < 0) { 393 hprime += 6; 394 } 395 short sx = (short) (chroma * (1 - Math.abs((hprime % 2) - 1)) + m); 396 short sc = (short) (chroma + m); 397 short sm = (short) m; 398 399 if (hprime < 1) { 400 rgb[0] = sc; 401 rgb[1] = sx; 402 rgb[2] = sm; 403 } else if (hprime < 2) { 404 rgb[0] = sx; 405 rgb[1] = sc; 406 rgb[2] = sm; 407 } else if (hprime < 3) { 408 rgb[0] = sm; 409 rgb[1] = sc; 410 rgb[2] = sx; 411 } else if (hprime < 4) { 412 rgb[0] = sm; 413 rgb[1] = sx; 414 rgb[2] = sc; 415 } else if (hprime < 5) { 416 rgb[0] = sx; 417 rgb[1] = sm; 418 rgb[2] = sc; 419 } else if (hprime < 6) { 420 rgb[0] = sc; 421 rgb[1] = sm; 422 rgb[2] = sx; 423 } else { // if hue is outside domain 424 rgb[0] = sm; 425 rgb[1] = sm; 426 rgb[2] = sm; 427 } 428 } 429 430 @Override 431 public RGBDataset getSlice(SliceIterator siter) { 432 CompoundShortDataset base = super.getSlice(siter); 433 434 RGBDataset slice = new RGBDataset(); 435 copyToView(base, slice, false, false); 436 slice.setData(); 437 return slice; 438 } 439 440 @Override 441 public RGBDataset getView(boolean deepCopyMetadata) { 442 RGBDataset view = new RGBDataset(); 443 copyToView(this, view, true, deepCopyMetadata); 444 view.setData(); 445 return view; 446 } 447 448 /** 449 * @return red value in the first position 450 * @since 2.0 451 */ 452 public short getRed() { 453 return data[getFirst1DIndex()]; 454 } 455 456 /** 457 * @param i position in first dimension 458 * @return red value in given position 459 */ 460 public short getRed(final int i) { 461 return data[get1DIndex(i)]; 462 } 463 464 /** 465 * @param i position in first dimension 466 * @param j position in second dimension 467 * @return red value in given position 468 */ 469 public short getRed(final int i, final int j) { 470 return data[get1DIndex(i, j)]; 471 } 472 473 /** 474 * @param pos position 475 * @return red value in given position 476 */ 477 public short getRed(final int... pos) { 478 return data[get1DIndex(pos)]; 479 } 480 481 /** 482 * @return green value in the first position 483 * @since 2.0 484 */ 485 public short getGreen() { 486 return data[getFirst1DIndex() + 1]; 487 } 488 489 /** 490 * @param i position in first dimension 491 * @return green value in given position 492 */ 493 public short getGreen(final int i) { 494 return data[get1DIndex(i) + 1]; 495 } 496 497 /** 498 * @param i position in first dimension 499 * @param j position in second dimension 500 * @return green value in given position 501 */ 502 public short getGreen(final int i, final int j) { 503 return data[get1DIndex(i, j) + 1]; 504 } 505 506 /** 507 * @param pos position 508 * @return green value in given position 509 */ 510 public short getGreen(final int... pos) { 511 return data[get1DIndex(pos) + 1]; 512 } 513 514 /** 515 * @return blue value in the first position 516 * @since 2.0 517 */ 518 public short getBlue() { 519 return data[getFirst1DIndex() + 2]; 520 } 521 522 /** 523 * @param i position in first dimension 524 * @return blue value in given position 525 */ 526 public short getBlue(final int i) { 527 return data[get1DIndex(i) + 2]; 528 } 529 530 /** 531 * @param i position in first dimension 532 * @param j position in second dimension 533 * @return blue value in given position 534 */ 535 public short getBlue(final int i, final int j) { 536 return data[get1DIndex(i, j) + 2]; 537 } 538 539 /** 540 * @param pos position 541 * @return blue value in given position 542 */ 543 public short getBlue(final int... pos) { 544 return data[get1DIndex(pos) + 2]; 545 } 546 547 /** 548 * Get a red value from given absolute index as a short - note this index does not 549 * take in account the item size so be careful when using with multi-element items 550 * 551 * @param n absolute index 552 * @return red value 553 */ 554 public short getRedAbs(int n) { 555 return data[n*isize]; 556 } 557 558 /** 559 * Get a green value from given absolute index as a short - note this index does not 560 * take in account the item size so be careful when using with multi-element items 561 * 562 * @param n absolute index 563 * @return green value 564 */ 565 public short getGreenAbs(int n) { 566 return data[n*isize + 1]; 567 } 568 569 /** 570 * Get a blue value from given absolute index as a short - note this index does not 571 * take in account the item size so be careful when using with multi-element items 572 * 573 * @param n absolute index 574 * @return blue value 575 */ 576 public short getBlueAbs(int n) { 577 return data[n*isize + 2]; 578 } 579 580 581 // weights from NTSC formula aka ITU-R BT.601 for mapping RGB to luma 582 private static final double Wr = 0.299, Wg = 0.587, Wb = 0.114; 583 584 /** 585 * Convert colour dataset to a grey-scale one using the NTSC formula, aka ITU-R BT.601, for RGB to luma mapping 586 * @param <T> dataset sub-interface 587 * @param clazz dataset sub-interface 588 * @return a grey-scale dataset of given type 589 * @since 2.2 590 */ 591 public <T extends Dataset> T createGreyDataset(final Class<T> clazz) { 592 return createGreyDataset(clazz, Wr, Wg, Wb); 593 } 594 595 /** 596 * Convert colour dataset to a grey-scale one using given RGB to luma mapping 597 * @param <T> dataset sub-interface 598 * @param clazz dataset sub-interface 599 * @param red weight 600 * @param green weight 601 * @param blue weight 602 * @return a grey-scale dataset of given class 603 * @since 2.2 604 */ 605 public <T extends Dataset> T createGreyDataset(final Class<T> clazz, final double red, final double green, final double blue) { 606 final T grey = DatasetFactory.zeros(clazz, shape); 607 final IndexIterator it = getIterator(); 608 609 int i = 0; 610 while (it.hasNext()) { 611 grey.setObjectAbs(i++, red*data[it.index] + green*data[it.index + 1] + blue*data[it.index + 2]); 612 } 613 return grey; 614 } 615 616 /** 617 * Convert colour dataset to a grey-scale one using the NTSC formula, aka ITU-R BT.601, for RGB to luma mapping 618 * @param dtype dataset type 619 * @return a grey-scale dataset of given class 620 * @deprecated Use {@link RGBDataset#createGreyDataset(Class)} 621 */ 622 @Deprecated 623 public Dataset createGreyDataset(final int dtype) { 624 return createGreyDataset(Wr, Wg, Wb, dtype); 625 } 626 627 /** 628 * Convert colour dataset to a grey-scale one using given RGB to luma mapping 629 * @param red weight 630 * @param green weight 631 * @param blue weight 632 * @param dtype dataset type 633 * @return a grey-scale dataset of given type 634 * @deprecated Use {@link RGBDataset#createGreyDataset(Class, double, double, double)} 635 */ 636 @Deprecated 637 public Dataset createGreyDataset(final double red, final double green, final double blue, final int dtype) { 638 return createGreyDataset(DTypeUtils.getInterface(dtype), red, green, blue); 639 } 640 641 /** 642 * Extract red colour channel 643 * @param <T> dataset sub-interface 644 * @param clazz dataset sub-interface 645 * @return a dataset of given class 646 * @since 2.1 647 */ 648 public <T extends Dataset> T createRedDataset(final Class<T> clazz) { 649 return createColourChannelDataset(0, clazz, "red"); 650 } 651 652 /** 653 * Extract green colour channel 654 * @param <T> dataset sub-interface 655 * @param clazz dataset sub-interface 656 * @return a dataset of given class 657 * @since 2.1 658 */ 659 public <T extends Dataset> T createGreenDataset(final Class<T> clazz) { 660 return createColourChannelDataset(1, clazz, "green"); 661 } 662 663 /** 664 * Extract blue colour channel 665 * @param <T> dataset sub-interface 666 * @param clazz dataset sub-interface 667 * @return a dataset of given class 668 * @since 2.1 669 */ 670 public <T extends Dataset> T createBlueDataset(final Class<T> clazz) { 671 return createColourChannelDataset(2, clazz, "blue"); 672 } 673 674 /** 675 * Extract red colour channel 676 * @param dtype dataset type 677 * @return a dataset of given type 678 * @deprecated Use {@link #createRedDataset} 679 */ 680 @Deprecated 681 public Dataset createRedDataset(final int dtype) { 682 return createColourChannelDataset(0, DTypeUtils.getInterface(dtype), "red"); 683 } 684 685 /** 686 * Extract green colour channel 687 * @param dtype dataset type 688 * @return a dataset of given type 689 * @deprecated Use {@link #createGreenDataset} 690 */ 691 @Deprecated 692 public Dataset createGreenDataset(final int dtype) { 693 return createColourChannelDataset(1, DTypeUtils.getInterface(dtype), "green"); 694 } 695 696 /** 697 * Extract blue colour channel 698 * @param dtype dataset type 699 * @return a dataset of given type 700 * @deprecated Use {@link #createBlueDataset} 701 */ 702 @Deprecated 703 public Dataset createBlueDataset(final int dtype) { 704 return createColourChannelDataset(2, DTypeUtils.getInterface(dtype), "blue"); 705 } 706 707 private <T extends Dataset> T createColourChannelDataset(int channelOffset, Class<T> clazz, String cName) { 708 final T channel = DatasetFactory.zeros(clazz, shape); 709 710 final StringBuilder cname = name == null ? new StringBuilder() : new StringBuilder(name); 711 if (cname.length() > 0) { 712 cname.append('.'); 713 } 714 cname.append(cName); 715 channel.setName(cname.toString()); 716 717 final IndexIterator it = getIterator(); 718 719 int i = 0; 720 while (it.hasNext()) { 721 channel.setObjectAbs(i++, data[it.index + channelOffset]); 722 } 723 724 return channel; 725 } 726 727 728 /** 729 * @return red view 730 */ 731 public ShortDataset getRedView() { 732 return getColourChannelView(0, "red"); 733 } 734 735 /** 736 * @return green view 737 */ 738 public ShortDataset getGreenView() { 739 return getColourChannelView(1, "green"); 740 } 741 742 /** 743 * @return blue view 744 */ 745 public ShortDataset getBlueView() { 746 return getColourChannelView(2, "blue"); 747 } 748 749 private ShortDataset getColourChannelView(final int channelOffset, final String cName) { 750 ShortDataset view = getElements(channelOffset); 751 view.setName(cName); 752 return view; 753 } 754 755 @Override 756 public Number max(boolean... ignored) { 757 short max = Short.MIN_VALUE; 758 final IndexIterator it = getIterator(); 759 760 while (it.hasNext()) { 761 for (int i = 0; i < ISIZE; i++) { 762 final short value = data[it.index + i]; 763 if (value > max) 764 max = value; 765 } 766 } 767 return max; 768 } 769 770 @Override 771 public Number min(boolean... ignored) { 772 short min = Short.MAX_VALUE; 773 final IndexIterator it = getIterator(); 774 775 while (it.hasNext()) { 776 for (int i = 0; i < ISIZE; i++) { 777 final short value = data[it.index + i]; 778 if (value < min) 779 min = value; 780 } 781 } 782 return min; 783 } 784}