git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1866809 13f79535-47bb-0310-9956-ffa450edef68tags/REL_4_1_1
@@ -18,12 +18,11 @@ | |||
package org.apache.poi.hssf.usermodel; | |||
import org.apache.poi.ddf.EscherBitmapBlip; | |||
import org.apache.poi.ddf.EscherBlipRecord; | |||
import org.apache.poi.ddf.EscherMetafileBlip; | |||
import org.apache.poi.ddf.EscherRecordTypes; | |||
import org.apache.poi.sl.image.ImageHeaderPNG; | |||
import org.apache.poi.ss.usermodel.PictureData; | |||
import org.apache.poi.ss.usermodel.Workbook; | |||
import org.apache.poi.util.PngUtils; | |||
/** | |||
* Represents binary data stored in the file. Eg. A GIF, JPEG etc... | |||
@@ -58,20 +57,8 @@ public class HSSFPictureData implements PictureData | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.hssf.usermodel.PictureData#getData() | |||
*/ | |||
public byte[] getData() | |||
{ | |||
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; | |||
public byte[] getData() { | |||
return new ImageHeaderPNG(blip.getPicturedata()).extractPNG(); | |||
} | |||
/** | |||
@@ -93,18 +80,18 @@ public class HSSFPictureData implements PictureData | |||
* @return 'wmf', 'jpeg' etc depending on the format. never <code>null</code> | |||
*/ | |||
public String suggestFileExtension() { | |||
switch (blip.getRecordId()) { | |||
case EscherMetafileBlip.RECORD_ID_WMF: | |||
switch (EscherRecordTypes.forTypeID(blip.getRecordId())) { | |||
case BLIP_WMF: | |||
return "wmf"; | |||
case EscherMetafileBlip.RECORD_ID_EMF: | |||
case BLIP_EMF: | |||
return "emf"; | |||
case EscherMetafileBlip.RECORD_ID_PICT: | |||
case BLIP_PICT: | |||
return "pict"; | |||
case EscherBitmapBlip.RECORD_ID_PNG: | |||
case BLIP_PNG: | |||
return "png"; | |||
case EscherBitmapBlip.RECORD_ID_JPEG: | |||
case BLIP_JPEG: | |||
return "jpeg"; | |||
case EscherBitmapBlip.RECORD_ID_DIB: | |||
case BLIP_DIB: | |||
return "dib"; | |||
default: | |||
return ""; | |||
@@ -115,18 +102,18 @@ public class HSSFPictureData implements PictureData | |||
* Returns the mime type for the image | |||
*/ | |||
public String getMimeType() { | |||
switch (blip.getRecordId()) { | |||
case EscherMetafileBlip.RECORD_ID_WMF: | |||
switch (EscherRecordTypes.forTypeID(blip.getRecordId())) { | |||
case BLIP_WMF: | |||
return "image/x-wmf"; | |||
case EscherMetafileBlip.RECORD_ID_EMF: | |||
case BLIP_EMF: | |||
return "image/x-emf"; | |||
case EscherMetafileBlip.RECORD_ID_PICT: | |||
case BLIP_PICT: | |||
return "image/x-pict"; | |||
case EscherBitmapBlip.RECORD_ID_PNG: | |||
case BLIP_PNG: | |||
return "image/png"; | |||
case EscherBitmapBlip.RECORD_ID_JPEG: | |||
case BLIP_JPEG: | |||
return "image/jpeg"; | |||
case EscherBitmapBlip.RECORD_ID_DIB: | |||
case BLIP_DIB: | |||
return "image/bmp"; | |||
default: | |||
return "image/unknown"; | |||
@@ -144,18 +131,18 @@ public class HSSFPictureData implements PictureData | |||
* @see Workbook#PICTURE_TYPE_WMF | |||
*/ | |||
public int getPictureType() { | |||
switch (blip.getRecordId()) { | |||
case EscherMetafileBlip.RECORD_ID_WMF: | |||
switch (EscherRecordTypes.forTypeID(blip.getRecordId())) { | |||
case BLIP_WMF: | |||
return Workbook.PICTURE_TYPE_WMF; | |||
case EscherMetafileBlip.RECORD_ID_EMF: | |||
case BLIP_EMF: | |||
return Workbook.PICTURE_TYPE_EMF; | |||
case EscherMetafileBlip.RECORD_ID_PICT: | |||
case BLIP_PICT: | |||
return Workbook.PICTURE_TYPE_PICT; | |||
case EscherBitmapBlip.RECORD_ID_PNG: | |||
case BLIP_PNG: | |||
return Workbook.PICTURE_TYPE_PNG; | |||
case EscherBitmapBlip.RECORD_ID_JPEG: | |||
case BLIP_JPEG: | |||
return Workbook.PICTURE_TYPE_JPEG; | |||
case EscherBitmapBlip.RECORD_ID_DIB: | |||
case BLIP_DIB: | |||
return Workbook.PICTURE_TYPE_DIB; | |||
default: | |||
return -1; |
@@ -0,0 +1,59 @@ | |||
/* ==================================================================== | |||
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.io.ByteArrayInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import org.apache.poi.poifs.filesystem.FileMagic; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.RecordFormatException; | |||
public final class ImageHeaderPNG { | |||
private static final int MAGIC_OFFSET = 16; | |||
private byte[] data; | |||
/** | |||
* @param data The raw image data | |||
*/ | |||
public ImageHeaderPNG(byte[] data) { | |||
this.data = data; | |||
} | |||
/** | |||
* PNG created on MAC may have a 16-byte prefix which prevents successful reading. | |||
* @return the trimmed PNG data | |||
*/ | |||
public byte[] extractPNG() { | |||
// | |||
//Just cut it off!. | |||
try (InputStream is = new ByteArrayInputStream(data)) { | |||
if (is.skip(MAGIC_OFFSET) == MAGIC_OFFSET && FileMagic.valueOf(is) == FileMagic.PNG) { | |||
return IOUtils.toByteArray(is); | |||
} | |||
} catch (IOException e) { | |||
throw new RecordFormatException("Unable to parse PNG header", e); | |||
} | |||
return data; | |||
} | |||
} |
@@ -1,53 +0,0 @@ | |||
/* ==================================================================== | |||
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; | |||
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,7 +17,7 @@ | |||
package org.apache.poi.hslf.blip; | |||
import org.apache.poi.util.PngUtils; | |||
import org.apache.poi.sl.image.ImageHeaderPNG; | |||
/** | |||
* Represents a PNG picture data in a PPT file | |||
@@ -26,17 +26,7 @@ public final class PNG extends Bitmap { | |||
@Override | |||
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 new ImageHeaderPNG(super.getData()).extractPNG(); | |||
} | |||
@Override |
@@ -34,7 +34,7 @@ import org.apache.poi.ddf.EscherProperty; | |||
import org.apache.poi.ddf.EscherRecord; | |||
import org.apache.poi.hwpf.model.PICF; | |||
import org.apache.poi.hwpf.model.PICFAndOfficeArtData; | |||
import org.apache.poi.util.PngUtils; | |||
import org.apache.poi.sl.image.ImageHeaderPNG; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.StringUtil; | |||
@@ -169,16 +169,7 @@ public final class Picture { | |||
else | |||
{ | |||
// Raw data is not compressed. | |||
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; | |||
} | |||
content = new ImageHeaderPNG(rawContent).extractPNG(); | |||
} | |||
} | |||