What Is a .WMF File?
Windows metafile
📂Image
🏷️.wmf
🎯image/wmf
WMF (Windows Metafile) Format
Overview
Windows Metafile (WMF) is a graphics file format developed by Microsoft for storing vector and bitmap graphics. WMF files contain drawing commands that can be replayed to recreate images, making them resolution-independent and scalable.
Technical Specifications
- Format Type: Vector graphics metafile
- File Extension:
.wmf - MIME Type:
image/wmf - Bit Depth: Supports various color depths
- Compression: None (stores drawing commands)
- Maximum Size: 64KB due to 16-bit addressing
- Coordinate System: Device-dependent or device-independent
Format Structure
WMF files consist of:
- Header with metadata and file information
- Series of metafile records (drawing commands)
- Placeable WMF header (optional, for positioning)
- Graphics Device Interface (GDI) function calls
- End-of-file record
History and Development
- 1988: Introduction with Windows 2.0
- 1990: Enhanced in Windows 3.0
- 1995: Succeeded by Enhanced Metafile (EMF) format
- 1998: Security concerns led to restricted usage
- 2000s: Largely replaced by newer formats but still supported
WMF Record Types
- Drawing commands: Lines, curves, shapes, text
- Attribute changes: Colors, fonts, line styles
- State management: Save/restore graphics state
- Bitmap operations: Raster image embedding
- Clipping: Define drawing boundaries
Use Cases
- Legacy document formats
- Vector graphics exchange
- Clipboard operations in Windows
- Scientific and technical drawings
- CAD file interchange
- Print spooling operations
Code Examples
C# WMF Reading and Processing
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
class WmfProcessor
{
public static void ConvertWmfToPng(string wmfPath, string pngPath)
{
using (var metafile = new Metafile(wmfPath))
{
// Get metafile bounds
var bounds = metafile.GetBounds(ref GraphicsUnit.Pixel);
// Create bitmap to render metafile
using (var bitmap = new Bitmap((int)bounds.Width, (int)bounds.Height))
{
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.White);
graphics.DrawImage(metafile, Point.Empty);
}
bitmap.Save(pngPath, ImageFormat.Png);
}
}
}
public static void CreateWmfFromDrawing(string outputPath)
{
using (var bitmap = new Bitmap(400, 300))
{
using (var graphics = Graphics.FromImage(bitmap))
{
// Create metafile from graphics context
IntPtr hdc = graphics.GetHdc();
var bounds = new Rectangle(0, 0, 400, 300);
using (var metafile = new Metafile(outputPath, hdc, bounds, MetafileFrameUnit.Pixel))
{
using (var metaGraphics = Graphics.FromImage(metafile))
{
// Draw shapes that will be recorded as WMF commands
metaGraphics.DrawRectangle(Pens.Black, 10, 10, 100, 80);
metaGraphics.FillEllipse(Brushes.Red, 150, 20, 60, 60);
metaGraphics.DrawString("Hello WMF",
new Font("Arial", 16), Brushes.Blue, 50, 150);
}
}
graphics.ReleaseHdc(hdc);
}
}
}
public static void AnalyzeWmfMetadata(string wmfPath)
{
using (var metafile = new Metafile(wmfPath))
{
var header = metafile.GetMetafileHeader();
Console.WriteLine($"Type: {header.Type}");
Console.WriteLine($"Size: {header.Size} bytes");
Console.WriteLine($"Version: {header.Version:X}");
Console.WriteLine($"DPI X: {header.DpiX}");
Console.WriteLine($"DPI Y: {header.DpiY}");
Console.WriteLine($"Bounds: {header.Bounds}");
Console.WriteLine($"Empty: {header.IsEmpty()}");
Console.WriteLine($"Display: {header.IsDisplay()}");
}
}
}
Python WMF Processing with Pillow
from PIL import Image, ImageDraw, ImageFont
import struct
class WmfProcessor:
def __init__(self):
self.records = []
def read_wmf_header(self, filename):
"""Read WMF file header information."""
with open(filename, 'rb') as f:
# Check for Placeable WMF header
magic = struct.unpack('<I', f.read(4))[0]
if magic == 0x9AC6CDD7: # Placeable WMF
# Read placeable header
hmf = struct.unpack('<H', f.read(2))[0]
left, top, right, bottom = struct.unpack('<4h', f.read(8))
inch = struct.unpack('<H', f.read(2))[0]
reserved = struct.unpack('<I', f.read(4))[0]
checksum = struct.unpack('<H', f.read(2))[0]
return {
'type': 'Placeable WMF',
'bounds': (left, top, right, bottom),
'dpi': inch,
'checksum': checksum
}
else:
# Standard WMF header
f.seek(0)
file_type = struct.unpack('<H', f.read(2))[0]
header_size = struct.unpack('<H', f.read(2))[0]
version = struct.unpack('<H', f.read(2))[0]
file_size = struct.unpack('<I', f.read(4))[0]
return {
'type': 'Standard WMF',
'header_size': header_size,
'version': f'0x{version:04X}',
'file_size': file_size
}
def convert_wmf_to_image(self, wmf_path, output_path, size=(400, 300)):
"""Convert WMF to raster image using approximation."""
try:
# Try to open with Pillow (limited WMF support)
with Image.open(wmf_path) as img:
img = img.resize(size, Image.Resampling.LANCZOS)
img.save(output_path)
return True
except Exception as e:
print(f"Error converting WMF: {e}")
return False
def create_sample_wmf_like(self, output_path, size=(400, 300)):
"""Create a sample image that mimics WMF content."""
img = Image.new('RGB', size, 'white')
draw = ImageDraw.Draw(img)
# Draw various shapes (simulating WMF commands)
draw.rectangle([10, 10, 110, 90], outline='black', width=2)
draw.ellipse([150, 20, 210, 80], fill='red')
draw.line([250, 30, 350, 70], fill='blue', width=3)
draw.polygon([(50, 150), (100, 120), (150, 150), (125, 200)],
fill='green', outline='darkgreen')
# Add text
try:
font = ImageFont.truetype("arial.ttf", 16)
except:
font = ImageFont.load_default()
draw.text((50, 220), "WMF Sample", fill='black', font=font)
img.save(output_path)
# Usage example
processor = WmfProcessor()
header_info = processor.read_wmf_header('sample.wmf')
print("WMF Header:", header_info)
processor.convert_wmf_to_image('input.wmf', 'output.png')
processor.create_sample_wmf_like('sample.png')
JavaScript WMF Header Parser
class WmfParser {
constructor(buffer) {
this.buffer = buffer;
this.view = new DataView(buffer);
this.offset = 0;
}
readUint16() {
const value = this.view.getUint16(this.offset, true); // little endian
this.offset += 2;
return value;
}
readUint32() {
const value = this.view.getUint32(this.offset, true);
this.offset += 4;
return value;
}
readInt16() {
const value = this.view.getInt16(this.offset, true);
this.offset += 2;
return value;
}
parseHeader() {
this.offset = 0;
// Check for Placeable WMF magic number
const magic = this.readUint32();
if (magic === 0x9AC6CDD7) {
return this.parsePlaceableHeader();
} else {
this.offset = 0;
return this.parseStandardHeader();
}
}
parsePlaceableHeader() {
const hmf = this.readUint16();
const left = this.readInt16();
const top = this.readInt16();
const right = this.readInt16();
const bottom = this.readInt16();
const inch = this.readUint16();
const reserved = this.readUint32();
const checksum = this.readUint16();
return {
type: 'Placeable WMF',
handle: hmf,
bounds: { left, top, right, bottom },
unitsPerInch: inch,
checksum: checksum,
width: right - left,
height: bottom - top
};
}
parseStandardHeader() {
const fileType = this.readUint16();
const headerSize = this.readUint16();
const version = this.readUint16();
const fileSize = this.readUint32();
const numObjects = this.readUint16();
const maxRecord = this.readUint32();
const numMembers = this.readUint16();
return {
type: 'Standard WMF',
fileType: fileType,
headerSize: headerSize,
version: `0x${version.toString(16).toUpperCase()}`,
fileSize: fileSize,
numObjects: numObjects,
maxRecordSize: maxRecord,
numMembers: numMembers
};
}
}
// Usage example
async function analyzeWmfFile(file) {
const buffer = await file.arrayBuffer();
const parser = new WmfParser(buffer);
const header = parser.parseHeader();
console.log('WMF Header Information:');
console.table(header);
return header;
}
// HTML file input handler
document.getElementById('wmfInput').addEventListener('change', (event) => {
const file = event.target.files[0];
if (file && file.name.toLowerCase().endsWith('.wmf')) {
analyzeWmfFile(file);
}
});
Security Considerations
- Historical vulnerabilities: WMF format has had security issues
- Parsing risks: Malformed files can cause crashes or exploits
- Limited support: Many modern applications don't support WMF
- Code execution: WMF files can contain executable code
- Validation required: Always validate WMF files from untrusted sources
Conversion and Migration
Converting WMF to Modern Formats
# Using ImageMagick (if WMF support is available)
convert input.wmf output.svg
convert input.wmf output.png
# Using Inkscape
inkscape --file=input.wmf --export-plain-svg=output.svg
inkscape --file=input.wmf --export-png=output.png --export-dpi=300
# Using LibreOffice command line
libreoffice --headless --convert-to svg input.wmf
libreoffice --headless --convert-to pdf input.wmf
Batch Conversion Script
# PowerShell script for batch WMF conversion
$wmfFiles = Get-ChildItem -Path "C:\WMF_Files" -Filter "*.wmf"
foreach ($file in $wmfFiles) {
$outputPath = $file.FullName -replace '\.wmf$', '.png'
try {
# Using .NET System.Drawing
$metafile = [System.Drawing.Imaging.Metafile]::FromFile($file.FullName)
$bitmap = New-Object System.Drawing.Bitmap(800, 600)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.DrawImage($metafile, [System.Drawing.Point]::Empty)
$bitmap.Save($outputPath, [System.Drawing.Imaging.ImageFormat]::Png)
$graphics.Dispose()
$bitmap.Dispose()
$metafile.Dispose()
Write-Host "Converted: $($file.Name) -> $([System.IO.Path]::GetFileName($outputPath))"
}
catch {
Write-Error "Failed to convert $($file.Name): $($_.Exception.Message)"
}
}
Best Practices
- Avoid using WMF for new projects
- Convert legacy WMF files to modern formats (SVG, PNG, PDF)
- Implement proper security validation for WMF files
- Use EMF format instead of WMF when possible
- Test WMF rendering across different applications
- Maintain backup copies during format migration
Modern Alternatives
- SVG: Scalable Vector Graphics (web standard)
- EMF: Enhanced Metafile (improved WMF successor)
- PDF: Portable Document Format
- EPS: Encapsulated PostScript
- PNG/JPEG: For raster conversion
- WebP: Modern image format with vector support
Troubleshooting Common Issues
- Rendering problems: Use compatible viewers or converters
- Size limitations: WMF limited to 64KB, use EMF for larger files
- Color issues: Check color palette and bit depth settings
- Font problems: Ensure fonts are available on target system
- Scaling artifacts: Convert to vector formats for better scaling
File Information
File Description
Windows metafile
Category
Image
Extensions
.wmf
MIME Type
image/wmf
Related File Types
Other file types in the Image category you might also need:
Start Analyzing WMF Files Now
Use our free AI-powered tool to detect and analyze Windows metafile files instantly with Google's Magika technology.
⚡Try File Detection Tool