Improved picture support for HSLF, from Yegor in bug 40388
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@448001 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
79606540c1
commit
6e1236c74a
@ -17,7 +17,7 @@
|
||||
<li><link href="#PageSize">How to retrieve or change slide size</link></li>
|
||||
<li><link href="#GetShapes">How to get shapes contained in a particular slide</link></li>
|
||||
<li><link href="#Shapes">Drawing a shape on a slide</link></li>
|
||||
<li><link href="#Pictures">How to add/retrieve pictures</link></li>
|
||||
<li><link href="#Pictures">How to work with pictures</link></li>
|
||||
<li><link href="#SlideTitle">How to set slide title</link></li>
|
||||
</ul>
|
||||
</section>
|
||||
@ -106,7 +106,7 @@
|
||||
corner of the slide. Distances in the drawing layer are measured in points (72 points = 1 inch).
|
||||
</p>
|
||||
<source>
|
||||
SlideShow ppt = new SlideShow);
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
|
||||
@ -120,10 +120,18 @@
|
||||
//TextBox
|
||||
TextBox txt = new TextBox();
|
||||
txt.setText("Hello, World!");
|
||||
txt.setAnchor(new java.awt.Rectangle(100, 100, 200, 50));
|
||||
txt.setFontSize(32);
|
||||
txt.setFontName("Arial");
|
||||
txt.setBold(true);
|
||||
txt.setAnchor(new java.awt.Rectangle(300, 100, 300, 50));
|
||||
|
||||
//use RichTextRun to work with the text format
|
||||
RichTextRun rt = txt.getRichTextRuns()[0];
|
||||
rt.setFontSize(32);
|
||||
rt.setFontName("Arial");
|
||||
rt.setBold(true);
|
||||
rt.setItalic(true);
|
||||
rt.setUnderlined(true);
|
||||
rt.setFontColor(Color.red);
|
||||
rt.setAlignment(TextBox.AlignRight);
|
||||
|
||||
slide.addShape(txt);
|
||||
|
||||
//Autoshape
|
||||
@ -140,15 +148,24 @@
|
||||
slide.addShape(sh2);
|
||||
|
||||
FileOutputStream out = new FileOutputStream("slideshow.ppt");
|
||||
wb.write(out);
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
</source>
|
||||
</section>
|
||||
<anchor id="Pictures"/>
|
||||
<section><title>How to add/retrieve pictures</title>
|
||||
<p>
|
||||
Note, for now only PNG and JPEG formats are supported.
|
||||
</p>
|
||||
<section><title>How to work with pictures</title>
|
||||
|
||||
<p>
|
||||
Currently, HSLF API supports the following types of pictures:
|
||||
<ul>
|
||||
<li>Windows Metafiles (WMF)</li>
|
||||
<li>Enhanced Metafiles (EMF)</li>
|
||||
<li>JPEG Interchange Format</li>
|
||||
<li>Portable Network Graphics (PNG)</li>
|
||||
<li>Macintosh PICT</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<source>
|
||||
SlideShow ppt = new SlideShow(new HSLFSlideShow("slideshow.ppt"));
|
||||
|
||||
@ -157,19 +174,23 @@
|
||||
for (int i = 0; i < pdata.length; i++){
|
||||
PictureData pict = pdata[i];
|
||||
|
||||
//raw picture data
|
||||
// picture data
|
||||
byte[] data = pict.getData();
|
||||
|
||||
int type = pict.getType();
|
||||
if (type == Picture.JPEG){
|
||||
FileOutputStream out = new FileOutputStream("pict"+i+".jpg");
|
||||
out.write(data);
|
||||
out.close();
|
||||
} else if (type == Picture.PNG){
|
||||
FileOutputStream out = new FileOutputStream("pict"+i+".png");
|
||||
out.write(data);
|
||||
out.close();
|
||||
String ext;
|
||||
switch (type){
|
||||
case Picture.JPEG: ext=".jpg"; break;
|
||||
case Picture.PNG: ext=".png"; break;
|
||||
case Picture.WMF: ext=".wmf"; break;
|
||||
case Picture.EMF: ext=".emf"; break;
|
||||
case Picture.PICT: ext=".pict"; break;
|
||||
default: continue;
|
||||
}
|
||||
FileOutputStream out = new FileOutputStream("pict_"+i + ext);
|
||||
out.write(data);
|
||||
out.close();
|
||||
|
||||
}
|
||||
|
||||
// add a new picture to this slideshow and insert it in a new slide
|
||||
|
@ -23,6 +23,7 @@ import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
@ -251,13 +252,31 @@ public class HSLFSlideShow extends POIDocument
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList p = new ArrayList();
|
||||
int pos = 0;
|
||||
while (pos < (pictstream.length - PictureData.HEADER_SIZE)) {
|
||||
PictureData pict = new PictureData(pictstream, pos);
|
||||
p.add(pict);
|
||||
pos += PictureData.HEADER_SIZE + pict.getSize();
|
||||
}
|
||||
List p = new ArrayList();
|
||||
int pos = 0;
|
||||
|
||||
while (pos < pictstream.length) {
|
||||
int offset = pos;
|
||||
|
||||
//image signature
|
||||
int signature = LittleEndian.getUShort(pictstream, pos);
|
||||
pos += LittleEndian.SHORT_SIZE;
|
||||
//image type + 0xF018
|
||||
int type = LittleEndian.getUShort(pictstream, pos);
|
||||
pos += LittleEndian.SHORT_SIZE;
|
||||
//image size
|
||||
int imgsize = LittleEndian.getInt(pictstream, pos);
|
||||
pos += LittleEndian.INT_SIZE;
|
||||
|
||||
byte[] imgdata = new byte[imgsize];
|
||||
System.arraycopy(pictstream, pos, imgdata, 0, imgdata.length);
|
||||
|
||||
PictureData pict = PictureData.create(type - 0xF018);
|
||||
pict.setRawData(imgdata);
|
||||
pict.setOffset(offset);
|
||||
p.add(pict);
|
||||
pos += imgsize;
|
||||
}
|
||||
|
||||
_pictures = (PictureData[])p.toArray(new PictureData[p.size()]);
|
||||
}
|
||||
|
47
src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
Normal file
47
src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
Normal file
@ -0,0 +1,47 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* Represents a bitmap picture data: JPEG or PNG.
|
||||
* The data is not compressed and the exact file content is written in the stream.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public abstract class Bitmap extends PictureData {
|
||||
|
||||
public byte[] getData(){
|
||||
byte[] rawdata = getRawData();
|
||||
byte[] imgdata = new byte[rawdata.length-17];
|
||||
System.arraycopy(rawdata, 17, imgdata, 0, imgdata.length);
|
||||
return imgdata;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] checksum = getChecksum(data);
|
||||
out.write(checksum);
|
||||
out.write(0);
|
||||
out.write(data);
|
||||
|
||||
setRawData(out.toByteArray());
|
||||
}
|
||||
}
|
92
src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java
Normal file
92
src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java
Normal file
@ -0,0 +1,92 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* Represents EMF (Windows Enhanced Metafile) picture data.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class EMF extends Metafile {
|
||||
|
||||
/**
|
||||
* Extract compressed EMF data from a ppt
|
||||
*/
|
||||
public byte[] getData(){
|
||||
try {
|
||||
byte[] rawdata = getRawData();
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
InputStream is = new ByteArrayInputStream( rawdata );
|
||||
Header header = new Header();
|
||||
header.read(rawdata, CHECKSUM_SIZE);
|
||||
is.skip(header.getSize() + CHECKSUM_SIZE);
|
||||
|
||||
InflaterInputStream inflater = new InflaterInputStream( is );
|
||||
byte[] chunk = new byte[4096];
|
||||
int count;
|
||||
while ((count = inflater.read(chunk)) >=0 ) {
|
||||
out.write(chunk,0,count);
|
||||
}
|
||||
inflater.close();
|
||||
return out.toByteArray();
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(byte[] data) throws IOException {
|
||||
byte[] compressed = compress(data, 0, data.length);
|
||||
|
||||
Header header = new Header();
|
||||
header.wmfsize = data.length;
|
||||
//we don't have a EMF reader in java, have to set default image size 200x200
|
||||
header.bounds = new java.awt.Rectangle(0, 0, 200, 200);
|
||||
header.size = new java.awt.Dimension(header.bounds.width*Shape.EMU_PER_POINT, header.bounds.height*Shape.EMU_PER_POINT);
|
||||
header.zipsize = compressed.length;
|
||||
|
||||
byte[] checksum = getChecksum(data);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(checksum);
|
||||
header.write(out);
|
||||
out.write(compressed);
|
||||
|
||||
setRawData(out.toByteArray());
|
||||
}
|
||||
|
||||
public int getType(){
|
||||
return Picture.EMF;
|
||||
}
|
||||
|
||||
/**
|
||||
* EMF signature is <code>0x3D40</code>
|
||||
*
|
||||
* @return EMF signature (<code>0x3D40</code>)
|
||||
*/
|
||||
public int getSignature(){
|
||||
return 0x3D40;
|
||||
}
|
||||
}
|
43
src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java
Normal file
43
src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java
Normal file
@ -0,0 +1,43 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
|
||||
/**
|
||||
* Represents a JPEG picture data in a PPT file
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class JPEG extends Bitmap {
|
||||
|
||||
/**
|
||||
* @return type of this picture
|
||||
* @see org.apache.poi.hslf.model.Picture#JPEG
|
||||
*/
|
||||
public int getType(){
|
||||
return Picture.JPEG;
|
||||
}
|
||||
|
||||
/**
|
||||
* JPEG signature is <code>0x46A0</code>
|
||||
*
|
||||
* @return JPEG signature (<code>0x46A0</code>)
|
||||
*/
|
||||
public int getSignature(){
|
||||
return 0x46A0;
|
||||
}
|
||||
}
|
123
src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
Normal file
123
src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
Normal file
@ -0,0 +1,123 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
/**
|
||||
* Represents a metafile picture which can be one of the following types: EMF, WMF, or PICT.
|
||||
* A metafile is stored compressed using the ZIP deflate/inflate algorithm.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public abstract class Metafile extends PictureData {
|
||||
|
||||
/**
|
||||
* A structure which represents a 34-byte header preceeding the compressed metafile data
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public static class Header{
|
||||
|
||||
/**
|
||||
* size of the original file
|
||||
*/
|
||||
public int wmfsize;
|
||||
|
||||
/**
|
||||
* Boundary of the metafile drawing commands
|
||||
*/
|
||||
public Rectangle bounds;
|
||||
|
||||
/**
|
||||
* Size of the metafile in EMUs
|
||||
*/
|
||||
public Dimension size;
|
||||
|
||||
/**
|
||||
* size of the compressed metafile data
|
||||
*/
|
||||
public int zipsize;
|
||||
|
||||
/**
|
||||
* Reserved. Always 0.
|
||||
*/
|
||||
public int compression;
|
||||
|
||||
/**
|
||||
* Reserved. Always 254.
|
||||
*/
|
||||
public int filter = 254;
|
||||
|
||||
public void read(byte[] data, int offset){
|
||||
int pos = offset;
|
||||
wmfsize = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
|
||||
int left = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
int top = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
int right = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
int bottom = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
|
||||
bounds = new Rectangle(left, top, right-left, bottom-top);
|
||||
int width = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
int height = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
|
||||
size = new Dimension(width, height);
|
||||
|
||||
zipsize = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
|
||||
compression = LittleEndian.getUnsignedByte(data, pos); pos++;
|
||||
filter = LittleEndian.getUnsignedByte(data, pos); pos++;
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException {
|
||||
byte[] header = new byte[34];
|
||||
int pos = 0;
|
||||
LittleEndian.putInt(header, pos, wmfsize); pos += LittleEndian.INT_SIZE; //hmf
|
||||
|
||||
LittleEndian.putInt(header, pos, bounds.x); pos += LittleEndian.INT_SIZE; //left
|
||||
LittleEndian.putInt(header, pos, bounds.y); pos += LittleEndian.INT_SIZE; //top
|
||||
LittleEndian.putInt(header, pos, bounds.x + bounds.width); pos += LittleEndian.INT_SIZE; //right
|
||||
LittleEndian.putInt(header, pos, bounds.y + bounds.height); pos += LittleEndian.INT_SIZE; //bottom
|
||||
LittleEndian.putInt(header, pos, size.width); pos += LittleEndian.INT_SIZE; //inch
|
||||
LittleEndian.putInt(header, pos, size.height); pos += LittleEndian.INT_SIZE; //inch
|
||||
LittleEndian.putInt(header, pos, zipsize); pos += LittleEndian.INT_SIZE; //inch
|
||||
|
||||
header[pos] = 0; pos ++;
|
||||
header[pos] = (byte)filter; pos ++;
|
||||
|
||||
out.write(header);
|
||||
}
|
||||
|
||||
public int getSize(){
|
||||
return 34;
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] compress(byte[] bytes, int offset, int length) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream deflater = new DeflaterOutputStream( out );
|
||||
deflater.write(bytes, offset, length);
|
||||
deflater.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
117
src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
Normal file
117
src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
Normal file
@ -0,0 +1,117 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* Represents Macintosh PICT picture data.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class PICT extends Metafile {
|
||||
|
||||
public PICT(){
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract compressed PICT data from a ppt
|
||||
*/
|
||||
public byte[] getData(){
|
||||
byte[] rawdata = getRawData();
|
||||
try {
|
||||
byte[] macheader = new byte[512];
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(macheader);
|
||||
int pos = CHECKSUM_SIZE;
|
||||
byte[] pict;
|
||||
try {
|
||||
pict = read(rawdata, pos);
|
||||
} catch (IOException e){
|
||||
//weird MAC behaviour.
|
||||
//if failed to read right after the checksum - skip 16 bytes and try again
|
||||
pict = read(rawdata, pos + 16);
|
||||
}
|
||||
out.write(pict);
|
||||
return out.toByteArray();
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] read(byte[] data, int pos) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
Header header = new Header();
|
||||
header.read(data, pos);
|
||||
bis.skip(pos + header.getSize());
|
||||
InflaterInputStream inflater = new InflaterInputStream( bis );
|
||||
byte[] chunk = new byte[4096];
|
||||
int count;
|
||||
while ((count = inflater.read(chunk)) >=0 ) {
|
||||
out.write(chunk,0,count);
|
||||
}
|
||||
inflater.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public void setData(byte[] data) throws IOException {
|
||||
int pos = 512; //skip the first 512 bytes - they are MAC specific crap
|
||||
byte[] compressed = compress(data, pos, data.length-pos);
|
||||
|
||||
Header header = new Header();
|
||||
header.wmfsize = data.length - 512;
|
||||
//we don't have a PICT reader in java, have to set default image size 200x200
|
||||
header.bounds = new java.awt.Rectangle(0, 0, 200, 200);
|
||||
header.size = new java.awt.Dimension(header.bounds.width*Shape.EMU_PER_POINT,
|
||||
header.bounds.height*Shape.EMU_PER_POINT);
|
||||
header.zipsize = compressed.length;
|
||||
|
||||
byte[] checksum = getChecksum(data);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(checksum);
|
||||
|
||||
out.write(new byte[16]); //16-byte prefix which is safe to ignore
|
||||
header.write(out);
|
||||
out.write(compressed);
|
||||
|
||||
setRawData(out.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hslf.model.Picture#PICT
|
||||
*/
|
||||
public int getType(){
|
||||
return Picture.PICT;
|
||||
}
|
||||
|
||||
/**
|
||||
* PICT signature is <code>0x5430</code>
|
||||
*
|
||||
* @return PICT signature (<code>0x5430</code>)
|
||||
*/
|
||||
public int getSignature(){
|
||||
return 0x5430;
|
||||
}
|
||||
|
||||
}
|
68
src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java
Normal file
68
src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java
Normal file
@ -0,0 +1,68 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Represents a PNG picture data in a PPT file
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class PNG extends Bitmap {
|
||||
|
||||
/**
|
||||
* @return PNG data
|
||||
*/
|
||||
public byte[] getData(){
|
||||
byte[] data = super.getData();
|
||||
try {
|
||||
//PNG created on MAC may have a 16-byte prefix which prevents successful reading.
|
||||
//Just cut it off!.
|
||||
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(data));
|
||||
if (bi == null){
|
||||
byte[] png = new byte[data.length-16];
|
||||
System.arraycopy(data, 16, png, 0, png.length);
|
||||
data = png;
|
||||
}
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type of this picture
|
||||
* @see org.apache.poi.hslf.model.Picture#PNG
|
||||
*/
|
||||
public int getType(){
|
||||
return Picture.PNG;
|
||||
}
|
||||
|
||||
/**
|
||||
* PNG signature is <code>0x6E00</code>
|
||||
*
|
||||
* @return PNG signature (<code>0x6E00</code>)
|
||||
*/
|
||||
public int getSignature(){
|
||||
return 0x6E00;
|
||||
}
|
||||
}
|
187
src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java
Normal file
187
src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java
Normal file
@ -0,0 +1,187 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.blip;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* Represents a WMF (Windows Metafile) picture data.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class WMF extends Metafile {
|
||||
|
||||
/**
|
||||
* Extract compressed WMF data from a ppt
|
||||
*/
|
||||
public byte[] getData(){
|
||||
try {
|
||||
byte[] rawdata = getRawData();
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
InputStream is = new ByteArrayInputStream( rawdata );
|
||||
Header header = new Header();
|
||||
header.read(rawdata, CHECKSUM_SIZE);
|
||||
is.skip(header.getSize() + CHECKSUM_SIZE);
|
||||
|
||||
AldusHeader aldus = new AldusHeader();
|
||||
aldus.left = header.bounds.x;
|
||||
aldus.top = header.bounds.y;
|
||||
aldus.right = header.bounds.x + header.bounds.width;
|
||||
aldus.bottom = header.bounds.y + header.bounds.height;
|
||||
aldus.write(out);
|
||||
|
||||
InflaterInputStream inflater = new InflaterInputStream( is );
|
||||
byte[] chunk = new byte[4096];
|
||||
int count;
|
||||
while ((count = inflater.read(chunk)) >=0 ) {
|
||||
out.write(chunk,0,count);
|
||||
}
|
||||
inflater.close();
|
||||
return out.toByteArray();
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setData(byte[] data) throws IOException {
|
||||
int pos = 0;
|
||||
AldusHeader aldus = new AldusHeader();
|
||||
aldus.read(data, pos);
|
||||
pos += aldus.getSize();
|
||||
|
||||
byte[] compressed = compress(data, pos, data.length-pos);
|
||||
|
||||
Header header = new Header();
|
||||
header.wmfsize = data.length - aldus.getSize();
|
||||
header.bounds = new java.awt.Rectangle((short)aldus.left, (short)aldus.top, (short)aldus.right-(short)aldus.left, (short)aldus.bottom-(short)aldus.top);
|
||||
//coefficiaent to translate from WMF dpi to 96pdi
|
||||
int coeff = 96*Shape.EMU_PER_POINT/aldus.inch;
|
||||
header.size = new java.awt.Dimension(header.bounds.width*coeff, header.bounds.height*coeff);
|
||||
header.zipsize = compressed.length;
|
||||
|
||||
byte[] checksum = getChecksum(data);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(checksum);
|
||||
header.write(out);
|
||||
out.write(compressed);
|
||||
|
||||
setRawData(out.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* We are of type <code>Picture.WMF</code>
|
||||
*/
|
||||
public int getType(){
|
||||
return Picture.WMF;
|
||||
}
|
||||
|
||||
/**
|
||||
* WMF signature is <code>0x2160</code>
|
||||
*/
|
||||
public int getSignature(){
|
||||
return 0x2160;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Aldus Placeable Metafile header - 22 byte structure before WMF data.
|
||||
* <ul>
|
||||
* <li>int Key; Magic number (always 9AC6CDD7h)
|
||||
* <li>short Handle; Metafile HANDLE number (always 0)
|
||||
* <li>short Left; Left coordinate in metafile units
|
||||
* <li>short Top; Top coordinate in metafile units
|
||||
* <li>short Right; Right coordinate in metafile units
|
||||
* <li>short Bottom; Bottom coordinate in metafile units
|
||||
* <li>short Inch; Number of metafile units per inch
|
||||
* <li>int Reserved; Reserved (always 0)
|
||||
* <li>short Checksum; Checksum value for previous 10 shorts
|
||||
* </ul>
|
||||
*/
|
||||
public static class AldusHeader{
|
||||
public static final int APMHEADER_KEY = 0x9AC6CDD7;
|
||||
|
||||
public int handle;
|
||||
public int left, top, right, bottom;
|
||||
public int inch = 72; //default resolution is 72 dpi
|
||||
public int reserved;
|
||||
public int checksum;
|
||||
|
||||
public void read(byte[] data, int offset){
|
||||
int pos = offset;
|
||||
int key = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; //header key
|
||||
if (key != APMHEADER_KEY) throw new RuntimeException("Not a valid WMF file");
|
||||
|
||||
handle = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
left = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
top = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
right = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
bottom = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
|
||||
inch = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
reserved = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
|
||||
|
||||
checksum = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||
if (checksum != getChecksum())
|
||||
throw new RuntimeException("WMF checksum does not match the header data");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a checksum value for the previous 10 shorts in the header.
|
||||
* The checksum is calculated by XORing each short value to an initial value of 0:
|
||||
*/
|
||||
public int getChecksum(){
|
||||
int checksum = 0;
|
||||
checksum ^= (APMHEADER_KEY & 0x0000FFFF);
|
||||
checksum ^= ((APMHEADER_KEY & 0xFFFF0000) >> 16);
|
||||
checksum ^= left;
|
||||
checksum ^= top;
|
||||
checksum ^= right;
|
||||
checksum ^= bottom;
|
||||
checksum ^= inch;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException {
|
||||
byte[] header = new byte[22];
|
||||
int pos = 0;
|
||||
LittleEndian.putInt(header, pos, APMHEADER_KEY); pos += LittleEndian.INT_SIZE; //header key
|
||||
LittleEndian.putUShort(header, pos, 0); pos += LittleEndian.SHORT_SIZE; //hmf
|
||||
LittleEndian.putUShort(header, pos, left); pos += LittleEndian.SHORT_SIZE; //left
|
||||
LittleEndian.putUShort(header, pos, top); pos += LittleEndian.SHORT_SIZE; //top
|
||||
LittleEndian.putUShort(header, pos, right); pos += LittleEndian.SHORT_SIZE; //right
|
||||
LittleEndian.putUShort(header, pos, bottom); pos += LittleEndian.SHORT_SIZE; //bottom
|
||||
LittleEndian.putUShort(header, pos, inch); pos += LittleEndian.SHORT_SIZE; //inch
|
||||
LittleEndian.putInt(header, pos, 0); pos += LittleEndian.INT_SIZE; //reserved
|
||||
|
||||
checksum = getChecksum();
|
||||
LittleEndian.putUShort(header, pos, checksum);
|
||||
|
||||
out.write(header);
|
||||
}
|
||||
|
||||
public int getSize(){
|
||||
return 22;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
package org.apache.poi.hslf.extractor;
|
||||
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* Utility to extract pictures from a PowerPoint file.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ImageExtractor {
|
||||
public static void main(String args[]) throws IOException {
|
||||
if (args.length < 1) {
|
||||
System.err.println("Usage:");
|
||||
System.err.println("\tImageExtractor <file>");
|
||||
return;
|
||||
}
|
||||
SlideShow ppt = new SlideShow(new HSLFSlideShow(args[0]));
|
||||
|
||||
//extract all pictures contained in the presentation
|
||||
PictureData[] pdata = ppt.getPictureData();
|
||||
for (int i = 0; i < pdata.length; i++) {
|
||||
PictureData pict = pdata[i];
|
||||
|
||||
// picture data
|
||||
byte[] data = pict.getData();
|
||||
|
||||
int type = pict.getType();
|
||||
String ext;
|
||||
switch (type) {
|
||||
case Picture.JPEG:
|
||||
ext = ".jpg";
|
||||
break;
|
||||
case Picture.PNG:
|
||||
ext = ".png";
|
||||
break;
|
||||
case Picture.WMF:
|
||||
ext = ".wmf";
|
||||
break;
|
||||
case Picture.EMF:
|
||||
ext = ".emf";
|
||||
break;
|
||||
case Picture.PICT:
|
||||
ext = ".pict";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
FileOutputStream out = new FileOutputStream("pict_" + i + ext);
|
||||
out.write(data);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,9 +4,11 @@ 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;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@ -22,33 +24,23 @@ import java.util.Arrays;
|
||||
* type, image index to refer by slides etc.
|
||||
* <li> "Pictures" OLE stream holds the actual data of the image.
|
||||
* </p>
|
||||
* <p>
|
||||
* Data in the "Pictures" OLE stream is organized as follows:<br>
|
||||
* For each image there is an entry: 25 byte header + image data.
|
||||
* Image data is the exact content of the JPEG file, i.e. PowerPoint
|
||||
* puts the whole jpeg file there without any modifications.<br>
|
||||
* Header format:
|
||||
* <li> 2 byte: image type. For JPEGs it is 0x46A0, for PNG it is 0x6E00.
|
||||
* <li> 2 byte: unknown.
|
||||
* <li> 4 byte : image size + 17. Looks like shift from the end of
|
||||
* header but why to add it to the image size?
|
||||
* <li> next 16 bytes. Unique identifier of this image which is used by
|
||||
* EscherBSE record.
|
||||
* </p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class Picture extends SimpleShape {
|
||||
|
||||
/**
|
||||
* Windows Metafile
|
||||
* ( NOT YET SUPPORTED )
|
||||
* Windows Enhanced Metafile (EMF)
|
||||
*/
|
||||
public static final int EMF = 2;
|
||||
|
||||
/**
|
||||
* Windows Metafile (WMF)
|
||||
*/
|
||||
public static final int WMF = 3;
|
||||
|
||||
/**
|
||||
* Macintosh PICT
|
||||
* ( NOT YET SUPPORTED )
|
||||
*/
|
||||
public static final int PICT = 4;
|
||||
|
||||
@ -63,10 +55,10 @@ public class Picture extends SimpleShape {
|
||||
public static final int PNG = 6;
|
||||
|
||||
/**
|
||||
* Windows DIB (BMP)
|
||||
*/
|
||||
public static final int DIB = 7;
|
||||
|
||||
* Windows DIB (BMP)
|
||||
*/
|
||||
public static final byte DIB = 7;
|
||||
|
||||
/**
|
||||
* Create a new <code>Picture</code>
|
||||
*
|
||||
@ -129,11 +121,17 @@ public class Picture extends SimpleShape {
|
||||
*/
|
||||
public void setDefaultSize(){
|
||||
PictureData pict = getPictureData();
|
||||
try {
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
|
||||
setAnchor(new java.awt.Rectangle(0, 0, img.getWidth(), img.getHeight()));
|
||||
} catch (IOException e){
|
||||
throw new RuntimeException(e);
|
||||
if (pict instanceof Bitmap){
|
||||
try {
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
|
||||
if(img != null) setAnchor(new java.awt.Rectangle(0, 0, img.getWidth(), img.getHeight()));
|
||||
else setAnchor(new java.awt.Rectangle(0, 0, 200, 200));
|
||||
} catch (IOException e){
|
||||
;
|
||||
}
|
||||
} else {
|
||||
//default size of a metafile picture is 200x200
|
||||
setAnchor(new java.awt.Rectangle(50, 50, 200, 200));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ package org.apache.poi.hslf.usermodel;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.blip.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
@ -24,172 +25,95 @@ import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* A class that represents the image data contained in the Presentation.
|
||||
*
|
||||
* A class that represents image data contained in a slide show.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class PictureData {
|
||||
public abstract class PictureData {
|
||||
|
||||
/**
|
||||
* The size of the header
|
||||
*/
|
||||
public static final int HEADER_SIZE = 25;
|
||||
|
||||
protected static final int JPEG_HEADER = -266516832;
|
||||
protected static final int PNG_HEADER = -266441216;
|
||||
/**
|
||||
* Size of the image checksum calculated using MD5 algorithm.
|
||||
*/
|
||||
protected static final int CHECKSUM_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Binary data of the picture
|
||||
*/
|
||||
protected byte[] pictdata;
|
||||
|
||||
/**
|
||||
* Header which holds information about this picture
|
||||
*/
|
||||
protected byte[] header;
|
||||
|
||||
private byte[] rawdata;
|
||||
/**
|
||||
* The offset to the picture in the stream
|
||||
*/
|
||||
protected int offset;
|
||||
|
||||
public PictureData(){
|
||||
header = new byte[PictureData.HEADER_SIZE];
|
||||
}
|
||||
/**
|
||||
* Returns type of this picture.
|
||||
* Must be one of the static constants defined in the <code>Picture<code> class.
|
||||
*
|
||||
* @return type of this picture.
|
||||
*/
|
||||
public abstract int getType();
|
||||
|
||||
/**
|
||||
* Read a picture from "Pictures" OLE stream
|
||||
*
|
||||
* @param pictstream the bytes to read
|
||||
* @param offset the index of the first byte to read
|
||||
*/
|
||||
public PictureData(byte[] pictstream, int offset){
|
||||
header = new byte[PictureData.HEADER_SIZE];
|
||||
System.arraycopy(pictstream, offset, header, 0, header.length);
|
||||
|
||||
// Get the size of the picture, and make sure it's sane
|
||||
// Size is stored unsigned, since it must always be positive
|
||||
int size = (int)LittleEndian.getUInt(header, 4) - 17;
|
||||
int startPos = offset + PictureData.HEADER_SIZE;
|
||||
if(size < 0) { size = 0; }
|
||||
if(size > (pictstream.length - startPos)) {
|
||||
int remaining = pictstream.length - startPos;
|
||||
System.err.println("Warning: PictureData claimed picture was of length " + size + ", but only " + remaining + " remained!");
|
||||
size = remaining;
|
||||
}
|
||||
|
||||
// Save the picture data
|
||||
pictdata = new byte[size];
|
||||
this.offset = offset;
|
||||
System.arraycopy(pictstream, startPos, pictdata, 0, pictdata.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the binary data of this picture
|
||||
*/
|
||||
public byte[] getData(){
|
||||
return pictdata;
|
||||
}
|
||||
/**
|
||||
* Returns the binary data of this Picture
|
||||
* @return picture data
|
||||
*/
|
||||
public abstract byte[] getData();
|
||||
|
||||
/**
|
||||
* Set picture data
|
||||
*/
|
||||
public void setData(byte[] data) {
|
||||
pictdata = data;
|
||||
LittleEndian.putInt(header, 4, data.length + 17);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image size in bytes
|
||||
*
|
||||
* @return the size of the picture in bytes
|
||||
*/
|
||||
public int getSize(){
|
||||
return pictdata.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier (UID) of this picture.
|
||||
* The UID is a checksum of the picture data. Its length is 16 bytes
|
||||
* and it must be unique across the presentation.
|
||||
*
|
||||
* @return the unique identifier of this picture
|
||||
*/
|
||||
public byte[] getUID(){
|
||||
byte[] uid = new byte[16];
|
||||
System.arraycopy(header, 8, uid, 0, uid.length);
|
||||
return uid;
|
||||
}
|
||||
public abstract void setData(byte[] data) throws IOException;
|
||||
|
||||
/**
|
||||
* Set the unique identifier (UID) of this picture.
|
||||
*
|
||||
* @param uid checksum of the picture data
|
||||
* Blip signature.
|
||||
*/
|
||||
public void setUID(byte[] uid){
|
||||
System.arraycopy(uid, 0, header, 8, uid.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of this picture.
|
||||
*
|
||||
* @return type of this picture.
|
||||
* Must be one of the static constans defined in the <code>Picture<code> class.
|
||||
*/
|
||||
public void setType(int format){
|
||||
switch (format){
|
||||
case Picture.JPEG: LittleEndian.putInt(header, 0, PictureData.JPEG_HEADER); break;
|
||||
case Picture.PNG: LittleEndian.putInt(header, 0, PictureData.PNG_HEADER); break;
|
||||
}
|
||||
}
|
||||
protected abstract int getSignature();
|
||||
|
||||
/**
|
||||
* Returns type of this picture.
|
||||
* Must be one of the static constans defined in the <code>Picture<code> class.
|
||||
* Returns the raw binary data of this Picture excluding the first 8 bytes
|
||||
* which hold image signature and size of the image data.
|
||||
*
|
||||
* @return type of this picture.
|
||||
* @return picture data
|
||||
*/
|
||||
public int getType(){
|
||||
int format = 0;
|
||||
int val = LittleEndian.getInt(header, 0);
|
||||
switch (val){
|
||||
case PictureData.JPEG_HEADER: format = Picture.JPEG; break;
|
||||
case PictureData.PNG_HEADER: format = Picture.PNG; break;
|
||||
}
|
||||
return format;
|
||||
public byte[] getRawData(){
|
||||
return rawdata;
|
||||
}
|
||||
|
||||
public void setRawData(byte[] data){
|
||||
rawdata = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header of the Picture
|
||||
* File offset in the 'Pictures' stream
|
||||
*
|
||||
* @return the header of the Picture
|
||||
* @return offset in the 'Pictures' stream
|
||||
*/
|
||||
public byte[] getHeader(){
|
||||
return header;
|
||||
public int getOffset(){
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* File offset in the 'Pictures' stream
|
||||
*
|
||||
* @return offset in the 'Pictures' stream
|
||||
*/
|
||||
public int getOffset(){
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set offset of this picture in the 'Pictures' stream.
|
||||
* We need to set it when a new picture is created.
|
||||
*
|
||||
* @param offset in the 'Pictures' stream
|
||||
*/
|
||||
public void setOffset(int offset){
|
||||
this.offset = offset;
|
||||
}
|
||||
/**
|
||||
* Set offset of this picture in the 'Pictures' stream.
|
||||
* We need to set it when a new picture is created.
|
||||
*
|
||||
* @param offset in the 'Pictures' stream
|
||||
*/
|
||||
public void setOffset(int offset){
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute 16-byte checksum of this picture
|
||||
* Returns 16-byte checksum of this picture
|
||||
*/
|
||||
public byte[] getUID(){
|
||||
byte[] uid = new byte[16];
|
||||
System.arraycopy(rawdata, 0, uid, 0, uid.length);
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute 16-byte checksum of this picture using MD5 algorithm.
|
||||
*/
|
||||
public static byte[] getChecksum(byte[] data) {
|
||||
MessageDigest sha;
|
||||
@ -206,8 +130,81 @@ public class PictureData {
|
||||
* Write this picture into <code>OutputStream</code>
|
||||
*/
|
||||
public void write(OutputStream out) throws IOException {
|
||||
out.write(header);
|
||||
out.write(pictdata);
|
||||
byte[] data;
|
||||
|
||||
data = new byte[LittleEndian.SHORT_SIZE];
|
||||
LittleEndian.putUShort(data, 0, getSignature());
|
||||
out.write(data);
|
||||
|
||||
data = new byte[LittleEndian.SHORT_SIZE];
|
||||
LittleEndian.putUShort(data, 0, getType() + 0xF018);
|
||||
out.write(data);
|
||||
|
||||
byte[] rawdata = getRawData();
|
||||
|
||||
data = new byte[LittleEndian.INT_SIZE];
|
||||
LittleEndian.putInt(data, 0, rawdata.length);
|
||||
out.write(data);
|
||||
|
||||
out.write(rawdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of <code>PictureData</code> by type.
|
||||
*
|
||||
* @param type type of the picture data.
|
||||
* Must be one of the static constants defined in the <code>Picture<code> class.
|
||||
* @return concrete instance of <code>PictureData</code>
|
||||
*/
|
||||
public static PictureData create(int type){
|
||||
PictureData pict;
|
||||
switch (type){
|
||||
case Picture.EMF:
|
||||
pict = new EMF();
|
||||
break;
|
||||
case Picture.WMF:
|
||||
pict = new WMF();
|
||||
break;
|
||||
case Picture.PICT:
|
||||
pict = new PICT();
|
||||
break;
|
||||
case Picture.JPEG:
|
||||
pict = new JPEG();
|
||||
break;
|
||||
case Picture.PNG:
|
||||
pict = new PNG();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unsupported picture type: " + type);
|
||||
}
|
||||
return pict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 24 byte header which preceeds the actual picture data.
|
||||
* <p>
|
||||
* The header consists of 2-byte signature, 2-byte type,
|
||||
* 4-byte image size and 16-byte checksum of the image data.
|
||||
* </p>
|
||||
*
|
||||
* @return the 24 byte header which preceeds the actual picture data.
|
||||
*/
|
||||
public byte[] getHeader() {
|
||||
byte[] header = new byte[16 + 8];
|
||||
LittleEndian.putInt(header, 0, getSignature());
|
||||
LittleEndian.putInt(header, 4, getRawData().length);
|
||||
System.arraycopy(rawdata, 0, header, 8, 16);
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image size in bytes
|
||||
*
|
||||
* @return the size of the picture in bytes
|
||||
* @deprecated Use <code>getData().length</code> instead.
|
||||
*/
|
||||
public int getSize(){
|
||||
return getData().length;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -620,7 +620,7 @@ public class SlideShow
|
||||
* @param format the format of the picture. One of constans defined in the <code>Picture</code> class.
|
||||
* @return the index to this picture (1 based).
|
||||
*/
|
||||
public int addPicture(byte[] data, int format) {
|
||||
public int addPicture(byte[] data, int format) throws IOException {
|
||||
byte[] uid = PictureData.getChecksum(data);
|
||||
|
||||
EscherContainerRecord bstore;
|
||||
@ -652,14 +652,23 @@ public class SlideShow
|
||||
}
|
||||
}
|
||||
|
||||
PictureData pict = PictureData.create(format);
|
||||
pict.setData(data);
|
||||
pict.setOffset(offset);
|
||||
|
||||
EscherBSERecord bse = new EscherBSERecord();
|
||||
bse.setRecordId(EscherBSERecord.RECORD_ID);
|
||||
bse.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
|
||||
bse.setSize(data.length + PictureData.HEADER_SIZE);
|
||||
bse.setSize(pict.getRawData().length + 8);
|
||||
bse.setUid(uid);
|
||||
|
||||
bse.setBlipTypeMacOS((byte)format);
|
||||
bse.setBlipTypeWin32((byte)format);
|
||||
|
||||
if (format == Picture.EMF) bse.setBlipTypeMacOS((byte)Picture.PICT);
|
||||
else if (format == Picture.WMF) bse.setBlipTypeMacOS((byte)Picture.PICT);
|
||||
else if (format == Picture.PICT) bse.setBlipTypeWin32((byte)Picture.WMF);
|
||||
|
||||
bse.setRef(1);
|
||||
bse.setOffset(offset);
|
||||
|
||||
@ -667,12 +676,6 @@ public class SlideShow
|
||||
int count = bstore.getChildRecords().size();
|
||||
bstore.setOptions((short)( (count << 4) | 0xF ));
|
||||
|
||||
PictureData pict = new PictureData();
|
||||
pict.setUID(uid);
|
||||
pict.setData(data);
|
||||
pict.setType(format);
|
||||
pict.setOffset(offset);
|
||||
|
||||
_hslfSlideShow.addPicture(pict);
|
||||
|
||||
return count;
|
||||
@ -685,7 +688,7 @@ public class SlideShow
|
||||
* @param format the format of the picture. One of constans defined in the <code>Picture</code> class.
|
||||
* @return the index to this picture (1 based).
|
||||
*/
|
||||
public int addPicture(File pict, int format) {
|
||||
public int addPicture(File pict, int format) throws IOException {
|
||||
int length = (int)pict.length();
|
||||
byte[] data = new byte[length];
|
||||
try {
|
||||
|
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/cow.pict
Normal file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/cow.pict
Normal file
Binary file not shown.
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/pictures.ppt
Normal file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/pictures.ppt
Normal file
Binary file not shown.
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/santa.wmf
Normal file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/santa.wmf
Normal file
Binary file not shown.
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/tomcat.png
Normal file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/tomcat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/wrench.emf
Normal file
BIN
src/scratchpad/testcases/org/apache/poi/hslf/data/wrench.emf
Normal file
Binary file not shown.
@ -17,106 +17,316 @@
|
||||
package org.apache.poi.hslf.usermodel;
|
||||
|
||||
import org.apache.poi.hslf.*;
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hslf.model.Slide;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hslf.blip.*;
|
||||
import org.apache.poi.hslf.model.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Test extracting images from a ppt file
|
||||
* Test adding/reading pictures
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestPictures extends TestCase{
|
||||
public static String dirname = System.getProperty("HSLF.testdata.path");
|
||||
public static String filename = dirname + "/ppt_with_png.ppt";
|
||||
|
||||
public void testReadPictures() throws Exception {
|
||||
protected File cwd;
|
||||
|
||||
HSLFSlideShow ppt = new HSLFSlideShow(filename);
|
||||
PictureData[] pict = ppt.getPictures();
|
||||
assertNotNull(pict);
|
||||
for (int i = 0; i < pict.length; i++) {
|
||||
byte[] data = pict[i].getData();
|
||||
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
|
||||
assertNotNull(img);
|
||||
assertEquals(Picture.PNG, pict[i].getType());
|
||||
}
|
||||
ppt.close();
|
||||
public void setUp() throws Exception {
|
||||
cwd = new File(System.getProperty("HSLF.testdata.path"));
|
||||
}
|
||||
|
||||
public void testReadPicturesForSlide() throws Exception {
|
||||
|
||||
SlideShow ppt = new SlideShow(new HSLFSlideShow(filename));
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for (int i = 0; i < slide.length; i++) {
|
||||
Slide sl = slide[i];
|
||||
Shape[] sh = sl.getShapes();
|
||||
for (int j = 0; j < sh.length; j++) {
|
||||
Shape shape = sh[j];
|
||||
if (shape instanceof Picture){
|
||||
Picture picture = (Picture)shape;
|
||||
|
||||
PictureData pictdata = picture.getPictureData();
|
||||
assertEquals(Picture.PNG, pictdata.getType());
|
||||
|
||||
//raw data.
|
||||
byte[] data = pictdata.getData();
|
||||
BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
|
||||
assertNotNull(img);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerializePictures() throws Exception {
|
||||
HSLFSlideShow ppt = new HSLFSlideShow(filename);
|
||||
PictureData[] pict = ppt.getPictures();
|
||||
assertNotNull(pict);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
|
||||
pict = ppt.getPictures();
|
||||
assertNotNull(pict);
|
||||
}
|
||||
|
||||
public void testAddPictures() throws Exception {
|
||||
int idx;
|
||||
Slide slide;
|
||||
Picture pict;
|
||||
|
||||
/**
|
||||
* Test read/write Macintosh PICT
|
||||
*/
|
||||
public void testPICT() throws Exception {
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
idx = ppt.addPicture(new File(dirname + "/clock.jpg"), Picture.JPEG);
|
||||
slide = ppt.createSlide();
|
||||
pict = new Picture(idx);
|
||||
slide.addShape(pict);
|
||||
|
||||
idx = ppt.addPicture(new File(dirname + "/painting.png"), Picture.PNG);
|
||||
pict = new Picture(idx);
|
||||
Slide slide = ppt.createSlide();
|
||||
File img = new File(cwd, "cow.pict");
|
||||
int idx = ppt.addPicture(img, Picture.PICT);
|
||||
Picture pict = new Picture(idx);
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
slide.addShape(pict);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
assertTrue(ppt.getPictureData().length == 2 );
|
||||
|
||||
//make sure we can read this picture shape and it refers to the correct picture data
|
||||
Shape[] sh = ppt.getSlides()[0].getShapes();
|
||||
assertEquals(1, sh.length);
|
||||
pict = (Picture)sh[0];
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
|
||||
//check picture data
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
//the Picture shape refers to the PictureData object in the Presentation
|
||||
assertEquals(pict.getPictureData(), pictures[0]);
|
||||
|
||||
assertEquals(1, pictures.length);
|
||||
assertEquals(Picture.PICT, pictures[0].getType());
|
||||
assertTrue(pictures[0] instanceof PICT);
|
||||
//compare the content of the initial file with what is stored in the PictureData
|
||||
byte[] src_bytes = read(img);
|
||||
byte[] ppt_bytes = pictures[0].getData();
|
||||
assertEquals(src_bytes.length, ppt_bytes.length);
|
||||
//in PICT the first 512 bytes are MAC specific and may not be preserved, ignore them
|
||||
byte[] b1 = new byte[src_bytes.length-512];
|
||||
System.arraycopy(src_bytes, 512, b1, 0, b1.length);
|
||||
byte[] b2 = new byte[ppt_bytes.length-512];
|
||||
System.arraycopy(ppt_bytes, 512, b2, 0, b2.length);
|
||||
assertTrue(Arrays.equals(b1, b2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read/write WMF
|
||||
*/
|
||||
public void testWMF() throws Exception {
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
File img = new File(cwd, "santa.wmf");
|
||||
int idx = ppt.addPicture(img, Picture.WMF);
|
||||
Picture pict = new Picture(idx);
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
slide.addShape(pict);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
|
||||
//make sure we can read this picture shape and it refers to the correct picture data
|
||||
Shape[] sh = ppt.getSlides()[0].getShapes();
|
||||
assertEquals(1, sh.length);
|
||||
pict = (Picture)sh[0];
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
|
||||
//check picture data
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
//the Picture shape refers to the PictureData object in the Presentation
|
||||
assertEquals(pict.getPictureData(), pictures[0]);
|
||||
|
||||
assertEquals(1, pictures.length);
|
||||
assertEquals(Picture.WMF, pictures[0].getType());
|
||||
assertTrue(pictures[0] instanceof WMF);
|
||||
//compare the content of the initial file with what is stored in the PictureData
|
||||
byte[] src_bytes = read(img);
|
||||
byte[] ppt_bytes = pictures[0].getData();
|
||||
assertEquals(src_bytes.length, ppt_bytes.length);
|
||||
//in WMF the first 22 bytes - is a metafile header
|
||||
byte[] b1 = new byte[src_bytes.length-22];
|
||||
System.arraycopy(src_bytes, 22, b1, 0, b1.length);
|
||||
byte[] b2 = new byte[ppt_bytes.length-22];
|
||||
System.arraycopy(ppt_bytes, 22, b2, 0, b2.length);
|
||||
assertTrue(Arrays.equals(b1, b2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read/write EMF
|
||||
*/
|
||||
public void testEMF() throws Exception {
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
File img = new File(cwd, "wrench.emf");
|
||||
int idx = ppt.addPicture(img, Picture.EMF);
|
||||
Picture pict = new Picture(idx);
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
slide.addShape(pict);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
|
||||
//make sure we can get this picture shape and it refers to the correct picture data
|
||||
Shape[] sh = ppt.getSlides()[0].getShapes();
|
||||
assertEquals(1, sh.length);
|
||||
pict = (Picture)sh[0];
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
|
||||
//check picture data
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
//the Picture shape refers to the PictureData object in the Presentation
|
||||
assertEquals(pict.getPictureData(), pictures[0]);
|
||||
|
||||
assertEquals(1, pictures.length);
|
||||
assertEquals(Picture.EMF, pictures[0].getType());
|
||||
assertTrue(pictures[0] instanceof EMF);
|
||||
//compare the content of the initial file with what is stored in the PictureData
|
||||
byte[] src_bytes = read(img);
|
||||
byte[] ppt_bytes = pictures[0].getData();
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read/write PNG
|
||||
*/
|
||||
public void testPNG() throws Exception {
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
File img = new File(cwd, "tomcat.png");
|
||||
int idx = ppt.addPicture(img, Picture.PNG);
|
||||
Picture pict = new Picture(idx);
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
slide.addShape(pict);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
|
||||
//make sure we can read this picture shape and it refers to the correct picture data
|
||||
Shape[] sh = ppt.getSlides()[0].getShapes();
|
||||
assertEquals(1, sh.length);
|
||||
pict = (Picture)sh[0];
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
|
||||
//check picture data
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
//the Picture shape refers to the PictureData object in the Presentation
|
||||
assertEquals(pict.getPictureData(), pictures[0]);
|
||||
|
||||
assertEquals(1, pictures.length);
|
||||
assertEquals(Picture.PNG, pictures[0].getType());
|
||||
assertTrue(pictures[0] instanceof PNG);
|
||||
//compare the content of the initial file with what is stored in the PictureData
|
||||
byte[] src_bytes = read(img);
|
||||
byte[] ppt_bytes = pictures[0].getData();
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test read/write JPEG
|
||||
*/
|
||||
public void testJPEG() throws Exception {
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
||||
Slide slide = ppt.createSlide();
|
||||
File img = new File(cwd, "clock.jpg");
|
||||
int idx = ppt.addPicture(img, Picture.JPEG);
|
||||
Picture pict = new Picture(idx);
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
slide.addShape(pict);
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ppt.write(out);
|
||||
out.close();
|
||||
|
||||
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
|
||||
|
||||
//make sure we can read this picture shape and it refers to the correct picture data
|
||||
Shape[] sh = ppt.getSlides()[0].getShapes();
|
||||
assertEquals(1, sh.length);
|
||||
pict = (Picture)sh[0];
|
||||
assertEquals(idx, pict.getPictureIndex());
|
||||
|
||||
//check picture data
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
//the Picture shape refers to the PictureData object in the Presentation
|
||||
assertEquals(pict.getPictureData(), pictures[0]);
|
||||
|
||||
assertEquals(1, pictures.length);
|
||||
assertEquals(Picture.JPEG, pictures[0].getType());
|
||||
assertTrue(pictures[0] instanceof JPEG);
|
||||
//compare the content of the initial file with what is stored in the PictureData
|
||||
byte[] src_bytes = read(img);
|
||||
byte[] ppt_bytes = pictures[0].getData();
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read file into a byte array
|
||||
*/
|
||||
protected byte[] read(File f) throws IOException {
|
||||
byte[] bytes = new byte[(int)f.length()];
|
||||
FileInputStream is = new FileInputStream(f);
|
||||
is.read(bytes);
|
||||
is.close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read pictures in different formats from a reference slide show
|
||||
*/
|
||||
public void testReadPictures() throws Exception {
|
||||
|
||||
byte[] src_bytes, ppt_bytes, b1, b2;
|
||||
Picture pict;
|
||||
PictureData pdata;
|
||||
|
||||
SlideShow ppt = new SlideShow(new HSLFSlideShow(new File(cwd, "pictures.ppt").getPath()));
|
||||
Slide[] slides = ppt.getSlides();
|
||||
PictureData[] pictures = ppt.getPictureData();
|
||||
assertEquals(5, pictures.length);
|
||||
|
||||
pict = (Picture)slides[0].getShapes()[0]; //the first slide contains JPEG
|
||||
pdata = pict.getPictureData();
|
||||
assertTrue(pdata instanceof JPEG);
|
||||
assertEquals(Picture.JPEG, pdata.getType());
|
||||
src_bytes = pdata.getData();
|
||||
ppt_bytes = read(new File(cwd, "clock.jpg"));
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
|
||||
pict = (Picture)slides[1].getShapes()[0]; //the second slide contains PNG
|
||||
pdata = pict.getPictureData();
|
||||
assertTrue(pdata instanceof PNG);
|
||||
assertEquals(Picture.PNG, pdata.getType());
|
||||
src_bytes = pdata.getData();
|
||||
ppt_bytes = read(new File(cwd, "tomcat.png"));
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
|
||||
pict = (Picture)slides[2].getShapes()[0]; //the third slide contains WMF
|
||||
pdata = pict.getPictureData();
|
||||
assertTrue(pdata instanceof WMF);
|
||||
assertEquals(Picture.WMF, pdata.getType());
|
||||
src_bytes = pdata.getData();
|
||||
ppt_bytes = read(new File(cwd, "santa.wmf"));
|
||||
assertEquals(src_bytes.length, ppt_bytes.length);
|
||||
//ignore the first 22 bytes - it is a WMF metafile header
|
||||
b1 = new byte[src_bytes.length-22];
|
||||
System.arraycopy(src_bytes, 22, b1, 0, b1.length);
|
||||
b2 = new byte[ppt_bytes.length-22];
|
||||
System.arraycopy(ppt_bytes, 22, b2, 0, b2.length);
|
||||
assertTrue(Arrays.equals(b1, b2));
|
||||
|
||||
pict = (Picture)slides[3].getShapes()[0]; //the forth slide contains PICT
|
||||
pdata = pict.getPictureData();
|
||||
assertTrue(pdata instanceof PICT);
|
||||
assertEquals(Picture.PICT, pdata.getType());
|
||||
src_bytes = pdata.getData();
|
||||
ppt_bytes = read(new File(cwd, "cow.pict"));
|
||||
assertEquals(src_bytes.length, ppt_bytes.length);
|
||||
//ignore the first 512 bytes - it is a MAC specific crap
|
||||
b1 = new byte[src_bytes.length-512];
|
||||
System.arraycopy(src_bytes, 512, b1, 0, b1.length);
|
||||
b2 = new byte[ppt_bytes.length-512];
|
||||
System.arraycopy(ppt_bytes, 512, b2, 0, b2.length);
|
||||
assertTrue(Arrays.equals(b1, b2));
|
||||
|
||||
pict = (Picture)slides[4].getShapes()[0]; //the fifth slide contains EMF
|
||||
pdata = pict.getPictureData();
|
||||
assertTrue(pdata instanceof EMF);
|
||||
assertEquals(Picture.EMF, pdata.getType());
|
||||
src_bytes = pdata.getData();
|
||||
ppt_bytes = read(new File(cwd, "wrench.emf"));
|
||||
assertTrue(Arrays.equals(src_bytes, ppt_bytes));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user