1    /*
2     *  ====================================================================
3     *  The Apache Software License, Version 1.1
4     *
5     *  Copyright (c) 2000 The Apache Software Foundation.  All rights
6     *  reserved.
7     *
8     *  Redistribution and use in source and binary forms, with or without
9     *  modification, are permitted provided that the following conditions
10    *  are met:
11    *
12    *  1. Redistributions of source code must retain the above copyright
13    *  notice, this list of conditions and the following disclaimer.
14    *
15    *  2. Redistributions in binary form must reproduce the above copyright
16    *  notice, this list of conditions and the following disclaimer in
17    *  the documentation and/or other materials provided with the
18    *  distribution.
19    *
20    *  3. The end-user documentation included with the redistribution,
21    *  if any, must include the following acknowledgment:
22    *  "This product includes software developed by the
23    *  Apache Software Foundation (http://www.apache.org/)."
24    *  Alternately, this acknowledgment may appear in the software itself,
25    *  if and wherever such third-party acknowledgments normally appear.
26    *
27    *  4. The names "Apache" and "Apache Software Foundation" must
28    *  not be used to endorse or promote products derived from this
29    *  software without prior written permission. For written
30    *  permission, please contact apache@apache.org.
31    *
32    *  5. Products derived from this software may not be called "Apache",
33    *  nor may "Apache" appear in their name, without prior written
34    *  permission of the Apache Software Foundation.
35    *
36    *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    *  SUCH DAMAGE.
48    *  ====================================================================
49    *
50    *  This software consists of voluntary contributions made by many
51    *  individuals on behalf of the Apache Software Foundation.  For more
52    *  information on the Apache Software Foundation, please see
53    *  <http://www.apache.org/>.
54    */
55   package org.apache.poi.hpsf;
56   
57   import org.apache.poi.util.LittleEndian;
58   /**
59    * <p>Class to manipulate data in the Clipboard Variant ({@link
60    * Variant#VT_CF VT_CF}) format.</p>
61    *
62    * @author Drew Varner (Drew.Varner inOrAround sc.edu)
63    * @see SummaryInformation#getThumbnail()
64    * @version $Id: Thumbnail.java,v 1.5 2003/02/01 13:28:28 klute Exp $
65    * @since 2002-04-29
66    */
67   public class Thumbnail
68   {
69   
70       /**
71        * <p>Offset in bytes where the Clipboard Format Tag starts in the
72        * <code>byte[]</code> returned by {@link
73        * SummaryInformation#getThumbnail()}</p>
74        */
75       public static int OFFSET_CFTAG = 4;
76   
77       /**
78        * <p>Offset in bytes where the Clipboard Format starts in the
79        * <code>byte[]</code> returned by {@link
80        * SummaryInformation#getThumbnail()}</p>
81        *
82        * <p>This is only valid if the Clipboard Format Tag is {@link
83        * #CFTAG_WINDOWS}</p>
84        */
85       public static int OFFSET_CF = 8;
86   
87       /**
88        * <p>Offset in bytes where the Windows Metafile (WMF) image data
89        * starts in the <code>byte[]</code> returned by {@link
90        * SummaryInformation#getThumbnail()}</p>
91        *
92        * <p>There is only WMF data at this point in the
93        * <code>byte[]</code> if the Clipboard Format Tag is {@link
94        * #CFTAG_WINDOWS} and the Clipboard Format is {@link
95        * #CF_METAFILEPICT}.</p>
96        *
97        * <p>Note: The <code>byte[]</code> that starts at
98        * <code>OFFSET_WMFDATA</code> and ends at
99        * <code>getThumbnail().length - 1</code> forms a complete WMF
100       * image. It can be saved to disk with a <code>.wmf</code> file
101       * type and read using a WMF-capable image viewer.</p>
102       */
103      public static int OFFSET_WMFDATA = 20;
104  
105      /**
106       * <p>Clipboard Format Tag - Windows clipboard format</p>
107       *
108       * <p>A <code>DWORD</code> indicating a built-in Windows clipboard
109       * format value</p>
110       *
111       * <p>See: <a
112       * href="http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp"
113       * target="_blank">http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp</a>.</p>
114       */
115      public static int CFTAG_WINDOWS = -1;
116  
117      /**
118       * <p>Clipboard Format Tag - Macintosh clipboard format</p>
119       *
120       * <p>A <code>DWORD</code> indicating a Macintosh clipboard format
121       * value</p>
122       *
123       * <p>See: <a
124       * href="http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp"
125       * target="_blank">http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp</a>.</p>
126       */
127      public static int CFTAG_MACINTOSH = -2;
128  
129      /**
130       * <p>Clipboard Format Tag - Format ID</p>
131       *
132       * <p>A GUID containing a format identifier (FMTID). This is
133       * rarely used.</p>
134       *
135       * <p>See: <a
136       * href="http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp"
137       * target="_blank">http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp</a>.</p>
138       */
139      public static int CFTAG_FMTID = -3;
140  
141      /**
142       * <p>Clipboard Format Tag - No Data</p>
143       *
144       * <p>A <code>DWORD</code> indicating No data. This is rarely
145       * used.</p>
146       *
147       * <p>See: <a
148       * href="http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp"
149       * target="_blank">
150       * http://msdn.microsoft.com/library/en-us/dnolegen/html/msdn_propset.asp</a>.</p>
151       */
152      public static int CFTAG_NODATA = 0;
153  
154      /**
155       * <p>Clipboard Format - Windows metafile format. This is the
156       * recommended way to store thumbnails in Property Streams.</p>
157       *
158       * <p><strong>Note:</strong> This is not the same format used in
159       * regular WMF images. The clipboard version of this format has an
160       * extra clipboard-specific header.</p>
161       */
162      public static int CF_METAFILEPICT = 3;
163  
164      /**
165       * <p>Clipboard Format - Device Independent Bitmap</p>
166       */
167      public static int CF_DIB = 8;
168  
169      /**
170       * <p>Clipboard Format - Enhanced Windows metafile format</p>
171       */
172      public static int CF_ENHMETAFILE = 14;
173  
174      /**
175       * <p>Clipboard Format - Bitmap</p>
176       *
177       * <p>Obsolete, see <a
178       * href="msdn.microsoft.com/library/en-us/dnw98bk/html/clipboardoperations.asp
179       * target="_blank">msdn.microsoft.com/library/en-us/dnw98bk/html/clipboardoperations.asp</a>.</p>
180       */
181      public static int CF_BITMAP = 2;
182  
183      /**
184       * <p>A <code>byte[]</code> to hold a thumbnail image in ({@link
185       * Variant#VT_CF VT_CF}) format.</p>
186       */
187      private byte[] thumbnailData = null;
188  
189  
190  
191      /**
192       * <p>Default Constructor. If you use it then one you'll have to add
193       * the thumbnail <code>byte[]</code> from {@link
194       * SummaryInformation#getThumbnail()} to do any useful
195       * manipulations, otherwise you'll get a
196       * <code>NullPointerException</code>.</p>
197       */
198      public Thumbnail()
199      {
200          super();
201      }
202  
203  
204  
205      /**
206       * <p>Creates a <code>Thumbnail</code> instance and initializes
207       * with the specified image bytes.</p>
208       *
209       * @param thumbnailData The thumbnail data
210       */
211      public Thumbnail(byte[] thumbnailData)
212      {
213          this.thumbnailData = thumbnailData;
214      }
215  
216  
217  
218      /**
219       * <p>Returns the thumbnail as a <code>byte[]</code> in {@link
220       * Variant#VT_CF VT_CF} format.</p>
221       *
222       * @return The thumbnail value
223       * @see SummaryInformation#getThumbnail()
224       */
225      public byte[] getThumbnail()
226      {
227          return thumbnailData;
228      }
229  
230  
231  
232      /**
233       * <p>Sets the Thumbnail's underlying <code>byte[]</code> in
234       * {@link Variant#VT_CF VT_CF} format.</p>
235       *
236       * @param thumbnail The new thumbnail value
237       * @see SummaryInformation#getThumbnail()
238       */
239      public void setThumbnail(byte[] thumbnail)
240      {
241          this.thumbnailData = thumbnail;
242      }
243  
244  
245  
246      /**
247       * <p>Returns an <code>int</code> representing the Clipboard
248       * Format Tag</p>
249       *
250       * <p>Possible return values are:</p>
251       * <ul>
252       *  <li>{@link #CFTAG_WINDOWS CFTAG_WINDOWS}</li>
253       *  <li>{@link #CFTAG_MACINTOSH CFTAG_MACINTOSH}</li>
254       *  <li>{@link #CFTAG_FMTID CFTAG_FMTID}</li>
255       *  <li>{@link #CFTAG_NODATA CFTAG_NODATA}</li>
256       * </ul>
257       *
258       * @return A flag indicating the Clipboard Format Tag
259       */
260      public long getClipboardFormatTag()
261      {
262          long clipboardFormatTag = LittleEndian.getUInt(getThumbnail(),
263  						       OFFSET_CFTAG);
264          return clipboardFormatTag;
265      }
266  
267  
268  
269      /**
270       * <p>Returns an <code>int</code> representing the Clipboard
271       * Format</p>
272       *
273       * <p>Will throw an exception if the Thumbnail's Clipboard Format
274       * Tag is not {@link Thumbnail#CFTAG_WINDOWS CFTAG_WINDOWS}.</p>
275       *
276       * <p>Possible return values are:</p>
277       *
278       * <ul>
279       *  <li>{@link #CF_METAFILEPICT CF_METAFILEPICT}</li>
280       *  <li>{@link #CF_DIB CF_DIB}</li>
281       *  <li>{@link #CF_ENHMETAFILE CF_ENHMETAFILE}</li>
282       *  <li>{@link #CF_BITMAP CF_BITMAP}</li>
283       * </ul>
284       *
285       * @return a flag indicating the Clipboard Format
286       * @throws HPSFException if the Thumbnail isn't CFTAG_WINDOWS
287       */
288      public long getClipboardFormat() throws HPSFException
289      {
290          if (!(getClipboardFormatTag() == CFTAG_WINDOWS))
291              throw new HPSFException("Clipboard Format Tag of Thumbnail must " +
292  				    "be CFTAG_WINDOWS.");
293  
294          return LittleEndian.getUInt(getThumbnail(), OFFSET_CF);
295      }
296  
297  
298  
299      /**
300       * <p>Returns the Thumbnail as a <code>byte[]</code> of WMF data
301       * if the Thumbnail's Clipboard Format Tag is {@link
302       * #CFTAG_WINDOWS CFTAG_WINDOWS} and its Clipboard Format is
303       * {@link #CF_METAFILEPICT CF_METAFILEPICT}</p> <p>This
304       * <code>byte[]</code> is in the traditional WMF file, not the
305       * clipboard-specific version with special headers.</p>
306       *
307       * <p>See <a href="http://www.wvware.com/caolan/ora-wmf.html"
308       * target="_blank">http://www.wvware.com/caolan/ora-wmf.html</a>
309       * for more information on the WMF image format.</p>
310       *
311       * @return A WMF image of the Thumbnail
312       * @throws HPSFException if the Thumbnail isn't CFTAG_WINDOWS and
313       * CF_METAFILEPICT
314       */
315      public byte[] getThumbnailAsWMF() throws HPSFException
316      {
317          if (!(getClipboardFormatTag() == CFTAG_WINDOWS))
318              throw new HPSFException("Clipboard Format Tag of Thumbnail must " +
319  				    "be CFTAG_WINDOWS.");
320          if (!(getClipboardFormat() == CF_METAFILEPICT))
321              throw new HPSFException("Clipboard Format of Thumbnail must " +
322  				    "be CF_METAFILEPICT.");
323          else
324  	{
325              byte[] thumbnail = getThumbnail();
326              int wmfImageLength = thumbnail.length - OFFSET_WMFDATA;
327              byte[] wmfImage = new byte[wmfImageLength];
328              System.arraycopy(thumbnail,
329  			     OFFSET_WMFDATA,
330  			     wmfImage,
331  			     0,
332  			     wmfImageLength);
333              return wmfImage;
334          }
335      }
336  
337  }
338