All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.algart.multimatrix.SimpleMultiMatrix Maven / Gradle / Ivy

Go to download

Open-source libraries, providing the base core functionality for SciChains product.

There is a newer version: 4.4.7
Show newest version
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2017-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.algart.multimatrix;

import net.algart.arrays.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

class SimpleMultiMatrix implements MultiMatrix {
    final List> channels;
    private final PArray[] channelArrays;
    private final Class elementType;

    SimpleMultiMatrix(List> channels) {
        Objects.requireNonNull(channels, "Null channels");
        this.channels = new ArrayList<>(channels);
        checkNumberOfChannels(channels, false);
        Matrices.checkDimensionEquality(this.channels, true);
        this.elementType = channels.get(0).elementType();
        this.channelArrays = new PArray[channels.size()];
        for (int k = 0; k < channelArrays.length; k++) {
            channelArrays[k] = channels.get(k).array();
        }
    }

    @Override
    public Class elementType() {
        return elementType;
    }

    @Override
    public int numberOfChannels() {
        return channelArrays.length;
    }

    @Override
    public List> allChannels() {
        return Collections.unmodifiableList(channels);
    }

    @Override
    public Matrix channel(int channelIndex) {
        return channels.get(channelIndex);
    }

    @Override
    public PArray channelArray(int channelIndex) {
        return channelArrays[channelIndex];
    }

    @Override
    public long indexInArray(long... coordinates) {
        return channels.get(0).index(coordinates);
    }

    @Override
    public MultiMatrix asPrecision(Class newElementType) {
        if (newElementType == elementType()) {
            return this;
        }
        return new SimpleMultiMatrix(asPrecision(channels, newElementType));
    }

    @Override
    public MultiMatrix toPrecisionIfNot(Class newElementType) {
        if (newElementType == elementType()) {
            return this;
        }
        return new SimpleMultiMatrix(toPrecision(channels, newElementType));
    }

    @Override
    public MultiMatrix asMono() {
        return numberOfChannels() == 1 ?
                this :
                new SimpleMultiMatrix(Collections.singletonList(intensityChannel()));
    }

    public MultiMatrix asOtherNumberOfChannels(int newNumberOfChannels) {
        return newNumberOfChannels == numberOfChannels() ?
                this :
                new SimpleMultiMatrix(otherNumberOfChannels(newNumberOfChannels));
    }

    @Override
    public MultiMatrix clone() {
        return new SimpleMultiMatrix(MultiMatrix.cloneMatrices(channels));
    }

    @Override
    public MultiMatrix actualizeLazy() {
        return new SimpleMultiMatrix(MultiMatrix.actualizeLazyMatrices(channels));
    }

    @Override
    public String toString() {
        final long[] dimensions = dimensions();
        return "multi-matrix " + elementType()
                + " (" + numberOfChannels() + " channels, "
                + (dimensions.length == 1 ?
                dimensions[0] + "(x1)" :
                JArrays.toString(dimensions, "x", 1000)) + ")";
    }

    List> otherNumberOfChannels(int newNumberOfChannels) {
        if (newNumberOfChannels == 1 && isColor()) {
            return Collections.singletonList(intensityChannel());
        } else if (newNumberOfChannels < numberOfChannels()) {
            // - source is RGBA, but result is RGB only; 4th channels will be just ignored
            return allChannels().subList(0, newNumberOfChannels);
        } else {
            assert newNumberOfChannels > numberOfChannels();
            // in current implementation (possible 1, 3, 4 channels) it means
            // that result is RGBA, but source is grayscale or RGB
            final List> newChannels = new ArrayList<>(this.channels);
            for (int i = newChannels.size(), n = Math.min(3, newNumberOfChannels); i < n; i++) {
                // suppose that 1st 3 channels are identical (probably intensity)
                newChannels.add(this.channels.get(0));
            }
            // if newNumberOfChannels > 3, let's append it by alpha=1.0 (opacity)
            for (int i = newChannels.size(); i < newNumberOfChannels; i++) {
                newChannels.add(constantMatrix(maxPossibleValue()));
            }
            return newChannels;
        }
    }

    static void checkNumberOfChannels(List> channels, boolean illegalState) {
        Objects.requireNonNull(channels, "Null channels");
        final int n = channels.size();
        checkNumberOfChannels(n, illegalState);
    }

    static void checkNumberOfChannels(long n, boolean illegalState) {
        if (n <= 0 || n > MAX_NUMBER_OF_CHANNELS) {
            final String message = "Number of channels must be in range 1.." + MAX_NUMBER_OF_CHANNELS
                    + " (for example, 1 for monochrome, 3 for RGB, 4 for RGB+alpha), "
                    + "but " + n + " channels specified";
            throw illegalState ? new IllegalStateException(message) : new IllegalArgumentException(message);
        }
    }

    static List> flipRB(List> channels) {
        final List> newChannels = new ArrayList<>(channels);
        int n = newChannels.size();
        if (n == 3 || n == 4) {
            Matrix temp = newChannels.get(0);
            newChannels.set(0, newChannels.get(2));
            newChannels.set(2, temp);
        }
        return newChannels;
    }

    static List> asPrecision(
            List> channels,
            Class newElementType) {
        final List> result = new ArrayList<>();
        for (Matrix c : channels) {
            result.add(Matrices.asPrecision(c, newElementType));
        }
        return result;
    }

    static List> toPrecision(
            List> channels,
            Class newElementType) {
        final List> result = new ArrayList<>();
        for (Matrix c : channels) {
            final Matrix m = Arrays.SMM.newMatrix(
                    UpdatablePArray.class, newElementType, c.dimensions());
            Matrices.applyPrecision(null, m, c);
            result.add(m);
        }
        return result;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy