001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package imagingbook.common.image;
010
011import ij.process.Blitter;
012import ij.process.ImageProcessor;
013
014/**
015 * This class defines static methods for non-destructive, arithmetic operations on ImageJ's {@link ImageProcessor}
016 * objects. Unlike the built-in {@link ImageProcessor} methods, the methods below always return new images (of the same
017 * type) and keep the original images unmodified.
018 *
019 * @version 2013/08/23: static methods converted to use generics.
020 */
021public abstract class ImageMath {
022        
023        private ImageMath() {}
024
025        /**
026         * Calculates the absolute pixel values of the specified image and returns a new image of the same type.
027         *
028         * @param <T> the type of {@link ImageProcessor}
029         * @param ip the input image
030         * @return the resulting image
031         */
032        public static <T extends ImageProcessor> T abs(T ip) {
033                @SuppressWarnings("unchecked")
034                T ip2 = (T) ip.duplicate();
035                ip2.abs();
036                return ip2;
037        }
038
039        /**
040         * Calculates the squared pixel values of the specified image and returns a new image of the same type.
041         *
042         * @param <T> the type of {@link ImageProcessor}
043         * @param ip the input image
044         * @return the resulting image
045         */
046        public static <T extends ImageProcessor> T sqr(T ip) {
047                @SuppressWarnings("unchecked")
048                T ip2 = (T) ip.duplicate();
049                ip2.sqr();
050                return ip2;
051        }
052
053        /**
054         * Calculates the square root of the pixel values of the specified image and returns a new image of the same type.
055         *
056         * @param <T> the type of {@link ImageProcessor}
057         * @param ip the input image
058         * @return the resulting image
059         */
060        public static <T extends ImageProcessor> T sqrt(T ip) {
061                @SuppressWarnings("unchecked")
062                T ip2 = (T) ip.duplicate();
063                ip2.sqrt();
064                return ip2;
065        }
066
067        /**
068         * Adds the pixel values of the specified images and returns a new image of the same type as the first image.
069         *
070         * @param <T> the type of {@link ImageProcessor}
071         * @param ip1 first input image
072         * @param ip2 second input image
073         * @return the resulting image
074         */
075        public static<T extends ImageProcessor> T add(T ip1, T ip2) {
076                if (!ip1.getClass().equals(ip2.getClass())) {
077                        throw new IllegalArgumentException("input images must be of the same type");
078                }
079                @SuppressWarnings("unchecked")
080                T ip3 = (T) ip1.duplicate();
081                ip3.copyBits(ip2, 0, 0, Blitter.ADD);
082                return ip3;
083        }
084
085        /**
086         * Multiplies the pixel values of the specified images and returns a new image of the same type as the first image.
087         *
088         * @param <T> the type of {@link ImageProcessor}
089         * @param ip1 first input image
090         * @param ip2 second input image
091         * @return the resulting image
092         */
093        public static<T extends ImageProcessor> T mult(T ip1, T ip2) {
094                if (!ip1.getClass().equals(ip2.getClass())) {
095                        throw new IllegalArgumentException("input images must be of the same type");
096                }
097                @SuppressWarnings("unchecked")
098                T ip3 = (T) ip1.duplicate();
099                ip3.copyBits(ip2, 0, 0, Blitter.MULTIPLY);
100                return ip3;
101        }
102
103}