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)
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);
});
}
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);
});
}
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.
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:
- Convert JPG → PNG (to get a lossless, alpha-capable format)
- Use background removal (AI tools, manual selection, or chroma key)
- 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);
}
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)