1

My code below is pulled from an official guide. The code will render some SVG files without issue, but others cause an exception java.awt.image.ImagingOpException: Unable to transform src image. I have created one "working image" and one "problem image" as small examples.

Please note that I cannot add SVG files directly to StackOverflow questions, they are not a supported file type, so here are links for one working image and one problem image. Below are the raw file contents as well.

I have found multiple potential duplicate questions, but none have the answer. Can I fix this inside my own program without patching Batik? Is there some other recommended manner to display SVGs in Java? AFAIK, Batik is the reference implementation. What causes one SVG to fail while the other (nearly identical) one works fine? How can I avoid this issue without having to scan/edit each SVG my user may choose to load to avoid some edge case bugs?

public class SVGApplication {

    public static void main(String[] args) {
        // Create a new JFrame.
        JFrame f = new JFrame("Batik");
        SVGApplication app = new SVGApplication();
        app.frame = f;

        f.getContentPane().add(app.createComponents());
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.setSize(400, 400);
        f.setVisible(true);
    }

    JFrame frame;
    JButton button = new JButton("Load...");
    JLabel label = new JLabel();
    JSVGCanvas svgCanvas = new JSVGCanvas();

    public JComponent createComponents() {
        final JPanel panel = new JPanel(new BorderLayout());
        JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
        p.add(button);
        p.add(label);
        panel.add("North", p);
        panel.add("Center", svgCanvas);

        // Set the button action.
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                JFileChooser fc = new JFileChooser(".");
                int choice = fc.showOpenDialog(panel);
                if (choice == JFileChooser.APPROVE_OPTION) {
                    File f = fc.getSelectedFile();
                    try {
                        svgCanvas.setURI(f.toURL().toString());
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });

        return panel;
    }
}

For all images, the program will initially load the image just fine, but the moment you scale the JFrame it starts to spew exceptions on the "problem" images e.g.

java.awt.image.ImagingOpException: Unable to transform src image
    at java.awt.image.AffineTransformOp.filter(AffineTransformOp.java:358)
    at org.apache.batik.ext.awt.image.rendered.AffineRed.genRect(AffineRed.java:193)
    at org.apache.batik.ext.awt.image.rendered.AffineRed.copyData(AffineRed.java:109)
    at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
    at org.apache.batik.ext.awt.image.rendered.ColorMatrixRed.copyData(ColorMatrixRed.java:116)
    at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
    at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
    at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
    at org.apache.batik.ext.awt.image.rendered.CompositeRed.genRect(CompositeRed.java:179)
    at org.apache.batik.ext.awt.image.rendered.CompositeRed.copyData(CompositeRed.java:139)
    at org.apache.batik.ext.awt.image.rendered.Any2sRGBRed.copyData(Any2sRGBRed.java:166)
    at org.apache.batik.ext.awt.image.rendered.FormatRed.copyData(FormatRed.java:116)
    at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:347)
    at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:455)
    at org.apache.batik.ext.awt.image.renderable.PadRable8Bit.paintRable(PadRable8Bit.java:135)
    at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
    at org.apache.batik.ext.awt.image.renderable.PadRable8Bit.paintRable(PadRable8Bit.java:135)
    at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
    at org.apache.batik.ext.awt.image.renderable.FilterChainRable8Bit.paintRable(FilterChainRable8Bit.java:251)
    at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
    at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:549)
    at org.apache.batik.gvt.ShapeNode.paint(ShapeNode.java:143)
    at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
    at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
    at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
    at org.apache.batik.gvt.CanvasGraphicsNode.primitivePaint(CanvasGraphicsNode.java:159)
    at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
    at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
    at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
    at org.apache.batik.gvt.renderer.MacRenderer.repaint(MacRenderer.java:360)
    at org.apache.batik.gvt.renderer.MacRenderer.repaint(MacRenderer.java:291)
    at org.apache.batik.swing.gvt.GVTTreeRenderer.run(GVTTreeRenderer.java:123)

Similar prior questions: This post recommends patching Batik sources, which is not very attractive. This post explains a fix that was indeed applied in batik 1.7+, however I am using 1.11 and this is no longer working

Additional Data: Because SVG files seem to be difficult to host, I have chosen to also include the raw contents of the "working" vs "problem" files as text here. That seems to strike the right balance of a "complete, verifiable" question.

Working Image: <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="141px" preserveAspectRatio="none" style="width:94px;height:141px;" version="1.1" viewBox="0 0 94 141" width="94px" zoomAndPan="magnify"><defs><filter height="300%" id="fdmfjjhypbn8w" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="40" x2="40" y1="38.4883" y2="100.7988"/><rect fill="#FEFECE" filter="url(#fdmfjjhypbn8w)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="23.5352">Actor1</text><rect fill="#FEFECE" filter="url(#fdmfjjhypbn8w)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="99.7988"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="120.334">Actor1</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="40" x2="82" y1="69.7988" y2="69.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="82" x2="82" y1="69.7988" y2="82.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="41" x2="82" y1="82.7988" y2="82.7988"/><polygon fill="#A80036" points="51,78.7988,41,82.7988,51,86.7988,47,82.7988" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="47" y="65.0566">test</text><!--@startuml\nActor1 -> Actor1: test\n@enduml--></g></svg>
Problem Image: <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="183px" preserveAspectRatio="none" style="width:168px;height:183px;" version="1.1" viewBox="0 0 168 183" width="168px" zoomAndPan="magnify"><defs><filter height="300%" id="fc9m2fo3xvklq" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="40" x2="40" y1="38.4883" y2="143.1094"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="114" x2="114" y1="38.4883" y2="143.1094"/><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="23.5352">Actor1</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="142.1094"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="162.6445">Actor1</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="82" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="89" y="23.5352">Actor2</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="82" y="142.1094"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="89" y="162.6445">Actor2</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="40" x2="82" y1="69.7988" y2="69.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="82" x2="82" y1="69.7988" y2="82.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="41" x2="82" y1="82.7988" y2="82.7988"/><polygon fill="#A80036" points="51,78.7988,41,82.7988,51,86.7988,47,82.7988" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="47" y="65.0566">test</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="114" x2="156" y1="112.1094" y2="112.1094"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="156" x2="156" y1="112.1094" y2="125.1094"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="115" x2="156" y1="125.1094" y2="125.1094"/><polygon fill="#A80036" points="125,121.1094,115,125.1094,125,129.1094,121,125.1094" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="121" y="107.3672">test</text><!--\n@startuml\nActor1 -> Actor1: test\nActor2 -> Actor2: test\n@enduml\n--></g></svg>
Hamy
  • 20,662
  • 15
  • 74
  • 102
  • Please cut down your SVG into a [mcve] and add it to the question. The svg link currently displays an error page instead of anything useful which is why we insist on questions being self contained. – Robert Longson Feb 23 '19 at 07:18
  • @RobertLongson I have verified the SVG link renders properly for Chrome 72, Safari 12, and Firefox 63 (all on MacOS). What browser are you using? The SVG file contents are pretty minimal, but I will try to find a smaller file that reproduces the issue – Hamy Feb 23 '19 at 07:34
  • @RobertLongson OK, I have minimized as much as I can and tried to strike the minimal+complete+verifiable balance. Would greatly appreciate any input you may have. Of particular confusion, the two SVG file contents look nearly identical to my (untrained) eye, I'm at a loss as to how one works and one causes errors – Hamy Feb 23 '19 at 08:09
  • Fixed. I caused that typo while trying to fit the SVG contents in one line. I have confirmed the issue still exists, that typo was not the root failure – Hamy Feb 23 '19 at 08:25
  • One thing worth testing could be to make the filter effects region smaller. Currently, the regions of the drop shadow (which would count as a "locally created image") overlap in the second image. Try changing the filter tag: `` – ccprog Feb 23 '19 at 12:02
  • @ccprog I think you're onto something. I've played with it. If I remove `` I no longer get the exception. I'm not sure why Batik starts spewing errors with this "feBlend" thing, but any combo of feBlend parameters causes the errrors – Hamy Feb 23 '19 at 18:22
  • It's as the bug reports you quoted say: blend is the operation where the yellow rect is placed on top of the shadow, and Batik seems to (sometimes) fail if that combo is scaled. You could try to use another operation that achieves the same (but may, internally, be implemented differently): either `` or `` – ccprog Feb 23 '19 at 19:14
  • @ccprog I must be slow, but I'm not understanding :-( The prior bug reports are all "fixed" e.g. the batik sources were patched between 1.7 and 1.11 and the java 1.7 issue is marked fixed in java 1.8. This seems to me to be a new issue. I'm receiving SVG files from another library, I don't see a way to search and edit SVGs dynamically to work around batik/java failure cases – Hamy Feb 23 '19 at 19:45

0 Answers0