You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by hirschberger <sc...@gmx.de> on 2008/02/24 13:01:40 UTC

out of memory while creating large jpg from svg

Hi guys,

I am trying to use BATIK to create JPG-images from SVG-DOM-trees which are
retrieved from a directory containing svg-files. The images contain mostly
basic geometric shapes (lines, polylines, circles, rectangles and text). The
following code works just fine, unless it comes to really large pictures -
e.g. 800x3500. As one might expect the engine runs out of memory and the
application crashes. 
My question: is there any way to solve this problem or at least find an
acceptable workaround that works also for even bigger images up to about
5000x5000? I am very much looking forward to your answers.

Best regards,
Max Hirschberger

public class ImageGenerator {

	public static void createJPEGS(String sourceDir, String targetDir) {

		try {
			File source = new File(sourceDir);
			/*
			 * Get all SVG-files from the specified directory
			 */
			String[] svgFiles = source.list(new FilenameFilter() {

				public boolean accept(File directory, String filename) {

					if (filename.endsWith(".svg"))
						return true;
					return false;

				}
			});
			for (int i = 0; i < svgFiles.length; i++) {

				int count = svgFiles[i].lastIndexOf(".");
				String filename = svgFiles[i].substring(0, count);
				String destination = targetDir + filename + ".jpg";
				String destinationThumbnail = targetDir + filename
						+ "_thumbnail.jpg";

				String sourceFile = sourceDir + svgFiles[i];

				
				String parser = XMLResourceDescriptor.getXMLParserClassName();
				SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
				String svgUri = new File(sourceFile).toURI().toString();
				Document doc = f.createDocument(svgUri);

				int[] size = getSVGSize(doc);

				/*
				 * Add height and width to the svg so it is displayed in a
				 * normal fashion
				 */
				XMLSupportMethods.addAttribute((Element) doc.getFirstChild(),
						"width", Integer.toString(size[0]));
				XMLSupportMethods.addAttribute((Element) doc.getFirstChild(),
						"height", Integer.toString(size[1]));
				XMLSupportMethods
						.storeDocumentToFile(doc, new File(sourceFile));
				/*
				 * Add area of Interest that determines which part of the SVG is
				 * displayed in the JPG; important or tooltip creation
				 */
				int aoiSize = Math.min(size[0], size[1]);
				Svg2Jpg(doc, new File(destination), size[0]+100, size[1]+100,
						new Rectangle(0, 0, size[0]+100, size[1]+100));
				Svg2Jpg(doc, new File(destinationThumbnail), 120, 150,
						new Rectangle(0, 0, aoiSize, aoiSize
								- ((int) 0.2 * aoiSize)));

			}
		} catch (TranscoderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
/**
 * Function taking a svg dom and converting it to a jpeg file
 * @param document SVG-DOM
 * @param destination where to save
 * @param width width of JPEG-Image
 * @param height height of JPEG-Image
 * @param areaOfInterest Determines which Part of the svg will be displayed.
 * @throws TranscoderException
 * @throws IOException
 */
	public static void Svg2Jpg(Document document, File destination, int width,
			int height, Rectangle areaOfInterest) throws TranscoderException,
			IOException {

		// Create Transcoder and set its quality and size hints
		JPEGTranscoder t = new JPEGTranscoder();
		t.addTranscodingHint(JPEGTranscoder.KEY_HEIGHT, new Float(height));
		t.addTranscodingHint(JPEGTranscoder.KEY_WIDTH, new Float(width));
		t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(.8));
		t.addTranscodingHint(JPEGTranscoder.KEY_AOI, areaOfInterest);

		// Set the transcoder input and output.
		TranscoderInput input = new TranscoderInput(document);
		OutputStream ostream = new FileOutputStream(destination);
		TranscoderOutput output = new TranscoderOutput(ostream);

		// Perform the transcoding.
		t.transcode(input, output);
		ostream.flush();
		ostream.close();

	}
-- 
View this message in context: http://www.nabble.com/out-of-memory-while-creating-large-jpg-from-svg-tp15663329p15663329.html
Sent from the Batik - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: out of memory while creating large jpg from svg

Posted by Cameron McCormack <ca...@mcc.id.au>.
Hi Max.

hirschberger:
> I am trying to use BATIK to create JPG-images from SVG-DOM-trees which are
> retrieved from a directory containing svg-files. The images contain mostly
> basic geometric shapes (lines, polylines, circles, rectangles and text). The
> following code works just fine, unless it comes to really large pictures -
> e.g. 800x3500. As one might expect the engine runs out of memory and the
> application crashes. 
> My question: is there any way to solve this problem or at least find an
> acceptable workaround that works also for even bigger images up to about
> 5000x5000? I am very much looking forward to your answers.

Are you using the -Xmx command line argument to java to set the maximum
usable heap memory?  The transcoder does need to hold the entire image
buffer in memory before writing it out as a JPEG, so if you need a
5000x5000 image, you will need at least 5000 * 5000 * 4 = 100MB of
memory to give to java, e.g.:

  java -Xmx100M MyApp …

Cameron

-- 
Cameron McCormack, http://mcc.id.au/
	xmpp:heycam@jabber.org  ▪  ICQ 26955922  ▪  MSN cam@mcc.id.au

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org