Плохое качество изображения при использовании SVGConverter в Batik для преобразования svg в png

Качество моего конвертированного изображения очень низкое. Я пробовал использовать метод setQuality, но, похоже, он ничего не меняет.

Это часть кода, которая преобразует 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"));

Кто-нибудь знает, как я могу улучшить качество изображения?


person KrispyDonuts    schedule 27.06.2012    source источник


Ответы (3)


Я использую этот код при преобразовании 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];
}

Кроме того, элементы clipPath в документах SVG должны содержать этот атрибут, иначе будут странные артефакты:

<clipPath shape-rendering="geometricPrecision" ... >
person Kestas    schedule 25.11.2012

Попробуй это....

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);

Вам нужно увеличить высоту и ширину, например установить keyQuality 1.0f.

Если height=200, увеличьте высоту на 200*3(height*scalePercentage). Аналогично ширине также

person gani    schedule 20.01.2016
comment
почему параметр KEY_QUALITY устанавливается дважды? также похоже, что вы ответили JPEGTranscoder, вопрос касался вывода png. - person rumman0786; 23.07.2019

В Apache Batik вы можете изменить разрешение, передав подсказку Transcoder KEY_PIXEL_UNIT_TO_MILLIMETER.

Однако важным аспектом является то, что вам нужно масштабировать высоту и ширину до того же масштаба, что и новое разрешение, которое вы ищете.

Например:

Размер моего SVG составляет 3,5 * 2,0 дюйма (252 * 144 пикселя).

Целевое разрешение – 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);
person ashokkumarprajapati    schedule 01.09.2020