You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

XSLFPictureData.java 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * ====================================================================
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with
  5. * this work for additional information regarding copyright ownership.
  6. * The ASF licenses this file to You under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. * ====================================================================
  18. */
  19. package org.apache.poi.xslf.usermodel;
  20. import java.awt.Dimension;
  21. import java.awt.image.BufferedImage;
  22. import java.io.ByteArrayInputStream;
  23. import java.io.IOException;
  24. import java.io.InputStream;
  25. import java.io.OutputStream;
  26. import javax.imageio.ImageIO;
  27. import org.apache.poi.POIXMLDocumentPart;
  28. import org.apache.poi.POIXMLException;
  29. import org.apache.poi.hslf.blip.EMF;
  30. import org.apache.poi.hslf.blip.PICT;
  31. import org.apache.poi.hslf.blip.WMF;
  32. import org.apache.poi.openxml4j.opc.PackagePart;
  33. import org.apache.poi.openxml4j.opc.PackageRelationship;
  34. import org.apache.poi.sl.usermodel.PictureData;
  35. import org.apache.poi.util.Beta;
  36. import org.apache.poi.util.IOUtils;
  37. import org.apache.poi.util.LittleEndian;
  38. import org.apache.poi.util.LittleEndianConsts;
  39. import org.apache.poi.util.POILogFactory;
  40. import org.apache.poi.util.POILogger;
  41. import org.apache.poi.util.Units;
  42. /**
  43. * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type
  44. */
  45. @Beta
  46. public final class XSLFPictureData extends POIXMLDocumentPart implements PictureData {
  47. private static final POILogger logger = POILogFactory.getLogger(XSLFPictureData.class);
  48. private Long checksum = null;
  49. // original image dimensions (for formats supported by BufferedImage)
  50. private Dimension origSize = null;
  51. private int index = -1;
  52. /**
  53. * Create a new XSLFGraphicData node
  54. */
  55. protected XSLFPictureData() {
  56. super();
  57. }
  58. /**
  59. * Construct XSLFPictureData from a package part
  60. *
  61. * @param part the package part holding the drawing data
  62. *
  63. * @since POI 3.14-Beta1
  64. */
  65. public XSLFPictureData(PackagePart part) {
  66. super(part);
  67. }
  68. /**
  69. * Construct XSLFPictureData from a package part
  70. *
  71. * @param part the package part holding the drawing data,
  72. * @param rel the package relationship holding this drawing,
  73. * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image
  74. * @deprecated in POI 3.14, scheduled for removal in POI 3.16
  75. */
  76. @Deprecated
  77. public XSLFPictureData(PackagePart part, PackageRelationship rel) {
  78. this(part);
  79. }
  80. /**
  81. * An InputStream to read the picture data directly
  82. * from the underlying package part
  83. *
  84. * @return InputStream
  85. */
  86. public InputStream getInputStream() throws IOException {
  87. return getPackagePart().getInputStream();
  88. }
  89. /**
  90. * Gets the picture data as a byte array.
  91. *
  92. * You can grab the picture data directly from the underlying package part with the {@link #getInputStream()} method
  93. *
  94. * @return the Picture data.
  95. */
  96. public byte[] getData() {
  97. try {
  98. return IOUtils.toByteArray(getInputStream());
  99. } catch (IOException e) {
  100. throw new POIXMLException(e);
  101. }
  102. }
  103. /**
  104. * Returns the file name of the image, eg image7.jpg . The original filename
  105. * isn't always available, but if it can be found it's likely to be in the
  106. * CTDrawing
  107. */
  108. public String getFileName() {
  109. String name = getPackagePart().getPartName().getName();
  110. return name.substring(name.lastIndexOf('/') + 1);
  111. }
  112. /**
  113. * Suggests a file extension for this image.
  114. *
  115. * @return the file extension.
  116. */
  117. public String suggestFileExtension() {
  118. return getPackagePart().getPartName().getExtension();
  119. }
  120. @Override
  121. public byte[] getChecksum() {
  122. cacheProperties();
  123. byte cs[] = new byte[LittleEndianConsts.LONG_SIZE];
  124. LittleEndian.putLong(cs,0,checksum);
  125. return cs;
  126. }
  127. @Override
  128. public Dimension getImageDimension() {
  129. cacheProperties();
  130. return origSize;
  131. }
  132. @Override
  133. public Dimension getImageDimensionInPixels() {
  134. Dimension dim = getImageDimension();
  135. return new Dimension(
  136. Units.pointsToPixel(dim.getWidth()),
  137. Units.pointsToPixel(dim.getHeight())
  138. );
  139. }
  140. /**
  141. * Determine and cache image properties
  142. */
  143. protected void cacheProperties() {
  144. if (origSize == null || checksum == null) {
  145. byte data[] = getData();
  146. checksum = IOUtils.calculateChecksum(data);
  147. PictureType pt = getType();
  148. if (pt == null) {
  149. origSize = new Dimension(1,1);
  150. return;
  151. }
  152. switch (pt) {
  153. case EMF:
  154. origSize = new EMF.NativeHeader(data, 0).getSize();
  155. break;
  156. case WMF:
  157. // wmf files in pptx usually have their placeable header
  158. // stripped away, so this returns only the dummy size
  159. origSize = new WMF.NativeHeader(data, 0).getSize();
  160. break;
  161. case PICT:
  162. origSize = new PICT.NativeHeader(data, 0).getSize();
  163. break;
  164. default:
  165. BufferedImage img = null;
  166. try {
  167. img = ImageIO.read(new ByteArrayInputStream(data));
  168. } catch (IOException e) {
  169. logger.log(POILogger.WARN, "Can't determine image dimensions", e);
  170. }
  171. // set dummy size, in case of dummy dimension can't be set
  172. origSize = (img == null)
  173. ? new Dimension(200,200)
  174. : new Dimension(
  175. (int)Units.pixelToPoints(img.getWidth()),
  176. (int)Units.pixelToPoints(img.getHeight())
  177. );
  178. break;
  179. }
  180. }
  181. }
  182. /**
  183. * *PictureData objects store the actual content in the part directly without keeping a
  184. * copy like all others therefore we need to handle them differently.
  185. */
  186. @Override
  187. protected void prepareForCommit() {
  188. // do not clear the part here
  189. }
  190. @Override
  191. public String getContentType() {
  192. return getPackagePart().getContentType();
  193. }
  194. public void setData(byte[] data) throws IOException {
  195. OutputStream os = getPackagePart().getOutputStream();
  196. os.write(data);
  197. os.close();
  198. // recalculate now since we already have the data bytes available anyhow
  199. checksum = IOUtils.calculateChecksum(data);
  200. origSize = null; // need to recalculate image size
  201. }
  202. @Override
  203. public PictureType getType() {
  204. String ct = getContentType();
  205. if (XSLFRelation.IMAGE_EMF.getContentType().equals(ct)) {
  206. return PictureType.EMF;
  207. } else if (XSLFRelation.IMAGE_WMF.getContentType().equals(ct)) {
  208. return PictureType.WMF;
  209. } else if (XSLFRelation.IMAGE_PICT.getContentType().equals(ct)) {
  210. return PictureType.PICT;
  211. } else if (XSLFRelation.IMAGE_JPEG.getContentType().equals(ct)) {
  212. return PictureType.JPEG;
  213. } else if (XSLFRelation.IMAGE_PNG.getContentType().equals(ct)) {
  214. return PictureType.PNG;
  215. } else if (XSLFRelation.IMAGE_DIB.getContentType().equals(ct)) {
  216. return PictureType.DIB;
  217. } else if (XSLFRelation.IMAGE_GIF.getContentType().equals(ct)) {
  218. return PictureType.GIF;
  219. } else if (XSLFRelation.IMAGE_EPS.getContentType().equals(ct)) {
  220. return PictureType.EPS;
  221. } else if (XSLFRelation.IMAGE_BMP.getContentType().equals(ct)) {
  222. return PictureType.BMP;
  223. } else if (XSLFRelation.IMAGE_WPG.getContentType().equals(ct)) {
  224. return PictureType.WPG;
  225. } else if (XSLFRelation.IMAGE_WDP.getContentType().equals(ct)) {
  226. return PictureType.WDP;
  227. } else if (XSLFRelation.IMAGE_TIFF.getContentType().equals(ct)) {
  228. return PictureType.TIFF;
  229. } else {
  230. return null;
  231. }
  232. }
  233. /* package */ static XSLFRelation getRelationForType(PictureType pt) {
  234. switch (pt) {
  235. case EMF: return XSLFRelation.IMAGE_EMF;
  236. case WMF: return XSLFRelation.IMAGE_WMF;
  237. case PICT: return XSLFRelation.IMAGE_PICT;
  238. case JPEG: return XSLFRelation.IMAGE_JPEG;
  239. case PNG: return XSLFRelation.IMAGE_PNG;
  240. case DIB: return XSLFRelation.IMAGE_DIB;
  241. case GIF: return XSLFRelation.IMAGE_GIF;
  242. case EPS: return XSLFRelation.IMAGE_EPS;
  243. case BMP: return XSLFRelation.IMAGE_BMP;
  244. case WPG: return XSLFRelation.IMAGE_WPG;
  245. case WDP: return XSLFRelation.IMAGE_WDP;
  246. case TIFF: return XSLFRelation.IMAGE_TIFF;
  247. default: return null;
  248. }
  249. }
  250. /**
  251. * @return the 0-based index of this pictures within the picture parts
  252. */
  253. public int getIndex() {
  254. return index;
  255. }
  256. /**
  257. * @param index sets the 0-based index of this pictures within the picture parts
  258. */
  259. public void setIndex(int index) {
  260. this.index = index;
  261. }
  262. }