Example usage for java.awt.geom AffineTransform scale

List of usage examples for java.awt.geom AffineTransform scale

Introduction

In this page you can find the example usage for java.awt.geom AffineTransform scale.

Prototype

@SuppressWarnings("fallthrough")
public void scale(double sx, double sy) 

Source Link

Document

Concatenates this transform with a scaling transformation.

Usage

From source file:org.geomajas.plugin.rasterizing.layer.RasterDirectLayer.java

protected void addImage(Graphics2D graphics, ImageResult imageResult, MapViewport viewport) throws IOException {
    Rectangle screenArea = viewport.getScreenArea();
    ReferencedEnvelope worldBounds = viewport.getBounds();
    // convert map bounds to application bounds
    double printScale = screenArea.getWidth() / worldBounds.getWidth();
    if (tileScale < 0) {
        tileScale = printScale;/* www . ja va2  s. c o  m*/
    }
    Envelope applicationBounds = new Envelope((worldBounds.getMinX()) * printScale,
            (worldBounds.getMaxX()) * printScale, -(worldBounds.getMinY()) * printScale,
            -(worldBounds.getMaxY()) * printScale);
    Bbox imageBounds = imageResult.getRasterImage().getBounds();
    // find transform between image bounds and application bounds
    double tx = (imageBounds.getX() * printScale / tileScale - applicationBounds.getMinX());
    double ty = (imageBounds.getY() * printScale / tileScale - applicationBounds.getMinY());
    BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageResult.getImage()));
    double scaleX = imageBounds.getWidth() / image.getWidth() * printScale / tileScale;
    double scaleY = imageBounds.getHeight() / image.getHeight() * printScale / tileScale;
    AffineTransform transform = new AffineTransform();
    transform.translate(tx, ty);
    transform.scale(scaleX, scaleY);
    if (log.isDebugEnabled()) {
        log.debug("adding image, width=" + image.getWidth() + ",height=" + image.getHeight() + ",x=" + tx
                + ",y=" + ty);
    }
    // opacity
    log.debug("before drawImage");
    // create a copy to apply transform
    Graphics2D g = (Graphics2D) graphics.create();
    // apply opacity to image off-graphics to avoid interference with whatever opacity model is used by graphics
    BufferedImage opaqueCopy = makeOpaque(image);
    g.drawImage(opaqueCopy, transform, null);
    log.debug("after drawImage");
}

From source file:be.fedict.eidviewer.gui.printing.IDPrintout.java

