Word documents often contain images that are useful outside the original file, such as screenshots in technical guides, diagrams in project reports, or product photos in documentation. If you only need one or two images, saving them manually in Microsoft Word is straightforward. But extracting dozens of images from a large document can quickly become tedious.
With Java, you can automate this process by reading a Word document, locating its embedded images, and saving them to a folder. This approach eliminates repetitive manual work and can be integrated into document processing applications.
In this tutorial, we'll explore how to extract images from Word documents in Java, including images embedded in paragraphs and tables, while preserving their image data without unnecessary format conversion.
Prerequisites: Set Up the Java Project
To work with Word documents programmatically, you'll need a library that can read their content and access embedded images.
If you're using Maven, add the following repository and dependency to your pom.xml file:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>14.10.6</version>
</dependency>
</dependencies>
Extract All Images from a Word Document in Java
A Word document can contain images in different locations, including regular paragraphs, tables, headers, and footers. To find these images, we can traverse the document's object hierarchy instead of examining only its paragraphs.
The extraction process involves four main steps:
- Load the Word document and create an output folder.
- Traverse the document's child objects to locate embedded pictures.
- Retrieve the image bytes and identify each image's format.
- Save the extracted images to individual files.
Rather than converting every picture to PNG or JPEG, we'll save the image bytes directly and use the appropriate file extension. This avoids additional image encoding and preserves the data returned by the document API.
Complete Java Code
The following example extracts images from an existing Word document and saves them to an output/images folder.
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.*;
import com.spire.doc.interfaces.*;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class ExtractImagesFromWord {
public static void main(String[] args) throws IOException {
// Load the Word document
Document document = new Document();
document.loadFromFile("input.docx");
// Create the output directory
Path outputDir = Paths.get("output/images");
Files.createDirectories(outputDir);
// Create a queue for traversing document objects
Queue<ICompositeObject> queue = new LinkedList<>();
queue.add(document);
int imageIndex = 1;
// Traverse the document object hierarchy
while (!queue.isEmpty()) {
ICompositeObject parent = queue.poll();
for (int i = 0; i < parent.getChildObjects().getCount(); i++) {
IDocumentObject child = parent.getChildObjects().get(i);
// Check whether the current object is a picture
if (child.getDocumentObjectType() == DocumentObjectType.Picture) {
DocPicture picture = (DocPicture) child;
// Get the image data
byte[] imageBytes = picture.getImageBytes();
// Identify the image format
String extension = getImageExtension(imageBytes);
// Generate the output filename
String fileName = "image_" + imageIndex + "." + extension;
// Save the image without re-encoding
Files.write(outputDir.resolve(fileName), imageBytes);
imageIndex++;
} else if (child instanceof ICompositeObject) {
// Continue traversing nested objects
queue.add((ICompositeObject) child);
}
}
}
// Release document resources
document.dispose();
System.out.println("Extraction complete. "
+ (imageIndex - 1) + " images saved.");
}
// Identify the image format from its byte data
private static String getImageExtension(byte[] bytes) throws IOException {
try (ImageInputStream stream = ImageIO.createImageInputStream(
new ByteArrayInputStream(bytes))) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
String format = reader.getFormatName()
.toLowerCase(Locale.ROOT);
// Normalize common file extensions
switch (format) {
case "jpeg":
return "jpg";
case "tiff":
return "tif";
default:
return format;
}
} finally {
reader.dispose();
}
}
}
// Use .bin if the format cannot be identified
return "bin";
}
}
How the Code Works
1. Load the Word document
The Document class opens the source file using loadFromFile(). The example uses input.docx, but the same approach also works with legacy .doc files.
2. Traverse the document objects
The program uses a Queue<ICompositeObject> to walk through the document hierarchy.
For each object, it checks whether the object is a picture. If the object contains nested child objects, it is added to the queue for further processing.
This allows the program to locate standard embedded pictures inside tables and other nested document structures, not just those in ordinary paragraphs.
3. Retrieve the embedded image data
When a picture is found, it is accessed through the DocPicture class:
DocPicture picture = (DocPicture) child;
byte[] imageBytes = picture.getImageBytes();
The getImageBytes() method retrieves the image's byte data, which can then be written directly to a file.
4. Identify the image format and save the file
The helper method getImageExtension() uses Java's built-in ImageIO API to recognize common image formats.
Once the extension is identified, Files.write() saves the bytes to the output directory:
Files.write(outputDir.resolve(fileName), imageBytes);
The images are named sequentially, such as image_1.png and image_2.jpg, so each extracted picture receives a distinct filename during the run.
Output Example
Suppose the Word document contains four embedded images in different formats.
After running the program, the output directory might look like this:
output/
└── images/
├── image_1.png
├── image_2.jpg
├── image_3.png
└── image_4.gif
The console displays:
Extraction complete. 4 images saved.
The images are saved separately and can be opened, organized, or processed by other applications.
Which Image Formats Can Be Extracted?
The example supports several common image formats through Java's ImageIO API.
| Image Format | Output Extension |
|---|---|
| JPEG | .jpg |
| PNG | .png |
| GIF | .gif |
| BMP | .bmp |
| TIFF | .tif |
Notice that the code includes only two explicit format checks:
switch (format) {
case "jpeg":
return "jpg";
case "tiff":
return "tif";
default:
return format;
}
These checks simply normalize the extensions for JPEG and TIFF images. Other recognized formats, such as PNG, GIF, and BMP, are handled by the default branch.
This means that an embedded PNG image is saved as a PNG file rather than being converted to another format.
A note about TIFF and less common formats: Standard TIFF support is available in Java 9 and later. On older Java versions, or when processing formats such as EMF and WMF, the default image readers may not recognize the data.
In those cases, the example saves the bytes with a .bin extension rather than incorrectly labeling the file as JPEG or PNG.
Common Questions
Can I Extract Images from Both DOC and DOCX Files?
Yes. The example works with both .doc and .docx documents.
To process a legacy Word file, simply change the input path:
document.loadFromFile("input.doc");
The remaining extraction logic stays the same.
Does Extracting Images Reduce Their Quality?
The example does not resize, compress, or re-encode the image data.
Instead, it retrieves the bytes exposed by the Word document API and writes them directly to disk. This avoids quality loss caused by additional image conversion.
However, the extracted image's resolution and quality still depend on the image data stored in the source document.
Why Are Some Shapes or Graphics Not Extracted?
Not everything that looks like an image in Word is stored as a picture object.
For example, charts, SmartArt diagrams, text boxes, and certain drawing shapes may use different document object types.
The example focuses on DocPicture objects. Extracting other graphical elements may require separate handling, depending on how they are stored in the document.
Conclusion
Extracting images from Word documents in Java is a practical way to automate repetitive tasks, especially when working with reports, manuals, or documentation containing many pictures.
By traversing the document hierarchy, retrieving embedded image data, and saving each picture to a separate file, you can collect images without manually opening and editing the Word document. The approach also avoids unnecessary format conversion, making it useful for document archiving, content management, and other automated workflows.
Top comments (0)