private static String writeLayer(ZipOutputStream zos, int layerIndex, Layer layer) throws IOException { if (!(layer instanceof ImageLayer)) { return ""; // currently only image layers are supported } ImageLayer imageLayer = (ImageLayer) layer; String stackXML = String.format( Locale.ENGLISH, "<layer name=\"%s\" visibility=\"%s\" composite-op=\"%s\" opacity=\"%f\" src=\"data/%d.png\" x=\"%d\" y=\"%d\"/>\n", layer.getName(), layer.getVisibilityAsORAString(), layer.getBlendingMode().toSVGName(), layer.getOpacity(), layerIndex, imageLayer.getTranslationX(), imageLayer.getTranslationX()); ZipEntry entry = new ZipEntry(String.format("data/%d.png", layerIndex)); zos.putNextEntry(entry); BufferedImage image = imageLayer.getImage(); ImageIO.write(image, "PNG", zos); zos.closeEntry(); return stackXML; }
private void updateGUI() { comp.imageChanged(FULL); layer.updateIconImage(); if (imageEdit instanceof ImageAndMaskEdit) { layer.getMask().updateIconImage(); } History.notifyMenus(this); }
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(); } } }
@Override public BufferedImage doTransform(BufferedImage src, BufferedImage dest) { // fill with the background color Graphics2D g = dest.createGraphics(); g.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); g.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC); g.setColor(bgColorParam.getColor()); g.fillRect(0, 0, dest.getWidth(), dest.getHeight()); double theta = angleParam.getValueInRadians(); ImageLayer layer = ImageComponents.getActiveImageLayerOrMask().get(); float relativeX = centerParam.getRelativeX(); float relativeY = centerParam.getRelativeY(); double centerShiftX = (-layer.getTX() + src.getWidth()) * relativeX; double centerShiftY = (-layer.getTY() + src.getHeight()) * relativeY; AffineTransform transform = AffineTransform.getRotateInstance(theta, centerShiftX, centerShiftY); int scaleX = scaleParam.getValue(0); int scaleY = scaleParam.getValue(1); if ((scaleX != 100) || (scaleY != 100)) { transform.translate(centerShiftX, centerShiftY); transform.scale(scaleX / 100.0, scaleY / 100.0); transform.translate(-centerShiftX, -centerShiftY); } int shearX = shearParam.getValue(0); int shearY = shearParam.getValue(1); if ((shearX != 0) || (shearY != 0)) { transform.translate(centerShiftX, centerShiftY); transform.shear(shearX / 100.0, shearY / 100.0); transform.translate(-centerShiftX, -centerShiftY); } g.drawImage(src, transform, null); g.dispose(); return dest; }
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); }
private void testMoveToolImpl(boolean altDrag) { move(400, 400); click(); if (altDrag) { altDrag(300, 300); } else { ImageLayer layer = ImageComponents.getActiveIC().getComp().getActiveImageLayerOrMask(); int txx = layer.getTranslationX(); int txy = layer.getTranslationY(); assert txx == 0; assert txy == 0; drag(200, 300); txx = layer.getTranslationX(); txy = layer.getTranslationY(); // This will be true only if we are at 100% zoom! assert txx == -200 : "txx = " + txx; assert txy == -100 : "txy = " + txx; } keyboardUndoRedo(); keyboardUndo(); }
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; }