Advertisement
Guest User

bpai

a guest
Apr 8th, 2016
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.85 KB | None | 0 0
  1. /*
  2. * Copyright 2007-2008, Plutext Pty Ltd.
  3. *
  4. * This file is part of docx4j.
  5.  
  6. docx4j is licensed under the Apache License, Version 2.0 (the "License");
  7. you may not use this file except in compliance with the License.
  8.  
  9. You may obtain a copy of the License at
  10.  
  11. http://www.apache.org/licenses/LICENSE-2.0
  12.  
  13. Unless required by applicable law or agreed to in writing, software
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18.  
  19. */
  20. package org.docx4j.openpackaging.parts.WordprocessingML;
  21.  
  22.  
  23. import java.io.File;
  24. import java.io.FileInputStream;
  25. import java.io.FileOutputStream;
  26. import java.net.URL;
  27.  
  28. import org.apache.xmlgraphics.image.loader.ImageInfo;
  29. import org.apache.xmlgraphics.image.loader.ImageSize;
  30. import org.docx4j.UnitsOfMeasurement;
  31. import org.docx4j.dml.picture.Pic;
  32. import org.docx4j.dml.wordprocessingDrawing.Inline;
  33. import org.docx4j.model.structure.PageDimensions;
  34. import org.docx4j.openpackaging.Base;
  35. import org.docx4j.openpackaging.contenttype.ContentTypeManager;
  36. import org.docx4j.openpackaging.contenttype.ContentTypes;
  37. import org.docx4j.openpackaging.exceptions.InvalidFormatException;
  38. import org.docx4j.openpackaging.packages.OpcPackage;
  39. import org.docx4j.openpackaging.packages.PresentationMLPackage;
  40. import org.docx4j.openpackaging.packages.SpreadsheetMLPackage;
  41. import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
  42. import org.docx4j.openpackaging.parts.ExternalTarget;
  43. import org.docx4j.openpackaging.parts.Part;
  44. import org.docx4j.openpackaging.parts.PartName;
  45. import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
  46. import org.docx4j.relationships.Relationship;
  47.  
  48. import android.util.Log;
  49.  
  50. public abstract class BinaryPartAbstractImage extends BinaryPart {
  51.  
  52. final static String IMAGE_DIR_PREFIX = "/word/media/";
  53. final static String IMAGE_NAME_PREFIX = "image";
  54.  
  55. public BinaryPartAbstractImage(PartName partName) throws InvalidFormatException {
  56. super(partName);
  57.  
  58. // Can't setContentType or setRelationshipType, since
  59. // these will differ depending on the nature of the data.
  60. // Common binary parts should extend this class to
  61. // provide that information.
  62.  
  63. this.getOwningRelationshipPart();
  64.  
  65. }
  66.  
  67. public BinaryPartAbstractImage(ExternalTarget externalTarget) {
  68. super(externalTarget);
  69. }
  70.  
  71.  
  72. // TODO, instead of Part.getOwningRelationshipPart(),
  73. // it would be better to have getOwningRelationship(),
  74. // and if required, to get OwningRelationshipPart from that
  75. // This is a temp workaround
  76. Relationship rel;
  77.  
  78.  
  79. /**
  80. * This method assumes your package is a docx (not a pptx or xlsx).
  81. *
  82. * @param sourcePart
  83. * @param proposedRelId
  84. * @param ext
  85. * @return
  86. */
  87. @Deprecated
  88. public static String createImageName(Base sourcePart, String proposedRelId, String ext) {
  89.  
  90. return PartName.generateUniqueName(sourcePart, proposedRelId,
  91. IMAGE_DIR_PREFIX, IMAGE_NAME_PREFIX, ext);
  92. }
  93.  
  94. public static String createImageName(OpcPackage opcPackage, Base sourcePart, String proposedRelId, String ext) {
  95.  
  96. if (opcPackage instanceof WordprocessingMLPackage) {
  97. return PartName.generateUniqueName(sourcePart, proposedRelId,
  98. IMAGE_DIR_PREFIX, IMAGE_NAME_PREFIX, ext);
  99. } else if (opcPackage instanceof PresentationMLPackage) {
  100. return PartName.generateUniqueName(sourcePart, proposedRelId,
  101. "/ppt/media/", IMAGE_NAME_PREFIX, ext);
  102. } else if (opcPackage instanceof SpreadsheetMLPackage) {
  103. return PartName.generateUniqueName(sourcePart, proposedRelId,
  104. "/xl/media/", IMAGE_NAME_PREFIX, ext);
  105. } else {
  106. // Shouldn't happen
  107. return PartName.generateUniqueName(sourcePart, proposedRelId,
  108. IMAGE_DIR_PREFIX, IMAGE_NAME_PREFIX, ext);
  109. }
  110. }
  111.  
  112. /**
  113. * Create an image part from the provided byte array, attach it to the source part
  114. * (eg the main document part, a header part etc), and return it.
  115. *
  116. * Works for both docx and pptx.
  117. *
  118. * @param opcPackage
  119. * @param sourcePart
  120. * @param bytes
  121. * @return
  122. * @throws Exception
  123. */
  124. public static BinaryPartAbstractImage createImagePart(
  125. OpcPackage opcPackage,
  126. Part sourcePart, byte[] bytes) throws Exception {
  127.  
  128. // Whatever image type this is, we're going to need
  129. // to know its dimensions.
  130. // For that we use ImageInfo, which can only
  131. // load an image from a URI.
  132.  
  133. // So first, write the bytes to a temp file
  134. File tmpImageFile = File.createTempFile("img", ".img");
  135.  
  136. FileOutputStream fos = new FileOutputStream(tmpImageFile);
  137. fos.write(bytes);
  138. fos.close();
  139.  
  140. // In the absence of an exception, tmpImageFile now contains an image
  141. // Word will accept
  142.  
  143. ContentTypeManager ctm = opcPackage.getContentTypeManager();
  144.  
  145. // Ensure the relationships part exists
  146. if (sourcePart.getRelationshipsPart() == null) {
  147. RelationshipsPart.createRelationshipsPartForPart(sourcePart);
  148. }
  149.  
  150. String proposedRelId = sourcePart.getRelationshipsPart().getNextId();
  151.  
  152. String ext = "JPG";
  153.  
  154. BinaryPartAbstractImage imagePart =
  155. (BinaryPartAbstractImage) ctm.newPartForContentType(
  156. ContentTypes.IMAGE_JPEG,
  157. createImageName(opcPackage, sourcePart, proposedRelId, ext), null);
  158.  
  159.  
  160. FileInputStream fis = new FileInputStream(tmpImageFile);
  161.  
  162. imagePart.setBinaryData(fis);
  163.  
  164. imagePart.rel = sourcePart.addTargetPart(imagePart, proposedRelId);
  165.  
  166. System.gc();
  167.  
  168. if (false == tmpImageFile.delete()) {
  169. Log.e("mcapps debug","Couldn't delete tmp file " + tmpImageFile.getAbsolutePath());
  170. tmpImageFile.deleteOnExit();
  171. }
  172.  
  173. return imagePart;
  174. }
  175.  
  176.  
  177. /**
  178. * Create a <wp:inline> element suitable for this image, which can be
  179. * linked or embedded in w:p/w:r/w:drawing, specifying height and width. Note
  180. * that you'd ordinarily use one of the methods which don't require
  181. * you to specify height (cy).
  182. *
  183. * @param filenameHint
  184. * Any text, for example the original filename
  185. * @param altText
  186. * Like HTML's alt text
  187. * @param id1
  188. * An id unique in the document
  189. * @param id2
  190. * Another id unique in the document None of these things seem to
  191. * be exposed in Word 2007's user interface, but Word won't open
  192. * the document if any of the attributes these go in (except @ desc) aren't
  193. * present!
  194. * @param cx Image width in EMU
  195. * @param cy Image height in EMU
  196. * @param link true if this is to be linked not embedded
  197. * @throws Exception
  198. */
  199. public Inline createImageInline(String filenameHint, String altText,
  200. /*int id1, int id2,*/ long cx, long cy) throws Exception {
  201.  
  202. if (filenameHint == null) {
  203. filenameHint = "";
  204. }
  205. if (altText == null) {
  206. altText = "";
  207. }
  208.  
  209. cx *= 2 * 2035; //twips
  210. cy *= 2 * 2035;
  211.  
  212.  
  213. String type = "r:embed";
  214.  
  215. String ml =
  216. // "<w:p ><w:r>" +
  217. // "<w:drawing>" +
  218. "<wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\"" + namespaces + ">"
  219. + "<wp:extent cx=\"${cx}\" cy=\"${cy}\"/>"
  220. + "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>" + //l=\"19050\"
  221. "<wp:docPr id=\"${id1}\" name=\"${filenameHint}\" descr=\"${altText}\"/><wp:cNvGraphicFramePr><a:graphicFrameLocks xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" noChangeAspect=\"1\"/></wp:cNvGraphicFramePr><a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
  222. + "<a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
  223. + "<pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><pic:nvPicPr><pic:cNvPr id=\"${id2}\" name=\"${filenameHint}\"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill>"
  224. + "<a:blip " + type + "=\"${rEmbedId}\"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill>"
  225. + "<pic:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"${cx}\" cy=\"${cy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic>"
  226. + "</wp:inline>"; // +
  227. // "</w:drawing>" +
  228. // "</w:r></w:p>";
  229. java.util.HashMap<String, String> mappings = new java.util.HashMap<String, String>();
  230.  
  231.  
  232.  
  233.  
  234. mappings.put("cx", Long.toString(cx));
  235. mappings.put("cy", Long.toString(cy));
  236. mappings.put("filenameHint", filenameHint);
  237. mappings.put("altText", altText);
  238. mappings.put("rEmbedId", rel.getId());
  239. mappings.put("id1", Integer.toString(0)); //id1
  240. mappings.put("id2", Integer.toString(1)); //id2
  241.  
  242. Object o = org.docx4j.XmlUtils.unmarshallFromTemplate(ml, mappings);
  243.  
  244. Inline inline = (Inline) ((ae.javax.xml.bind.JAXBElement) o).getValue();
  245.  
  246. return inline;
  247. }
  248.  
  249.  
  250. final static String namespaces = " xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" "
  251. + "xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
  252. + "xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"";
  253.  
  254. public static ImageInfo getImageInfo(URL url) throws Exception {
  255.  
  256. // XmlGraphics images caches images by their URI;
  257. // therefore it can only load images from a URI, rather
  258. // than say a byte array, byte buffer, or input stream.
  259.  
  260. ImageInfo info = new ImageInfo(url.toURI().toString(), ContentTypes.IMAGE_JPEG);
  261.  
  262.  
  263. // Note that these figures do not appear to be reliable for EPS
  264. // eg ImageMagick 6.2.4 10/02/07 Q16
  265. // identify fig1.eps
  266. // reports:
  267. // fig1.eps PS 516x429 516x429+0+0 DirectClass 869kb
  268. // whereas ImageInfo reports 1147x953
  269.  
  270. /* Note2: odd results for PNG?
  271. *
  272. If for an image, ImageMagick (v.6.2.4 and 6.3.7) identify says:
  273.  
  274. Resolution: 320x320 (or whatever)
  275. Units: Undefined <---------------------
  276.  
  277. then ImageInfo will report a default value, using Toolkit.getDefaultToolkit().getScreenResolution(),
  278. which may be say 160.
  279.  
  280. To prevent the "Undefined", be sure to use -units when you call convert.
  281.  
  282. * When PreloaderImageIO.preloadImage does:
  283.  
  284. ImageIOUtil.extractResolution(iiometa, size);
  285.  
  286. it is finding the Dimension child, but not "HorizontalPixelSize" or VerticalPixelSize (these are null).
  287. * */
  288.  
  289. return info;
  290. }
  291.  
  292. /**
  293. * Convenience method, given a Graphic in a document,
  294. * to get the byte[] representing
  295. * the associated image
  296. *
  297. * @param wmlPkg
  298. * @param graphic
  299. * @return
  300. */
  301. public static byte[] getImage(WordprocessingMLPackage wmlPkg,
  302. org.docx4j.dml.Graphic graphic) {
  303.  
  304. if (wmlPkg == null
  305. || wmlPkg.getMainDocumentPart() == null
  306. || wmlPkg.getMainDocumentPart().getRelationshipsPart() == null) {
  307. return null;
  308. }
  309.  
  310. Pic pic = graphic.getGraphicData().getPic();
  311. String rId = pic.getBlipFill().getBlip().getEmbed();
  312. if (rId.equals("")) {
  313. rId = pic.getBlipFill().getBlip().getLink();
  314. }
  315. log.debug("Image rel id: " + rId);
  316. org.docx4j.relationships.Relationship rel =
  317. wmlPkg.getMainDocumentPart().getRelationshipsPart().getRelationshipByID(rId);
  318. if (rel != null) {
  319. org.docx4j.openpackaging.parts.Part part =
  320. wmlPkg.getMainDocumentPart().getRelationshipsPart().getPart(rel);
  321. if (part == null) {
  322. log.error("Couldn't get Part!");
  323. } else if (part instanceof org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart) {
  324. log.debug("getting bytes...");
  325. org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart binaryPart =
  326. (org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart) part;
  327. java.nio.ByteBuffer bb = binaryPart.getBuffer();
  328. bb.clear();
  329. byte[] bytes = new byte[bb.capacity()];
  330. bb.get(bytes, 0, bytes.length);
  331.  
  332. return bytes;
  333. } else {
  334. log.error("Part was a " + part.getClass().getName());
  335. }
  336. } else {
  337. log.error("Couldn't find rel " + rId);
  338. }
  339.  
  340. return null;
  341. }
  342.  
  343. // public static class CxCy {
  344. //
  345. // long cx;
  346. //
  347. // /**
  348. // * @return the resulting cx
  349. // */
  350. // public long getCx() {
  351. // return cx;
  352. // }
  353. // long cy;
  354. //
  355. // /**
  356. // * @return the resulting cy
  357. // */
  358. // public long getCy() {
  359. // return cy;
  360. // }
  361. // boolean scaled;
  362. //
  363. // /**
  364. // * @return whether it was necessary to scale
  365. // * the image to fit the page width
  366. // */
  367. // public boolean isScaled() {
  368. // return scaled;
  369. // }
  370. //
  371. // CxCy(long cx, long cy, boolean scaled) {
  372. //
  373. // this.cx = cx;
  374. // this.cy = cy;
  375. // this.scaled = scaled;
  376. //
  377. // }
  378.  
  379. // public static CxCy scale(ImageInfo imageInfo, PageDimensions page) {
  380. //
  381. // double writableWidthTwips = page.getWritableWidthTwips();
  382. // log.debug("writableWidthTwips: " + writableWidthTwips);
  383. //
  384. // ImageSize size = imageInfo.getSize();
  385. //
  386. // ae.java.awt.geom.Dimension2D dPt = size.getDimensionPt();
  387. // double imageWidthTwips = dPt.getWidth() * 20;
  388. // log.debug("imageWidthTwips: " + imageWidthTwips);
  389. //
  390. // long cx;
  391. // long cy;
  392. // boolean scaled = false;
  393. // if (imageWidthTwips > writableWidthTwips) {
  394. //
  395. // log.debug("Scaling image to fit page width");
  396. // scaled = true;
  397. //
  398. // cx = UnitsOfMeasurement.twipToEMU(writableWidthTwips);
  399. // cy = UnitsOfMeasurement.twipToEMU(dPt.getHeight() * 20 * writableWidthTwips / imageWidthTwips);
  400. //
  401. // } else {
  402. //
  403. // log.debug("Scaling image - not necessary");
  404. //
  405. // cx = UnitsOfMeasurement.twipToEMU(imageWidthTwips);
  406. // cy = UnitsOfMeasurement.twipToEMU(dPt.getHeight() * 20);
  407. // }
  408. //
  409. // return new CxCy(cx, cy, scaled);
  410. // }
  411. // }
  412. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement