public MultiLayerEdit(Composition comp, String name, MultiLayerBackup backup) { super(comp, name); this.canvasChangeEdit = backup.getCanvasChangeEdit(); this.translationEdit = backup.getTranslationEdit(); int nrLayers = comp.getNrImageLayers(); if (nrLayers == 1) { layer = comp.getAnyImageLayer(); imageEdit = backup.createImageEdit(layer.getImage()); undoable = true; } else { imageEdit = null; undoable = false; } if (comp.hasSelection()) { assert backup.hasSavedSelection(); selectionChangeEdit = backup.createSelectionChangeEdit(); } else { if (backup.hasSavedSelection()) { // it was a deselect: // either a selection crop or a crop tool crop without // overlap with the existing selection. deselectEdit = backup.createDeselectEdit(); } } }
public static void testLayers() { FgBgColors.setBG(WHITE); FgBgColors.setFG(BLACK); NewImage.addNewImage(FillType.TRANSPARENT, 400, 400, "Layer Test"); Composition comp = ImageComponents.getActiveComp().get(); addRasterizedTextLayer(comp, "this should be deleted", 0); addRasterizedTextLayer(comp, "this should at the bottom", 100); comp.moveActiveLayerToBottom(); comp.moveLayerSelectionUp(); comp.moveLayerSelectionUp(); DeleteActiveLayerAction.INSTANCE.actionPerformed(null); addRasterizedTextLayer(comp, "this should at the top", -100); addRasterizedTextLayer(comp, "this should be selected", 50); comp.moveActiveLayerDown(); // ic.moveActiveLayerDown(); // ic.flattenImage(); // merge down // HueSat // ColorBalance // Channel mixer comp.imageChanged(FULL); }
/** This code is executed with busy cursor */ public void runit(Composition comp, ChangeReason changeReason) { BufferedImage src = comp.getFilterSource(); // Utils.debugImage(src, "src"); BufferedImage dest = null; try { dest = executeForOneLayer(src); } catch (Exception e) { Layer activeLayer = comp.getActiveLayer(); String msg = String.format( "Error while executing the filter '%s'\n" + "composition = '%s'\n" + "layer = '%s'\n" + "mask editing = '%b'", getName(), comp.getName(), activeLayer.getName(), activeLayer.isMaskEditing()); throw new IllegalStateException(msg, e); } assert dest != null; if (changeReason.isPreview()) { comp.changePreviewImage(dest, getName(), changeReason); } else { comp.filterWithoutDialogFinished(dest, changeReason, getName()); } }
public static void randomToolActions(int numStrokes, boolean brushOnly) { Composition comp = ImageComponents.getActiveComp().get(); Random random = new Random(); if (comp != null) { int canvasWidth = comp.getCanvasWidth(); int canvasHeight = comp.getCanvasHeight(); ProgressMonitor progressMonitor = Utils.createPercentageProgressMonitor("1001 Tool Actions"); // So far we are on the EDT Runnable notEDTThreadTask = () -> { assert !SwingUtilities.isEventDispatchThread(); for (int i = 0; i < numStrokes; i++) { int progressPercentage = (int) ((float) i * 100 / numStrokes); progressMonitor.setProgress(progressPercentage); progressMonitor.setNote(progressPercentage + "%"); Runnable edtRunnable = () -> testToolAction(comp, random, canvasWidth, canvasHeight, brushOnly); try { SwingUtilities.invokeAndWait(edtRunnable); } catch (InterruptedException | InvocationTargetException e) { e.printStackTrace(); } comp.repaint(); } progressMonitor.close(); }; new Thread(notEDTThreadTask).start(); } }
public static void addRadialBWGradientToActiveLayer(Composition comp, boolean radial) { int canvasWidth = comp.getCanvasWidth(); int canvasHeight = comp.getCanvasHeight(); int startX = canvasWidth / 2; int startY = canvasHeight / 2; int endX = 0; int endY = 0; if (canvasWidth > canvasHeight) { endX = startX; } else { endY = startY; } GradientType gradientType; if (radial) { gradientType = GradientType.RADIAL; } else { gradientType = GradientType.SPIRAL_CW; } GradientTool.drawGradient( comp.getActiveMaskOrImageLayer(), gradientType, BLACK_TO_WHITE, REFLECT, AlphaComposite.SrcOver, new UserDrag(startX, startY, endX, endY), false); }
private static void paintDiagonals( AbstractBrushTool eraseTool, Composition comp, int xDistanceFormEdge, int yDistanceFormEdge) { int canvasWidth = comp.getCanvasWidth(); int canvasHeight = comp.getCanvasHeight(); Point topLeft = new Point(xDistanceFormEdge, yDistanceFormEdge); Point topRight = new Point(canvasWidth - xDistanceFormEdge, yDistanceFormEdge); Point bottomRight = new Point(canvasWidth - xDistanceFormEdge, canvasHeight - yDistanceFormEdge); Point bottomLeft = new Point(xDistanceFormEdge, canvasHeight - yDistanceFormEdge); eraseTool.drawBrushStrokeProgrammatically(comp, topLeft, bottomRight); eraseTool.drawBrushStrokeProgrammatically(comp, topRight, bottomLeft); }
private static void paintHeartShape(Composition comp) { ShapesTool shapesTool = Tools.SHAPES; int canvasWidth = comp.getCanvasWidth(); int canvasHeight = comp.getCanvasHeight(); UserDrag userDrag = new UserDrag( (int) (canvasWidth * 0.25), (int) (canvasHeight * 0.25), (int) (canvasWidth * 0.75), (int) (canvasHeight * 0.75)); shapesTool.setShapeType(ShapeType.HEART); shapesTool.paintShapeOnIC(comp, userDrag); }
public static void createSplashImage() { assert EventQueue.isDispatchThread(); NewImage.addNewImage(FillType.WHITE, 400, 247, "Splash"); Composition ic = ImageComponents.getActiveComp().get(); ic.getActiveLayer().setName("Color Wheel", AddToHistory.YES); new ColorWheel().execute(OP_WITHOUT_DIALOG); addNewLayer("Value Noise"); ValueNoise valueNoise = new ValueNoise(); valueNoise.setDetails(7); valueNoise.execute(OP_WITHOUT_DIALOG); ImageLayer layer = (ImageLayer) ic.getActiveLayer(); layer.setOpacity(0.3f, UpdateGUI.YES, AddToHistory.YES, true); layer.setBlendingMode(BlendingMode.SCREEN, UpdateGUI.YES, AddToHistory.YES, true); addNewLayer("Gradient"); ToolTests.addRadialBWGradientToActiveLayer(ic, true); layer = (ImageLayer) ic.getActiveLayer(); layer.setOpacity(0.4f, UpdateGUI.YES, AddToHistory.YES, true); layer.setBlendingMode(BlendingMode.LUMINOSITY, UpdateGUI.YES, AddToHistory.YES, true); FgBgColors.setFG(WHITE); Font font = new Font(SPLASH_SCREEN_FONT, Font.BOLD, 48); addRasterizedTextLayer(ic, "Pixelitor", WHITE, font, -17, BlendingMode.NORMAL, 0.9f, false); addDropShadow(); font = new Font(SPLASH_SCREEN_FONT, Font.BOLD, 22); addRasterizedTextLayer(ic, "Loading...", WHITE, font, -70, BlendingMode.NORMAL, 0.9f, false); addDropShadow(); font = new Font(SPLASH_SCREEN_FONT, Font.PLAIN, 20); addRasterizedTextLayer( ic, "version " + Build.VERSION_NUMBER, WHITE, font, 50, BlendingMode.NORMAL, 0.9f, false); addDropShadow(); // font = new Font(Font.SANS_SERIF, Font.PLAIN, 10); // addRasterizedTextLayer(ic, new Date().toString(), font, 0.8f, 100, false); }
public static void setEnabled(boolean b, Composition comp) { assert SwingUtilities.isEventDispatchThread() : "not EDT thread"; if (Build.CURRENT.isRobotTest()) { if (comp != null) { boolean hasSelection = comp.hasSelection(); if (hasSelection != b) { String name = comp.getName(); throw new IllegalStateException( "composition " + name + ": hasSelection = " + hasSelection + ", b = " + b); } } } cropAction.setEnabled(b); traceWithBrush.setEnabled(b); traceWithEraser.setEnabled(b); deselectAction.setEnabled(b); invertSelectionAction.setEnabled(b); modifyAction.setEnabled(b); }
public static void writeOpenRaster(Composition comp, File outFile, boolean addMergedImage) throws IOException { FileOutputStream fos = new FileOutputStream(outFile); ZipOutputStream zos = new ZipOutputStream(fos); String stackXML = String.format( "<?xml version='1.0' encoding='UTF-8'?>\n" + "<image w=\"%d\" h=\"%d\">\n" + "<stack>\n", comp.getCanvasWidth(), comp.getCanvasHeight()); int nrLayers = comp.getNrLayers(); // Reverse iteration: in stack.xml the first element in a stack is the uppermost. for (int i = nrLayers - 1; i >= 0; i--) { Layer layer = comp.getLayer(i); stackXML += writeLayer(zos, i, layer); } if (addMergedImage) { zos.putNextEntry(new ZipEntry("mergedimage.png")); ImageIO.write(comp.getCompositeImage(), "PNG", zos); zos.closeEntry(); } stackXML += "</stack>\n</image>"; // write the stack.xml file zos.putNextEntry(new ZipEntry("stack.xml")); zos.write(stackXML.getBytes("UTF-8")); zos.closeEntry(); // write the mimetype zos.putNextEntry(new ZipEntry("mimetype")); zos.write("image/openraster".getBytes("UTF-8")); zos.closeEntry(); zos.close(); }
@Override public void onClick() { ImageDisplay ic = ImageComponents.getActiveIC(); if (ic == null) { return; } Composition comp = ic.getComp(); if (!comp.activeIsImageLayer()) { Messages.showNotImageLayerError(); return; } getActiveComp() .flatMap(Composition::getSelection) .ifPresent( selection -> { Shape shape = selection.getShape(); if (shape != null) { brushTool.trace(getActiveComp().get(), shape); } }); }
private static void addRasterizedTextLayer( Composition ic, String text, Color textColor, Font font, int translationY, BlendingMode blendingMode, float opacity, boolean dropShadow) { addNewLayer(text); TextFilter textFilter = TextFilter.INSTANCE; AreaEffects effects = null; if (dropShadow) { effects = new AreaEffects(); effects.setDropShadowEffect(new ShadowPathEffect(1.0f)); } TextSettings settings = new TextSettings( text, font, textColor, effects, AbstractLayoutPainter.HorizontalAlignment.CENTER, AbstractLayoutPainter.VerticalAlignment.CENTER, false); textFilter.setSettings(settings); textFilter.execute(OP_WITHOUT_DIALOG); ImageLayer layer = (ImageLayer) ic.getActiveLayer(); layer.setTranslation(0, translationY); layer.enlargeImage(layer.getComp().getCanvasBounds()); layer.setOpacity(opacity, UpdateGUI.YES, AddToHistory.YES, true); layer.setBlendingMode(blendingMode, UpdateGUI.YES, AddToHistory.YES, true); }
public static Composition readOpenRaster(File file) throws IOException, ParserConfigurationException, SAXException { boolean DEBUG = System.getProperty("openraster.debug", "false").equals("true"); String stackXML = null; Map<String, BufferedImage> images = new HashMap<>(); try (ZipFile zipFile = new ZipFile(file)) { Enumeration<? extends ZipEntry> fileEntries = zipFile.entries(); while (fileEntries.hasMoreElements()) { ZipEntry entry = fileEntries.nextElement(); String name = entry.getName(); if (name.equalsIgnoreCase("stack.xml")) { stackXML = extractString(zipFile.getInputStream(entry)); } else if (name.equalsIgnoreCase("mergedimage.png")) { // no need for that } else { String extension = FileExtensionUtils.getFileExtension(name); if ("png".equalsIgnoreCase(extension)) { BufferedImage image = ImageIO.read(zipFile.getInputStream(entry)); images.put(name, image); if (DEBUG) { System.out.println( String.format( "OpenRaster::readOpenRaster: found png image in zip file at the path '%s'", name)); } } } } } if (stackXML == null) { throw new IllegalStateException("No stack.xml found."); } if (DEBUG) { System.out.println(String.format("OpenRaster::readOpenRaster: stackXML = '%s'", stackXML)); } Document doc = loadXMLFromString(stackXML); Element documentElement = doc.getDocumentElement(); documentElement.normalize(); String documentElementNodeName = documentElement.getNodeName(); if (!documentElementNodeName.equals("image")) { throw new IllegalStateException( String.format( "stack.xml root element is '%s', expected: 'image'", documentElementNodeName)); } String w = documentElement.getAttribute("w"); int compositionWidth = Integer.parseInt(w); String h = documentElement.getAttribute("h"); int compositionHeight = Integer.parseInt(h); if (DEBUG) { System.out.println( String.format( "OpenRaster::readOpenRaster: w = '%s', h = '%s', compositionWidth = %d, compositionHeight = %d", w, h, compositionWidth, compositionHeight)); } Composition comp = Composition.empty(compositionWidth, compositionHeight); comp.setFile(file); NodeList layers = documentElement.getElementsByTagName("layer"); for (int i = layers.getLength() - 1; i >= 0; i--) { // stack.xml contains layers in reverse order Node node = layers.item(i); Element element = (Element) node; String layerName = element.getAttribute("name"); String layerVisibility = element.getAttribute("visibility"); String layerVisible = element.getAttribute("visible"); String layerBlendingMode = element.getAttribute("composite-op"); String layerOpacity = element.getAttribute("opacity"); String layerImageSource = element.getAttribute("src"); String layerX = element.getAttribute("x"); String layerY = element.getAttribute("y"); BufferedImage image = images.get(layerImageSource); image = ImageUtils.toCompatibleImage(image); if (DEBUG) { int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); System.out.println( "OpenRaster::readOpenRaster: imageWidth = " + imageWidth + ", imageHeight = " + imageHeight); // Utils.debugImage(image, layerImageSource); } if (layerVisibility == null || layerVisibility.isEmpty()) { // workaround: paint.net exported files use "visible" attribute instead of "visibility" layerVisibility = layerVisible; } boolean visibility = layerVisibility == null ? true : layerVisibility.equals("visible"); ImageLayer layer = new ImageLayer(comp, image, layerName, null); layer.setVisible(visibility, AddToHistory.NO); BlendingMode blendingMode = BlendingMode.fromSVGName(layerBlendingMode); if (DEBUG) { System.out.println("OpenRaster::readOpenRaster: blendingMode = " + blendingMode); } layer.setBlendingMode(blendingMode, UpdateGUI.NO, AddToHistory.NO, false); float opacity = Utils.parseFloat(layerOpacity, 1.0f); layer.setOpacity(opacity, UpdateGUI.NO, AddToHistory.NO, false); int translationX = Utils.parseInt(layerX, 0); int translationY = Utils.parseInt(layerY, 0); // TODO assuming that there is no layer mask layer.setTranslation(translationX, translationY); if (DEBUG) { System.out.println( String.format( "OpenRaster::readOpenRaster: opacity = %.2f, translationX = %d, translationY = %d", opacity, translationX, translationY)); } comp.addLayerNoGUI(layer); } comp.setActiveLayer(comp.getLayer(0), AddToHistory.NO); return comp; }
public String dump() { String compDescr = comp == null ? "null" : comp.getName(); return name + " (" + compDescr + ')'; }