/* * Copyright 2017 Laszlo Balazs-Csiki * * This file is part of Pixelitor. Pixelitor is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License, version 3 as published by the Free * Software Foundation. * * Pixelitor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Pixelitor. If not, see <http://www.gnu.org/licenses/>. */ package pixelitor.filters.jhlabsproxies; import com.jhlabs.composite.MiscComposite; import com.jhlabs.image.RaysFilter; import pixelitor.filters.FilterWithParametrizedGUI; import pixelitor.filters.ResizingFilterHelper; import pixelitor.filters.gui.BooleanParam; import pixelitor.filters.gui.ImagePositionParam; import pixelitor.filters.gui.ParamSet; import pixelitor.filters.gui.RangeParam; import pixelitor.filters.gui.ShowOriginal; import pixelitor.utils.BasicProgressTracker; import pixelitor.utils.ImageUtils; import pixelitor.utils.ProgressTracker; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import static pixelitor.filters.ResizingFilterHelper.ScaleUpQuality.BILINEAR_FAST; import static pixelitor.filters.gui.RandomizePolicy.IGNORE_RANDOMIZE; /** * Rays based on the JHLabs RaysFilter */ public class JHRays extends FilterWithParametrizedGUI { public static final String NAME = "Rays"; private final ImagePositionParam center = new ImagePositionParam("Light Source"); private final RangeParam rotation = new RangeParam("Twirl", -90, 0, 90); private final RangeParam length = new RangeParam("Length", 0, 20, 200); private final RangeParam opacity = new RangeParam("Opacity (%)", 0, 80, 100); private final RangeParam strength = new RangeParam("Strength", 0, 200, 500); private final RangeParam threshold = new RangeParam("Threshold (%)", 0, 25, 100); private final BooleanParam raysOnly = new BooleanParam("Rays Only", false, IGNORE_RANDOMIZE); private RaysFilter filter; public JHRays() { super(ShowOriginal.YES); setParamSet(new ParamSet( center, length, threshold, strength, opacity, rotation, raysOnly )); } @Override public BufferedImage doTransform(BufferedImage src, BufferedImage dest) { if (filter == null) { filter = new RaysFilter(NAME); } filter.setCentreX(center.getRelativeX()); filter.setCentreY(center.getRelativeY()); filter.setStrength(strength.getValueAsPercentage()); filter.setRotation(rotation.getValueInRadians()); // filter.setOpacity(opacity.getValueAsPercentage()); filter.setThreshold(threshold.getValueAsPercentage()); // filter.setRaysOnly(raysOnly.isChecked()); // this value should not be divided by resizeFactor because // this is a scale and not really a length filter.setZoom(length.getValueAsPercentage()); ResizingFilterHelper r = new ResizingFilterHelper(src); boolean shouldResize = r.shouldResize(); int filterUnits = 3; int workUnits = filterUnits + 3; // +3 for the rays only step at the end if (shouldResize) { int resizeUnits = r.getResizeWorkUnits(BILINEAR_FAST); workUnits += resizeUnits; } ProgressTracker pt = new BasicProgressTracker(NAME, workUnits); // ProgressTracker pt = new DebugProgressTracker(NAME, workUnits); filter.setProgressTracker(pt); BufferedImage rays; if (shouldResize) { rays = r.invoke(BILINEAR_FAST, filter, pt, 0); } else { // normal case, no resizing rays = filter.filter(src, dest); } // so far we have the rays image, // which contains white rays on a black background if (raysOnly.isChecked()) { // make sure we have a transparent background if (dest == null) { dest = filter.createCompatibleDestImage(src, null); } Graphics2D g = dest.createGraphics(); g.setComposite(MiscComposite.getInstance(MiscComposite.ADD, opacity.getValueAsPercentage())); g.drawRenderedImage(rays, null); g.dispose(); pt.addUnits(3); pt.finish(); return dest; } // add the rays on top of the source dest = ImageUtils.copyImage(src); Graphics2D g = dest.createGraphics(); g.setComposite(MiscComposite.getInstance(MiscComposite.ADD, opacity.getValueAsPercentage())); g.drawRenderedImage(rays, null); g.dispose(); pt.addUnits(3); pt.finish(); return dest; } @Override public boolean supportsGray() { return false; } }