Extract Images from PDF Showcase Demo Code Sample

Easily add PDF image extraction capability to the viewer. Download each image separately or all images in a compressed ZIP file.

This demo allows you to:

  • Load a PDF with annotations and images
  • Edit the PDF
  • Extract the images contained in the file

Implementation steps
To add image extraction capability to WebViewer:

Step 1: Choose your preferred web stack
Step 2: Download any required modules listed in the Demo Dependencies section below
Step 3: Add the ES6 JavaScript sample code provided in this guide

Demo Dependencies

This sample uses the following:

Want to see a live version of this demo?

Try the Extract Images from PDF demo

1// ES6 Compliant Syntax
2// GitHub Copilot v1.0 - GPT-4o model - July 24, 2025
3// File: index.js
4
5import WebViewer from '@pdftron/webviewer';
6import JSZip from 'jszip';
7import saveAs from 'file-saver';
8
9// extracted images array
10let extractedImages = [];
11
12// Customize the WebViewer UI
13const customizeUI = (instance) => {
14 const { UI } = instance;
15
16 // Set the toolbar group to the annotate tools
17 UI.setToolbarGroup('toolbarGroup-Annotate');
18
19 // Extract images button
20 const extractImagesButton = new UI.Components.CustomButton({
21 dataElement: 'extractImagesButton',
22 className: 'custom-button-class',
23 label: 'Extract Images',
24 onClick: () => extractImages(instance), // extract images from the PDF
25 style: {
26 padding: '10px 10px',
27 backgroundColor: 'blue',
28 color: 'white',
29 }
30 });
31
32 const defaultHeader = UI.getModularHeader('default-top-header');
33 defaultHeader.setItems([...defaultHeader.items, extractImagesButton]);
34};
35
36// Extract images by traversing the display list for
37// every page. With this approach it is possible to obtain
38// image positioning information and DPI.
39const extractImages = async (instance) => {
40 // Clear previously extracted images
41 extractedImages = [];
42
43 // PDFNet is only available with full API enabled
44 const { PDFNet, documentViewer } = instance.Core;
45 let pageLimit = 5;
46 try {
47 // Start the full workers
48 PDFNet.initialize().then(async () => {
49 const document = documentViewer.getDocument();
50 const doc = await document.getPDFDoc();
51 doc.initSecurityHandler();
52
53 const reader = await PDFNet.ElementReader.create();
54 const itr = await doc.getPageIterator(1);
55
56 // Read every page
57 for (itr; (await itr.hasNext()) && pageLimit > 0; await itr.next()) {
58 const page = await itr.current();
59 reader.beginOnPage(page);
60 await extractImagesFromPage(reader, PDFNet);
61 reader.end();
62 pageLimit--;
63 }
64
65 extractedImagesDialogBox();
66 });
67
68 } catch (e) {
69 console.error('❌ Failed to extract images:', e);
70 }
71}
72
73// Recursive function to extract images from a page
74const extractImagesFromPage = async (reader, PDFNet) => {
75 let element;
76 while ((element = await reader.next()) !== null) {
77 switch (await element.getType()) {
78 case PDFNet.Element.Type.e_image:
79 case PDFNet.Element.Type.e_inline_image:
80 if ((await element.getType()) == PDFNet.Element.Type.e_image) {
81 const image = await PDFNet.Image.createFromObj(await element.getXObject());
82 const filter = await PDFNet.Filter.createMemoryFilter(65536, false);
83 const writer = await PDFNet.FilterWriter.create(filter);
84
85 await image.exportAsPngFromStream(writer);
86 await writer.flush();
87 await filter.memoryFilterSetAsInputFilter();
88
89 const reader = await PDFNet.FilterReader.create(filter);
90 const pngBuffer = await reader.readAllIntoBuffer();
91
92 const file = new Blob([pngBuffer], { type: 'image/png' });
93 extractedImages.push(file);
94 }
95 break;
96 case PDFNet.Element.Type.e_form: // Process form XObjects
97 reader.formBegin();
98 await extractImagesFromPage(reader, PDFNet);
99 reader.end();
100 break;
101 }
102 }
103};
104
105// Dialog box for displaying extracted images
106const extractedImagesDialogBox = async () => {
107 // Create overlay
108 const overlay = document.createElement('div');
109 overlay.style.position = 'fixed';
110 overlay.style.top = '0';
111 overlay.style.left = '0';
112 overlay.style.width = '100%';
113 overlay.style.height = '100%';
114 overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
115 overlay.style.zIndex = '999';
116 overlay.style.display = 'flex';
117 overlay.style.justifyContent = 'center';
118 overlay.style.alignItems = 'center';
119
120 // Create dialog box
121 const dialogBox = document.createElement('div');
122 dialogBox.style.backgroundColor = 'white';
123 dialogBox.style.padding = '20px';
124 dialogBox.style.border = '2px solid #ccc';
125 dialogBox.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
126 dialogBox.style.width = '300px';
127 dialogBox.style.textAlign = 'center';
128 dialogBox.style.borderRadius = '8px';
129
130 // Message
131 const message = document.createElement('p');
132 message.style.fontFamily = 'Arial';
133 message.style.fontWeight = 'bold';
134 message.textContent = 'Extracted Images';
135 dialogBox.appendChild(message);
136
137 // Note
138 const note = document.createElement('p');
139 note.style.marginTop = "20px";
140 note.style.fontFamily = 'Arial';
141 note.textContent = 'For demo purposes, only the first 5 pages of the PDF will be processed.';
142 dialogBox.appendChild(note);
143
144 // Listbox (select element)
145 const listBox = document.createElement('select');
146 listBox.size = 6;
147 listBox.id = 'listBox';
148 listBox.style.marginTop = "20px";
149 listBox.style.alignItems = 'center';
150 listBox.style.border = '2px solid blue';
151 listBox.style.borderRadius = '4px';
152
153 // Add images to the listbox dynamically
154 extractedImages.forEach((image, index) => {
155 const imageFileName = `image${index + 1}.png`;
156 const item = document.createElement('option');
157 item.value = index;
158 item.textContent = `Download ${imageFileName}`;
159 item.style.color = 'blue';
160 item.style.cursor = 'pointer';
161 item.onclick = () => saveAs(image, imageFileName); // Download the image when clicked
162 listBox.appendChild(item);
163 });
164 dialogBox.appendChild(listBox);
165
166 // Download all images button
167 const downloadButton = document.createElement('button');
168 downloadButton.textContent = 'Download All Images (.zip)';
169 downloadButton.style.marginTop = "20px";
170 downloadButton.style.backgroundColor = 'blue';
171 downloadButton.style.color = 'white';
172 downloadButton.style.border = '1px solid blue';
173 downloadButton.style.borderRadius = '4px';
174 downloadButton.style.cursor = 'pointer';
175 downloadButton.onclick = () => downloadAllImagesZip();
176 dialogBox.appendChild(downloadButton);
177
178 // Close button
179 const closeButton = document.createElement('button');
180 closeButton.textContent = 'Close';
181 closeButton.style.marginLeft = '10px';
182 closeButton.style.color = 'blue';
183 closeButton.style.border = '1px solid blue';
184 closeButton.style.borderColor = 'blue';
185 closeButton.style.borderRadius = '4px';
186 closeButton.style.cursor = 'pointer';
187 closeButton.onclick = () => document.body.removeChild(overlay);
188 dialogBox.appendChild(closeButton);
189
190 // Append dialog to overlay and overlay to body
191 overlay.appendChild(dialogBox);
192 document.body.appendChild(overlay);
193};
194
195const downloadAllImagesZip = () => {
196 const zip = new JSZip();
197 extractedImages.forEach((image, index) => {
198 zip.file(`image${index + 1}.png`, image);
199 });
200
201 zip.generateAsync({ type: 'blob' }).then(function (content) {
202 saveAs(content, 'extracted.zip');
203 });
204
205 // Close dialog box after download
206 const overlay = document.body.querySelector('div[style*="position: fixed"]');
207 document.body.removeChild(overlay);
208};
209
210WebViewer(
211 {
212 path: '/lib',
213 initialDoc: 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/lexpress.pdf',
214 fullAPI: true, // Enable full API access. This will make the PDFNet namespace available on the WebViewer instance and allow accessing a PDFDoc instance from the WebViewer document object.
215 enableFilePicker: true, // Enable file picker to open files
216 licenseKey: 'YOUR_LICENSE_KEY',
217 },
218 document.getElementById('viewer')
219).then((instance) => {
220
221 // customize WebViewer UI
222 customizeUI(instance);
223
224 console.log('✅ WebViewer loaded successfully.');
225}).catch((error) => {
226 console.error('❌ Failed to initialize WebViewer:', error);
227});

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales