DEV Community

zepubo-code
zepubo-code

Posted on

JPG to PNG: Why Transparency Matters (And How to Convert in the Browser)


You've got a logo saved as a JPG. You drop it onto a colored background in your design tool — and suddenly there's an ugly white box around it.

That's the JPG transparency problem. And the fix is simple: convert it to PNG.

But there's more to it than just changing the file extension. Let's break down why transparency works the way it does, and how to handle JPG → PNG conversion entirely in the browser.

Why JPG Doesn't Support Transparency

JPG (JPEG) uses lossy compression designed for photographs. Every pixel in a JPG has three values: Red, Green, Blue. That's it — no fourth channel for transparency.

PNG, on the other hand, supports an alpha channel — a fourth value per pixel that controls opacity from 0 (fully transparent) to 255 (fully opaque).

JPG pixel:  R, G, B          (3 channels)
PNG pixel:  R, G, B, A       (4 channels — A = alpha/transparency)
Enter fullscreen mode Exit fullscreen mode

When you open a JPG in an editor and "remove the background," what actually happens is the editor replaces those pixels with transparency — but if you save back to JPG, that transparency is lost and replaced with white (or whatever background color the encoder uses).

The only way to preserve transparency is to save as PNG (or WebP, or GIF for simple cases).

What Gets Lost When Converting JPG → PNG

Here's something most tutorials skip: converting JPG to PNG doesn't recover transparency. It just gives you a format that supports it.

If your JPG has a white background, converting to PNG gives you a PNG with a white background — not a transparent one. To get actual transparency, you need background removal (a separate step).

What the conversion does give you:

  • A lossless format — no further quality loss on re-save
  • Support for transparency if you then edit the image
  • Larger file size (PNG is uncompressed or lossless-compressed)
  • Better quality for screenshots, UI elements, and text-heavy images

Converting JPG to PNG in JavaScript

Since both formats are supported natively by the browser's Canvas API, conversion is straightforward:

async function jpgToPng(file) {
  return new Promise((resolve, reject) => {
    const img = new Image();

    img.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;

      const ctx = canvas.getContext('2d');

      // Draw the JPG onto the canvas
      // Note: we do NOT fill a white background here
      // This preserves any semi-transparent edges if present
      ctx.drawImage(img, 0, 0);

      // Export as PNG — lossless, supports alpha
      canvas.toBlob((blob) => {
        if (!blob) return reject(new Error('Canvas toBlob failed'));

        const pngFile = new File(
          [blob],
          file.name.replace(/\.jpe?g$/i, '.png'),
          { type: 'image/png' }
        );
        resolve(pngFile);
      }, 'image/png');
      // No quality parameter for PNG — it's always lossless
    };

    img.onerror = () => reject(new Error('Failed to load image'));
    img.src = URL.createObjectURL(file);
  });
}
Enter fullscreen mode Exit fullscreen mode

Key difference from JPG export: Notice there's no ctx.fillStyle = '#ffffff' before drawing. For JPG export you need to fill white (because JPG can't represent transparency). For PNG, skip the fill — let the canvas default to transparent.

Handling Batch Conversion

async function batchJpgToPng(files) {
  const pngFiles = [];

  for (const file of files) {
    // Only process JPG files
    if (!/\.jpe?g$/i.test(file.name) && file.type !== 'image/jpeg') {
      continue;
    }

    try {
      const png = await jpgToPng(file);
      pngFiles.push(png);
    } catch (err) {
      console.error(`Failed to convert ${file.name}:`, err);
    }
  }

  return pngFiles;
}

// Trigger downloads
function downloadAll(files) {
  files.forEach((file, index) => {
    // Stagger downloads to avoid browser blocking
    setTimeout(() => {
      const url = URL.createObjectURL(file);
      const a = document.createElement('a');
      a.href = url;
      a.download = file.name;
      a.click();
      URL.revokeObjectURL(url);
    }, index * 200);
  });
}
Enter fullscreen mode Exit fullscreen mode

File Size: What to Expect

PNG files are almost always larger than the original JPG. Here's why:

Format Compression Typical size
JPG Lossy (DCT) Small
PNG Lossless (DEFLATE) 2–5x larger than JPG
WebP Lossy or Lossless Smallest overall

For a 500KB JPG photo, expect a 1.5–3MB PNG. That's normal — PNG is preserving every pixel exactly.

Exception: Screenshots, diagrams, and images with large flat-color areas often compress well in PNG. A 200KB JPG screenshot might be 150KB as PNG because DEFLATE handles repetitive pixels efficiently.

When to Use JPG vs PNG

Is it a photograph?
  → JPG. Smaller file, barely noticeable quality loss.

Does it need transparency?
  → PNG (or WebP).

Is it a screenshot, diagram, or has text?
  → PNG. Sharper edges, no compression artifacts.

Is it a logo or icon?
  → PNG or SVG. Never JPG.

Do you need the smallest possible file for web?
  → WebP with PNG fallback.
Enter fullscreen mode Exit fullscreen mode

The convert jpg to png transparent background Problem

This is one of the most Googled image questions — and it's a source of confusion.

Converting JPG to PNG does not remove the background.

If you want a transparent background PNG from a JPG:

  1. Convert JPG → PNG (to get a lossless, alpha-capable format)
  2. Use background removal (AI tools, manual selection, or chroma key)
  3. Save the result as PNG

The conversion step just enables transparency — it doesn't create it.

In code, if you want to make white pixels transparent (a naive but sometimes useful trick for logos on pure white):

function makeWhiteTransparent(canvas, threshold = 240) {
  const ctx = canvas.getContext('2d');
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  for (let i = 0; i < data.length; i += 4) {
    const r = data[i];
    const g = data[i + 1];
    const b = data[i + 2];

    // If pixel is close to white, make it transparent
    if (r > threshold && g > threshold && b > threshold) {
      data[i + 3] = 0; // Set alpha to 0 (transparent)
    }
  }

  ctx.putImageData(imageData, 0, 0);
}
Enter fullscreen mode Exit fullscreen mode

This works well for simple logos on pure white. For photos or complex edges, you'd need a proper segmentation algorithm.

Real-World Tool

If you want to convert JPG to PNG without writing code, I built a free browser-based converter at OneWeeb — handles batch conversion, runs entirely in your browser, and your files never leave your device.


TL;DR

  • JPG has no alpha channel — transparency is impossible in JPG
  • Converting to PNG gives you a lossless format that supports transparency
  • It does not automatically remove backgrounds — that's a separate step
  • PNG files are larger than JPG — that's expected and normal
  • For web: use WebP where possible, PNG as fallback for transparency needs
  • In Canvas API: skip the white fill when exporting PNG (unlike JPG)

Building something with image conversion in the browser? Drop a question in the comments.

Top comments (0)