简体   繁体   English

在 Batik 中使用 SVGConverter 将 svg 转换为 png 时图像质量不佳

[英]Poor Image Quality when using SVGConverter in Batik to convert svg to png

My converted image's quality is very low.我转换后的图像质量非常低。 I have tried using the setQuality method but it does not seem to change anything.我曾尝试使用 setQuality 方法,但它似乎没有改变任何东西。

This is the part of the code that converts svg to png:这是将 svg 转换为 png 的代码部分:

SVGConverter svgConverter = new SVGConverter();
String[] sources = { "C:/imageData.svg" };
svgConverter.setSources(sources);
svgConverter.setDestinationType(DestinationType.PNG);
svgConverter.setDst(new File("C:/image.png"));

Does anyone know how I could make the image quality better?有谁知道我怎样才能使图像质量更好?

I use this code when converting SVG to PNG (using byte arrays):我在将 SVG 转换为 PNG 时使用此代码(使用字节数组):

private byte[] renderPng(byte[] svgBytes) {
    try {
        TranscoderInput transcoderInput = new TranscoderInput(new ByteArrayInputStream(svgBytes));
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        TranscoderOutput transcoderOutput = new TranscoderOutput(output);

        Transcoder transcoder = null;
        String type = "png";
        if(type.equalsIgnoreCase("png")) { 
            transcoder = new PNGTranscoder()
            {
                @Override
                protected ImageRenderer createRenderer()
                {
                    ImageRenderer r = super.createRenderer();

                    RenderingHints rh = r.getRenderingHints();

                    rh.add(new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
                        RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY));
                    rh.add(new RenderingHints(RenderingHints.KEY_INTERPOLATION,
                        RenderingHints.VALUE_INTERPOLATION_BICUBIC));

                    rh.add(new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON));

                    rh.add(new RenderingHints(RenderingHints.KEY_COLOR_RENDERING,
                        RenderingHints.VALUE_COLOR_RENDER_QUALITY));
                    rh.add(new RenderingHints(RenderingHints.KEY_DITHERING,
                        RenderingHints.VALUE_DITHER_DISABLE));

                    rh.add(new RenderingHints(RenderingHints.KEY_RENDERING,
                        RenderingHints.VALUE_RENDER_QUALITY));

                    rh.add(new RenderingHints(RenderingHints.KEY_STROKE_CONTROL,
                        RenderingHints.VALUE_STROKE_PURE));

                    rh.add(new RenderingHints(RenderingHints.KEY_FRACTIONALMETRICS,
                        RenderingHints.VALUE_FRACTIONALMETRICS_ON));
                    rh.add(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));

                    r.setRenderingHints(rh);

                    return r;
                }
            };

            transcoder.addTranscodingHint(PNGTranscoder.KEY_BACKGROUND_COLOR, Color.WHITE);
        } else {
            transcoder = new JPEGTranscoder();

            Float jpegQuality = new Float(0.95);
            // KEY_WIDTH - seems to pick it up just fine from the SVG charts.  Set to 560 otherwise.
            // KEY_QUALITY 0-1.0 with 1.0 being No Loss.  Value must be of type Float.  0.95 is 30% smaller and looks great.
            transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, jpegQuality);
        }

        // NOTE: for linux you need Java 1.4.1+ AND the headless environment (e.g. export JAVA_OPTS='-Djava.awt.headless=true').
        try {
            transcoder.transcode(transcoderInput, transcoderOutput);
        }
        catch(Exception e) {
            logger.error("SVG To Raster response transcode exception", e);
            if(output != null) {
                output.close();
            }
            throw( new RuntimeException("SVG To Raster Filter Response Stream Exception", e) );
        }

        if(output != null) {
            output.flush();
            output.close();
        }

        transcoderInput  = null;
        transcoderOutput = null;
        transcoder = null;

        return output.toByteArray();
    } catch (Exception exc) {
        logger.error("Error in rendering png method", exc);
    }
    return new byte[0];
}

Also, your clipPath elements in your SVG documents should contain this attribute, otherwise it will have strange artifacts:此外,SVG 文档中的 clipPath 元素应包含此属性,否则会出现奇怪的工件:

<clipPath shape-rendering="geometricPrecision" ... >

In Apache Batik, you can change resolution by passing Transcoder hint KEY_PIXEL_UNIT_TO_MILLIMETER.在 Apache Batik 中,您可以通过传递转码器提示 KEY_PIXEL_UNIT_TO_MILLIMETER 来更改分辨率。

However the important aspect is that you need to scale your height & width to same scale as the new resolution you are seeking.然而,重要的方面是您需要将高度和宽度缩放到与您正在寻求的新分辨率相同的比例。

For example:例如:

my SVG has 3.5 * 2.0 Inches (252 * 144 Pixels) size.我的 SVG 有 3.5 * 2.0 英寸(252 * 144 像素)大小。

Target resolution is 600 DPI.目标分辨率为 600 DPI。

int RESOLUTION_DPI = 600;
float SCALE_BY_RESOLUTION = RESOLUTION_DPI / 72f;
float scaledWidth = 252*SCALE_BY_RESOLUTION;
float scaledHeight = 144*SCALE_BY_RESOLUTION;
float pixelUnitToMM = new Float(25.4f/RESOLUTION_DPI);

transcoderInput = new TranscoderInput(svgDocument);
TranscoderOutput transcoderOutput = new TranscoderOutput(ostream);
transcoder.addTranscodingHint(ImageTranscoder.KEY_BACKGROUND_COLOR, Color.WHITE);
transcoder.addTranscodingHint(PNGTranscoder.KEY_WIDTH, scaledWidth);
transcoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, scaledHeight);

transcoder.addTranscodingHint(PNGTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, pixelUnitToMM);

transcoder.transcode(transcoderInput, transcoderOutput);

Try this....尝试这个....

jpeg.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(keyQuality));
jpeg.addTranscodingHint(JPEGTranscoder.KEY_HEIGHT, height*scalePercentage);
jpeg.addTranscodingHint(JPEGTranscoder.KEY_WIDTH, width*scalePercentage);
jpeg.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, 1.0f);
jpeg.addTranscodingHint(JPEGTranscoder.KEY_BACKGROUND_COLOR, Color.WHITE);

You need to increase the height and width like set keyQuality 1.0f.您需要像 set keyQuality 1.0f 一样增加高度和宽度。

If height=200 increase height by 200*3(height*scalePercentage).如果 height=200 将高度增加 200*3(height*scalePercentage)。 Similar to width also宽度也类似

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM