Exception "Error reading Wmf record" while converting WMF images to PNG using Aspose.Imaging for Java

Hello, we are getting a Metafiles exception with a particular wmf image converting it to png.

Here are the parameters passed into our sample code:
byte[] resultPNGImage = null;
try(InputStream wmfInputStream = Files.newInputStream(Paths.get(“src/test/resources/rtfimage.wmf”)))
{
resultPNGImage = ImageConverter.convertWMFToPNGUsingAspose(wmfInputStream, 100, 100);
}
wmf image.zip (35.7 KB)

Here is the sample code:

static byte[] convertWMFToPNGUsingAspose(final InputStream wmfInputStream, final int preferredWidth, final int preferredHeight)
{
    //Measurement timer = MeasurementConformer.startMeasurement(TimerType.ENG, "XR", "Convert WMF bytes to PNG");

    ByteArrayOutputStream pngOS = null;
    try
    {
        WmfMetafileImage wmfMetafile = new WmfMetafileImage(wmfInputStream);

        double internalWidth = wmfMetafile.getWidth();
        double internalHeight = wmfMetafile.getHeight();
        if (internalWidth == 0 || internalHeight == 0)
        {
            throw new RuntimeException();
        }
        // use given preferred width and height if it's greater than zero, otherwise use wmf's internal width/height.
        // multiply pixel dimensions by two to increase the resolution of the image
        int width = preferredWidth > 0 ? preferredWidth * 2 : (int) (internalWidth * 2);
        int height = preferredHeight > 0 ? preferredHeight * 2 : (int) (internalHeight * 2);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D graphics = image.createGraphics();

        // Define rendering hints to make all lines and text anti-aliased
        Map<Key, Object> map = new ArrayMap<Key, Object>(4);
        map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        map.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics.addRenderingHints(map);
        wmfMetafile.setDefaultRenderingHints((RenderingHints) graphics.getRenderingHints().clone());

        // Draw metafile on created image
        graphics.setPaint(Color.WHITE);
        graphics.fill(new Rectangle(0, 0, width, height));

        double scaleX = width / internalWidth;
        double scaleY = height / internalHeight;

        double wmfMetafileMinX = wmfMetafile.getMinX();
        double wmfMetafileMinY = wmfMetafile.getMinY();

        if (TRACER.isEnabled())
        {
            TRACER.trace("Translating wmf image to account for offet with scaleX: {0}, scaleY: {1}, minX: {2}, minY: {3}", scaleX, scaleY, wmfMetafileMinX, wmfMetafileMinY);
        }
        // Translate wmf image appropriately to account for the offset
        AffineTransform transform = AffineTransform.getScaleInstance(scaleX, scaleY);
        transform.translate(-wmfMetafileMinX, -wmfMetafileMinY);
        graphics.setTransform(transform);

// if (TRACER.isEnabled())
// {
// TRACER.trace(“wmf image has been translated with height: {0}, width {1}”, height, width);
// }

        wmfMetafile.playMetafile(graphics);

        PNGEncodeParam param = PNGEncodeParam.getDefaultEncodeParam(image);
        // double DPI to match doubled height and width so that the rendered size of the image is the same.
        param.setPhysicalDimension(DEFAULT_PIXELS_PER_METER * 2, DEFAULT_PIXELS_PER_METER * 2, 1);
        pngOS = new ByteArrayOutputStream();
        ImageEncoder enc = ImageCodec.createImageEncoder("PNG", pngOS, param);
        enc.encode(image);

        return pngOS.toByteArray();
    }
    catch (Exception ex) // if an exception occurs, retry using Batik
    {
        //TRACER.trace("An exception occurred when converting WMF to PNG using Aspose.Imaging.", ex);
        return null;
    }
    finally
    {
        IOUtils.closeQuietly(pngOS);
        //timer.stop();
    }
}

Here is the stack trace:
class com.aspose.imaging.coreexceptions.imageformats.MetafilesException: Error reading Wmf record number 14 —> java.lang.ArrayIndexOutOfBoundsException: 2776
— End of inner exception stack trace —
com.aspose.imaging.fileformats.metafile.dC.a(Unknown Source)
com.aspose.imaging.fileformats.metafile.WmfMetafileImage.a(Unknown Source)
com.aspose.imaging.fileformats.metafile.WmfMetafileImage.(Unknown Source)
com.cerner.clinicalreporting.core.util.ImageConverter.convertWMFToPNGUsingAspose(ImageConverter.java:553)
com.cerner.clinicalreporting.core.util.ImageConverterTest.testConvertWMFToPNGUsingAspose(ImageConverterTest.java:751)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
org.junit.runners.ParentRunner.run(ParentRunner.java:309)
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

@drakegens,

I have observed your comments. Can you please share complete working code snippet. The code snippet you have shared includes some undeclared variables so would you please share SSCCE code reproducing the issue so that we may try to reproduce and investigate it in our environment.

Here is a minimum working code sample for you to reproduce the problem. Image attached above.

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.RenderingHints.Key;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;

import com.aspose.imaging.fileformats.metafile.WmfMetafileImage;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.PNGEncodeParam;

public class Test
{

/** Conversion factor for inches to meters. */
private static final double INCHES_TO_METERS_FACTOR = 0.0254;

/** Default pixels per meter. */
private static final int DEFAULT_PIXELS_PER_METER = (int) Math.round(72 / INCHES_TO_METERS_FACTOR);

public static void main(String[] args) throws IOException
{        
    FileInputStream in = new FileInputStream("C:\\rtfimage.wmf");
   byte[] result = convertWMFToPNGUsingAspose(in, 100, 100);
   
   Files.newOutputStream(Paths.get("C:\\testConvertWMFToPNG_Stream.png")).write(result);

}

public static byte[] convertWMFToPNGUsingAspose(final FileInputStream wmfInputStream, final int preferredWidth, final int preferredHeight)
{
    ByteArrayOutputStream pngOS = null;
    try
    {
        WmfMetafileImage wmfMetafile = new WmfMetafileImage(wmfInputStream);

        double internalWidth = wmfMetafile.getWidth();
        double internalHeight = wmfMetafile.getHeight();
        if (internalWidth == 0 || internalHeight == 0)
        {
            throw new RuntimeException();
        }
        // use given preferred width and height if it's greater than zero, otherwise use wmf's internal width/height.
        // multiply pixel dimensions by two to increase the resolution of the image
        int width = preferredWidth > 0 ? preferredWidth * 2 : (int) (internalWidth * 2);
        int height = preferredHeight > 0 ? preferredHeight * 2 : (int) (internalHeight * 2);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D graphics = image.createGraphics();

        // Define rendering hints to make all lines and text anti-aliased
        Map<Key, Object> map = new HashMap<Key, Object>(4);
        map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        map.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics.addRenderingHints(map);
        wmfMetafile.setDefaultRenderingHints((RenderingHints) graphics.getRenderingHints().clone());

        // Draw metafile on created image
        graphics.setPaint(Color.WHITE);
        graphics.fill(new Rectangle(0, 0, width, height));

        double scaleX = width / internalWidth;
        double scaleY = height / internalHeight;

        double wmfMetafileMinX = wmfMetafile.getMinX();
        double wmfMetafileMinY = wmfMetafile.getMinY();

        // Translate wmf image appropriately to account for the offset
        AffineTransform transform = AffineTransform.getScaleInstance(scaleX, scaleY);
        transform.translate(-wmfMetafileMinX, -wmfMetafileMinY);
        graphics.setTransform(transform);

        wmfMetafile.playMetafile(graphics);

        PNGEncodeParam param = PNGEncodeParam.getDefaultEncodeParam(image);
        // double DPI to match doubled height and width so that the rendered size of the image is the same.
        param.setPhysicalDimension(DEFAULT_PIXELS_PER_METER * 2, DEFAULT_PIXELS_PER_METER * 2, 1);
        pngOS = new ByteArrayOutputStream();
        ImageEncoder enc = ImageCodec.createImageEncoder("PNG", pngOS, param);
        enc.encode(image);

        return pngOS.toByteArray();
    }
    catch (Exception ex)
    {
        return null;
    }
    finally
    {
        IOUtils.closeQuietly(pngOS);
    }
}

}

@drakegens,

I have worked with the source files shared by you and have been able to observe the issue shared. An issue with ID IMAGINGJAVA-1196 has been created in our issue tracking system to further investigate and resolve the issue. This thread has been linked with the issue so that you may be notified once the issue will be fixed.