| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| |
| package org.apache.batik.transcoder.wmf.tosvg; |
| |
| import java.awt.Dimension; |
| import java.io.BufferedInputStream; |
| import java.io.DataInputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| |
| import org.apache.batik.svggen.SVGGraphics2D; |
| import org.apache.batik.transcoder.ToSVGAbstractTranscoder; |
| import org.apache.batik.transcoder.TranscoderException; |
| import org.apache.batik.transcoder.TranscoderInput; |
| import org.apache.batik.transcoder.TranscoderOutput; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| /** This class implements the <code>Transcoder</code> interface and |
| * can convert a WMF input document into an SVG document. |
| * <p>This class is copied from |
| * batik org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder class.</p> |
| * <p>It can use <code>TranscoderInput</code> that are either a URI |
| * or a <code>InputStream</code> or a <code>Reader</code>. The |
| * <code>XMLReader</code> and <code>Document</code> <code>TranscoderInput</code> |
| * types are not supported.</p> |
| * |
| * <p>This transcoder can use <code>TranscoderOutputs</code> that are |
| * of any type except the <code>XMLFilter</code> type.</p> |
| * |
| * <p>Corrected bugs from the original class:</p> |
| * <ul> |
| * <li> Manage images size</li> |
| * </ul> |
| * <p>Exemple of use :</p> |
| * <pre> |
| * WMFTranscoder transcoder = new WMFTranscoder(); |
| * try { |
| * TranscoderInput wmf = new TranscoderInput(wmffile.toURL().toString()); |
| * FileOutputStream fos = new FileOutputStream(svgFile); |
| * TranscoderOutput svg = |
| * new TranscoderOutput(new OutputStreamWriter(fos, "UTF-8")); |
| * transcoder.transcode(wmf, svg); |
| * } catch (MalformedURLException e){ |
| * throw new TranscoderException(e); |
| * } catch (IOException e){ |
| * throw new TranscoderException(e); |
| * } |
| * </pre> |
| * <p>Several transcoding hints are available for this transcoder :</p> |
| * <ul> |
| * <li>KEY_INPUT_WIDTH, KEY_INPUT_HEIGHT, KEY_XOFFSET, KEY_YOFFSET : this Integer values allows to |
| * set the portion of the image to transcode, defined by the width, height, and offset |
| * of this portion in Metafile units. |
| * </ul> |
| * <pre> |
| * transcoder.addTranscodingHint(FromWMFTranscoder.KEY_INPUT_WIDTH, Integer.valueOf(input_width)); |
| * </pre> |
| * </li> |
| * <li>KEY_WIDTH, KEY_HEIGHT : this Float values allows to force the width and height of the output: |
| * </ul> |
| * <pre> |
| * transcoder.addTranscodingHint(FromWMFTranscoder.KEY_WIDTH, Float.valueOf(width)); |
| * </pre> |
| * </li> |
| * </ul> |
| * |
| * @version $Id$ |
| */ |
| public class WMFTranscoder extends ToSVGAbstractTranscoder { |
| |
| /** |
| * Default constructor |
| */ |
| public WMFTranscoder(){ |
| } |
| |
| /** |
| * Transcodes the specified input in the specified output. |
| * @param input the input to transcode |
| * @param output the ouput where to transcode |
| * @exception TranscoderException if an error occured while transcoding |
| */ |
| public void transcode(TranscoderInput input, TranscoderOutput output) |
| throws TranscoderException { |
| // |
| // Extract the input |
| // |
| DataInputStream is = getCompatibleInput(input); |
| |
| // |
| // Build a RecordStore from the input |
| // |
| WMFRecordStore currentStore = new WMFRecordStore(); |
| try { |
| currentStore.read(is); |
| } catch (IOException e){ |
| handler.fatalError(new TranscoderException(e)); |
| return; |
| } |
| |
| // determines the width and height of output image |
| float wmfwidth; // width in pixels |
| float wmfheight; // height in pixels |
| float conv = 1.0f; // conversion factor |
| |
| if (hints.containsKey(KEY_INPUT_WIDTH)) { |
| wmfwidth = (Integer) hints.get(KEY_INPUT_WIDTH); |
| wmfheight = (Integer) hints.get(KEY_INPUT_HEIGHT); |
| } else { |
| wmfwidth = currentStore.getWidthPixels(); |
| wmfheight = currentStore.getHeightPixels(); |
| } |
| float width = wmfwidth; |
| float height = wmfheight; |
| |
| // change the output width and height if required |
| if (hints.containsKey(KEY_WIDTH)) { |
| width = (Float) hints.get(KEY_WIDTH); |
| conv = width / wmfwidth; |
| height = height * width / wmfwidth; |
| } |
| |
| // determine the offset values |
| int xOffset = 0; |
| int yOffset = 0; |
| if (hints.containsKey(KEY_XOFFSET)) { |
| xOffset = (Integer) hints.get(KEY_XOFFSET); |
| } |
| if (hints.containsKey(KEY_YOFFSET)) { |
| yOffset = (Integer) hints.get(KEY_YOFFSET); |
| } |
| |
| // Set the size and viewBox on the output document |
| float sizeFactor = currentStore.getUnitsToPixels() * conv; |
| |
| int vpX = (int)(currentStore.getVpX() * sizeFactor); |
| int vpY = (int)(currentStore.getVpY() * sizeFactor); |
| |
| int vpW; |
| int vpH; |
| // if we took only a part of the image, we use its dimension for computing |
| if (hints.containsKey(KEY_INPUT_WIDTH)) { |
| vpW = (int)((Integer) hints.get(KEY_INPUT_WIDTH) * conv); |
| vpH = (int)((Integer) hints.get(KEY_INPUT_HEIGHT) * conv); |
| // else we took the whole image dimension |
| } else { |
| vpW = (int)(currentStore.getWidthUnits() * sizeFactor); |
| vpH = (int)(currentStore.getHeightUnits() * sizeFactor); |
| } |
| |
| // Build a painter for the RecordStore |
| WMFPainter painter = new WMFPainter(currentStore, xOffset, yOffset, conv); |
| |
| // Use SVGGraphics2D to generate SVG content |
| Document doc = this.createDocument(output); |
| svgGenerator = new SVGGraphics2D(doc); |
| |
| /** set precision |
| ** otherwise Ellipses aren't working (for example) (because of Decimal format |
| * modifications ins SVGGenerator Context |
| */ |
| svgGenerator.getGeneratorContext().setPrecision(4); |
| |
| painter.paint(svgGenerator); |
| |
| svgGenerator.setSVGCanvasSize(new Dimension(vpW, vpH)); |
| |
| Element svgRoot = svgGenerator.getRoot(); |
| |
| svgRoot.setAttributeNS(null, SVG_VIEW_BOX_ATTRIBUTE, |
| String.valueOf( vpX ) + ' ' + vpY + ' ' + |
| vpW + ' ' + vpH ); |
| |
| // Now, write the SVG content to the output |
| writeSVGToOutput(svgGenerator, svgRoot, output); |
| } |
| |
| /** |
| * Checks that the input is one of URI or an <code>InputStream</code> |
| * returns it as a DataInputStream |
| */ |
| private DataInputStream getCompatibleInput(TranscoderInput input) |
| throws TranscoderException { |
| // Cannot deal with null input |
| if (input == null){ |
| handler.fatalError(new TranscoderException( String.valueOf( ERROR_NULL_INPUT ) )); |
| } |
| |
| // Can deal with InputStream |
| InputStream in = input.getInputStream(); |
| if (in != null){ |
| return new DataInputStream(new BufferedInputStream(in)); |
| } |
| |
| // Can deal with URI |
| String uri = input.getURI(); |
| if (uri != null){ |
| try{ |
| URL url = new URL(uri); |
| in = url.openStream(); |
| return new DataInputStream(new BufferedInputStream(in)); |
| } catch (MalformedURLException e){ |
| handler.fatalError(new TranscoderException(e)); |
| } catch (IOException e){ |
| handler.fatalError(new TranscoderException(e)); |
| } |
| } |
| |
| handler.fatalError(new TranscoderException( String.valueOf( ERROR_INCOMPATIBLE_INPUT_TYPE ) )); |
| return null; |
| } |
| |
| public static final String WMF_EXTENSION = ".wmf"; |
| public static final String SVG_EXTENSION = ".svg"; |
| |
| /** |
| * Unit testing : Illustrates how the transcoder might be used. |
| */ |
| public static void main(String[] args) throws TranscoderException { |
| if(args.length < 1){ |
| System.out.println("Usage : WMFTranscoder.main <file 1> ... <file n>"); |
| System.exit(1); |
| } |
| |
| WMFTranscoder transcoder = new WMFTranscoder(); |
| int nFiles = args.length; |
| |
| for (String fileName : args) { |
| if (!fileName.toLowerCase().endsWith(WMF_EXTENSION)) { |
| System.err.println(fileName + " does not have the " + WMF_EXTENSION + " extension. It is ignored"); |
| } else { |
| System.out.print("Processing : " + fileName + "..."); |
| String outputFileName = fileName.substring(0, fileName.toLowerCase().indexOf(WMF_EXTENSION)) + SVG_EXTENSION; |
| File inputFile = new File(fileName); |
| File outputFile = new File(outputFileName); |
| try { |
| TranscoderInput input = new TranscoderInput(inputFile.toURI().toURL().toString()); |
| TranscoderOutput output = new TranscoderOutput(new FileOutputStream(outputFile)); |
| transcoder.transcode(input, output); |
| } catch (MalformedURLException e) { |
| throw new TranscoderException(e); |
| } catch (IOException e) { |
| throw new TranscoderException(e); |
| } |
| System.out.println(".... Done"); |
| } |
| } |
| |
| System.exit(0); |
| } |
| } |