Bugzilla 53446 - Fixed some problems extracting PNGs
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1369263 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ef89213fd5
commit
fb1719c85d
@ -34,7 +34,8 @@
|
|||||||
|
|
||||||
<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>
|
||||||
|
@ -22,6 +22,7 @@ import org.apache.poi.ddf.EscherBitmapBlip;
|
|||||||
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...
|
||||||
@ -60,7 +61,18 @@ public class HSSFPictureData implements PictureData
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
57
src/java/org/apache/poi/util/PngUtils.java
Normal file
57
src/java/org/apache/poi/util/PngUtils.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.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;
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -35,20 +36,17 @@ public final class PNG extends Bitmap {
|
|||||||
/**
|
/**
|
||||||
* @return PNG data
|
* @return PNG data
|
||||||
*/
|
*/
|
||||||
public byte[] getData(){
|
public byte[] getData() {
|
||||||
byte[] data = super.getData();
|
byte[] data = super.getData();
|
||||||
try {
|
|
||||||
//PNG created on MAC may have a 16-byte prefix which prevents successful reading.
|
//PNG created on MAC may have a 16-byte prefix which prevents successful reading.
|
||||||
//Just cut it off!.
|
//Just cut it off!.
|
||||||
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(data));
|
if (PngUtils.matchesPngHeader(data, 16)) {
|
||||||
if (bi == null){
|
|
||||||
byte[] png = new byte[data.length-16];
|
byte[] png = new byte[data.length-16];
|
||||||
System.arraycopy(data, 16, png, 0, png.length);
|
System.arraycopy(data, 16, png, 0, png.length);
|
||||||
data = png;
|
data = png;
|
||||||
}
|
}
|
||||||
} catch (IOException e){
|
|
||||||
throw new HSLFException(e);
|
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import org.apache.poi.ddf.EscherProperty;
|
|||||||
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;
|
||||||
@ -191,6 +192,15 @@ public final class Picture
|
|||||||
{
|
{
|
||||||
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +20,13 @@ package org.apache.poi.hslf.model;
|
|||||||
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;
|
||||||
@ -88,4 +91,41 @@ public final class TestPicture extends TestCase {
|
|||||||
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
|
|
||||||
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;
|
||||||
@ -128,6 +132,30 @@ public final class TestHWPFPictures extends TestCase {
|
|||||||
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
|
||||||
|
@ -72,6 +72,29 @@ public final class TestHSSFPictureData extends TestCase{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SheetWithDrawing.xls");
|
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SheetWithDrawing.xls");
|
||||||
|
BIN
test-data/document/53446.doc
Normal file
BIN
test-data/document/53446.doc
Normal file
Binary file not shown.
BIN
test-data/slideshow/53446.ppt
Normal file
BIN
test-data/slideshow/53446.ppt
Normal file
Binary file not shown.
BIN
test-data/spreadsheet/53446.xls
Normal file
BIN
test-data/spreadsheet/53446.xls
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user