From b8e52ae6ff2c5f29a702f16a986b923f7fd21196 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 28 Nov 2011 18:42:30 +0000 Subject: [PATCH] Restore HWPF support for inline Escher images (stored in Escher rather than direct in a PICFAndOfficeArtData in the main stream), plus add test for this kind of file git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1207497 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hwpf/model/PicturesTable.java | 11 ++-- .../apache/poi/hwpf/usermodel/Picture.java | 58 ++++++++---------- .../poi/hwpf/usermodel/TestPictures.java | 10 +++ test-data/document/PngPicture.doc | Bin 0 -> 14336 bytes 4 files changed, 42 insertions(+), 37 deletions(-) create mode 100644 test-data/document/PngPicture.doc diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java index c0b440ff16..0b8b501bf3 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java @@ -18,12 +18,9 @@ package org.apache.poi.hwpf.model; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import org.apache.poi.util.POILogFactory; - -import org.apache.poi.util.POILogger; - import org.apache.poi.ddf.DefaultEscherRecordFactory; import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.ddf.EscherBlipRecord; @@ -35,6 +32,8 @@ import org.apache.poi.hwpf.usermodel.Picture; import org.apache.poi.hwpf.usermodel.Range; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; /** * Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via @@ -180,7 +179,7 @@ public final class PicturesTable EscherBlipRecord blip = bse.getBlipRecord(); if (blip != null) { - pictures.add(new Picture(blip.getPicturedata())); + pictures.add(new Picture(blip)); } else if ( bse.getOffset() > 0 ) { @@ -197,7 +196,7 @@ public final class PicturesTable record.fillFields( _mainStream, bse.getOffset(), recordFactory ); blip = (EscherBlipRecord) record; - pictures.add( new Picture( blip.getPicturedata() ) ); + pictures.add( new Picture( blip ) ); } } catch ( Exception exc ) diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java index 06e84a4f11..413c030952 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java @@ -21,16 +21,10 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; import java.util.zip.InflaterInputStream; -import org.apache.poi.ddf.EscherSimpleProperty; - -import org.apache.poi.ddf.EscherProperty; - -import org.apache.poi.ddf.EscherOptRecord; - -import org.apache.poi.ddf.EscherContainerRecord; - import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.ddf.EscherBlipRecord; import org.apache.poi.ddf.EscherRecord; @@ -41,8 +35,6 @@ import org.apache.poi.util.POILogger; /** * Represents embedded picture extracted from Word Document - * - * @author Dmitry Romanov */ public final class Picture { @@ -109,6 +101,7 @@ public final class Picture private PICF _picf; private PICFAndOfficeArtData _picfAndOfficeArtData; + private List _blipRecords; private byte[] content; private int dataBlockStartOfsset; @@ -116,18 +109,20 @@ public final class Picture private int height = -1; private int width = -1; - public Picture( byte[] _dataStream ) + /** + * Builds a Picture object for a Picture stored as + * Escher. + * TODO We need to pass in the PICF data too somehow! + */ + public Picture( EscherBlipRecord blipRecord ) { - super(); - - // XXX: implement - // this._dataStream = _dataStream; - // this.dataBlockStartOfsset = 0; - // this.dataBlockSize = _dataStream.length; - // this.pictureBytesStartOffset = 0; - // this.size = _dataStream.length; + this._blipRecords = Arrays.asList(new EscherBlipRecord[] {blipRecord}); } + /** + * Builds a Picture object for a Picture stored in the + * DataStream + */ public Picture( int dataBlockStartOfsset, byte[] _dataStream, boolean fillBytes ) { @@ -137,8 +132,13 @@ public final class Picture this.dataBlockStartOfsset = dataBlockStartOfsset; - if ( fillBytes ) + if ( _picfAndOfficeArtData != null && _picfAndOfficeArtData.getBlipRecords() != null) { + _blipRecords = _picfAndOfficeArtData.getBlipRecords(); + } + + if ( fillBytes ) { fillImageContent(); + } } private void fillImageContent() @@ -432,13 +432,11 @@ public final class Picture */ public byte[] getRawContent() { - if ( _picfAndOfficeArtData == null || - _picfAndOfficeArtData.getBlipRecords()== null || - _picfAndOfficeArtData.getBlipRecords().size() != 1 ) - return new byte[0]; + if (_blipRecords == null || _blipRecords.size() != 1) { + return new byte[0]; + } - EscherRecord escherRecord = _picfAndOfficeArtData.getBlipRecords().get( - 0 ); + EscherRecord escherRecord = _blipRecords.get( 0 ); if ( escherRecord instanceof EscherBlipRecord ) { return ( (EscherBlipRecord) escherRecord ).getPicturedata(); @@ -518,13 +516,11 @@ public final class Picture public PictureType suggestPictureType() { - if ( _picfAndOfficeArtData == null || - _picfAndOfficeArtData.getBlipRecords()== null || - _picfAndOfficeArtData.getBlipRecords().size() != 1 ) + if (_blipRecords == null || _blipRecords.size() != 1 ) { return PictureType.UNKNOWN; + } - EscherRecord escherRecord = _picfAndOfficeArtData.getBlipRecords().get( - 0 ); + EscherRecord escherRecord = _blipRecords.get( 0 ); switch ( escherRecord.getRecordId() ) { case (short) 0xF007: diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestPictures.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestPictures.java index 526cb5a478..a3fcd3abfb 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestPictures.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestPictures.java @@ -324,4 +324,14 @@ public final class TestPictures extends TestCase { assertEquals(0, pic2.getDyaCropBottom()); } + public void testPictureDetectionWithPNG() throws Exception { + HWPFDocument document = HWPFTestDataSamples.openSampleFile("PngPicture.doc"); + PicturesTable pictureTable = document.getPicturesTable(); + + assertEquals(1, pictureTable.getAllPictures().size()); + + Picture p = pictureTable.getAllPictures().get(0); + assertEquals(PictureType.PNG, p.suggestPictureType()); + assertEquals("png", p.suggestFileExtension()); + } } diff --git a/test-data/document/PngPicture.doc b/test-data/document/PngPicture.doc new file mode 100644 index 0000000000000000000000000000000000000000..4d8c41792c8097f9da68ca14321d26f8a90349a7 GIT binary patch literal 14336 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