Extract Images from PDF Showcase Demo Code Sample

Requirements
View Demo

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: Add the ES6 JavaScript sample code provided in this guide

Once you generate your license key, it will automatically be included in your sample code below.

License Key

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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales