View | Details | Raw Unified | Return to bug 49658
Collapse All | Expand All

(-)src/java/org/apache/poi/ddf/EscherMetafileBlip.java (-10 / +31 lines)
Lines 21-26 Link Here
21
import org.apache.poi.util.LittleEndian;
21
import org.apache.poi.util.LittleEndian;
22
import org.apache.poi.util.POILogFactory;
22
import org.apache.poi.util.POILogFactory;
23
import org.apache.poi.util.POILogger;
23
import org.apache.poi.util.POILogger;
24
import org.apache.poi.hssf.usermodel.HSSFPictureData;
24
25
25
import java.awt.Dimension;
26
import java.awt.Dimension;
26
import java.awt.Rectangle;
27
import java.awt.Rectangle;
Lines 28-33 Link Here
28
import java.io.ByteArrayOutputStream;
29
import java.io.ByteArrayOutputStream;
29
import java.io.IOException;
30
import java.io.IOException;
30
import java.util.zip.InflaterInputStream;
31
import java.util.zip.InflaterInputStream;
32
import java.util.zip.DeflaterOutputStream;
31
33
32
/**
34
/**
33
 * @author Daniel Noll
35
 * @author Daniel Noll
Lines 39-51 Link Here
39
    public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
41
    public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
40
    public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
42
    public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
41
43
42
    /**
43
     * BLIP signatures as defined in the escher spec
44
     */
45
    public static final short SIGNATURE_EMF  = 0x3D40;
46
    public static final short SIGNATURE_WMF  = 0x2160;
47
    public static final short SIGNATURE_PICT = 0x5420;
48
49
    private static final int HEADER_SIZE = 8;
44
    private static final int HEADER_SIZE = 8;
50
45
51
    private byte[] field_1_UID;
46
    private byte[] field_1_UID;
Lines 288-298 Link Here
288
     */
283
     */
289
    public short getSignature() {
284
    public short getSignature() {
290
        switch (getRecordId()) {
285
        switch (getRecordId()) {
291
            case RECORD_ID_EMF:  return SIGNATURE_EMF;
286
            case RECORD_ID_EMF:  return HSSFPictureData.MSOBI_EMF;
292
            case RECORD_ID_WMF:  return SIGNATURE_WMF;
287
            case RECORD_ID_WMF:  return HSSFPictureData.MSOBI_WMF;
293
            case RECORD_ID_PICT: return  SIGNATURE_PICT;
288
            case RECORD_ID_PICT: return HSSFPictureData.MSOBI_PICT;
294
        }
289
        }
295
        log.log(POILogger.WARN, "Unknown metafile: " + getRecordId());
290
        log.log(POILogger.WARN, "Unknown metafile: " + getRecordId());
296
        return 0;
291
        return 0;
297
    }
292
    }
293
294
    public void setPictureData(byte[] pictureData) {
295
    	super.setPictureData(pictureData);
296
        setUncompressedSize(pictureData.length);
297
298
        // info of chicago project:
299
        // "... LZ compression algorithm in the format used by GNU Zip deflate/inflate with a 32k window ..."
300
        // not sure what to do, when lookup tables exceed 32k ...
301
302
        try {
303
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
304
	        DeflaterOutputStream dos = new DeflaterOutputStream(bos);
305
	        dos.write(pictureData);
306
	        dos.close();
307
	        raw_pictureData = bos.toByteArray();
308
        } catch (IOException e) {
309
        	throw new RuntimeException("Can't compress metafile picture data", e);
310
        }
311
        
312
        setCompressedSize(raw_pictureData.length);
313
        setCompressed(true);
314
    }
315
316
    public void setFilter(byte filter) {
317
    	field_7_fFilter = filter;
318
    }
298
}
319
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (-9 / +40 lines)
Lines 34-39 Link Here
34
import org.apache.poi.ddf.EscherBSERecord;
34
import org.apache.poi.ddf.EscherBSERecord;
35
import org.apache.poi.ddf.EscherBitmapBlip;
35
import org.apache.poi.ddf.EscherBitmapBlip;
36
import org.apache.poi.ddf.EscherBlipRecord;
36
import org.apache.poi.ddf.EscherBlipRecord;
37
import org.apache.poi.ddf.EscherMetafileBlip;
37
import org.apache.poi.ddf.EscherRecord;
38
import org.apache.poi.ddf.EscherRecord;
38
import org.apache.poi.hssf.OldExcelFormatException;
39
import org.apache.poi.hssf.OldExcelFormatException;
39
import org.apache.poi.hssf.model.DrawingManager2;
40
import org.apache.poi.hssf.model.DrawingManager2;
Lines 57-62 Link Here
57
import org.apache.poi.ss.util.CellRangeAddress;
58
import org.apache.poi.ss.util.CellRangeAddress;
58
import org.apache.poi.ss.util.WorkbookUtil;
59
import org.apache.poi.ss.util.WorkbookUtil;
59
import org.apache.poi.util.Configurator;
60
import org.apache.poi.util.Configurator;
61
import org.apache.poi.util.LittleEndian;
60
import org.apache.poi.util.POILogFactory;
62
import org.apache.poi.util.POILogFactory;
61
import org.apache.poi.util.POILogger;
63
import org.apache.poi.util.POILogger;
62
64
Lines 1587-1593 Link Here
1587
        initDrawings();
1589
        initDrawings();
1588
1590
1589
        byte[] uid = DigestUtils.md5(pictureData);
1591
        byte[] uid = DigestUtils.md5(pictureData);
1590
        EscherBitmapBlip blipRecord = new EscherBitmapBlip();
1592
        EscherBlipRecord blipRecord;
1593
        int blipSize;
1594
        short escherTag;
1595
        switch (format) {
1596
            case PICTURE_TYPE_WMF:
1597
                // remove first 22 bytes if file starts with magic bytes D7-CD-C6-9A
1598
                // see also http://de.wikipedia.org/wiki/Windows_Metafile#Hinweise_zur_WMF-Spezifikation
1599
                if (LittleEndian.getInt(pictureData) == 0x9AC6CDD7) {
1600
                    byte picDataNoHeader[] = new byte[pictureData.length-22];
1601
                    System.arraycopy(pictureData, 22, picDataNoHeader, 0, pictureData.length-22);
1602
                    pictureData = picDataNoHeader;
1603
                }
1604
                // fall through
1605
            case PICTURE_TYPE_EMF:
1606
                EscherMetafileBlip blipRecordMeta = new EscherMetafileBlip();
1607
                blipRecord = blipRecordMeta;
1608
                blipRecordMeta.setUID(uid);
1609
                blipRecordMeta.setPictureData(pictureData);
1610
                // taken from libre office export, it won't open, if this is left to 0
1611
                blipRecordMeta.setFilter((byte)-2);
1612
                blipSize = blipRecordMeta.getCompressedSize() + 58;
1613
                escherTag = 0;
1614
                break;
1615
            default:
1616
                EscherBitmapBlip blipRecordBitmap = new EscherBitmapBlip();
1617
                blipRecord = blipRecordBitmap;
1618
                blipRecordBitmap.setUID( uid );
1619
                blipRecordBitmap.setMarker( (byte) 0xFF );
1620
                blipRecordBitmap.setPictureData( pictureData );
1621
                blipSize = pictureData.length + 25;
1622
                escherTag = (short) 0xFF;
1623
    	        break;
1624
        }
1625
1591
        blipRecord.setRecordId( (short) ( EscherBitmapBlip.RECORD_ID_START + format ) );
1626
        blipRecord.setRecordId( (short) ( EscherBitmapBlip.RECORD_ID_START + format ) );
1592
        switch (format)
1627
        switch (format)
1593
        {
1628
        {
Lines 1610-1620 Link Here
1610
                blipRecord.setOptions(HSSFPictureData.MSOBI_DIB);
1645
                blipRecord.setOptions(HSSFPictureData.MSOBI_DIB);
1611
                break;
1646
                break;
1612
        }
1647
        }
1613
1648
        
1614
        blipRecord.setUID( uid );
1615
        blipRecord.setMarker( (byte) 0xFF );
1616
        blipRecord.setPictureData( pictureData );
1617
1618
        EscherBSERecord r = new EscherBSERecord();
1649
        EscherBSERecord r = new EscherBSERecord();
1619
        r.setRecordId( EscherBSERecord.RECORD_ID );
1650
        r.setRecordId( EscherBSERecord.RECORD_ID );
1620
        r.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
1651
        r.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
Lines 1621-1632 Link Here
1621
        r.setBlipTypeMacOS( (byte) format );
1652
        r.setBlipTypeMacOS( (byte) format );
1622
        r.setBlipTypeWin32( (byte) format );
1653
        r.setBlipTypeWin32( (byte) format );
1623
        r.setUid( uid );
1654
        r.setUid( uid );
1624
        r.setTag( (short) 0xFF );
1655
        r.setTag( escherTag );
1625
        r.setSize( pictureData.length + 25 );
1656
        r.setSize( blipSize );
1626
        r.setRef( 0 );
1657
        r.setRef( 0 );
1627
        r.setOffset( 0 );
1658
        r.setOffset( 0 );
1628
        r.setBlipRecord( blipRecord );
1659
        r.setBlipRecord( blipRecord );
1629
1660
        
1630
        return workbook.addBSERecord( r );
1661
        return workbook.addBSERecord( r );
1631
    }
1662
    }
1632
1663
(-)src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java (-4 / +62 lines)
Lines 17-33 Link Here
17
17
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
import java.io.FileInputStream;
21
import java.io.FileOutputStream;
22
import java.io.IOException;
23
import java.util.Arrays;
24
import java.util.List;
25
26
import org.apache.poi.POIDataSamples;
20
import org.apache.poi.ddf.EscherBSERecord;
27
import org.apache.poi.ddf.EscherBSERecord;
28
import org.apache.poi.hssf.HSSFITestDataProvider;
21
import org.apache.poi.hssf.HSSFTestDataSamples;
29
import org.apache.poi.hssf.HSSFTestDataSamples;
22
import org.apache.poi.hssf.HSSFITestDataProvider;
23
import org.apache.poi.hssf.model.InternalSheet;
30
import org.apache.poi.hssf.model.InternalSheet;
24
import org.apache.poi.ss.usermodel.BaseTestPicture;
31
import org.apache.poi.ss.usermodel.BaseTestPicture;
32
import org.apache.poi.ss.usermodel.ClientAnchor;
33
import org.apache.poi.ss.usermodel.CreationHelper;
25
import org.apache.poi.ss.usermodel.PictureData;
34
import org.apache.poi.ss.usermodel.PictureData;
26
import org.apache.poi.ss.usermodel.Workbook;
35
import org.apache.poi.ss.usermodel.Workbook;
27
36
28
import java.util.Arrays;
29
import java.util.List;
30
31
/**
37
/**
32
 * Test <code>HSSFPicture</code>.
38
 * Test <code>HSSFPicture</code>.
33
 *
39
 *
Lines 210-213 Link Here
210
        p1 = (HSSFPicture) dr.getChildren().get(0);
216
        p1 = (HSSFPicture) dr.getChildren().get(0);
211
        assertEquals(p1.getFileName(), "aaa");
217
        assertEquals(p1.getFileName(), "aaa");
212
    }
218
    }
219
220
    public void test49658() throws IOException {
221
    	// test if inserted EscherMetafileBlip will be read again
222
        HSSFWorkbook wb = new HSSFWorkbook();
223
224
        byte pictureDataEmf[] = POIDataSamples.getDocumentInstance().readFile("vector_image.emf");
225
        int indexEmf = wb.addPicture(pictureDataEmf, HSSFWorkbook.PICTURE_TYPE_EMF);
226
        byte pictureDataPng[] = POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png");
227
        int indexPng = wb.addPicture(pictureDataPng, HSSFWorkbook.PICTURE_TYPE_PNG);
228
        byte pictureDataWmf[] = POIDataSamples.getSlideShowInstance().readFile("santa.wmf");
229
        int indexWmf = wb.addPicture(pictureDataWmf, HSSFWorkbook.PICTURE_TYPE_WMF);
230
231
        HSSFSheet sheet = wb.createSheet();
232
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
233
        CreationHelper ch = wb.getCreationHelper();
234
235
        ClientAnchor anchor = ch.createClientAnchor();
236
        anchor.setCol1(2);
237
        anchor.setCol2(5);
238
        anchor.setRow1(1);
239
        anchor.setRow2(6);
240
        patriarch.createPicture(anchor, indexEmf);
241
        
242
        anchor = ch.createClientAnchor();
243
        anchor.setCol1(2);
244
        anchor.setCol2(5);
245
        anchor.setRow1(10);
246
        anchor.setRow2(16);
247
        patriarch.createPicture(anchor, indexPng);
248
249
        anchor = ch.createClientAnchor();
250
        anchor.setCol1(6);
251
        anchor.setCol2(9);
252
        anchor.setRow1(1);
253
        anchor.setRow2(6);
254
        patriarch.createPicture(anchor, indexWmf);
255
        
256
        
257
        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
258
        byte pictureDataOut[] = wb.getAllPictures().get(0).getData();
259
        assertTrue(Arrays.equals(pictureDataEmf, pictureDataOut));
260
261
        byte wmfNoHeader[] = new byte[pictureDataWmf.length-22];
262
        System.arraycopy(pictureDataWmf, 22, wmfNoHeader, 0, pictureDataWmf.length-22);
263
        pictureDataOut = wb.getAllPictures().get(2).getData();
264
        assertTrue(Arrays.equals(wmfNoHeader, pictureDataOut));
265
        
266
        FileOutputStream fos = new FileOutputStream("vect.xls");
267
        wb.write(fos);
268
        fos.close();
269
    }
270
213
}
271
}

Return to bug 49658