aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Beeker <kiwiwings@apache.org>2015-12-31 20:23:20 +0000
committerAndreas Beeker <kiwiwings@apache.org>2015-12-31 20:23:20 +0000
commited27fea0e682e2bc302fd6d0bdbb2754f7ac3eb7 (patch)
tree3acf405f316db2511d1a9a7a193103906f163608 /src
parent38017a61de81ab74c8717b024b3788ed0a305d2b (diff)
downloadpoi-ed27fea0e682e2bc302fd6d0bdbb2754f7ac3eb7.tar.gz
poi-ed27fea0e682e2bc302fd6d0bdbb2754f7ac3eb7.zip
WMF fixes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722465 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java29
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java73
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java6
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java7
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java38
-rw-r--r--src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java8
-rw-r--r--src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java98
7 files changed, 129 insertions, 130 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java
index c0293b4336..2ff0d118a8 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java
@@ -76,33 +76,8 @@ public class HwmfBitmap16 {
byte buf[] = new byte[bytes];
leis.read(buf);
-// FileOutputStream fos = new FileOutputStream("bla16.bmp");
-// fos.write(buf);
-// fos.close();
-
-
-// BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
-//
-// int size2 = 0;
-// byte buf[] = new byte[widthBytes];
-// for (int h=0; h<height; h++) {
-// leis.read(buf);
-// size2 += widthBytes;
-//
-// ImageInputStream iis = new MemoryCacheImageInputStream(new ByteArrayInputStream(buf));
-//
-// for (int w=0; w<width; w++) {
-// long bitsAtPixel = iis.readBits(bitsPixel);
-// // TODO: is bitsPixel a multiple of 3 (r,g,b)
-// // which colortable should be used for the various bit sizes???
-//
-// }
-// }
-//
-// assert (bytes == size2);
-//
-// size += size2;
-
+ // TODO: this is not implemented ... please provide a sample, if it
+ // ever happens to you, to come here ...
return size;
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
index 12f9b30a9f..0f720239f3 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
@@ -22,6 +22,7 @@ import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -207,7 +208,7 @@ public class HwmfBitmapDib {
@SuppressWarnings("unused")
private Color colorTable[];
@SuppressWarnings("unused")
- private int colorMaskRed=0,colorMaskGreen=0,colorMaskBlue=0;
+ private int colorMaskR=0,colorMaskG=0,colorMaskB=0;
// size of header and color table, for start of image data calculation
private int introSize;
@@ -222,7 +223,7 @@ public class HwmfBitmapDib {
introSize += readColors(leis);
assert(introSize < 10000);
- int fileSize = (headerImageSize != 0) ? (int)(introSize+headerImageSize) : recordSize;
+ int fileSize = (headerImageSize < headerSize) ? recordSize : (int)Math.min(introSize+headerImageSize,recordSize);
imageData = new byte[fileSize];
leis.reset();
@@ -316,41 +317,43 @@ public class HwmfBitmapDib {
return 0;
case BI_BITCOUNT_1:
// 2 colors
- return readRGBQuad(leis, 2);
+ return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 2 : Math.min(headerColorUsed,2)));
case BI_BITCOUNT_2:
// 16 colors
- return readRGBQuad(leis, 16);
+ return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 16 : Math.min(headerColorUsed,16)));
case BI_BITCOUNT_3:
// 256 colors
- return readRGBQuad(leis, (int)headerColorUsed);
- case BI_BITCOUNT_5:
- colorMaskRed=0xFF;
- colorMaskGreen=0xFF;
- colorMaskBlue=0xFF;
- return 0;
+ return readRGBQuad(leis, (int)(headerColorUsed == 0 ? 256 : Math.min(headerColorUsed,256)));
case BI_BITCOUNT_4:
- if (headerCompression == Compression.BI_RGB) {
- colorMaskBlue = 0x1F;
- colorMaskGreen = 0x1F<<5;
- colorMaskRed = 0x1F<<10;
+ switch (headerCompression) {
+ case BI_RGB:
+ colorMaskB = 0x1F;
+ colorMaskG = 0x1F<<5;
+ colorMaskR = 0x1F<<10;
return 0;
- } else {
- assert(headerCompression == Compression.BI_BITFIELDS);
- colorMaskBlue = leis.readInt();
- colorMaskGreen = leis.readInt();
- colorMaskRed = leis.readInt();
+ case BI_BITFIELDS:
+ colorMaskB = leis.readInt();
+ colorMaskG = leis.readInt();
+ colorMaskR = leis.readInt();
return 3*LittleEndianConsts.INT_SIZE;
+ default:
+ throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+").");
}
+ case BI_BITCOUNT_5:
case BI_BITCOUNT_6:
- if (headerCompression == Compression.BI_RGB) {
- colorMaskBlue = colorMaskGreen = colorMaskRed = 0xFF;
+ switch (headerCompression) {
+ case BI_RGB:
+ colorMaskR=0xFF;
+ colorMaskG=0xFF;
+ colorMaskB=0xFF;
return 0;
- } else {
- assert(headerCompression == Compression.BI_BITFIELDS);
- colorMaskBlue = leis.readInt();
- colorMaskGreen = leis.readInt();
- colorMaskRed = leis.readInt();
+ case BI_BITFIELDS:
+ colorMaskB = leis.readInt();
+ colorMaskG = leis.readInt();
+ colorMaskR = leis.readInt();
return 3*LittleEndianConsts.INT_SIZE;
+ default:
+ throw new IOException("Invalid compression option ("+headerCompression+") for bitcount ("+headerBitCount+").");
}
}
}
@@ -372,30 +375,36 @@ public class HwmfBitmapDib {
return size;
}
- public BufferedImage getImage() {
+ public InputStream getBMPStream() {
if (imageData == null) {
throw new RecordFormatException("bitmap not initialized ... need to call init() before");
}
+ // sometimes there are missing bytes after the imageData which will be 0-filled
+ int imageSize = (int)Math.max(imageData.length, introSize+headerImageSize);
+
// create the image data and leave the parsing to the ImageIO api
- byte buf[] = new byte[BMP_HEADER_SIZE+imageData.length];
+ byte buf[] = new byte[BMP_HEADER_SIZE+imageSize];
// https://en.wikipedia.org/wiki/BMP_file_format # Bitmap file header
buf[0] = (byte)'B';
buf[1] = (byte)'M';
// the full size of the bmp
- LittleEndian.putInt(buf, 2, (int)(BMP_HEADER_SIZE + introSize + headerImageSize));
+ LittleEndian.putInt(buf, 2, BMP_HEADER_SIZE+imageSize);
// the next 4 bytes are unused
LittleEndian.putInt(buf, 6, 0);
// start of image = BMP header length + dib header length + color tables length
LittleEndian.putInt(buf, 10, BMP_HEADER_SIZE + introSize);
-
+ // fill the "known" image data
System.arraycopy(imageData, 0, buf, BMP_HEADER_SIZE, imageData.length);
+ return new ByteArrayInputStream(buf);
+ }
+
+ public BufferedImage getImage() {
try {
- return ImageIO.read(new ByteArrayInputStream(buf));
+ return ImageIO.read(getBMPStream());
} catch (IOException e) {
- // ... shouldn't happen
throw new RecordFormatException("invalid bitmap data", e);
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java
index ee38c7b94e..4b01deb07d 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java
@@ -614,7 +614,7 @@ public class HwmfFill {
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
- boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));
+ boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3));
int size = 0;
int rasterOpCode = leis.readUShort();
@@ -802,7 +802,7 @@ public class HwmfFill {
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
- boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));
+ boolean hasBitmap = (recordSize/2 != ((recordFunction >> 8) + 3));
int size = 0;
int rasterOpCode = leis.readUShort();
@@ -840,7 +840,7 @@ public class HwmfFill {
@Override
public BufferedImage getImage() {
- return target.getImage();
+ return (target == null) ? null : target.getImage();
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java
index 6d332607f3..5e6dde83a6 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java
@@ -259,6 +259,9 @@ public class HwmfText {
@Override
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+ // -6 bytes of record function and length header
+ final int remainingRecordSize = (int)(recordSize-6);
+
y = leis.readShort();
x = leis.readShort();
stringLength = leis.readShort();
@@ -266,7 +269,7 @@ public class HwmfText {
int size = 4*LittleEndianConsts.SHORT_SIZE;
- if (fwOpts != 0) {
+ if (fwOpts != 0 && size+8<=remainingRecordSize) {
// the bounding rectangle is optional and only read when fwOpts are given
left = leis.readShort();
top = leis.readShort();
@@ -280,8 +283,6 @@ public class HwmfText {
text = new String(buf, 0, stringLength, LocaleUtil.CHARSET_1252);
size += buf.length;
- // -6 bytes of record function and length header
- int remainingRecordSize = (int)(recordSize-6);
if (size < remainingRecordSize) {
if (size + stringLength*LittleEndianConsts.SHORT_SIZE < remainingRecordSize) {
throw new RecordFormatException("can't read Dx array - given recordSize doesn't contain enough values for string length "+stringLength);
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java
index 1cb19e005f..a6d7204583 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java
@@ -542,14 +542,17 @@ public class HwmfWindowing {
count = leis.readUShort();
top = leis.readUShort();
bottom = leis.readUShort();
- left_scanline = new int[count];
- right_scanline = new int[count];
- for (int i=0; i*2<count; i++) {
+ int size = 3*LittleEndianConsts.SHORT_SIZE;
+ left_scanline = new int[count/2];
+ right_scanline = new int[count/2];
+ for (int i=0; i<count/2; i++) {
left_scanline[i] = leis.readUShort();
right_scanline[i] = leis.readUShort();
+ size += 2*LittleEndianConsts.SHORT_SIZE;
}
count2 = leis.readUShort();
- return 8 + count*4;
+ size += LittleEndianConsts.SHORT_SIZE;
+ return size;
}
}
@@ -618,26 +621,23 @@ public class HwmfWindowing {
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
nextInChain = leis.readShort();
objectType = leis.readShort();
- objectCount = leis.readUShort();
+ objectCount = leis.readInt();
regionSize = leis.readShort();
scanCount = leis.readShort();
maxScan = leis.readShort();
- bottom = leis.readShort();
- right = leis.readShort();
- top = leis.readShort();
left = leis.readShort();
+ top = leis.readShort();
+ right = leis.readShort();
+ bottom = leis.readShort();
+
+ int size = 9*LittleEndianConsts.SHORT_SIZE+LittleEndianConsts.INT_SIZE;
+
+ scanObjects = new WmfScanObject[scanCount];
+ for (int i=0; i<scanCount; i++) {
+ size += (scanObjects[i] = new WmfScanObject()).init(leis);
+ }
- List<WmfScanObject> soList = new ArrayList<WmfScanObject>();
- int scanCountI = 0, size = 0;
- do {
- WmfScanObject so = new WmfScanObject();
- size += so.init(leis);
- scanCountI += so.count;
- soList.add(so);
- } while (scanCountI < scanCount);
- scanObjects = soList.toArray(new WmfScanObject[soList.size()]);
-
- return 20 + size;
+ return size;
}
@Override
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java
index 3ebd23bf30..3bea50eaf6 100644
--- a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java
+++ b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java
@@ -70,12 +70,8 @@ public class HwmfPicture {
int remainingSize = (int)(recordSize - consumedSize);
assert(remainingSize >= 0);
if (remainingSize > 0) {
-// byte remaining[] = new byte[remainingSize];
-// leis.read(remaining);
-// FileOutputStream fos = new FileOutputStream("remaining.dat");
-// fos.write(remaining);
-// fos.close();
- leis.skip(remainingSize);
+ // skip size in loops, because not always all bytes are skipped in one call
+ for (int i=remainingSize; i>0; i-=leis.skip(i));
}
}
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java
index a1f2cbf1d0..ad585eccbd 100644
--- a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java
+++ b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java
@@ -20,14 +20,17 @@ package org.apache.poi.hwmf;
import static org.junit.Assert.assertEquals;
import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FilterInputStream;
import java.io.IOException;
+import java.net.URL;
import java.util.List;
import java.util.Locale;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
import javax.imageio.ImageIO;
@@ -55,55 +58,70 @@ public class TestHwmfParsing {
@Test
@Ignore
- public void extract() throws IOException {
- File dir = new File("test-data/slideshow");
- File files[] = dir.listFiles(new FileFilter() {
- public boolean accept(File pathname) {
- return pathname.getName().matches("(?i).*\\.pptx?$");
- }
- });
-
- boolean outputFiles = false;
-
+ public void fetchWmfFromGovdocs() throws IOException {
+ URL url = new URL("http://digitalcorpora.org/corpora/files/govdocs1/by_type/ppt.zip");
File outdir = new File("build/ppt");
- if (outputFiles) {
- outdir.mkdirs();
- }
- int wmfIdx = 1;
- for (File f : files) {
+ outdir.mkdirs();
+ ZipInputStream zis = new ZipInputStream(url.openStream());
+ ZipEntry ze;
+ while ((ze = zis.getNextEntry()) != null) {
+ String basename = ze.getName().replaceAll(".*?([^/]+)\\.wmf", "$1");
+ FilterInputStream fis = new FilterInputStream(zis){
+ public void close() throws IOException {}
+ };
try {
- SlideShow<?,?> ss = SlideShowFactory.create(f);
+ SlideShow<?,?> ss = SlideShowFactory.create(fis);
+ int wmfIdx = 1;
for (PictureData pd : ss.getPictureData()) {
if (pd.getType() != PictureType.WMF) continue;
byte wmfData[] = pd.getData();
- if (outputFiles) {
- String filename = String.format(Locale.ROOT, "pic%04d.wmf", wmfIdx);
- FileOutputStream fos = new FileOutputStream(new File(outdir, filename));
- fos.write(wmfData);
- fos.close();
- }
-
- HwmfPicture wmf = new HwmfPicture(new ByteArrayInputStream(wmfData));
-
- int bmpIndex = 1;
- for (HwmfRecord r : wmf.getRecords()) {
- if (r instanceof HwmfImageRecord) {
- BufferedImage bi = ((HwmfImageRecord)r).getImage();
- if (outputFiles) {
- String filename = String.format(Locale.ROOT, "pic%04d-%04d.png", wmfIdx, bmpIndex);
- ImageIO.write(bi, "PNG", new File(outdir, filename));
- }
- bmpIndex++;
- }
- }
-
+ String filename = String.format(Locale.ROOT, "%s-%04d.wmf", basename, wmfIdx);
+ FileOutputStream fos = new FileOutputStream(new File(outdir, filename));
+ fos.write(wmfData);
+ fos.close();
wmfIdx++;
}
ss.close();
} catch (Exception e) {
- System.out.println(f+" ignored.");
+ System.out.println(ze.getName()+" ignored.");
+ }
+ }
+ }
+
+ @Test
+ @Ignore
+ public void parseWmfs() throws IOException {
+ boolean outputFiles = false;
+ File indir = new File("build/ppt"), outdir = indir;
+ final String startFile = "";
+ File files[] = indir.listFiles(new FileFilter() {
+ boolean foundStartFile = false;
+ public boolean accept(File pathname) {
+ foundStartFile |= startFile.isEmpty() || pathname.getName().contains(startFile);
+ return foundStartFile && pathname.getName().matches("(?i).*\\.wmf?$");
+ }
+ });
+ for (File f : files) {
+ try {
+ String basename = f.getName().replaceAll(".*?([^/]+)\\.wmf", "$1");
+ FileInputStream fis = new FileInputStream(f);
+ HwmfPicture wmf = new HwmfPicture(fis);
+ fis.close();
+
+ int bmpIndex = 1;
+ for (HwmfRecord r : wmf.getRecords()) {
+ if (r instanceof HwmfImageRecord) {
+ BufferedImage bi = ((HwmfImageRecord)r).getImage();
+ if (bi != null && outputFiles) {
+ String filename = String.format(Locale.ROOT, "%s-%04d.png", basename, bmpIndex);
+ ImageIO.write(bi, "PNG", new File(outdir, filename));
+ }
+ bmpIndex++;
+ }
+ }
+ } catch (Exception e) {
+ System.out.println(f.getName()+" ignored.");
}
}
}
-
}