public int print(Graphics graphics, PageFormat pageFormat, int pageNumber) throws PrinterException {
    // we only support printing all in one single page
    if (pageNumber > 0)
        return Printable.NO_SUCH_PAGE;

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("width", pageFormat.getWidth()).append("height", pageFormat.getHeight())
            .append("imageableWidth", pageFormat.getImageableWidth())
            .append("imageableHeight", pageFormat.getImageableHeight())
            .append("imageableX", pageFormat.getImageableX()).append("imageableY", pageFormat.getImageableY())
            .append("orientation", pageFormat.getOrientation())
            .append("paper.width", pageFormat.getPaper().getWidth())
            .append("paper.height", pageFormat.getPaper().getHeight())
            .append("paper.imageableWidth", pageFormat.getPaper().getImageableWidth())
            .append("paper.imageableHeight", pageFormat.getPaper().getImageableHeight())
            .append("paper.imageableX", pageFormat.getPaper().getImageableX())
            .append("paper.imageableY", pageFormat.getPaper().getImageableY()).toString());

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("clip.width", graphics.getClipBounds().width)
            .append("clip.height", graphics.getClipBounds().height).append("clip.x", graphics.getClipBounds().x)
            .append("clip.y", graphics.getClipBounds().y).toString());

    // translate graphics2D with origin at top left first imageable location
    Graphics2D graphics2D = (Graphics2D) graphics;
    graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

    // keep imageable width and height as variables for clarity (we use them often)
    float imageableWidth = (float) pageFormat.getImageableWidth();
    float imageableHeight = (float) pageFormat.getImageableHeight();

    // Coat of Arms images are stored at approx 36 DPI, scale 1/2 to get to Java default of 72DPI
    AffineTransform coatOfArmsTransform = new AffineTransform();
    coatOfArmsTransform.scale(0.5, 0.5);

    // photo images are stored at approx 36 DPI, scale 1/2 to get to Java default of 72DPI
    AffineTransform photoTransform = new AffineTransform();
    photoTransform.scale(0.5, 0.5);//from  w ww.  j a v  a 2  s  .  c om
    photoTransform.translate((imageableWidth * 2) - (photo.getWidth(this)), 0);

    // make sure foreground is black, and draw coat of Arms and photo at the top of the page
    // using the transforms to scale them to 72DPI.
    graphics2D.setColor(Color.BLACK);
    graphics2D.drawImage(coatOfArms, coatOfArmsTransform, null);
    graphics2D.drawImage(photo, photoTransform, null);

    // calculate some sizes that need to take into account the scaling of the graphics, to avoid dragging
    // those non-intuitive "/2" further along in the code.
    float headerHeight = (float) (coatOfArms.getHeight(this)) / 2;
    float coatOfArmsWidth = (float) (coatOfArms.getWidth(this)) / 2;
    float photoWidth = (float) (photo.getWidth(this)) / 2;
    float headerSpaceBetweenImages = imageableWidth
            - (coatOfArmsWidth + photoWidth + (SPACE_BETWEEN_ITEMS * 2));

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("headerHeight", headerHeight)
            .append("coatOfArmsWidth", coatOfArmsWidth).append("photoWidth", photoWidth)
            .append("headerSpaceBetweenImages", headerSpaceBetweenImages).toString());

    // get localised strings for card type. We'll take a new line every time a ";" is found in the resource
    String[] cardTypeStr = (bundle.getString("type_" + this.identity.getDocumentType().toString())
            .toUpperCase()).split(";");

    // if a "mention" is present, append it so it appears below the card type string, between brackets

    if (identity.getSpecialOrganisation() != SpecialOrganisation.UNSPECIFIED) {
        String mention = TextFormatHelper.getSpecialOrganisationString(bundle,
                identity.getSpecialOrganisation());
        if (mention != null && !mention.isEmpty()) {
            String[] cardTypeWithMention = new String[cardTypeStr.length + 1];
            System.arraycopy(cardTypeStr, 0, cardTypeWithMention, 0, cardTypeStr.length);
            cardTypeWithMention[cardTypeStr.length] = "(" + mention + ")";
            cardTypeStr = cardTypeWithMention;
        }
    }

    // iterate from MAXIMAL_FONT_SIZE, calculating how much space would be required to fit the card type strings
    // stop when a font size is found where they all fit the space between the graphics in an orderly manner
    boolean sizeFound = false;
    int fontSize;
    for (fontSize = TITLE_MAXIMAL_FONT_SIZE; (fontSize >= MINIMAL_FONT_SIZE) && (!sizeFound); fontSize--) // count down slowly until we find one that fits nicely
    {
        logger.log(Level.FINE, "fontSize=" + fontSize + " sizeFound=" + sizeFound);
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));
        sizeFound = (ImageUtilities.getTotalStringWidth(graphics2D, cardTypeStr) < headerSpaceBetweenImages)
                && (ImageUtilities.getTotalStringHeight(graphics2D, cardTypeStr) < headerHeight);
    }

    // unless with extremely small papers, a size should always have been found.
    // draw the card type strings, centered, between the images at the top of the page
    if (sizeFound) {
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize + 1));
        float cardTypeHeight = cardTypeStr.length * ImageUtilities.getStringHeight(graphics2D);
        float cardTypeBaseLine = ((headerHeight - cardTypeHeight) / 2) + ImageUtilities.getAscent(graphics2D);
        float cardTypeLineHeight = ImageUtilities.getStringHeight(graphics2D);

        logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("cardTypeHeight", cardTypeHeight).append("cardTypeBaseLine", cardTypeBaseLine)
                .append("cardTypeLineHeight", cardTypeLineHeight).toString());

        for (int i = 0; i < cardTypeStr.length; i++) {
            float left = (coatOfArmsWidth + SPACE_BETWEEN_ITEMS
                    + (headerSpaceBetweenImages - ImageUtilities.getStringWidth(graphics2D, cardTypeStr[i]))
                            / 2);
            float leading = (float) cardTypeLineHeight * i;
            graphics2D.drawString(cardTypeStr[i], left, cardTypeBaseLine + leading);
        }
    }

    // populate idAttributes with all the information from identity and address
    // as well as date printed and some separators
    List<IdentityAttribute> idAttributes = populateAttributeList();

    // draw a horizontal line just below the header (images + card type titles)
    graphics2D.drawLine(0, (int) headerHeight, (int) imageableWidth, (int) headerHeight);

    // calculate how much space is left between the header and the bottom of the imageable area

    headerHeight += 32; // take some distance from header

    float imageableDataHeight = imageableHeight - headerHeight;
    float totalDataWidth = 0, totalDataHeight = 0;
    float labelWidth, widestLabelWidth = 0;
    float valueWidth, widestValueWidth = 0;

    // iterate from MAXIMAL_FONT_SIZE, calculating how much space would be required to fit the information in idAttributes into
    // the space between the header and the bottom of the imageable area
    // stop when a font size is found where it all fits in an orderly manner
    sizeFound = false;
    for (fontSize = MAXIMAL_FONT_SIZE; (fontSize >= MINIMAL_FONT_SIZE) && (!sizeFound); fontSize--) // count down slowly until we find one that fits nicely
    {
        logger.log(Level.FINE, "fontSize=" + fontSize + " sizeFound=" + sizeFound);
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));

        widestLabelWidth = 0;
        widestValueWidth = 0;

        for (IdentityAttribute attribute : idAttributes) {
            if (attribute == SEPARATOR)
                continue;

            labelWidth = ImageUtilities.getStringWidth(graphics2D, attribute.getLabel());
            valueWidth = ImageUtilities.getStringWidth(graphics2D, attribute.getValue());
            if (labelWidth > widestLabelWidth)
                widestLabelWidth = labelWidth;
            if (valueWidth > widestValueWidth)
                widestValueWidth = valueWidth;
        }

        totalDataWidth = widestLabelWidth + SPACE_BETWEEN_ITEMS + widestValueWidth;
        totalDataHeight = ImageUtilities.getStringHeight(graphics2D)
                + (ImageUtilities.getStringHeight(graphics2D) * idAttributes.size());

        if ((totalDataWidth < imageableWidth) && (totalDataHeight < imageableDataHeight))
            sizeFound = true;
    }

    logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
            .append("widestLabelWidth", widestLabelWidth).append("widestValueWidth", widestValueWidth)
            .append("totalDataWidth", totalDataWidth).append("totalDataHeight", totalDataHeight).toString());

    // unless with extremely small papers, a size should always have been found.
    // draw the identity, addess and date printed information, in 2 columns, centered inside the
    // space between the header and the bottom of the imageable area
    if (sizeFound) {
        graphics2D.setFont(new Font(FONT, Font.PLAIN, fontSize));
        float labelsLeft = (imageableWidth - totalDataWidth) / 2;
        float valuesLeft = labelsLeft + widestLabelWidth + SPACE_BETWEEN_ITEMS;
        float dataLineHeight = ImageUtilities.getStringHeight(graphics2D);
        float dataTop = dataLineHeight + headerHeight + ((imageableDataHeight - totalDataHeight) / 2);
        float lineNumber = 0;

        logger.finest(new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("labelsLeft", labelsLeft)
                .append("valuesLeft", valuesLeft).append("dataLineHeight", dataLineHeight)
                .append("dataTop", dataTop).toString());

        for (IdentityAttribute attribute : idAttributes) {
            if (attribute != SEPARATOR) // data
            {
                graphics2D.setColor(attribute.isRelevant() ? Color.BLACK : Color.LIGHT_GRAY);
                graphics2D.drawString(attribute.getLabel(), labelsLeft,
                        dataTop + (lineNumber * dataLineHeight));
                graphics2D.drawString(attribute.getValue(), valuesLeft,
                        dataTop + (lineNumber * dataLineHeight));
            } else // separator
            {
                int y = (int) (((dataTop + (lineNumber * dataLineHeight) + (dataLineHeight / 2)))
                        - ImageUtilities.getAscent(graphics2D));
                graphics2D.setColor(Color.BLACK);
                graphics2D.drawLine((int) labelsLeft, y, (int) (labelsLeft + totalDataWidth), y);
            }
            lineNumber++;
        }
    }

    // tell Java printing that all this makes for a page worth printing :-)
    return Printable.PAGE_EXISTS;
}

