Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

PictureData.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hslf.usermodel;
  16. import java.awt.Graphics2D;
  17. import java.io.IOException;
  18. import java.io.OutputStream;
  19. import java.security.MessageDigest;
  20. import org.apache.poi.hslf.blip.BitmapPainter;
  21. import org.apache.poi.hslf.blip.DIB;
  22. import org.apache.poi.hslf.blip.EMF;
  23. import org.apache.poi.hslf.blip.ImagePainter;
  24. import org.apache.poi.hslf.blip.JPEG;
  25. import org.apache.poi.hslf.blip.PICT;
  26. import org.apache.poi.hslf.blip.PNG;
  27. import org.apache.poi.hslf.blip.WMF;
  28. import org.apache.poi.hslf.model.Picture;
  29. import org.apache.poi.poifs.crypt.CryptoFunctions;
  30. import org.apache.poi.poifs.crypt.HashAlgorithm;
  31. import org.apache.poi.util.LittleEndian;
  32. import org.apache.poi.util.POILogFactory;
  33. import org.apache.poi.util.POILogger;
  34. /**
  35. * A class that represents image data contained in a slide show.
  36. *
  37. * @author Yegor Kozlov
  38. */
  39. public abstract class PictureData {
  40. protected POILogger logger = POILogFactory.getLogger(this.getClass());
  41. /**
  42. * Size of the image checksum calculated using MD5 algorithm.
  43. */
  44. protected static final int CHECKSUM_SIZE = 16;
  45. /**
  46. * Binary data of the picture
  47. */
  48. private byte[] rawdata;
  49. /**
  50. * The offset to the picture in the stream
  51. */
  52. protected int offset;
  53. /**
  54. * The instance type/signatures defines if one or two UID instances will be included
  55. */
  56. protected int uidInstanceCount = 1;
  57. /**
  58. * Returns type of this picture.
  59. * Must be one of the static constants defined in the <code>Picture<code> class.
  60. *
  61. * @return type of this picture.
  62. */
  63. public abstract int getType();
  64. /**
  65. * Returns the binary data of this Picture
  66. * @return picture data
  67. */
  68. public abstract byte[] getData();
  69. /**
  70. * Set picture data
  71. */
  72. public abstract void setData(byte[] data) throws IOException;
  73. /**
  74. * Blip signature.
  75. */
  76. public abstract int getSignature();
  77. public abstract void setSignature(int signature);
  78. /**
  79. * The instance type/signatures defines if one or two UID instances will be included
  80. */
  81. protected int getUIDInstanceCount() {
  82. return uidInstanceCount;
  83. }
  84. protected static final ImagePainter[] painters = new ImagePainter[8];
  85. static {
  86. PictureData.setImagePainter(Picture.PNG, new BitmapPainter());
  87. PictureData.setImagePainter(Picture.JPEG, new BitmapPainter());
  88. PictureData.setImagePainter(Picture.DIB, new BitmapPainter());
  89. }
  90. /**
  91. * Returns the raw binary data of this Picture excluding the first 8 bytes
  92. * which hold image signature and size of the image data.
  93. *
  94. * @return picture data
  95. */
  96. public byte[] getRawData(){
  97. return rawdata;
  98. }
  99. public void setRawData(byte[] data){
  100. rawdata = data;
  101. }
  102. /**
  103. * File offset in the 'Pictures' stream
  104. *
  105. * @return offset in the 'Pictures' stream
  106. */
  107. public int getOffset(){
  108. return offset;
  109. }
  110. /**
  111. * Set offset of this picture in the 'Pictures' stream.
  112. * We need to set it when a new picture is created.
  113. *
  114. * @param offset in the 'Pictures' stream
  115. */
  116. public void setOffset(int offset){
  117. this.offset = offset;
  118. }
  119. /**
  120. * Returns 16-byte checksum of this picture
  121. */
  122. public byte[] getUID(){
  123. byte[] uid = new byte[16];
  124. System.arraycopy(rawdata, 0, uid, 0, uid.length);
  125. return uid;
  126. }
  127. /**
  128. * Compute 16-byte checksum of this picture using MD5 algorithm.
  129. */
  130. public static byte[] getChecksum(byte[] data) {
  131. MessageDigest md5 = CryptoFunctions.getMessageDigest(HashAlgorithm.md5);
  132. md5.update(data);
  133. return md5.digest();
  134. }
  135. /**
  136. * Write this picture into <code>OutputStream</code>
  137. */
  138. public void write(OutputStream out) throws IOException {
  139. byte[] data;
  140. data = new byte[LittleEndian.SHORT_SIZE];
  141. LittleEndian.putUShort(data, 0, getSignature());
  142. out.write(data);
  143. data = new byte[LittleEndian.SHORT_SIZE];
  144. LittleEndian.putUShort(data, 0, getType() + 0xF018);
  145. out.write(data);
  146. byte[] rawdata = getRawData();
  147. data = new byte[LittleEndian.INT_SIZE];
  148. LittleEndian.putInt(data, 0, rawdata.length);
  149. out.write(data);
  150. out.write(rawdata);
  151. }
  152. /**
  153. * Create an instance of <code>PictureData</code> by type.
  154. *
  155. * @param type type of the picture data.
  156. * Must be one of the static constants defined in the <code>Picture<code> class.
  157. * @return concrete instance of <code>PictureData</code>
  158. */
  159. public static PictureData create(int type){
  160. PictureData pict;
  161. switch (type){
  162. case Picture.EMF:
  163. pict = new EMF();
  164. break;
  165. case Picture.WMF:
  166. pict = new WMF();
  167. break;
  168. case Picture.PICT:
  169. pict = new PICT();
  170. break;
  171. case Picture.JPEG:
  172. pict = new JPEG();
  173. break;
  174. case Picture.PNG:
  175. pict = new PNG();
  176. break;
  177. case Picture.DIB:
  178. pict = new DIB();
  179. break;
  180. default:
  181. throw new IllegalArgumentException("Unsupported picture type: " + type);
  182. }
  183. return pict;
  184. }
  185. /**
  186. * Return 24 byte header which preceeds the actual picture data.
  187. * <p>
  188. * The header consists of 2-byte signature, 2-byte type,
  189. * 4-byte image size and 16-byte checksum of the image data.
  190. * </p>
  191. *
  192. * @return the 24 byte header which preceeds the actual picture data.
  193. */
  194. public byte[] getHeader() {
  195. byte[] header = new byte[16 + 8];
  196. LittleEndian.putInt(header, 0, getSignature());
  197. LittleEndian.putInt(header, 4, getRawData().length);
  198. System.arraycopy(rawdata, 0, header, 8, 16);
  199. return header;
  200. }
  201. /**
  202. * Return image size in bytes
  203. *
  204. * @return the size of the picture in bytes
  205. * @deprecated Use <code>getData().length</code> instead.
  206. */
  207. public int getSize(){
  208. return getData().length;
  209. }
  210. public void draw(Graphics2D graphics, Picture parent){
  211. ImagePainter painter = painters[getType()];
  212. if(painter != null) painter.paint(graphics, this, parent);
  213. else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName());
  214. }
  215. /**
  216. * Register ImagePainter for the specified image type
  217. *
  218. * @param type image type, must be one of the static constants defined in the <code>Picture<code> class.
  219. * @param painter
  220. */
  221. public static void setImagePainter(int type, ImagePainter painter){
  222. painters[type] = painter;
  223. }
  224. /**
  225. * Return ImagePainter for the specified image type
  226. *
  227. * @param type blip type, must be one of the static constants defined in the <code>Picture<code> class.
  228. * @return ImagePainter for the specified image type
  229. */
  230. public static ImagePainter getImagePainter(int type){
  231. return painters[type];
  232. }
  233. }