Compress Images with JavaScript: Change Resolution, Quality, Format, and Color Depth

Image compressing on the browser is a useful operation. It can improve the uploading performance and save the storage. In this article, we are going to talk about how to compress an image with JavaScript using the Dynamsoft Document Viewer SDK.

We can compress an image by changing the following aspects:

  • Resolution
  • Color depth
  • Image format
  • Image quality

Online demo

What you’ll build: A browser-based image compression tool that reduces file size by adjusting resolution, color depth, JPEG/WebP quality, and output format using the Dynamsoft Document Viewer SDK.

Key Takeaways

  • JavaScript can compress images client-side by changing resolution, color depth, quality, and format — no server required.
  • WebP at quality 0.5 achieves ~91% size reduction compared to the original, outperforming JPEG at the same quality setting.
  • Converting to black & white with JBIG2 compression yields the smallest output (2.69% of original size) for document-style images.
  • Dynamsoft Document Viewer provides a unified API for resizing, color conversion, and multi-format export (PNG, JPEG, WebP, PDF with JP2000/JBIG2/FAX4/LZW).

Common Developer Questions

  • How do I compress an image in the browser with JavaScript without a server?
  • What is the best image format for maximum compression in JavaScript — JPEG, WebP, or PDF?
  • How do I convert an image to grayscale or black and white using JavaScript?

Step 1: Create the HTML Page

Create a new page with the following content:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>Image Compression</title>
  <style>
  </style>
</head>
<body>
</body>
<script>
</script>
</html>

Step 2: Set Up Dynamsoft Document Viewer

Dynamsoft Document Viewer provides a set of viewers for document scanning. It supports a bunch of image processing methods and image formats we can use to compress an image. Let’s add it to the page to use it.

  1. Include the CSS and JavaScript files of Dynamsoft Document Viewer

    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@1.1.0/dist/ddv.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@1.1.0/dist/ddv.css">
    
  2. Set the license. Get a 30-day free trial license if you don’t have one.

    let license = "LICENSE-KEY";
    Dynamsoft.DDV.Core.license = license;
    
  3. Init the library.

    Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@1.1.0/dist/engine";// Lead to a folder containing the distributed WASM files
    await Dynamsoft.DDV.Core.init();
    
  4. Create a doc instance for loading and saving image files.

    let doc;
    const docManager = Dynamsoft.DDV.documentManager;
    doc = docManager.createDocument();
    
  5. Load an image from blob waiting for processing.

    await doc.loadSource(imgBlob);
    

Step 3: Reduce the Image Resolution

Reducing the resolution can achieve significant size reduction.

Code:

function resize(newWidth, newHeight){
  const pageUid = doc.pages[0];
  const pageData = await doc.getPageData(pageUid)
  const imageProcess = Dynamsoft.DDV.Experiments.get("ImageProcess");
  const result = await imageProcess.process({type:3, data:pageData.display.data}, {type:13/*resize*/, params:{newWidth:newWidth, newHeight:newHeight, mode:2}});
  const newImage = new Blob([result.output],{type:result.outputContentType});
  await doc.updatePage(pageUid, newImage, {});
}

Example:

resolution

The 512x512 lena.png file is reduced from 482KB to 110KB by changing the resolution to 256x256.

Step 4: Convert to Grayscale or Black & White

We can convert the image to an 8-bit grayscale image or a 1-bit black and white image to reduce the size.

Code:

async function performColorConversion(type){
  const pageUid = doc.pages[0];
  const pageData = await doc.getPageData(pageUid)
  const imageProcess = Dynamsoft.DDV.Experiments.get("ImageProcess");
  const result = await imageProcess.process({type:3, data:pageData.display.data}, {type: type/*1: blackAndWhite 2: gray*/, params:{saveInk:false, level:1}});
  const newImage = new Blob([result.output],{type:result.outputContentType});
  await doc.updatePage(pageUid, newImage, {});
}

Example:

grayscale

black and white

The lena.png file can be reduced from a 482KB file to a 200KB grayscale file or a 11KB black and white file.

Step 5: Lower the JPEG Quality Setting

Some image formats like JPEG support setting the image quality. It will degrade the image quality to reduce the size. If the quality is not set too small, the image will not have perceptible changes but the size can be reduced.

Code:

let blob = await doc.saveToJpeg(0,{quality: 50});

Example:

image quality

The lena.jpg file can be reduced from a 125KB file to a 10KB file using the 0.1 quality.

Step 6: Choose a Higher-Compression Image Format

There are various image formats or compression algorithms we can use. The latter four are mainly used for compressing PDF files.

  • JPEG - a lossy algorithm for images
  • PNG - a raster-graphics file format that supports lossless data compression
  • WebP - a modern image format that provides superior lossless and lossy compression for images on the web
  • JP2000 - a more modern alternative to JPEG
  • CCITT-4 (FAX4) - used for monochrome images
  • JBIG2 - an alternative to CCITT compression for monochrome images
  • LZW - used for compressing text as well as images

Code:

let blob;
let quality = 1.0;
let imageFormat = "image/webp";
const isPDF = imageFormat.indexOf("pdf") != -1;
if (imageFormat === "image/png") {
  blob = await doc.saveToPng(0,{});
}else if (imageFormat === "image/jpeg") {
  blob = await doc.saveToJpeg(0,{quality: quality*100});
  console.log({quality: quality*100});
}else if (imageFormat === "image/webp") {
  let pngBlob = await doc.saveToPng(0,{});
  blob = await convertBlobToWebP(pngBlob,quality);
}else if (isPDF) {
  blob = await doc.saveToPdf([0],{quality: quality*100,compression:imageFormat});
}

function convertBlobToWebP(blob,quality){
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(blob);
    let tmpImg = document.createElement("img");
    tmpImg.onload = function(){
      let width = tmpImg.naturalWidth;
      let height = tmpImg.naturalHeight;
      let context = canvas.getContext('2d');
      canvas.width = width;
      canvas.height = height;
      context.drawImage(tmpImg, 0, 0, tmpImg.naturalWidth, tmpImg.naturalHeight, 0, 0, canvas.width, canvas.height);
      canvas.toBlob((blob)=>{
        resolve(blob);
      },"image/webp",quality)
    }
    tmpImg.src = url;
  })
}

Compression Benchmark Results

Here is a table of the test result compressing the images with different parameters of this image: link.

