    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}