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 Ch03_Point_Operations;
010
011import ij.ImagePlus;
012import ij.gui.GenericDialog;
013import ij.plugin.filter.PlugInFilter;
014import ij.process.ImageProcessor;
015import imagingbook.common.ij.DialogUtils;
016import imagingbook.core.jdoc.JavaDocHelp;
017import imagingbook.sampleimages.GeneralSampleImage;
018
019import static imagingbook.common.ij.IjUtils.noCurrentImage;
020
021/**
022 * <p>
023 * This ImageJ plugin increases the contrast of the selected grayscale image by 50%. The image is modified. See Sec.
024 * 3.1.1 (Prog. 3.1) of [1] for additional details.
025 * </p>
026 * <p>
027 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
028 * (2022).
029 * </p>
030 *
031 * @author WB
032 */
033public class Raise_Contrast implements PlugInFilter, JavaDocHelp {
034        
035        /** Contrast scale factor. */
036        public static double S = 1.5;
037
038        /** Constructor, asks to open a predefined sample image if no other image is currently open. */
039        public Raise_Contrast() {
040                if (noCurrentImage()) {
041                        DialogUtils.askForSampleImage(GeneralSampleImage.IrishManor);
042                }
043        }
044
045        @Override
046        public int setup(String arg, ImagePlus im) {
047                return DOES_8G;
048        }
049    
050        @Override
051        public void run(ImageProcessor ip) {
052                if (!runDialog()) {
053                        return;
054                }
055
056                int w = ip.getWidth();
057                int h = ip.getHeight();
058
059                for (int v = 0; v < h; v++) {
060                        for (int u = 0; u < w; u++) {
061                                int a = ip.get(u, v);
062                                int b = (int) (a * S + 0.5);    // safe form of rounding since a >= 0
063                                if (b > 255)
064                                        b = 255;                                        // clamp to the maximum value
065                                ip.set(u, v, b);
066                        }
067                }
068        }
069        private boolean runDialog() {
070                GenericDialog gd = new GenericDialog(this.getClass().getSimpleName());
071                gd.addHelp(getJavaDocUrl());
072                gd.addNumericField("Contrast scale (S > 0)", S, 2);
073
074                gd.showDialog();
075                if(gd.wasCanceled())
076                        return false;
077
078                S = gd.getNextNumber();
079                return true;
080        }
081}