Author: yegor
Date: Sun Oct 13 07:20:36 2013
New Revision: 1531622
URL: http://svn.apache.org/r1531622
Log:
Bugzilla 49658 - Support embedding EMF/WMF pictures in HSSF
Modified:
poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java
poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java
Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java?rev=1531622&r1=1531621&r2=1531622&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java Sun Oct 13
07:20:36 2013
@@ -21,6 +21,7 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
+import org.apache.poi.hssf.usermodel.HSSFPictureData;
import java.awt.Dimension;
import java.awt.Rectangle;
@@ -28,6 +29,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;
+import java.util.zip.DeflaterOutputStream;
/**
* @author Daniel Noll
@@ -39,13 +41,6 @@ public final class EscherMetafileBlip ex
public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
- /**
- * BLIP signatures as defined in the escher spec
- */
- public static final short SIGNATURE_EMF = 0x3D40;
- public static final short SIGNATURE_WMF = 0x2160;
- public static final short SIGNATURE_PICT = 0x5420;
-
private static final int HEADER_SIZE = 8;
private byte[] field_1_UID;
@@ -288,11 +283,37 @@ public final class EscherMetafileBlip ex
*/
public short getSignature() {
switch (getRecordId()) {
- case RECORD_ID_EMF: return SIGNATURE_EMF;
- case RECORD_ID_WMF: return SIGNATURE_WMF;
- case RECORD_ID_PICT: return SIGNATURE_PICT;
+ case RECORD_ID_EMF: return HSSFPictureData.MSOBI_EMF;
+ case RECORD_ID_WMF: return HSSFPictureData.MSOBI_WMF;
+ case RECORD_ID_PICT: return HSSFPictureData.MSOBI_PICT;
}
log.log(POILogger.WARN, "Unknown metafile: " + getRecordId());
return 0;
}
+
+ public void setPictureData(byte[] pictureData) {
+ super.setPictureData(pictureData);
+ setUncompressedSize(pictureData.length);
+
+ // info of chicago project:
+ // "... LZ compression algorithm in the format used by GNU Zip
deflate/inflate with a 32k window ..."
+ // not sure what to do, when lookup tables exceed 32k ...
+
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DeflaterOutputStream dos = new DeflaterOutputStream(bos);
+ dos.write(pictureData);
+ dos.close();
+ raw_pictureData = bos.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException("Can't compress metafile picture
data", e);
+ }
+
+ setCompressedSize(raw_pictureData.length);
+ setCompressed(true);
+ }
+
+ public void setFilter(byte filter) {
+ field_7_fFilter = filter;
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?rev=1531622&r1=1531621&r2=1531622&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java Sun Oct
13 07:20:36 2013
@@ -34,6 +34,7 @@ import org.apache.poi.POIDocument;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBitmapBlip;
import org.apache.poi.ddf.EscherBlipRecord;
+import org.apache.poi.ddf.EscherMetafileBlip;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.model.DrawingManager2;
@@ -57,6 +58,7 @@ import org.apache.poi.ss.usermodel.Row.M
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.util.Configurator;
+import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@@ -1587,7 +1589,40 @@ public final class HSSFWorkbook extends
initDrawings();
byte[] uid = DigestUtils.md5(pictureData);
- EscherBitmapBlip blipRecord = new EscherBitmapBlip();
+ EscherBlipRecord blipRecord;
+ int blipSize;
+ short escherTag;
+ switch (format) {
+ case PICTURE_TYPE_WMF:
+ // remove first 22 bytes if file starts with magic bytes
D7-CD-C6-9A
+ // see also
http://de.wikipedia.org/wiki/Windows_Metafile#Hinweise_zur_WMF-Spezifikation
+ if (LittleEndian.getInt(pictureData) == 0x9AC6CDD7) {
+ byte picDataNoHeader[] = new byte[pictureData.length-22];
+ System.arraycopy(pictureData, 22, picDataNoHeader, 0,
pictureData.length-22);
+ pictureData = picDataNoHeader;
+ }
+ // fall through
+ case PICTURE_TYPE_EMF:
+ EscherMetafileBlip blipRecordMeta = new EscherMetafileBlip();
+ blipRecord = blipRecordMeta;
+ blipRecordMeta.setUID(uid);
+ blipRecordMeta.setPictureData(pictureData);
+ // taken from libre office export, it won't open, if this is
left to 0
+ blipRecordMeta.setFilter((byte)-2);
+ blipSize = blipRecordMeta.getCompressedSize() + 58;
+ escherTag = 0;
+ break;
+ default:
+ EscherBitmapBlip blipRecordBitmap = new EscherBitmapBlip();
+ blipRecord = blipRecordBitmap;
+ blipRecordBitmap.setUID( uid );
+ blipRecordBitmap.setMarker( (byte) 0xFF );
+ blipRecordBitmap.setPictureData( pictureData );
+ blipSize = pictureData.length + 25;
+ escherTag = (short) 0xFF;
+ break;
+ }
+
blipRecord.setRecordId( (short) ( EscherBitmapBlip.RECORD_ID_START +
format ) );
switch (format)
{
@@ -1610,23 +1645,19 @@ public final class HSSFWorkbook extends
blipRecord.setOptions(HSSFPictureData.MSOBI_DIB);
break;
}
-
- blipRecord.setUID( uid );
- blipRecord.setMarker( (byte) 0xFF );
- blipRecord.setPictureData( pictureData );
-
+
EscherBSERecord r = new EscherBSERecord();
r.setRecordId( EscherBSERecord.RECORD_ID );
r.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
r.setBlipTypeMacOS( (byte) format );
r.setBlipTypeWin32( (byte) format );
r.setUid( uid );
- r.setTag( (short) 0xFF );
- r.setSize( pictureData.length + 25 );
+ r.setTag( escherTag );
+ r.setSize( blipSize );
r.setRef( 0 );
r.setOffset( 0 );
r.setBlipRecord( blipRecord );
-
+
return workbook.addBSERecord( r );
}
Modified:
poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java?rev=1531622&r1=1531621&r2=1531622&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java
(original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java
Sun Oct 13 07:20:36 2013
@@ -17,17 +17,23 @@
package org.apache.poi.hssf.usermodel;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.poi.POIDataSamples;
import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.HSSFITestDataProvider;
+import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.ss.usermodel.BaseTestPicture;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
-import java.util.Arrays;
-import java.util.List;
-
/**
* Test <code>HSSFPicture</code>.
*
@@ -210,4 +216,56 @@ public final class TestHSSFPicture exten
p1 = (HSSFPicture) dr.getChildren().get(0);
assertEquals(p1.getFileName(), "aaa");
}
+
+ public void test49658() throws IOException {
+ // test if inserted EscherMetafileBlip will be read again
+ HSSFWorkbook wb = new HSSFWorkbook();
+
+ byte pictureDataEmf[] =
POIDataSamples.getDocumentInstance().readFile("vector_image.emf");
+ int indexEmf = wb.addPicture(pictureDataEmf,
HSSFWorkbook.PICTURE_TYPE_EMF);
+ byte pictureDataPng[] =
POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png");
+ int indexPng = wb.addPicture(pictureDataPng,
HSSFWorkbook.PICTURE_TYPE_PNG);
+ byte pictureDataWmf[] =
POIDataSamples.getSlideShowInstance().readFile("santa.wmf");
+ int indexWmf = wb.addPicture(pictureDataWmf,
HSSFWorkbook.PICTURE_TYPE_WMF);
+
+ HSSFSheet sheet = wb.createSheet();
+ HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
+ CreationHelper ch = wb.getCreationHelper();
+
+ ClientAnchor anchor = ch.createClientAnchor();
+ anchor.setCol1(2);
+ anchor.setCol2(5);
+ anchor.setRow1(1);
+ anchor.setRow2(6);
+ patriarch.createPicture(anchor, indexEmf);
+
+ anchor = ch.createClientAnchor();
+ anchor.setCol1(2);
+ anchor.setCol2(5);
+ anchor.setRow1(10);
+ anchor.setRow2(16);
+ patriarch.createPicture(anchor, indexPng);
+
+ anchor = ch.createClientAnchor();
+ anchor.setCol1(6);
+ anchor.setCol2(9);
+ anchor.setRow1(1);
+ anchor.setRow2(6);
+ patriarch.createPicture(anchor, indexWmf);
+
+
+ wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
+ byte pictureDataOut[] = wb.getAllPictures().get(0).getData();
+ assertTrue(Arrays.equals(pictureDataEmf, pictureDataOut));
+
+ byte wmfNoHeader[] = new byte[pictureDataWmf.length-22];
+ System.arraycopy(pictureDataWmf, 22, wmfNoHeader, 0,
pictureDataWmf.length-22);
+ pictureDataOut = wb.getAllPictures().get(2).getData();
+ assertTrue(Arrays.equals(wmfNoHeader, pictureDataOut));
+
+ FileOutputStream fos = new FileOutputStream("vect.xls");
+ wb.write(fos);
+ fos.close();
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]