001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.poi.hslf.model;
018:
019: import org.apache.poi.ddf.*;
020: import org.apache.poi.hslf.usermodel.PictureData;
021: import org.apache.poi.hslf.usermodel.SlideShow;
022: import org.apache.poi.hslf.record.Document;
023: import org.apache.poi.hslf.blip.Bitmap;
024: import org.apache.poi.util.POILogger;
025:
026: import javax.imageio.ImageIO;
027: import java.awt.image.BufferedImage;
028: import java.awt.*;
029: import java.io.ByteArrayInputStream;
030: import java.io.IOException;
031: import java.util.List;
032: import java.util.Arrays;
033:
034: /**
035: * Represents a picture in a PowerPoint document.
036: *
037: * @author Yegor Kozlov
038: */
039: public class Picture extends SimpleShape {
040:
041: /**
042: * Windows Enhanced Metafile (EMF)
043: */
044: public static final int EMF = 2;
045:
046: /**
047: * Windows Metafile (WMF)
048: */
049: public static final int WMF = 3;
050:
051: /**
052: * Macintosh PICT
053: */
054: public static final int PICT = 4;
055:
056: /**
057: * JPEG
058: */
059: public static final int JPEG = 5;
060:
061: /**
062: * PNG
063: */
064: public static final int PNG = 6;
065:
066: /**
067: * Windows DIB (BMP)
068: */
069: public static final byte DIB = 7;
070:
071: /**
072: * Create a new <code>Picture</code>
073: *
074: * @param idx the index of the picture
075: */
076: public Picture(int idx) {
077: this (idx, null);
078: }
079:
080: /**
081: * Create a new <code>Picture</code>
082: *
083: * @param idx the index of the picture
084: * @param parent the parent shape
085: */
086: public Picture(int idx, Shape parent) {
087: super (null, parent);
088: _escherContainer = createSpContainer(idx,
089: parent instanceof ShapeGroup);
090: }
091:
092: /**
093: * Create a <code>Picture</code> object
094: *
095: * @param escherRecord the <code>EscherSpContainer</code> record which holds information about
096: * this picture in the <code>Slide</code>
097: * @param parent the parent shape of this picture
098: */
099: protected Picture(EscherContainerRecord escherRecord, Shape parent) {
100: super (escherRecord, parent);
101: }
102:
103: /**
104: * Returns index associated with this picture.
105: * Index starts with 1 and points to a EscherBSE record which
106: * holds information about this picture.
107: *
108: * @return the index to this picture (1 based).
109: */
110: public int getPictureIndex() {
111: EscherOptRecord opt = (EscherOptRecord) getEscherChild(
112: _escherContainer, EscherOptRecord.RECORD_ID);
113: EscherSimpleProperty prop = (EscherSimpleProperty) getEscherProperty(
114: opt, EscherProperties.BLIP__BLIPTODISPLAY + 0x4000);
115: return prop == null ? 0 : prop.getPropertyValue();
116: }
117:
118: /**
119: * Create a new Picture and populate the inital structure of the <code>EscherSp</code> record which holds information about this picture.
120:
121: * @param idx the index of the picture which referes to <code>EscherBSE</code> container.
122: * @return the create Picture object
123: */
124: protected EscherContainerRecord createSpContainer(int idx,
125: boolean isChild) {
126: EscherContainerRecord spContainer = super
127: .createSpContainer(isChild);
128: spContainer.setOptions((short) 15);
129:
130: EscherSpRecord spRecord = spContainer
131: .getChildById(EscherSpRecord.RECORD_ID);
132: spRecord
133: .setOptions((short) ((ShapeTypes.PictureFrame << 4) | 0x2));
134:
135: //set default properties for a picture
136: EscherOptRecord opt = (EscherOptRecord) getEscherChild(
137: spContainer, EscherOptRecord.RECORD_ID);
138: setEscherProperty(opt,
139: EscherProperties.PROTECTION__LOCKAGAINSTGROUPING,
140: 8388736);
141:
142: //another weird feature of powerpoint: for picture id we must add 0x4000.
143: setEscherProperty(
144: opt,
145: (short) (EscherProperties.BLIP__BLIPTODISPLAY + 0x4000),
146: idx);
147:
148: return spContainer;
149: }
150:
151: /**
152: * Resize this picture to the default size.
153: * For PNG and JPEG resizes the image to 100%,
154: * for other types sets the default size of 200x200 pixels.
155: */
156: public void setDefaultSize() {
157: PictureData pict = getPictureData();
158: if (pict instanceof Bitmap) {
159: BufferedImage img = null;
160: try {
161: img = ImageIO.read(new ByteArrayInputStream(pict
162: .getData()));
163: } catch (IOException e) {
164: } catch (NegativeArraySizeException ne) {
165: }
166:
167: if (img != null) {
168: // Valid image, set anchor from it
169: setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()
170: * POINT_DPI / PIXEL_DPI, img.getHeight()
171: * POINT_DPI / PIXEL_DPI));
172: } else {
173: // Invalid image, go with the default metafile size
174: setAnchor(new java.awt.Rectangle(0, 0, 200, 200));
175: }
176: } else {
177: //default size of a metafile picture is 200x200
178: setAnchor(new java.awt.Rectangle(50, 50, 200, 200));
179: }
180: }
181:
182: /**
183: * Returns the picture data for this picture.
184: *
185: * @return the picture data for this picture.
186: */
187: public PictureData getPictureData() {
188: SlideShow ppt = getSheet().getSlideShow();
189: PictureData[] pict = ppt.getPictureData();
190: Document doc = ppt.getDocumentRecord();
191: EscherContainerRecord dggContainer = doc.getPPDrawingGroup()
192: .getDggContainer();
193: EscherContainerRecord bstore = (EscherContainerRecord) Shape
194: .getEscherChild(dggContainer,
195: EscherContainerRecord.BSTORE_CONTAINER);
196:
197: List lst = bstore.getChildRecords();
198: int idx = getPictureIndex();
199: if (idx == 0) {
200: logger.log(POILogger.ERROR,
201: "no reference to picture data found ");
202: } else {
203: EscherBSERecord bse = (EscherBSERecord) lst.get(idx - 1);
204: for (int i = 0; i < pict.length; i++) {
205: if (pict[i].getOffset() == bse.getOffset()) {
206: return pict[i];
207: }
208: }
209: logger.log(POILogger.ERROR,
210: "no picture found for our BSE offset "
211: + bse.getOffset());
212: }
213: return null;
214: }
215:
216: /**
217: * By default set the orininal image size
218: */
219: protected void afterInsert(Sheet sh) {
220: java.awt.Rectangle anchor = getAnchor();
221: if (anchor.equals(new java.awt.Rectangle())) {
222: setDefaultSize();
223: }
224: }
225:
226: }
|