From source file:JXTransformer.java

public void scale(double sx, double sy) {
    AffineTransform transform = getTransform();
    transform.scale(sx, sy);
    setTransform(transform);/*from w  w  w . j  av a  2s.  co  m*/
}

From source file:org.apache.pdfbox.pdfviewer.PageDrawer.java

/**
 * You should override this method if you want to perform an action when a
 * text is being processed./*from   w w  w. j a  v a  2 s .  com*/
 *
 * @param text The text to process
 */
protected void processTextPosition(TextPosition text) {
    try {
        PDGraphicsState graphicsState = getGraphicsState();
        Composite composite;
        Paint paint;
        switch (graphicsState.getTextState().getRenderingMode()) {
        case PDTextState.RENDERING_MODE_FILL_TEXT:
            composite = graphicsState.getNonStrokeJavaComposite();
            paint = graphicsState.getNonStrokingColor().getJavaColor();
            if (paint == null) {
                paint = graphicsState.getNonStrokingColor().getPaint(pageSize.height);
            }
            break;
        case PDTextState.RENDERING_MODE_STROKE_TEXT:
            composite = graphicsState.getStrokeJavaComposite();
            paint = graphicsState.getStrokingColor().getJavaColor();
            if (paint == null) {
                paint = graphicsState.getStrokingColor().getPaint(pageSize.height);
            }
            break;
        case PDTextState.RENDERING_MODE_NEITHER_FILL_NOR_STROKE_TEXT:
            //basic support for text rendering mode "invisible"
            Color nsc = graphicsState.getStrokingColor().getJavaColor();
            float[] components = { Color.black.getRed(), Color.black.getGreen(), Color.black.getBlue() };
            paint = new Color(nsc.getColorSpace(), components, 0f);
            composite = graphicsState.getStrokeJavaComposite();
            break;
        default:
            // TODO : need to implement....
            LOG.debug("Unsupported RenderingMode " + this.getGraphicsState().getTextState().getRenderingMode()
                    + " in PageDrawer.processTextPosition()." + " Using RenderingMode "
                    + PDTextState.RENDERING_MODE_FILL_TEXT + " instead");
            composite = graphicsState.getNonStrokeJavaComposite();
            paint = graphicsState.getNonStrokingColor().getJavaColor();
        }
        graphics.setComposite(composite);
        graphics.setPaint(paint);

        PDFont font = text.getFont();
        Matrix textPos = text.getTextPos().copy();
        float x = textPos.getXPosition();
        // the 0,0-reference has to be moved from the lower left (PDF) to the upper left (AWT-graphics)
        float y = pageSize.height - textPos.getYPosition();
        // Set translation to 0,0. We only need the scaling and shearing
        textPos.setValue(2, 0, 0);
        textPos.setValue(2, 1, 0);
        // because of the moved 0,0-reference, we have to shear in the opposite direction
        textPos.setValue(0, 1, (-1) * textPos.getValue(0, 1));
        textPos.setValue(1, 0, (-1) * textPos.getValue(1, 0));
        AffineTransform at = textPos.createAffineTransform();
        PDMatrix fontMatrix = font.getFontMatrix();
        at.scale(fontMatrix.getValue(0, 0) * 1000f, fontMatrix.getValue(1, 1) * 1000f);
        //TODO setClip() is a massive performance hot spot. Investigate optimization possibilities
        graphics.setClip(graphicsState.getCurrentClippingPath());
        // the fontSize is no longer needed as it is already part of the transformation
        // we should remove it from the parameter list in the long run
        font.drawString(text.getCharacter(), text.getCodePoints(), graphics, 1, at, x, y);
    } catch (IOException io) {
        io.printStackTrace();
    }
}

