How to View Multi-Page TIFF Files in the Browser with JavaScript
Tag Image File Format, abbreviated TIFF or TIF, is an image file format for storing raster graphics images. It has several differences from most other image file formats:
- TIFF allows a flexible set of information fields called tags.
- TIFF allows a flexible combination of colorspace, bitdepth/datatype, and compression scheme.
- TIFF supports multi-page. It can store multiple images in a single file.
Due to the flexibility of TIFF, most browsers do not support this format. So how to display a TIFF file in the browser? We can convert TIFF files to JPG files for display. This can be done at the server side or directly in the browser with a third-party library. Dynamic Web TWAIN is a document scanning SDK which supports various image formats and TIFF is supported as well. It uses libTIFF as the backend and compiles it into WebAssembly for browsers to use.
In this article, we are going to talk about how to display TIFF in the browser with it.
What you’ll build: A browser-based TIFF viewer that loads local or remote multi-page TIFF files and renders them as JPG using Dynamic Web TWAIN’s WebAssembly-powered libTIFF engine.
Key Takeaways
- Browsers do not natively support TIFF — you need a JavaScript library to decode and render TIFF images client-side.
- Dynamic Web TWAIN compiles libTIFF to WebAssembly, enabling fast in-browser rendering of multi-page TIFF files without server-side conversion.
- Black-and-white TIFF pages must be converted to grayscale before JPEG export, since JPEG only supports 8-bit grayscale and 24-bit color.
- The SDK includes a built-in viewer with crop, rotate, and zoom — useful for enterprise document workflows.
Common Developer Questions
- How do I view multi-page TIFF files in JavaScript without a server?
- Why can’t browsers display TIFF images natively, and what are the workarounds?
- How do I convert TIFF to JPG in the browser using WebAssembly?
Prerequisites
To follow this tutorial you need:
- A modern browser (Chrome, Firefox, Edge, or Safari)
- A text editor or IDE
- A Dynamic Web TWAIN license key. Get a 30-day free trial license for Dynamic Web TWAIN.
Step 1: Create a New Web Page
Create a new web page with the following template.
<!DOCTYPE html>
<html>
<head>
<title>TIFF Viewer Example</title>
<style>
</style>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>
Step 2: Include Dynamic Web TWAIN
Add the following line in the head to include Dynamic Web TWAIN:
<script src="https://unpkg.com/dwt@18.0.2/dist/dynamsoft.webtwain.min.js"></script>
Step 3: Initialize Dynamic Web TWAIN
Create a new instance of Dynamic Web TWAIN and name it DWObject. We can use it to load and convert images as well as scan documents.
let DWObject;
Dynamsoft.DWT.AutoLoad = false;
Dynamsoft.DWT.Containers = [];
Dynamsoft.DWT.ResourcesPath = "https://unpkg.com/dwt@18.0.2/dist";
Dynamsoft.DWT.UseLocalService = false;
Dynamsoft.DWT.ProductKey = "LICENSE-KEY";
init();
function init(){
Dynamsoft.DWT.CreateDWTObjectEx(
{
WebTwainId: 'dwtcontrol'
},
function(obj) {
DWObject = obj;
},
function(err) {
console.log(err);
}
);
}
Step 4: Load TIFF Images from Local Files or Remote URIs
We can load TIFF images by selecting a local file or loading from a remote URI.
HTML:
<ol>
<li>
<label>
Select a TIFF file to load:
<input type="file" id="file" onchange="tiffSelected();" accept=".tiff,.tif"/>
</label>
</li>
<li>
<input type="text" id="url" value="ycbcr.tif"/>
<button onclick="loadRemoteImage();">Load a remote image</button>
<span id="status"></span>
</li>
</ol>
JavaScript:
function tiffSelected(){
let files = document.getElementById("file").files;
if (files.length>0 && DWObject) {
let file = files[0];
//get the content of the TIFF file
}
}
function loadRemoteImage(){
let xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('GET', document.getElementById("url").value);
xhr.onload = function (e) {
//get the content of the TIFF file
};
xhr.onerror = function(){
status.innerText = "Error";
}
xhr.send();
}
Step 5: Render TIFF Pages as JPG in the Browser
-
Load TIFF images into the buffer of Dynamic Web TWAIN.
function loadTiff(file){ DWObject.RemoveAllImages(); DWObject.LoadImageFromBinary(file, function () { console.log("success"); }, function (errorCode, errorString) { console.log(errorString); } ); } -
Convert the images in the buffer into JPG and display them in a viewer.
async function displayImagesInBuffer(){ let viewer = document.getElementsByClassName("tiff-viewer")[0]; viewer.innerHTML = ""; for (let index = 0; index < DWObject.HowManyImagesInBuffer; index++) { let dataURL = await getImageAsDataURL(index); let img = document.createElement("img"); img.src = dataURL; viewer.appendChild(img); } } function getImageAsDataURL(index){ return new Promise(async (resolve, reject) => { await ConvertToGrayScaleIfBW(index); DWObject.ConvertToBase64( [index], Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG, function (result, indices, type) { resolve("data:image/jpeg; base64,"+result.getData(0, result.getLength())) }, function (errorCode, errorString) { reject(errorString); } ); }) } async function ConvertToGrayScaleIfBW(index) { return new Promise((resolve, reject) => { //Check if the image is B&W. 1 is B&W, 8 is Gray, 24 is RGB if (DWObject.GetImageBitDepth(index) == 1) { //If so, convert the image to gray since only 24-bit true color bmp and 8-bit gray-scaled image are supported for JPEG compression. DWObject.ConvertToGrayScale(index, function(){ resolve(); }, function(errorCode,errorString){ reject(errorString); }); }else{ resolve(); } }) }HTML and CSS of the viewer:
<div class="tiff-viewer"></div> <style> .tiff-viewer { width: 270px; height: 360px; border: 1px solid gray; overflow-y: auto; } .tiff-viewer img { width: calc(100% - 20px); padding: 10px; } <style>
We’ve now finished the demo. You can visit the online demo to have a try.
Use the Built-in Viewer for Crop, Rotate, and Zoom
Dynamic Web TWAIN comes with a built-in viewer. We can bind the DWObject with a viewer and it can display the images in the buffer.
We just need to add the following lines to bind a viewer:
function init(){
Dynamsoft.DWT.CreateDWTObjectEx(
{
WebTwainId: 'dwtcontrol'
},
function(obj) {
DWObject = obj;
+ DWObject.Viewer.bind(document.getElementById('dwtcontrolContainer'));
+ DWObject.Viewer.show();
},
function(err) {
console.log(err);
}
);
}
After an image is loaded, the viewer will automatically display it. The viewer also comes with image editing features like crop, rotate and zoom.
Common Issues and Edge Cases
- Black-and-white TIFF pages produce errors on JPEG export. JPEG compression only supports 8-bit grayscale and 24-bit true color. If a TIFF page has 1-bit B&W depth, call
ConvertToGrayScalebefore converting to base64 JPEG — the code above handles this automatically. - Large multi-page TIFF files cause slow rendering. Each page is decoded and converted individually. For files with dozens of pages, consider lazy-loading pages on scroll rather than rendering all at once.
- CORS errors when loading remote TIFF files. If the TIFF is hosted on a different domain, the server must include appropriate CORS headers (
Access-Control-Allow-Origin). Otherwise the XHR request will fail silently.
Source Code
Get the source code of the demo to have a try:
https://github.com/tony-xlh/TIFF-Viewer/
If you need to scan documents to TIFF, check out this article.
Appendix
Colorspaces supported by TIFF:
- WhiteIsZero
- BlackIsZero
- RGB
- RGB Palette
- Transparency mask
- CMYK
- YCbCr
- CIELab
Compression schemes supported by TIFF:
- Uncompressed
- CCITT 1D
- Group 3 Fax
- Group 4 Fax
- LZW
- JPEG
- PackBits