WMF1.java

WMF1 parses .wmf files. It checks for a placeable header, reads the metafile header, and then the metarecords until it finds the EOF record (or the EOF of the file).

hex1.wmf

C:\ece538\WMF>java WMF1 hex1.wmf
metafile type  1
header size: 9
Version: 300
size: 54
number of objects 2
max record size (16-bit words) 12
unused (should be zero) 0

obj size type
  1    8  2fa
  2    4  12d
  3    7  2fc
  4    4  12c
  5    7  41b
  6   12  521
  7    3    0

 54 words including header

example1.wmf

C:\ece538\WMF>java WMF1 example1.wmf
placeable header 9ac6cdd7
handle  0
bounding box    0 6680afd
test subarray 668 1640
Inch: 576
Reserved: 0
Checksum: 59c4

metafile type  1
header size: 9
Version: 300
size: 199
number of objects 4
max record size (16-bit words) 12
unused (should be zero) 0

obj size type
  1    4  103
  2    5  20b
  3    5  20c
  4    3   1e
  5    3   1e
  6    7  416
  7    8  2fa
  8    4  12d
  9    7  2fc
 10    4  12d
 11   12  325
 12    8  2fa
 13    4  12d
 14    7  2fc
 15    4  12d
 16    4  127
 17    4  1f0
 18    8  2fa
 19    4  12d
 20    4  12d
 21    8  325
 22    4  12d
 23    4  12d
 24    4  1f0
 25    3   1e
 26    7  416
 27    8  2fa
 28    4  12d
 29    4  12d
 30   12  324
 31    4  12d
 32    4  12d
 33    4  127
 34    4  1f0
 35    4  127
 36    3    0

 199 words including header


WMF1.java

import java.io.*;
import java.util.Arrays;


public class WMF1 {

public static int get32(byte[] b) {
	int v;
	v  = (b[3]&0xff)<<24;
	v += (b[2]&0xff)<<16;
	v += (b[1]&0xff)<<8;
	v += (b[0]&0xff);
	return v;
}

public static int get16(byte[] b) {
	int v;
	v = (b[1]&0xff)<<8;
	v += (b[0]&0xff);
	return v;
}

public static void readFile(String filename) {

	try(BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename))) {
		byte[] b = new byte[64];
		byte[] c;
		int eof, count, n, type;
		int v1,v2;

		in.read(b,0,4);
		type = get32(b);
		if (type==0x9AC6CDD7) {
			// 11 words
			System.out.format("placeable header %4x\n",type);
			in.read(b,0,2);
			System.out.format("handle %2x\n",get16(b));
			in.read(b,0,4);
			v1 = get32(b);
			in.read(b,0,4);
			v2 = get32(b);
			System.out.format("bounding box %4x %4x\n",v1,v2);
			c = Arrays.copyOfRange(b,0,2);
			v1 = get16(c);
			c = Arrays.copyOfRange(b,2,4);
			v2 = get16(c);
			System.out.format("test subarray %2x %d\n",v2,v2);
			in.read(b,0,2);
			System.out.format("Inch: %d\n",get16(b));
			in.read(b,0,4);
			System.out.format("Reserved: %x\n",get32(b));
			in.read(b,0,2);
			System.out.format("Checksum: %x\n\n",get16(b));
			in.read(b,0,4);
		}

		// 9 words
		c = Arrays.copyOfRange(b,0,2);
		System.out.format("metafile type %2x\n",get16(c));
		c = Arrays.copyOfRange(b,2,4);
		System.out.format("header size: %d\n",get16(c));
		in.read(b,0,2);
		System.out.format("Version: %x\n",get16(b));
		in.read(b,0,4);
		System.out.format("size: %d\n",get32(b));
		in.read(b,0,2);
		System.out.format("number of objects %d\n",get16(b));
		in.read(b,0,4);
		System.out.format("max record size (16-bit words) %d\n",get32(b));
		in.read(b,0,2);
		System.out.format("unused (should be zero) %x\n",get16(b));


		count = 0;

		System.out.println("\nobj size type");
		for (int obj=1; obj<1024; obj++) {

			eof = in.read(b,0,4);
			if (eof<0) break;
			n = get32(b);
			count = count + n;
			in.read(b,0,2);
			type = get16(b);
			if (n>3) in.read(b,0,2*(n-3));
			System.out.format("%3d %4d %4x\n",obj,n,type);
		}
		System.out.format("\n %d words including header\n",count+9);


		// META_SAVEDC = 0x001E
		// 12d - META_SELECTOBJECT
		// 324 - META_POLYGON+
		// 325 - META_POLYLINE
		// META_INTERSECTCLIPRECT = 0x0416
 		// META_DELETEOBJECT = 0x01f0
		//  META_CREATEPENINDIRECT = 0x02FA
		//  META_CREATEBRUSHINDIRECT = 0x02FC, 

		in.close();

	}
	catch(Exception e) {
		System.err.println(e);
	}
}


public static void main(String [] args) {
	String filename = "example1.wmf";
	if (args.length>0) filename = args[0];

	readFile(filename);
}

}


Maintained by John Loomis, updated Sat Mar 25 20:57:42 2017