git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1369263 13f79535-47bb-0310-9956-ffa450edef68tags/3.10-beta1
<changes> | <changes> | ||||
<release version="3.9-beta1" date="2012-??-??"> | <release version="3.9-beta1" date="2012-??-??"> | ||||
<action dev="poi-developers" type="fix">53205 - Fix some parsing errors and encoding issues in HDGF </action> | |||||
<action dev="poi-developers" type="add">53446 - Fixed some problems extracting PNGs </action> | |||||
<action dev="poi-developers" type="fix">53205 - Fixed some parsing errors and encoding issues in HDGF </action> | |||||
<action dev="poi-developers" type="add">53204 - Improved performanceof PageSettingsBlock in HSSF </action> | <action dev="poi-developers" type="add">53204 - Improved performanceof PageSettingsBlock in HSSF </action> | ||||
<action dev="poi-developers" type="add">53500 - Getter for repeating rows and columns</action> | <action dev="poi-developers" type="add">53500 - Getter for repeating rows and columns</action> | ||||
<action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action> | <action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action> |
import org.apache.poi.ddf.EscherBlipRecord; | import org.apache.poi.ddf.EscherBlipRecord; | ||||
import org.apache.poi.ddf.EscherMetafileBlip; | import org.apache.poi.ddf.EscherMetafileBlip; | ||||
import org.apache.poi.ss.usermodel.PictureData; | import org.apache.poi.ss.usermodel.PictureData; | ||||
import org.apache.poi.util.PngUtils; | |||||
/** | /** | ||||
* Represents binary data stored in the file. Eg. A GIF, JPEG etc... | * Represents binary data stored in the file. Eg. A GIF, JPEG etc... | ||||
*/ | */ | ||||
public byte[] getData() | public byte[] getData() | ||||
{ | { | ||||
return blip.getPicturedata(); | |||||
byte[] pictureData = blip.getPicturedata(); | |||||
//PNG created on MAC may have a 16-byte prefix which prevents successful reading. | |||||
//Just cut it off!. | |||||
if (PngUtils.matchesPngHeader(pictureData, 16)) | |||||
{ | |||||
byte[] png = new byte[pictureData.length-16]; | |||||
System.arraycopy(pictureData, 16, png, 0, png.length); | |||||
pictureData = png; | |||||
} | |||||
return pictureData; | |||||
} | } | ||||
/** | /** |
/* ==================================================================== | |||||
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.util; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.OutputStream; | |||||
public final class PngUtils { | |||||
/** | |||||
* File header for PNG format. | |||||
*/ | |||||
private static final byte[] PNG_FILE_HEADER = | |||||
new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; | |||||
private PngUtils() { | |||||
// no instances of this class | |||||
} | |||||
/** | |||||
* Checks if the offset matches the PNG header. | |||||
* | |||||
* @param data the data to check. | |||||
* @param offset the offset to check at. | |||||
* @return {@code true} if the offset matches. | |||||
*/ | |||||
public static boolean matchesPngHeader(byte[] data, int offset) { | |||||
if (data == null || data.length - offset < PNG_FILE_HEADER.length) { | |||||
return false; | |||||
} | |||||
for (int i = 0; i < PNG_FILE_HEADER.length; i++) { | |||||
if (PNG_FILE_HEADER[i] != data[i + offset]) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
} |
package org.apache.poi.hslf.blip; | package org.apache.poi.hslf.blip; | ||||
import org.apache.poi.util.PngUtils; | |||||
import org.apache.poi.hslf.model.Picture; | import org.apache.poi.hslf.model.Picture; | ||||
import org.apache.poi.hslf.exceptions.HSLFException; | import org.apache.poi.hslf.exceptions.HSLFException; | ||||
/** | /** | ||||
* @return PNG data | * @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 HSLFException(e); | |||||
} | |||||
return data; | |||||
} | |||||
public byte[] getData() { | |||||
byte[] data = super.getData(); | |||||
//PNG created on MAC may have a 16-byte prefix which prevents successful reading. | |||||
//Just cut it off!. | |||||
if (PngUtils.matchesPngHeader(data, 16)) { | |||||
byte[] png = new byte[data.length-16]; | |||||
System.arraycopy(data, 16, png, 0, png.length); | |||||
data = png; | |||||
} | |||||
return data; | |||||
} | |||||
/** | /** | ||||
* @return type of this picture | * @return type of this picture |
import org.apache.poi.ddf.EscherRecord; | import org.apache.poi.ddf.EscherRecord; | ||||
import org.apache.poi.hwpf.model.PICF; | import org.apache.poi.hwpf.model.PICF; | ||||
import org.apache.poi.hwpf.model.PICFAndOfficeArtData; | import org.apache.poi.hwpf.model.PICFAndOfficeArtData; | ||||
import org.apache.poi.util.PngUtils; | |||||
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.StringUtil; | import org.apache.poi.util.StringUtil; | ||||
{ | { | ||||
// Raw data is not compressed. | // Raw data is not compressed. | ||||
content = rawContent; | content = rawContent; | ||||
//PNG created on MAC may have a 16-byte prefix which prevents successful reading. | |||||
//Just cut it off!. | |||||
if (PngUtils.matchesPngHeader(content, 16)) | |||||
{ | |||||
byte[] png = new byte[content.length-16]; | |||||
System.arraycopy(content, 16, png, 0, png.length); | |||||
content = png; | |||||
} | |||||
} | } | ||||
} | } | ||||
import java.awt.Graphics2D; | import java.awt.Graphics2D; | ||||
import java.awt.Rectangle; | import java.awt.Rectangle; | ||||
import java.awt.image.BufferedImage; | import java.awt.image.BufferedImage; | ||||
import java.io.ByteArrayInputStream; | |||||
import javax.imageio.ImageIO; | |||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.ddf.EscherBSERecord; | import org.apache.poi.ddf.EscherBSERecord; | ||||
import org.apache.poi.hslf.HSLFSlideShow; | |||||
import org.apache.poi.hslf.usermodel.PictureData; | import org.apache.poi.hslf.usermodel.PictureData; | ||||
import org.apache.poi.hslf.usermodel.SlideShow; | import org.apache.poi.hslf.usermodel.SlideShow; | ||||
import org.apache.poi.POIDataSamples; | import org.apache.poi.POIDataSamples; | ||||
Graphics2D graphics = img.createGraphics(); | Graphics2D graphics = img.createGraphics(); | ||||
pict.draw(graphics); | pict.draw(graphics); | ||||
} | } | ||||
public void testMacImages() throws Exception { | |||||
HSLFSlideShow hss = new HSLFSlideShow(_slTests.openResourceAsStream("53446.ppt")); | |||||
PictureData[] pictures = hss.getPictures(); | |||||
assertEquals(15, pictures.length); | |||||
int[][] expectedSizes = { | |||||
null, // WMF | |||||
{ 427, 428 }, // PNG | |||||
{ 371, 370 }, // PNG | |||||
{ 288, 183 }, // PNG | |||||
{ 285, 97 }, // PNG | |||||
{ 288, 168 }, // PNG | |||||
null, // WMF | |||||
null, // WMF | |||||
{ 199, 259 }, // PNG | |||||
{ 432, 244 }, // PNG | |||||
{ 261, 258 }, // PNG | |||||
null, // WMF | |||||
null, // WMF | |||||
null, // WMF | |||||
null // EMF | |||||
}; | |||||
for (int i = 0; i < pictures.length; i++) { | |||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(pictures[i].getData())); | |||||
if (pictures[i].getType() != Picture.WMF && pictures[i].getType() != Picture.EMF) { | |||||
assertNotNull(image); | |||||
int[] dimensions = expectedSizes[i]; | |||||
assertEquals(dimensions[0], image.getWidth()); | |||||
assertEquals(dimensions[1], image.getHeight()); | |||||
} | |||||
} | |||||
} | |||||
} | } |
package org.apache.poi.hwpf; | package org.apache.poi.hwpf; | ||||
import javax.imageio.ImageIO; | |||||
import java.awt.image.BufferedImage; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.util.List; | import java.util.List; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.POIDataSamples; | |||||
import org.apache.poi.hwpf.model.PicturesTable; | import org.apache.poi.hwpf.model.PicturesTable; | ||||
import org.apache.poi.hwpf.usermodel.Picture; | import org.apache.poi.hwpf.usermodel.Picture; | ||||
import org.apache.poi.POIDataSamples; | import org.apache.poi.POIDataSamples; | ||||
assertBytesSame(picBytes, pic.getContent()); | assertBytesSame(picBytes, pic.getContent()); | ||||
} | } | ||||
public void testMacImages() throws Exception { | |||||
HWPFDocument docC = HWPFTestDataSamples.openSampleFile("53446.doc"); | |||||
PicturesTable picturesTable = docC.getPicturesTable(); | |||||
List<Picture> pictures = picturesTable.getAllPictures(); | |||||
assertEquals(4, pictures.size()); | |||||
int[][] expectedSizes = { | |||||
{ 185, 42 }, // PNG | |||||
{ 260, 114 }, // PNG | |||||
{ 185, 42 }, // PNG | |||||
{ 260, 114 }, // PNG | |||||
}; | |||||
for (int i = 0; i < pictures.size(); i++) { | |||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(pictures.get(i).getContent())); | |||||
assertNotNull(image); | |||||
int[] dimensions = expectedSizes[i]; | |||||
assertEquals(dimensions[0], image.getWidth()); | |||||
assertEquals(dimensions[1], image.getHeight()); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Pending the missing files being uploaded to | * Pending the missing files being uploaded to | ||||
* bug #44937 | * bug #44937 |
} | } | ||||
} | } | ||||
} | } | ||||
public void testMacPicture() throws IOException { | |||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("53446.xls"); | |||||
@SuppressWarnings("unchecked") | |||||
List<HSSFPictureData> lst = (List<HSSFPictureData>)(List<?>)wb.getAllPictures(); | |||||
assertEquals(1, lst.size()); | |||||
HSSFPictureData pict = lst.get(0); | |||||
String ext = pict.suggestFileExtension(); | |||||
if (!ext.equals("png")) { | |||||
fail("Expected a PNG."); | |||||
} | |||||
//try to read image data using javax.imageio.* (JDK 1.4+) | |||||
byte[] data = pict.getData(); | |||||
BufferedImage png = ImageIO.read(new ByteArrayInputStream(data)); | |||||
assertNotNull(png); | |||||
assertEquals(78, png.getWidth()); | |||||
assertEquals(76, png.getHeight()); | |||||
assertEquals(HSSFWorkbook.PICTURE_TYPE_PNG, pict.getFormat()); | |||||
assertEquals("image/png", pict.getMimeType()); | |||||
} | |||||
public void testNotNullPictures() throws IOException { | public void testNotNullPictures() throws IOException { | ||||