Browse Source

Unify PNG extraction

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1866809 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_4_1_1
Andreas Beeker 4 years ago
parent
commit
8f051a0b88

+ 25
- 38
src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java View File

@@ -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;

+ 59
- 0
src/java/org/apache/poi/sl/image/ImageHeaderPNG.java View File

@@ -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;
}
}

+ 0
- 53
src/java/org/apache/poi/util/PngUtils.java View File

@@ -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;
}
}

+ 2
- 12
src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java View File

@@ -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

+ 2
- 11
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java View File

@@ -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();
}
}


Loading…
Cancel
Save