From source file:com.mucommander.ui.viewer.image.ImageViewer.java

private synchronized void zoom(double factor) {
    setFrameCursor(CURSOR_WAIT);/*w w w  .  java2  s . c  o m*/

    final int srcWidth = image.getWidth(null);
    final int srcHeight = image.getHeight(null);
    final int scaledWidth = (int) (srcWidth * factor);
    final int scaledHeight = (int) (srcHeight * factor);

    if (factor != 1.0) {
        AbstractFile file = filesInDirectory.get(indexInDirectory);
        if ("svg".equalsIgnoreCase(file.getExtension())) {
            try {
                this.scaledImage = transcodeSVGDocument(file, scaledWidth, scaledHeight);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            this.scaledImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
            AffineTransform at = new AffineTransform();
            at.scale(factor, factor);
            AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
            this.scaledImage = scaleOp.filter(this.image, this.scaledImage);
        }
    } else {
        this.scaledImage = image;
    }

    statusBar.setZoom(factor);
    checkZoom();
    setFrameCursor(CURSOR_DEFAULT);
}

From source file:graph.eventhandlers.MyEditingGraphMousePlugin.java

/**
 * code lifted from PluggableRenderer to move an edge shape into an
 * arbitrary position/*w ww. j a v a2  s.  co  m*/
 */
private void transformEdgeShape(Point2D down, Point2D out) {
    float x1 = (float) down.getX();
    float y1 = (float) down.getY();
    float x2 = (float) out.getX();
    float y2 = (float) out.getY();

    AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);

    float dx = x2 - x1;
    float dy = y2 - y1;
    float thetaRadians = (float) Math.atan2(dy, dx);
    xform.rotate(thetaRadians);
    float dist = (float) Math.sqrt(dx * dx + dy * dy);
    xform.scale(dist / rawEdge.getBounds().getWidth(), 1.0);
    edgeShape = xform.createTransformedShape(rawEdge);
}

