7

我已经看到它,因为 SVG-Salamander 对我的项目来说足够小。但我不知道我是否可以使用它,也不知道该怎么做。

我用过这段代码:

public static void main(String[] args) throws IOException, SVGException {
    // TODO Auto-generated method stub

    File f = new File("./src/game_scheme.svg");
    SVGUniverse svgUniverse = new SVGUniverse();
    SVGDiagram diagram = svgUniverse.getDiagram(svgUniverse.loadSVG(f.toURL()));
    BufferedImage bi = new BufferedImage(320, 240, BufferedImage.TYPE_INT_ARGB);
    Graphics2D ig2 = bi.createGraphics();
    diagram.render(ig2);
    ImageIO.write(bi, "PNG", new File("./yourImageName.png"));

}

但是图像不流畅:(,有什么想法吗?

4

2 回答 2

3

是的,使用 SVG Salamander 加载 SVG 文档:

  1. 创建一个BufferedImage.
  2. 从中创建一个Graphics2D上下文BufferedImage
  3. 调用render()绘制SVGDiagram图像。

这个过程可以使用 来简化SVGIcon,它处理 Salamander 内部,允许对象充当普通的 Swing Icon

要在命令行上光栅化多个 SVG 文件,可以使用 Ant 任务进行此类转换。有关详细信息,请参阅文档


下面是一个示例光栅器,给定 SVG 资源文件的路径,它将加载矢量图形并将其渲染到BufferedImage. 没有保修,没有支持。

SvgRasterizer.java

import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGException;
import com.kitfox.svg.SVGUniverse;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.Map;

import static java.awt.RenderingHints.*;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;

/**
 * Responsible for converting SVG images into rasterized PNG images.
 */
public class SvgRasterizer {
  public final static Map<Object, Object> RENDERING_HINTS = Map.of(
      KEY_ANTIALIASING,
      VALUE_ANTIALIAS_ON,
      KEY_ALPHA_INTERPOLATION,
      VALUE_ALPHA_INTERPOLATION_QUALITY,
      KEY_COLOR_RENDERING,
      VALUE_COLOR_RENDER_QUALITY,
      KEY_DITHERING,
      VALUE_DITHER_DISABLE,
      KEY_FRACTIONALMETRICS,
      VALUE_FRACTIONALMETRICS_ON,
      KEY_INTERPOLATION,
      VALUE_INTERPOLATION_BICUBIC,
      KEY_RENDERING,
      VALUE_RENDER_QUALITY,
      KEY_STROKE_CONTROL,
      VALUE_STROKE_PURE,
      KEY_TEXT_ANTIALIASING,
      VALUE_TEXT_ANTIALIAS_ON
  );

  private final static SVGUniverse sRenderer = new SVGUniverse();

  /**
   * Loads the resource specified by the given path into an instance of
   * {@link SVGDiagram} that can be rasterized into a bitmap format. The
   * {@link SVGUniverse} class will
   *
   * @param path The full path (starting at the root), relative to the
   *             application or JAR file's resources directory.
   * @return An {@link SVGDiagram} that can be rasterized onto a
   * {@link BufferedImage}.
   */
  public SVGDiagram loadDiagram( final String path ) {
    final var url = getResourceUrl( path );
    final var uri = sRenderer.loadSVG( url );
    final var diagram = sRenderer.getDiagram( uri );
    return applySettings( diagram );
  }

  /**
   * A reusable method to help compute the scaling factor between the
   * given {@link SVGDiagram} image and the target {@link Dimension}s.
   *
   * @param diagram A 2-dimensional vector graphic having a width and height.
   * @param dstDim  The image's target dimensions.
   * @return A key-value pair of the source image dimensions (key) and the
   * scaled image dimensions (value).
   */
  public DimensionTuple calculateScale(
      final SVGDiagram diagram, final Dimension dstDim ) {
    final var srcDim = new ScalableDimension(
        (int) diagram.getWidth(), (int) diagram.getHeight()
    );
    final var scaled = srcDim.scale( dstDim );

    return new DimensionTuple( srcDim, scaled );
  }

  /**
   * Rasterizes a vector graphic to a given size using a {@link BufferedImage}.
   * The rendering hints are set to produce high quality output.
   *
   * @param diagram The diagram to rasterize.
   * @param tuple   The source and destination image dimensions.
   * @return The rasterized {@link Image}.
   * @throws SVGException Could not open, read, parse, or render SVG data.
   */
  public BufferedImage rasterize(
      final SVGDiagram diagram, final DimensionTuple tuple )
      throws SVGException {
    final var scaled = tuple.getValue();
    final var wScaled = (int) scaled.getWidth();
    final var hScaled = (int) scaled.getHeight();
    final var image = new BufferedImage( wScaled, hScaled, TYPE_INT_ARGB );
    final var graphics = image.createGraphics();
    graphics.setRenderingHints( RENDERING_HINTS );

    final var transform = graphics.getTransform();
    transform.setToScale( tuple.getWidthRatio(), tuple.getHeightRatio() );

    graphics.setTransform( transform );
    diagram.render( graphics );
    graphics.dispose();

    return image;
  }

  /**
   * Rasterizes a vector graphic to a given size using a {@link BufferedImage}.
   * The rendering hints are set to produce high quality output.
   *
   * @param diagram The diagram to rasterize.
   * @param dstDim  The output image dimensions.
   * @return The rasterized {@link Image}.
   * @throws SVGException Could not open, read, parse, or render SVG data.
   */
  public Image rasterize(
      final SVGDiagram diagram, final Dimension dstDim ) throws SVGException {
    return rasterize( diagram, calculateScale( diagram, dstDim ) );
  }

  /**
   * Gets an instance of {@link URL} that references a file in the
   * application's resources.
   *
   * @param path The full path (starting at the root), relative to the
   *             application or JAR file's resources directory.
   * @return A {@link URL} to the file or {@code null} if the path does not
   * point to a resource.
   */
  private URL getResourceUrl( final String path ) {
    return SvgRasterizer.class.getResource( path );
  }

  /**
   * Instructs the SVG renderer to rasterize the image even if it would be
   * clipped.
   *
   * @param diagram The {@link SVGDiagram} to render.
   * @return The same instance with ignore clip heuristics set to {@code true}.
   */
  private SVGDiagram applySettings( final SVGDiagram diagram ) {
    diagram.setIgnoringClipHeuristic( true );
    return diagram;
  }
}

您还需要ScalableDimensionDimensionTuple类。

ScalableDimension.java

import java.awt.*;

public final class ScalableDimension extends Dimension {

  /**
   * Delegates construction to the superclass.
   *
   * @param w The dimension's width.
   * @param h The dimension's height.
   */
  public ScalableDimension( final int w, final int h ) {
    super( w, h );
  }

  /**
   * Delegates construction to this class.
   *
   * @param w The width, cast to an integer.
   * @param h The height, cast to an integer.
   */
  @SuppressWarnings("unused")
  public ScalableDimension( final double w, final double h ) {
    this( (int) w, (int) h );
  }

  /**
   * Scales the given source {@link Dimension} to the destination
   * {@link Dimension}, maintaining the aspect ratio with respect to
   * the best fit.
   *
   * @param dst The desired image dimensions to scale.
   * @return The given source dimensions scaled to the destination dimensions,
   * maintaining the aspect ratio.
   */
  public Dimension scale( final Dimension dst ) {
    final var srcWidth = getWidth();
    final var srcHeight = getHeight();

    // Determine the ratio that will have the best fit.
    final var ratio = Math.min(
        dst.getWidth() / srcWidth, dst.getHeight() / srcHeight
    );

    // Scale both dimensions with respect to the best fit ratio.
    return new ScalableDimension( (int) (srcWidth * ratio),
                                  (int) (srcHeight * ratio) );
  }
}

DimensionTuple.java

import java.awt.*;

public class DimensionTuple extends Pair<Dimension, Dimension> {
  /**
   * Associates a new {@link Dimension} tuple.
   *
   * @param key   The key for this key-value pairing.
   * @param value The value for this key-value pairing.
   */
  public DimensionTuple( final Dimension key, final Dimension value ) {
    super( key, value );
  }

  /**
   * Returns the ratio of the value width to the key width.
   *
   * @return A unit-less ratio between the value and key widths.
   */
  public double getWidthRatio() {
    return getValue().getWidth() / getKey().getWidth();
  }

  /**
   * Returns the ratio of the value height to the key height.
   *
   * @return A unit-less ratio between the value and key heights.
   */
  public double getHeightRatio() {
    return getValue().getHeight() / getKey().getHeight();
  }
}
于 2012-01-22T12:48:34.580 回答
3

如果您看到锯齿状边缘,您可以通过添加图形渲染提示来解决这个问题。

此外,在完成图形上下文后调用 dispose() 是个好主意。

Graphics2D ig2 = bi.createGraphics();
ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
diagram.render(ig2);
ig2.dispose();

ImageIO.write(bi, "PNG", new File("./yourImageName.png"));
于 2012-01-23T05:20:29.010 回答