#60427 - Creating pictures in PowerPoint slides requires scratchpad-jar for adding WMF images
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1771812 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
19842d1e58
commit
891e684eb7
57
src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java
Normal file
57
src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.sl.image;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public class ImageHeaderBitmap {
|
||||||
|
private static final POILogger LOG = POILogFactory.getLogger(ImageHeaderBitmap.class);
|
||||||
|
|
||||||
|
private final Dimension size;
|
||||||
|
|
||||||
|
public ImageHeaderBitmap(byte data[], int offset) {
|
||||||
|
BufferedImage img = null;
|
||||||
|
try {
|
||||||
|
img = ImageIO.read(new ByteArrayInputStream(data, offset, data.length-offset));
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.log(POILogger.WARN, "Can't determine image dimensions", e);
|
||||||
|
}
|
||||||
|
// set dummy size, in case of dummy dimension can't be set
|
||||||
|
size = (img == null)
|
||||||
|
? new Dimension(200,200)
|
||||||
|
: new Dimension(
|
||||||
|
(int)Units.pixelToPoints(img.getWidth()),
|
||||||
|
(int)Units.pixelToPoints(img.getHeight())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
68
src/java/org/apache/poi/sl/image/ImageHeaderEMF.java
Normal file
68
src/java/org/apache/poi/sl/image/ImageHeaderEMF.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.sl.image;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.apache.poi.util.LocaleUtil;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public class ImageHeaderEMF {
|
||||||
|
private static POILogger LOG = POILogFactory.getLogger(ImageHeaderEMF.class);
|
||||||
|
|
||||||
|
private final static String EMF_SIGNATURE = " EMF"; // 0x464D4520 (LE)
|
||||||
|
|
||||||
|
// rectangular inclusive-inclusive bounds, in device units, of the smallest
|
||||||
|
// rectangle that can be drawn around the image stored in the metafile.
|
||||||
|
private final Rectangle deviceBounds;
|
||||||
|
|
||||||
|
public ImageHeaderEMF(byte data[], int offset) {
|
||||||
|
int type = (int)LittleEndian.getUInt(data, offset); offset += 4;
|
||||||
|
if (type != 1) {
|
||||||
|
LOG.log(POILogger.WARN, "Invalid EMF picture - invalid type");
|
||||||
|
deviceBounds = new Rectangle(0,0,200,200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ignore header size
|
||||||
|
offset += 4;
|
||||||
|
int left = LittleEndian.getInt(data, offset); offset += 4;
|
||||||
|
int top = LittleEndian.getInt(data, offset); offset += 4;
|
||||||
|
int right = LittleEndian.getInt(data, offset); offset += 4;
|
||||||
|
int bottom = LittleEndian.getInt(data, offset); offset += 4;
|
||||||
|
deviceBounds = new Rectangle(left, top, right-left, bottom-top);
|
||||||
|
// ignore frame bounds
|
||||||
|
offset += 16;
|
||||||
|
String signature = new String(data, offset, EMF_SIGNATURE.length(), LocaleUtil.CHARSET_1252);
|
||||||
|
if (!EMF_SIGNATURE.equals(signature)) {
|
||||||
|
LOG.log(POILogger.WARN, "Invalid EMF picture - invalid signature");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getSize() {
|
||||||
|
return deviceBounds.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getBounds() {
|
||||||
|
return deviceBounds;
|
||||||
|
}
|
||||||
|
}
|
103
src/java/org/apache/poi/sl/image/ImageHeaderPICT.java
Normal file
103
src/java/org/apache/poi/sl/image/ImageHeaderPICT.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.sl.image;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public class ImageHeaderPICT {
|
||||||
|
/**
|
||||||
|
* skip the first 512 bytes - they are MAC specific crap
|
||||||
|
*/
|
||||||
|
public static final int PICT_HEADER_OFFSET = 512;
|
||||||
|
|
||||||
|
public static final double DEFAULT_RESOLUTION = Units.POINT_DPI;
|
||||||
|
|
||||||
|
private static final byte V2_HEADER[] = {
|
||||||
|
0x00, 0x11, // v2 version opcode
|
||||||
|
0x02, (byte)0xFF, // version number of new picture
|
||||||
|
0x0C, 0x00, // header opcode
|
||||||
|
(byte)0xFF, (byte)0xFE, 0x00, 0x00 // pic size dummy
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Rectangle bounds;
|
||||||
|
private final double hRes, vRes;
|
||||||
|
|
||||||
|
public ImageHeaderPICT(byte data[], int offset) {
|
||||||
|
// http://mirrors.apple2.org.za/apple.cabi.net/Graphics/PICT.and_QT.INFO/PICT.file.format.TI.txt
|
||||||
|
|
||||||
|
// low order 16 bits of picture size - can be ignored
|
||||||
|
offset += 2;
|
||||||
|
// rectangular bounding box of picture, at 72 dpi
|
||||||
|
// rect : 8 bytes (top, left, bottom, right: integer)
|
||||||
|
int y1 = readUnsignedShort(data, offset); offset += 2;
|
||||||
|
int x1 = readUnsignedShort(data, offset); offset += 2;
|
||||||
|
int y2 = readUnsignedShort(data, offset); offset += 2;
|
||||||
|
int x2 = readUnsignedShort(data, offset); offset += 2;
|
||||||
|
|
||||||
|
// check for version 2 ... otherwise we don't read any further
|
||||||
|
boolean isV2 = true;
|
||||||
|
for (byte b : V2_HEADER) {
|
||||||
|
if (b != data[offset++]) {
|
||||||
|
isV2 = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isV2) {
|
||||||
|
// 4 bytes - fixed, horizontal resolution (dpi) of source data
|
||||||
|
hRes = readFixedPoint(data, offset); offset += 4;
|
||||||
|
// 4 bytes - fixed, vertical resolution (dpi) of source data
|
||||||
|
vRes = readFixedPoint(data, offset); offset += 4;
|
||||||
|
} else {
|
||||||
|
hRes = DEFAULT_RESOLUTION;
|
||||||
|
vRes = DEFAULT_RESOLUTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds = new Rectangle(x1,y1,x2-x1,y2-y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dimension getSize() {
|
||||||
|
int height = (int)Math.round(bounds.height*DEFAULT_RESOLUTION/vRes);
|
||||||
|
int width = (int)Math.round(bounds.width*DEFAULT_RESOLUTION/hRes);
|
||||||
|
return new Dimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getBounds() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readUnsignedShort(byte data[], int offset) {
|
||||||
|
int b0 = data[offset] & 0xFF;
|
||||||
|
int b1 = data[offset+1] & 0xFF;
|
||||||
|
return b0 << 8 | b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double readFixedPoint(byte data[], int offset) {
|
||||||
|
int b0 = data[offset] & 0xFF;
|
||||||
|
int b1 = data[offset+1] & 0xFF;
|
||||||
|
int b2 = data[offset+2] & 0xFF;
|
||||||
|
int b3 = data[offset+3] & 0xFF;
|
||||||
|
int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
||||||
|
return i / (double)0x10000;
|
||||||
|
}
|
||||||
|
}
|
154
src/java/org/apache/poi/sl/image/ImageHeaderWMF.java
Normal file
154
src/java/org/apache/poi/sl/image/ImageHeaderWMF.java
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.sl.image;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
@Internal
|
||||||
|
public class ImageHeaderWMF {
|
||||||
|
|
||||||
|
public static final int APMHEADER_KEY = 0x9AC6CDD7;
|
||||||
|
private static POILogger LOG = POILogFactory.getLogger(ImageHeaderWMF.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final int handle;
|
||||||
|
private final int left, top, right, bottom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of logical units per inch used to represent the image.
|
||||||
|
* This value can be used to scale an image. By convention, an image is
|
||||||
|
* considered to be recorded at 1440 logical units (twips) per inch.
|
||||||
|
* Thus, a value of 720 specifies that the image SHOULD be rendered at
|
||||||
|
* twice its normal size, and a value of 2880 specifies that the image
|
||||||
|
* SHOULD be rendered at half its normal size.
|
||||||
|
*/
|
||||||
|
private final int inch;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final int reserved;
|
||||||
|
private int checksum;
|
||||||
|
|
||||||
|
public ImageHeaderWMF(Rectangle dim) {
|
||||||
|
handle = 0;
|
||||||
|
left = dim.x;
|
||||||
|
top = dim.y;
|
||||||
|
right = dim.x + dim.width;
|
||||||
|
bottom = dim.y + dim.height;
|
||||||
|
inch = Units.POINT_DPI; //default resolution is 72 dpi
|
||||||
|
reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageHeaderWMF(byte[] data, int pos) {
|
||||||
|
int key = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; //header key
|
||||||
|
if (key != APMHEADER_KEY) {
|
||||||
|
LOG.log(POILogger.WARN, "WMF file doesn't contain a placeable header - ignore parsing");
|
||||||
|
handle = 0;
|
||||||
|
left = 0;
|
||||||
|
top = 0;
|
||||||
|
right = 200;
|
||||||
|
bottom = 200;
|
||||||
|
inch = Units.POINT_DPI; //default resolution is 72 dpi
|
||||||
|
reserved = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||||
|
left = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||||
|
top = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||||
|
right = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
||||||
|
bottom = LittleEndian.getShort(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()){
|
||||||
|
LOG.log(POILogger.WARN, "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 cs = 0;
|
||||||
|
cs ^= (APMHEADER_KEY & 0x0000FFFF);
|
||||||
|
cs ^= ((APMHEADER_KEY & 0xFFFF0000) >> 16);
|
||||||
|
cs ^= left;
|
||||||
|
cs ^= top;
|
||||||
|
cs ^= right;
|
||||||
|
cs ^= bottom;
|
||||||
|
cs ^= inch;
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Dimension getSize() {
|
||||||
|
//coefficient to translate from WMF dpi to 72dpi
|
||||||
|
double coeff = ((double)Units.POINT_DPI)/inch;
|
||||||
|
return new Dimension((int)Math.round((right-left)*coeff), (int)Math.round((bottom-top)*coeff));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getBounds() {
|
||||||
|
return new Rectangle(left, top, right-left, bottom-top);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength(){
|
||||||
|
return 22;
|
||||||
|
}
|
||||||
|
}
|
@ -20,28 +20,23 @@
|
|||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
import org.apache.poi.POIXMLDocumentPart;
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.apache.poi.POIXMLException;
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.poi.hslf.blip.EMF;
|
|
||||||
import org.apache.poi.hslf.blip.PICT;
|
|
||||||
import org.apache.poi.hslf.blip.WMF;
|
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderBitmap;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderEMF;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderPICT;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderWMF;
|
||||||
import org.apache.poi.sl.usermodel.PictureData;
|
import org.apache.poi.sl.usermodel.PictureData;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LittleEndianConsts;
|
import org.apache.poi.util.LittleEndianConsts;
|
||||||
import org.apache.poi.util.POILogFactory;
|
|
||||||
import org.apache.poi.util.POILogger;
|
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,8 +44,6 @@ import org.apache.poi.util.Units;
|
|||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public final class XSLFPictureData extends POIXMLDocumentPart implements PictureData {
|
public final class XSLFPictureData extends POIXMLDocumentPart implements PictureData {
|
||||||
private static final POILogger logger = POILogFactory.getLogger(XSLFPictureData.class);
|
|
||||||
|
|
||||||
private Long checksum = null;
|
private Long checksum = null;
|
||||||
|
|
||||||
// original image dimensions (for formats supported by BufferedImage)
|
// original image dimensions (for formats supported by BufferedImage)
|
||||||
@ -171,30 +164,18 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture
|
|||||||
|
|
||||||
switch (pt) {
|
switch (pt) {
|
||||||
case EMF:
|
case EMF:
|
||||||
origSize = new EMF.NativeHeader(data, 0).getSize();
|
origSize = new ImageHeaderEMF(data, 0).getSize();
|
||||||
break;
|
break;
|
||||||
case WMF:
|
case WMF:
|
||||||
// wmf files in pptx usually have their placeable header
|
// wmf files in pptx usually have their placeable header
|
||||||
// stripped away, so this returns only the dummy size
|
// stripped away, so this returns only the dummy size
|
||||||
origSize = new WMF.NativeHeader(data, 0).getSize();
|
origSize = new ImageHeaderWMF(data, 0).getSize();
|
||||||
break;
|
break;
|
||||||
case PICT:
|
case PICT:
|
||||||
origSize = new PICT.NativeHeader(data, 0).getSize();
|
origSize = new ImageHeaderPICT(data, 0).getSize();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BufferedImage img = null;
|
origSize = new ImageHeaderBitmap(data, 0).getSize();
|
||||||
try {
|
|
||||||
img = ImageIO.read(new ByteArrayInputStream(data));
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.log(POILogger.WARN, "Can't determine image dimensions", e);
|
|
||||||
}
|
|
||||||
// set dummy size, in case of dummy dimension can't be set
|
|
||||||
origSize = (img == null)
|
|
||||||
? new Dimension(200,200)
|
|
||||||
: new Dimension(
|
|
||||||
(int)Units.pixelToPoints(img.getWidth()),
|
|
||||||
(int)Units.pixelToPoints(img.getHeight())
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package org.apache.poi.hslf.blip;
|
package org.apache.poi.hslf.blip;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -26,8 +25,7 @@ import java.io.InputStream;
|
|||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.sl.image.ImageHeaderEMF;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,38 +33,6 @@ import org.apache.poi.util.Units;
|
|||||||
*/
|
*/
|
||||||
public final class EMF extends Metafile {
|
public final class EMF extends Metafile {
|
||||||
|
|
||||||
public static class NativeHeader {
|
|
||||||
// rectangular inclusive-inclusive bounds, in device units, of the smallest
|
|
||||||
// rectangle that can be drawn around the image stored in the metafile.
|
|
||||||
private final Rectangle deviceBounds;
|
|
||||||
|
|
||||||
private final static String EMF_SIGNATURE = " EMF"; // 0x464D4520 (LE)
|
|
||||||
|
|
||||||
public NativeHeader(byte data[], int offset) {
|
|
||||||
int type = (int)LittleEndian.getUInt(data, offset); offset += 4;
|
|
||||||
if (type != 1) {
|
|
||||||
throw new HSLFException("Invalid EMF picture");
|
|
||||||
}
|
|
||||||
// ignore header size
|
|
||||||
offset += 4;
|
|
||||||
int left = LittleEndian.getInt(data, offset); offset += 4;
|
|
||||||
int top = LittleEndian.getInt(data, offset); offset += 4;
|
|
||||||
int right = LittleEndian.getInt(data, offset); offset += 4;
|
|
||||||
int bottom = LittleEndian.getInt(data, offset); offset += 4;
|
|
||||||
deviceBounds = new Rectangle(left, top, right-left, bottom-top);
|
|
||||||
// ignore frame bounds
|
|
||||||
offset += 16;
|
|
||||||
String signature = new String(data, offset, EMF_SIGNATURE.length(), LocaleUtil.CHARSET_1252);
|
|
||||||
if (!EMF_SIGNATURE.equals(signature)) {
|
|
||||||
throw new HSLFException("Invalid EMF picture");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dimension getSize() {
|
|
||||||
return deviceBounds.getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getData(){
|
public byte[] getData(){
|
||||||
try {
|
try {
|
||||||
@ -96,11 +62,11 @@ public final class EMF extends Metafile {
|
|||||||
public void setData(byte[] data) throws IOException {
|
public void setData(byte[] data) throws IOException {
|
||||||
byte[] compressed = compress(data, 0, data.length);
|
byte[] compressed = compress(data, 0, data.length);
|
||||||
|
|
||||||
NativeHeader nHeader = new NativeHeader(data, 0);
|
ImageHeaderEMF nHeader = new ImageHeaderEMF(data, 0);
|
||||||
|
|
||||||
Header header = new Header();
|
Header header = new Header();
|
||||||
header.wmfsize = data.length;
|
header.wmfsize = data.length;
|
||||||
header.bounds = nHeader.deviceBounds;
|
header.bounds = nHeader.getBounds();
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
||||||
header.zipsize = compressed.length;
|
header.zipsize = compressed.length;
|
||||||
|
@ -18,13 +18,13 @@
|
|||||||
package org.apache.poi.hslf.blip;
|
package org.apache.poi.hslf.blip;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderPICT;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
@ -35,79 +35,6 @@ import org.apache.poi.util.Units;
|
|||||||
public final class PICT extends Metafile {
|
public final class PICT extends Metafile {
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(PICT.class);
|
private static final POILogger LOG = POILogFactory.getLogger(PICT.class);
|
||||||
|
|
||||||
public static class NativeHeader {
|
|
||||||
/**
|
|
||||||
* skip the first 512 bytes - they are MAC specific crap
|
|
||||||
*/
|
|
||||||
public static final int PICT_HEADER_OFFSET = 512;
|
|
||||||
|
|
||||||
public static final double DEFAULT_RESOLUTION = Units.POINT_DPI;
|
|
||||||
|
|
||||||
private static final byte V2_HEADER[] = {
|
|
||||||
0x00, 0x11, // v2 version opcode
|
|
||||||
0x02, (byte)0xFF, // version number of new picture
|
|
||||||
0x0C, 0x00, // header opcode
|
|
||||||
(byte)0xFF, (byte)0xFE, 0x00, 0x00 // pic size dummy
|
|
||||||
};
|
|
||||||
|
|
||||||
public final Rectangle bounds;
|
|
||||||
public final double hRes, vRes;
|
|
||||||
|
|
||||||
public NativeHeader(byte data[], int offset) {
|
|
||||||
// http://mirrors.apple2.org.za/apple.cabi.net/Graphics/PICT.and_QT.INFO/PICT.file.format.TI.txt
|
|
||||||
|
|
||||||
// low order 16 bits of picture size - can be ignored
|
|
||||||
offset += 2;
|
|
||||||
// rectangular bounding box of picture, at 72 dpi
|
|
||||||
// rect : 8 bytes (top, left, bottom, right: integer)
|
|
||||||
int y1 = readUnsignedShort(data, offset); offset += 2;
|
|
||||||
int x1 = readUnsignedShort(data, offset); offset += 2;
|
|
||||||
int y2 = readUnsignedShort(data, offset); offset += 2;
|
|
||||||
int x2 = readUnsignedShort(data, offset); offset += 2;
|
|
||||||
|
|
||||||
// check for version 2 ... otherwise we don't read any further
|
|
||||||
boolean isV2 = true;
|
|
||||||
for (byte b : V2_HEADER) {
|
|
||||||
if (b != data[offset++]) {
|
|
||||||
isV2 = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isV2) {
|
|
||||||
// 4 bytes - fixed, horizontal resolution (dpi) of source data
|
|
||||||
hRes = readFixedPoint(data, offset); offset += 4;
|
|
||||||
// 4 bytes - fixed, vertical resolution (dpi) of source data
|
|
||||||
vRes = readFixedPoint(data, offset); offset += 4;
|
|
||||||
} else {
|
|
||||||
hRes = DEFAULT_RESOLUTION;
|
|
||||||
vRes = DEFAULT_RESOLUTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
bounds = new Rectangle(x1,y1,x2-x1,y2-y1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dimension getSize() {
|
|
||||||
int height = (int)Math.round(bounds.height*DEFAULT_RESOLUTION/vRes);
|
|
||||||
int width = (int)Math.round(bounds.width*DEFAULT_RESOLUTION/hRes);
|
|
||||||
return new Dimension(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int readUnsignedShort(byte data[], int offset) {
|
|
||||||
int b0 = data[offset] & 0xFF;
|
|
||||||
int b1 = data[offset+1] & 0xFF;
|
|
||||||
return b0 << 8 | b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double readFixedPoint(byte data[], int offset) {
|
|
||||||
int b0 = data[offset] & 0xFF;
|
|
||||||
int b1 = data[offset+1] & 0xFF;
|
|
||||||
int b2 = data[offset+2] & 0xFF;
|
|
||||||
int b3 = data[offset+3] & 0xFF;
|
|
||||||
int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
|
||||||
return i / (double)0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getData(){
|
public byte[] getData(){
|
||||||
@ -163,14 +90,14 @@ public final class PICT extends Metafile {
|
|||||||
@Override
|
@Override
|
||||||
public void setData(byte[] data) throws IOException {
|
public void setData(byte[] data) throws IOException {
|
||||||
// skip the first 512 bytes - they are MAC specific crap
|
// skip the first 512 bytes - they are MAC specific crap
|
||||||
final int nOffset = NativeHeader.PICT_HEADER_OFFSET;
|
final int nOffset = ImageHeaderPICT.PICT_HEADER_OFFSET;
|
||||||
NativeHeader nHeader = new NativeHeader(data, nOffset);
|
ImageHeaderPICT nHeader = new ImageHeaderPICT(data, nOffset);
|
||||||
|
|
||||||
Header header = new Header();
|
Header header = new Header();
|
||||||
header.wmfsize = data.length - nOffset;
|
header.wmfsize = data.length - nOffset;
|
||||||
byte[] compressed = compress(data, nOffset, header.wmfsize);
|
byte[] compressed = compress(data, nOffset, header.wmfsize);
|
||||||
header.zipsize = compressed.length;
|
header.zipsize = compressed.length;
|
||||||
header.bounds = nHeader.bounds;
|
header.bounds = nHeader.getBounds();
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
||||||
|
|
||||||
|
@ -18,18 +18,14 @@
|
|||||||
package org.apache.poi.hslf.blip;
|
package org.apache.poi.hslf.blip;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.sl.image.ImageHeaderWMF;
|
||||||
import org.apache.poi.util.POILogFactory;
|
|
||||||
import org.apache.poi.util.POILogger;
|
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +45,7 @@ public final class WMF extends Metafile {
|
|||||||
long len = is.skip(header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
|
long len = is.skip(header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
|
||||||
assert(len == header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
|
assert(len == header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
|
||||||
|
|
||||||
NativeHeader aldus = new NativeHeader(header.bounds);
|
ImageHeaderWMF aldus = new ImageHeaderWMF(header.bounds);
|
||||||
aldus.write(out);
|
aldus.write(out);
|
||||||
|
|
||||||
InflaterInputStream inflater = new InflaterInputStream( is );
|
InflaterInputStream inflater = new InflaterInputStream( is );
|
||||||
@ -68,14 +64,14 @@ public final class WMF extends Metafile {
|
|||||||
@Override
|
@Override
|
||||||
public void setData(byte[] data) throws IOException {
|
public void setData(byte[] data) throws IOException {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
NativeHeader nHeader = new NativeHeader(data, pos);
|
ImageHeaderWMF nHeader = new ImageHeaderWMF(data, pos);
|
||||||
pos += nHeader.getLength();
|
pos += nHeader.getLength();
|
||||||
|
|
||||||
byte[] compressed = compress(data, pos, data.length-pos);
|
byte[] compressed = compress(data, pos, data.length-pos);
|
||||||
|
|
||||||
Header header = new Header();
|
Header header = new Header();
|
||||||
header.wmfsize = data.length - nHeader.getLength();
|
header.wmfsize = data.length - nHeader.getLength();
|
||||||
header.bounds = new Rectangle((short)nHeader.left, (short)nHeader.top, (short)nHeader.right-(short)nHeader.left, (short)nHeader.bottom-(short)nHeader.top);
|
header.bounds = nHeader.getBounds();
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
|
||||||
header.zipsize = compressed.length;
|
header.zipsize = compressed.length;
|
||||||
@ -118,122 +114,4 @@ public final class WMF extends Metafile {
|
|||||||
throw new IllegalArgumentException(signature+" is not a valid instance/signature value for WMF");
|
throw new IllegalArgumentException(signature+" is not a valid instance/signature value for WMF");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static class NativeHeader {
|
|
||||||
public static final int APMHEADER_KEY = 0x9AC6CDD7;
|
|
||||||
private static POILogger logger = POILogFactory.getLogger(NativeHeader.class);
|
|
||||||
|
|
||||||
private final int handle;
|
|
||||||
private final int left, top, right, bottom;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of logical units per inch used to represent the image.
|
|
||||||
* This value can be used to scale an image. By convention, an image is
|
|
||||||
* considered to be recorded at 1440 logical units (twips) per inch.
|
|
||||||
* Thus, a value of 720 specifies that the image SHOULD be rendered at
|
|
||||||
* twice its normal size, and a value of 2880 specifies that the image
|
|
||||||
* SHOULD be rendered at half its normal size.
|
|
||||||
*/
|
|
||||||
private final int inch;
|
|
||||||
private final int reserved;
|
|
||||||
private int checksum;
|
|
||||||
|
|
||||||
public NativeHeader(Rectangle dim) {
|
|
||||||
handle = 0;
|
|
||||||
left = dim.x;
|
|
||||||
top = dim.y;
|
|
||||||
right = dim.x + dim.width;
|
|
||||||
bottom = dim.y + dim.height;
|
|
||||||
inch = Units.POINT_DPI; //default resolution is 72 dpi
|
|
||||||
reserved = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeHeader(byte[] data, int pos) {
|
|
||||||
int key = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; //header key
|
|
||||||
if (key != APMHEADER_KEY) {
|
|
||||||
logger.log(POILogger.WARN, "WMF file doesn't contain a placeable header - ignore parsing");
|
|
||||||
handle = 0;
|
|
||||||
left = 0;
|
|
||||||
top = 0;
|
|
||||||
right = 200;
|
|
||||||
bottom = 200;
|
|
||||||
inch = Units.POINT_DPI; //default resolution is 72 dpi
|
|
||||||
reserved = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
|
||||||
left = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
|
||||||
top = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
|
||||||
right = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
|
|
||||||
bottom = LittleEndian.getShort(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()){
|
|
||||||
logger.log(POILogger.WARN, "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 cs = 0;
|
|
||||||
cs ^= (APMHEADER_KEY & 0x0000FFFF);
|
|
||||||
cs ^= ((APMHEADER_KEY & 0xFFFF0000) >> 16);
|
|
||||||
cs ^= left;
|
|
||||||
cs ^= top;
|
|
||||||
cs ^= right;
|
|
||||||
cs ^= bottom;
|
|
||||||
cs ^= inch;
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 Dimension getSize() {
|
|
||||||
//coefficient to translate from WMF dpi to 72dpi
|
|
||||||
double coeff = ((double)Units.POINT_DPI)/inch;
|
|
||||||
return new Dimension((int)Math.round((right-left)*coeff), (int)Math.round((bottom-top)*coeff));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength(){
|
|
||||||
return 22;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -34,6 +35,9 @@ import org.apache.poi.hslf.blip.JPEG;
|
|||||||
import org.apache.poi.hslf.blip.PICT;
|
import org.apache.poi.hslf.blip.PICT;
|
||||||
import org.apache.poi.hslf.blip.PNG;
|
import org.apache.poi.hslf.blip.PNG;
|
||||||
import org.apache.poi.hslf.blip.WMF;
|
import org.apache.poi.hslf.blip.WMF;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderEMF;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderPICT;
|
||||||
|
import org.apache.poi.sl.image.ImageHeaderWMF;
|
||||||
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
@ -51,13 +55,13 @@ public final class TestPictures {
|
|||||||
* Test read/write Macintosh PICT
|
* Test read/write Macintosh PICT
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPICT() throws Exception {
|
public void testPICT() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
byte[] src_bytes = slTests.readFile("cow.pict");
|
byte[] src_bytes = slTests.readFile("cow.pict");
|
||||||
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.PICT);
|
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.PICT);
|
||||||
PICT.NativeHeader nHeader = new PICT.NativeHeader(src_bytes, 512);
|
ImageHeaderPICT nHeader = new ImageHeaderPICT(src_bytes, 512);
|
||||||
final int expWidth = 197, expHeight = 137;
|
final int expWidth = 197, expHeight = 137;
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
assertEquals(expWidth, nDim.getWidth(), 0);
|
assertEquals(expWidth, nDim.getWidth(), 0);
|
||||||
@ -114,13 +118,13 @@ public final class TestPictures {
|
|||||||
* Test read/write WMF
|
* Test read/write WMF
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testWMF() throws Exception {
|
public void testWMF() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
byte[] src_bytes = slTests.readFile("santa.wmf");
|
byte[] src_bytes = slTests.readFile("santa.wmf");
|
||||||
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.WMF);
|
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.WMF);
|
||||||
WMF.NativeHeader nHeader = new WMF.NativeHeader(src_bytes, 0);
|
ImageHeaderWMF nHeader = new ImageHeaderWMF(src_bytes, 0);
|
||||||
final int expWidth = 136, expHeight = 146;
|
final int expWidth = 136, expHeight = 146;
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
assertEquals(expWidth, nDim.getWidth(), 0);
|
assertEquals(expWidth, nDim.getWidth(), 0);
|
||||||
@ -176,13 +180,13 @@ public final class TestPictures {
|
|||||||
* Test read/write EMF
|
* Test read/write EMF
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEMF() throws Exception {
|
public void testEMF() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
byte[] src_bytes = slTests.readFile("wrench.emf");
|
byte[] src_bytes = slTests.readFile("wrench.emf");
|
||||||
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.EMF);
|
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.EMF);
|
||||||
EMF.NativeHeader nHeader = new EMF.NativeHeader(src_bytes, 0);
|
ImageHeaderEMF nHeader = new ImageHeaderEMF(src_bytes, 0);
|
||||||
final int expWidth = 190, expHeight = 115;
|
final int expWidth = 190, expHeight = 115;
|
||||||
Dimension nDim = nHeader.getSize();
|
Dimension nDim = nHeader.getSize();
|
||||||
assertEquals(expWidth, nDim.getWidth(), 0);
|
assertEquals(expWidth, nDim.getWidth(), 0);
|
||||||
@ -233,7 +237,7 @@ public final class TestPictures {
|
|||||||
* Test read/write PNG
|
* Test read/write PNG
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPNG() throws Exception {
|
public void testPNG() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
@ -273,7 +277,7 @@ public final class TestPictures {
|
|||||||
* Test read/write JPEG
|
* Test read/write JPEG
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testJPEG() throws Exception {
|
public void testJPEG() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
@ -314,7 +318,7 @@ public final class TestPictures {
|
|||||||
* Test read/write DIB
|
* Test read/write DIB
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDIB() throws Exception {
|
public void testDIB() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
@ -354,7 +358,7 @@ public final class TestPictures {
|
|||||||
* Read pictures in different formats from a reference slide show
|
* Read pictures in different formats from a reference slide show
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testReadPictures() throws Exception {
|
public void testReadPictures() throws IOException {
|
||||||
|
|
||||||
byte[] src_bytes, ppt_bytes, b1, b2;
|
byte[] src_bytes, ppt_bytes, b1, b2;
|
||||||
HSLFPictureShape pict;
|
HSLFPictureShape pict;
|
||||||
@ -417,6 +421,7 @@ public final class TestPictures {
|
|||||||
ppt_bytes = slTests.readFile("wrench.emf");
|
ppt_bytes = slTests.readFile("wrench.emf");
|
||||||
assertArrayEquals(src_bytes, ppt_bytes);
|
assertArrayEquals(src_bytes, ppt_bytes);
|
||||||
|
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -424,7 +429,7 @@ public final class TestPictures {
|
|||||||
* crazy pictures of type 0, we do our best.
|
* crazy pictures of type 0, we do our best.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testZeroPictureType() throws Exception {
|
public void testZeroPictureType() throws IOException {
|
||||||
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"));
|
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"));
|
||||||
|
|
||||||
// Should still have 2 real pictures
|
// Should still have 2 real pictures
|
||||||
@ -452,6 +457,8 @@ public final class TestPictures {
|
|||||||
pdata = pict.getPictureData();
|
pdata = pict.getPictureData();
|
||||||
assertTrue(pdata instanceof WMF);
|
assertTrue(pdata instanceof WMF);
|
||||||
assertEquals(PictureType.WMF, pdata.getType());
|
assertEquals(PictureType.WMF, pdata.getType());
|
||||||
|
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,7 +467,7 @@ public final class TestPictures {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void testZeroPictureLength() throws Exception {
|
public void testZeroPictureLength() throws IOException {
|
||||||
// take the data from www instead of test directory
|
// take the data from www instead of test directory
|
||||||
URL url = new URL("http://www.cs.sfu.ca/~anoop/courses/CMPT-882-Fall-2002/chris.ppt");
|
URL url = new URL("http://www.cs.sfu.ca/~anoop/courses/CMPT-882-Fall-2002/chris.ppt");
|
||||||
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream());
|
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream());
|
||||||
@ -504,19 +511,21 @@ public final class TestPictures {
|
|||||||
assertEquals(streamSize, offset);
|
assertEquals(streamSize, offset);
|
||||||
assertEquals(3, ppt.getPictureData().size());
|
assertEquals(3, ppt.getPictureData().size());
|
||||||
|
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPictureName() throws Exception {
|
public void testGetPictureName() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
|
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
|
||||||
HSLFSlide slide = ppt.getSlides().get(0);
|
HSLFSlide slide = ppt.getSlides().get(0);
|
||||||
|
|
||||||
HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG
|
HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG
|
||||||
assertEquals("test", p.getPictureName());
|
assertEquals("test", p.getPictureName());
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetPictureName() throws Exception {
|
public void testSetPictureName() throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow();
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
|
||||||
HSLFSlide slide = ppt.createSlide();
|
HSLFSlide slide = ppt.createSlide();
|
||||||
|
Loading…
Reference in New Issue
Block a user