From source file:PrintCanvas3D.java

public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {

    if (pi >= 1) {
        return Printable.NO_SUCH_PAGE;
    }/*from ww  w .ja  v a2 s .c  om*/

    Graphics2D g2d = (Graphics2D) g;
    //g2d.translate(pf.getImageableX(), pf.getImageableY());
    AffineTransform t2d = new AffineTransform();
    t2d.translate(pf.getImageableX(), pf.getImageableY());
    double xscale = pf.getImageableWidth() / (double) bImage.getWidth();
    double yscale = pf.getImageableHeight() / (double) bImage.getHeight();
    double scale = Math.min(xscale, yscale);
    t2d.scale(scale, scale);
    try {
        g2d.drawImage(bImage, t2d, this);
    } catch (Exception ex) {
        ex.printStackTrace();
        return Printable.NO_SUCH_PAGE;
    }
    return Printable.PAGE_EXISTS;
}

From source file:JXTransformer.java

public void stateChanged(ChangeEvent e) {
        AffineTransform at = new AffineTransform();
        at.rotate(rotationSlider.getValue() * Math.PI / 180);
        double scale = scalingSlider.getValue() / 100.0;
        at.scale(scale, scale);
        double shear = shearingSlider.getValue() / 10.0;
        at.shear(shear, 0);/*from w ww.j  ava  2  s  . c  o m*/
        for (JXTransformer t : transformers) {
            t.setTransform(at);
        }
    }