Color Conversion Image Format Quality Size Time Elapsed Compression Rate
No conversionimage/png19506.63KB1763ms440.60%
No conversionimage/jpeg0.1272.04KB580ms12.61%
No conversionimage/jpeg0.2326.59KB613ms15.14%
No conversionimage/jpeg0.3375.83KB581ms17.42%
No conversionimage/jpeg0.4428.28KB598ms19.85%
No conversionimage/jpeg0.5498.50KB618ms23.10%
No conversionimage/jpeg0.6576.01KB608ms26.70%
No conversionimage/jpeg0.7750.01KB590ms34.76%
No conversionimage/jpeg0.81069.88KB590ms49.59%
No conversionimage/jpeg0.91827.61KB604ms84.70%
No conversionimage/jpeg14049.13KB635ms187.66%
No conversionimage/webp0.1103.14KB2869ms4.78%
No conversionimage/webp0.2119.90KB2804ms5.56%
No conversionimage/webp0.3137.97KB2912ms6.39%
No conversionimage/webp0.4162.52KB2816ms7.53%
No conversionimage/webp0.5189.29KB2951ms8.77%
No conversionimage/webp0.6218.95KB2886ms10.15%
No conversionimage/webp0.7245.80KB2852ms11.39%
No conversionimage/webp0.8355.04KB2946ms16.45%
No conversionimage/webp0.9817.46KB3029ms37.89%
No conversionimage/webp15964.65KB4900ms276.44%
No conversionpdf/jbig211070.78KB684ms49.63%
No conversionpdf/fax411070.78KB613ms49.63%
No conversionpdf/jp20000.11.11KB2398ms0.05%
No conversionpdf/jp20000.21.51KB2612ms0.07%
No conversionpdf/jp20000.335.31KB2599ms1.64%
No conversionpdf/jp20000.4239.69KB2550ms11.11%
No conversionpdf/jp20000.51976.63KB2592ms91.61%
No conversionpdf/jp20000.63915.27KB2570ms181.46%
No conversionpdf/jp20000.74577.19KB2568ms212.14%
No conversionpdf/jp20000.84782.33KB2551ms221.65%
No conversionpdf/jp20000.94836.04KB2547ms224.13%
No conversionpdf/jp200014843.24KB2550ms224.47%
No conversionpdf/lzw19142.31KB1243ms423.72%
Grayscaleimage/png16001.92KB573ms278.17%
Grayscaleimage/jpeg0.1224.03KB268ms10.38%
Grayscaleimage/jpeg0.2277.29KB262ms12.85%
Grayscaleimage/jpeg0.3327.86KB258ms15.20%
Grayscaleimage/jpeg0.4388.02KB266ms17.98%
Grayscaleimage/jpeg0.5407.98KB260ms18.91%
Grayscaleimage/jpeg0.6777.40KB272ms36.03%
Grayscaleimage/jpeg0.7951.35KB284ms44.09%
Grayscaleimage/jpeg0.81012.78KB278ms46.94%
Grayscaleimage/jpeg0.91406.44KB283ms65.18%
Grayscaleimage/jpeg13213.54KB313ms148.94%
Grayscaleimage/webp0.198.02KB1419ms4.54%
Grayscaleimage/webp0.2117.39KB1473ms5.44%
Grayscaleimage/webp0.3136.96KB1439ms6.35%
Grayscaleimage/webp0.4162.58KB1466ms7.53%
Grayscaleimage/webp0.5191.67KB1483ms8.88%
Grayscaleimage/webp0.6225.83KB1539ms10.47%
Grayscaleimage/webp0.7257.49KB1504ms11.93%
Grayscaleimage/webp0.8391.60KB1611ms18.15%
Grayscaleimage/webp0.9856.50KB1717ms39.70%
Grayscaleimage/webp15990.37KB3264ms277.63%
Grayscalepdf/jbig211013.68KB418ms46.98%
Grayscalepdf/fax411013.68KB335ms46.98%
Grayscalepdf/jp20000.11.09KB1429ms0.05%
Grayscalepdf/jp20000.21.49KB1428ms0.07%
Grayscalepdf/jp20000.335.25KB1425ms1.63%
Grayscalepdf/jp20000.4247.83KB1447ms11.49%
Grayscalepdf/jp20000.51759.55KB1459ms81.55%
Grayscalepdf/jp20000.63337.76KB1499ms154.69%
Grayscalepdf/jp20000.73816.45KB1461ms176.88%
Grayscalepdf/jp20000.83878.43KB1488ms179.75%
Grayscalepdf/jp20000.93884.98KB1466ms180.06%
Grayscalepdf/jp200013885.36KB1460ms180.07%
Grayscalepdf/lzw15301.60KB476ms245.71%
Black & whiteimage/png1130.18KB115ms6.03%
Black & whiteimage/jpeg0.1363.82KB374ms16.86%
Black & whiteimage/jpeg0.2472.41KB190ms21.89%
Black & whiteimage/jpeg0.3570.84KB192ms26.46%
Black & whiteimage/jpeg0.4642.30KB191ms29.77%
Black & whiteimage/jpeg0.5706.09KB192ms32.72%
Black & whiteimage/jpeg0.6771.68KB195ms35.76%
Black & whiteimage/jpeg0.7855.62KB198ms39.66%
Black & whiteimage/jpeg0.8974.84KB194ms45.18%
Black & whiteimage/jpeg0.91222.58KB195ms56.66%
Black & whiteimage/jpeg12258.45KB215ms104.67%
Black & whiteimage/webp0.1290.87KB1037ms13.48%
Black & whiteimage/webp0.2327.36KB1057ms15.17%
Black & whiteimage/webp0.3352.60KB832ms16.34%
Black & whiteimage/webp0.4378.89KB856ms17.56%
Black & whiteimage/webp0.5396.79KB875ms18.39%
Black & whiteimage/webp0.6416.35KB869ms19.30%
Black & whiteimage/webp0.7432.61KB858ms20.05%
Black & whiteimage/webp0.8469.18KB868ms21.74%
Black & whiteimage/webp0.9543.33KB889ms25.18%
Black & whiteimage/webp1107.07KB259ms4.96%
Black & whitepdf/jbig2158.00KB198ms2.69%
Black & whitepdf/fax41127.27KB124ms5.90%
Black & whitepdf/jp20000.158.00KB185ms2.69%
Black & whitepdf/jp20000.258.00KB189ms2.69%
Black & whitepdf/jp20000.358.00KB175ms2.69%
Black & whitepdf/jp20000.458.00KB185ms2.69%
Black & whitepdf/jp20000.558.00KB176ms2.69%
Black & whitepdf/jp20000.658.00KB175ms2.69%
Black & whitepdf/jp20000.758.00KB177ms2.69%
Black & whitepdf/jp20000.858.00KB189ms2.69%
Black & whitepdf/jp20000.958.00KB177ms2.69%
Black & whitepdf/jp2000158.00KB184ms2.69%
Black & whitepdf/lzw1127.27KB110ms5.90%

Common Issues and Edge Cases

  • Large images may cause out-of-memory errors in the browser. Browsers impose memory limits on canvas and Blob operations. For images above ~50 MP, consider resizing before applying format conversion.
  • WebP is not supported in all browsers. Safari added WebP support in version 16+, but older Safari and some niche browsers lack it. Fall back to JPEG if canvas.toBlob("image/webp") returns null.
  • JPEG quality 1.0 can produce files larger than the original PNG. JPEG encoding at maximum quality inflates file size due to DCT overhead. Use quality 0.7–0.8 for a good balance between size and visual fidelity.

Source Code

You can find all the code and an online demo in the following repo:

https://github.com/tony-xlh/image-compression-javascript