2007-01-15 09:27:03 -05:00
|
|
|
/*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership.
|
|
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
|
* (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2006-12-22 15:56:04 -05:00
|
|
|
package org.apache.poi.hslf.model;
|
|
|
|
|
|
|
|
import org.apache.poi.ddf.*;
|
|
|
|
import org.apache.poi.hslf.usermodel.PictureData;
|
|
|
|
import org.apache.poi.hslf.usermodel.SlideShow;
|
|
|
|
import org.apache.poi.hslf.record.Document;
|
|
|
|
import org.apache.poi.hslf.blip.Bitmap;
|
2008-04-20 07:17:48 -04:00
|
|
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
2008-04-14 10:58:18 -04:00
|
|
|
import org.apache.poi.util.POILogger;
|
2006-12-22 15:56:04 -05:00
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.*;
|
2008-04-17 11:08:03 -04:00
|
|
|
import java.awt.geom.Rectangle2D;
|
2008-04-30 02:29:11 -04:00
|
|
|
import java.awt.geom.AffineTransform;
|
2006-12-22 15:56:04 -05:00
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import java.io.IOException;
|
2008-04-20 07:17:48 -04:00
|
|
|
import java.io.UnsupportedEncodingException;
|
2006-12-22 15:56:04 -05:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a picture in a PowerPoint document.
|
|
|
|
*
|
|
|
|
* @author Yegor Kozlov
|
|
|
|
*/
|
|
|
|
public class Picture extends SimpleShape {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Windows Enhanced Metafile (EMF)
|
|
|
|
*/
|
|
|
|
public static final int EMF = 2;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Windows Metafile (WMF)
|
|
|
|
*/
|
|
|
|
public static final int WMF = 3;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Macintosh PICT
|
|
|
|
*/
|
|
|
|
public static final int PICT = 4;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* JPEG
|
|
|
|
*/
|
|
|
|
public static final int JPEG = 5;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PNG
|
|
|
|
*/
|
|
|
|
public static final int PNG = 6;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Windows DIB (BMP)
|
|
|
|
*/
|
|
|
|
public static final byte DIB = 7;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new <code>Picture</code>
|
|
|
|
*
|
|
|
|
* @param idx the index of the picture
|
|
|
|
*/
|
|
|
|
public Picture(int idx){
|
2007-09-09 03:38:35 -04:00
|
|
|
this(idx, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new <code>Picture</code>
|
|
|
|
*
|
|
|
|
* @param idx the index of the picture
|
|
|
|
* @param parent the parent shape
|
|
|
|
*/
|
|
|
|
public Picture(int idx, Shape parent) {
|
|
|
|
super(null, parent);
|
|
|
|
_escherContainer = createSpContainer(idx, parent instanceof ShapeGroup);
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a <code>Picture</code> object
|
|
|
|
*
|
|
|
|
* @param escherRecord the <code>EscherSpContainer</code> record which holds information about
|
|
|
|
* this picture in the <code>Slide</code>
|
|
|
|
* @param parent the parent shape of this picture
|
|
|
|
*/
|
|
|
|
protected Picture(EscherContainerRecord escherRecord, Shape parent){
|
|
|
|
super(escherRecord, parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns index associated with this picture.
|
|
|
|
* Index starts with 1 and points to a EscherBSE record which
|
|
|
|
* holds information about this picture.
|
|
|
|
*
|
|
|
|
* @return the index to this picture (1 based).
|
|
|
|
*/
|
|
|
|
public int getPictureIndex(){
|
|
|
|
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
2008-01-25 14:37:22 -05:00
|
|
|
EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.BLIP__BLIPTODISPLAY);
|
2007-05-26 03:22:51 -04:00
|
|
|
return prop == null ? 0 : prop.getPropertyValue();
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new Picture and populate the inital structure of the <code>EscherSp</code> record which holds information about this picture.
|
|
|
|
|
|
|
|
* @param idx the index of the picture which referes to <code>EscherBSE</code> container.
|
|
|
|
* @return the create Picture object
|
|
|
|
*/
|
2007-09-09 03:38:35 -04:00
|
|
|
protected EscherContainerRecord createSpContainer(int idx, boolean isChild) {
|
2008-04-15 03:54:20 -04:00
|
|
|
_escherContainer = super.createSpContainer(isChild);
|
|
|
|
_escherContainer.setOptions((short)15);
|
2006-12-22 15:56:04 -05:00
|
|
|
|
2008-04-15 03:54:20 -04:00
|
|
|
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
|
2006-12-22 15:56:04 -05:00
|
|
|
spRecord.setOptions((short)((ShapeTypes.PictureFrame << 4) | 0x2));
|
|
|
|
|
|
|
|
//set default properties for a picture
|
2008-04-15 03:54:20 -04:00
|
|
|
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
2008-04-20 07:17:48 -04:00
|
|
|
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x800080);
|
2006-12-22 15:56:04 -05:00
|
|
|
|
|
|
|
//another weird feature of powerpoint: for picture id we must add 0x4000.
|
|
|
|
setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx);
|
|
|
|
|
2008-04-15 03:54:20 -04:00
|
|
|
return _escherContainer;
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resize this picture to the default size.
|
2007-04-18 10:22:55 -04:00
|
|
|
* For PNG and JPEG resizes the image to 100%,
|
|
|
|
* for other types sets the default size of 200x200 pixels.
|
2006-12-22 15:56:04 -05:00
|
|
|
*/
|
|
|
|
public void setDefaultSize(){
|
|
|
|
PictureData pict = getPictureData();
|
|
|
|
if (pict instanceof Bitmap){
|
|
|
|
BufferedImage img = null;
|
|
|
|
try {
|
|
|
|
img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
|
|
|
|
}
|
|
|
|
catch (IOException e){}
|
|
|
|
catch (NegativeArraySizeException ne) {}
|
|
|
|
|
|
|
|
if(img != null) {
|
|
|
|
// Valid image, set anchor from it
|
2007-03-30 09:48:56 -04:00
|
|
|
setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()*POINT_DPI/PIXEL_DPI, img.getHeight()*POINT_DPI/PIXEL_DPI));
|
2006-12-22 15:56:04 -05:00
|
|
|
} else {
|
|
|
|
// Invalid image, go with the default metafile size
|
|
|
|
setAnchor(new java.awt.Rectangle(0, 0, 200, 200));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//default size of a metafile picture is 200x200
|
|
|
|
setAnchor(new java.awt.Rectangle(50, 50, 200, 200));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the picture data for this picture.
|
|
|
|
*
|
|
|
|
* @return the picture data for this picture.
|
|
|
|
*/
|
|
|
|
public PictureData getPictureData(){
|
|
|
|
SlideShow ppt = getSheet().getSlideShow();
|
|
|
|
PictureData[] pict = ppt.getPictureData();
|
|
|
|
|
2008-06-08 08:30:25 -04:00
|
|
|
EscherBSERecord bse = getEscherBSERecord();
|
|
|
|
if (bse == null){
|
2008-04-14 10:58:18 -04:00
|
|
|
logger.log(POILogger.ERROR, "no reference to picture data found ");
|
2007-05-26 03:22:51 -04:00
|
|
|
} else {
|
|
|
|
for ( int i = 0; i < pict.length; i++ ) {
|
|
|
|
if (pict[i].getOffset() == bse.getOffset()){
|
|
|
|
return pict[i];
|
|
|
|
}
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|
2008-04-14 10:58:18 -04:00
|
|
|
logger.log(POILogger.ERROR, "no picture found for our BSE offset " + bse.getOffset());
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2008-06-08 08:30:25 -04:00
|
|
|
protected EscherBSERecord getEscherBSERecord(){
|
|
|
|
SlideShow ppt = getSheet().getSlideShow();
|
|
|
|
Document doc = ppt.getDocumentRecord();
|
|
|
|
EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
|
|
|
|
EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
|
|
|
|
|
|
|
|
List lst = bstore.getChildRecords();
|
|
|
|
int idx = getPictureIndex();
|
|
|
|
if (idx == 0){
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return (EscherBSERecord)lst.get(idx-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-20 07:17:48 -04:00
|
|
|
/**
|
|
|
|
* Name of this picture.
|
|
|
|
*
|
|
|
|
* @return name of this picture
|
|
|
|
*/
|
|
|
|
public String getPictureName(){
|
|
|
|
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
|
|
|
EscherComplexProperty prop = (EscherComplexProperty)getEscherProperty(opt, EscherProperties.BLIP__BLIPFILENAME);
|
|
|
|
String name = null;
|
|
|
|
if(prop != null){
|
|
|
|
try {
|
|
|
|
name = new String(prop.getComplexData(), "UTF-16LE");
|
|
|
|
int idx = name.indexOf('\u0000');
|
|
|
|
return idx == -1 ? name : name.substring(0, idx);
|
|
|
|
} catch (UnsupportedEncodingException e){
|
|
|
|
throw new HSLFException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Name of this picture.
|
|
|
|
*
|
|
|
|
* @param name of this picture
|
|
|
|
*/
|
|
|
|
public void setPictureName(String name){
|
|
|
|
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
|
|
|
|
try {
|
|
|
|
byte[] data = (name + '\u0000').getBytes("UTF-16LE");
|
|
|
|
EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, false, data);
|
|
|
|
opt.addEscherProperty(prop);
|
|
|
|
} catch (UnsupportedEncodingException e){
|
|
|
|
throw new HSLFException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-22 15:56:04 -05:00
|
|
|
/**
|
|
|
|
* By default set the orininal image size
|
|
|
|
*/
|
|
|
|
protected void afterInsert(Sheet sh){
|
2008-04-19 07:16:53 -04:00
|
|
|
super.afterInsert(sh);
|
2008-06-08 08:30:25 -04:00
|
|
|
|
|
|
|
EscherBSERecord bse = getEscherBSERecord();
|
|
|
|
bse.setRef(bse.getRef() + 1);
|
|
|
|
|
2006-12-22 15:56:04 -05:00
|
|
|
java.awt.Rectangle anchor = getAnchor();
|
|
|
|
if (anchor.equals(new java.awt.Rectangle())){
|
|
|
|
setDefaultSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-17 11:08:03 -04:00
|
|
|
public void draw(Graphics2D graphics){
|
2008-04-30 02:29:11 -04:00
|
|
|
AffineTransform at = graphics.getTransform();
|
|
|
|
ShapePainter.paint(this, graphics);
|
|
|
|
|
2008-04-17 11:08:03 -04:00
|
|
|
PictureData data = getPictureData();
|
2008-06-08 08:30:25 -04:00
|
|
|
data.draw(graphics, this);
|
|
|
|
|
2008-04-30 02:29:11 -04:00
|
|
|
graphics.setTransform(at);
|
2008-04-17 11:08:03 -04:00
|
|
|
}
|
2006-12-22 15:56:04 -05:00
|
|
|
}
|