From source file:org.apache.batchee.tools.maven.doc.DiagramGenerator.java

private void saveView(final Dimension currentSize, final Dimension desiredSize, final String name,
        final VisualizationViewer<Node, Edge> viewer) {
    BufferedImage bi = new BufferedImage(currentSize.width, currentSize.height, BufferedImage.TYPE_INT_ARGB);

    final Graphics2D g = bi.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

    final boolean db = viewer.isDoubleBuffered();
    viewer.setDoubleBuffered(false);//  w  w  w  .j  ava2s . c  o  m
    viewer.paint(g);
    viewer.setDoubleBuffered(db);
    if (!currentSize.equals(desiredSize)) {
        final double xFactor = desiredSize.width * 1. / currentSize.width;
        final double yFactor = desiredSize.height * 1. / currentSize.height;
        final double factor = Math.min(xFactor, yFactor);
        info("optimal size is (" + currentSize.width + ", " + currentSize.height + ")");
        info("scaling with a factor of " + factor);

        final AffineTransform tx = new AffineTransform();
        tx.scale(factor, factor);
        final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage biNew = new BufferedImage((int) (bi.getWidth() * factor), (int) (bi.getHeight() * factor),
                bi.getType());
        bi = op.filter(bi, biNew);
    }
    g.dispose();

    OutputStream os = null;
    try {
        final File file = new File(output, (outputFileName != null ? outputFileName : name) + "." + format);
        os = new FileOutputStream(file);
        if (!ImageIO.write(bi, format, os)) {
            throw new IllegalStateException("can't save picture " + name + "." + format);
        }
        info("Saved " + file.getAbsolutePath());
    } catch (final IOException e) {
        throw new IllegalStateException("can't save the diagram", e);
    } finally {
        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (final IOException e) {
                // no-op
            }
        }
    }
}

From source file:org.apache.batchee.tools.maven.DiagramMojo.java

private void saveView(final Dimension currentSize, final Dimension desiredSize, final String name,
        final VisualizationViewer<Node, Edge> viewer) throws MojoExecutionException {
    BufferedImage bi = new BufferedImage(currentSize.width, currentSize.height, BufferedImage.TYPE_INT_ARGB);

    final Graphics2D g = bi.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

    final boolean db = viewer.isDoubleBuffered();
    viewer.setDoubleBuffered(false);//from w ww  . j a v a2 s .  c  om
    viewer.paint(g);
    viewer.setDoubleBuffered(db);
    if (!currentSize.equals(desiredSize)) {
        final double xFactor = desiredSize.width * 1. / currentSize.width;
        final double yFactor = desiredSize.height * 1. / currentSize.height;
        final double factor = Math.min(xFactor, yFactor);
        getLog().info("optimal size is (" + currentSize.width + ", " + currentSize.height + ")");
        getLog().info("scaling with a factor of " + factor);

        final AffineTransform tx = new AffineTransform();
        tx.scale(factor, factor);
        final AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage biNew = new BufferedImage((int) (bi.getWidth() * factor), (int) (bi.getHeight() * factor),
                bi.getType());
        bi = op.filter(bi, biNew);
    }
    g.dispose();

    OutputStream os = null;
    try {
        final File file = new File(output, (outputFileName != null ? outputFileName : name) + "." + format);
        os = new FileOutputStream(file);
        if (!ImageIO.write(bi, format, os)) {
            throw new MojoExecutionException("can't save picture " + name + "." + format);
        }
        getLog().info("Saved " + file.getAbsolutePath());
    } catch (final IOException e) {
        throw new MojoExecutionException("can't save the diagram", e);
    } finally {
        if (os != null) {
            try {
                os.flush();
                os.close();
            } catch (final IOException e) {
                // no-op
            }
        }
    }
}