Converting

Convert PNG to JPG on Mac

By the Smol team8 min read

To convert PNG to JPG on a Mac, run mkdir -p jpg && sips -s format jpeg *.png --out jpg/ in Terminal, or open the PNG in Preview and choose File → Export As… with JPEG as the format. Both are free, built in, and take seconds.

The part that surprises people: JPEG has no alpha channel, so whatever was transparent in the PNG has to become an actual color. On the test badge below, 41% of the image was fully transparent. sips filled it with white. ImageMagick filled it with black. Measured against the same reference, those two outputs scored 40.59 dB and 3.21 dB. Same input, same pixel dimensions, and one of them is unusable.

What happens to the transparent parts of a PNG?

One of two things, depending on which tool you reach for, and the tools on a stock Mac do not agree.

The fixture is a 1200 × 630 badge drawn with an alpha channel: 308,832 pixels fully transparent (40.9%), 103,575 at partial alpha (13.7%), the rest opaque. Every tool below was handed that identical file, and every color is the actual value read back out of the JPEG at the same coordinate.

ToolOutput bytesWhere the transparency wasWhat it did
sips (built in)50,800rgb(255, 255, 255)Composited onto white
AppleScript Image Events50,800rgb(255, 255, 255)Byte-identical to sips
ImageMagick 7.1.2-2267,563rgb(0, 0, 0)Discarded alpha, kept RGB
Pillow 12.1.0 convert("RGB")34,789rgb(0, 0, 0)Discarded alpha, kept RGB
ffmpeg44,651rgb(0, 0, 0)Discarded alpha, kept RGB

Between the sips output and the ImageMagick output, 481,650 pixels differ (63.7% of the image) and 411,080 of them differ by more than 32 levels. That is not a quality setting. That is a different picture.

The distinction underneath is worth having in your head, because it predicts the behaviour of every tool you will ever use. Compositing blends each pixel toward a chosen background in proportion to its alpha, which is what your browser does when it draws the PNG. Discarding throws the alpha channel in the bin and writes the remaining RGB verbatim, which is fast, correct by the letter of the format, and visually wrong. Here is the proof, in PSNR against three different references built from the same source file:

Outputvs source on whitevs raw RGB, alpha ignored
sips40.59 dB3.21 dB
ImageMagick, default3.21 dB46.77 dB
Smol, convert to jpg3.21 dB49.35 dB
magick -background white -alpha remove47.30 dB3.21 dB

Each tool is nearly perfect against one reference and catastrophic against the other. Pick the reference that matches where the image is going to sit.

Why does my logo come out with a halo or a dark fringe?

Because of the 13.7% of pixels that were partly transparent, and because discarding alpha makes a barely-visible pixel fully visible.

Anti-aliased edges are stored as color plus a low alpha. Scan across the left edge of the badge at y=300 and one pixel reads rgba(30, 120, 210, 17). An alpha of 17 out of 255 means that pixel is 7% present. Composited onto white, sips wrote rgb(227, 249, 255), which is almost paper. ImageMagick wrote rgb(32, 120, 210): the full-strength blue, at full opacity, in a spot that was meant to be a whisper. Do that around an entire shape and you get a hard 1–2 px outline that was never in the design. Across every partial-alpha pixel in the fixture, the mean difference between the two outputs was 182 levels out of 255.

The fix is to decide the background yourself rather than letting the encoder decide. In ImageMagick that is two flags:

# flatten onto white, then drop the (now useless) alpha channel
magick logo.png -background white -alpha remove -alpha off logo.jpg

# same idea, onto the exact page color the image will sit on
magick logo.png -background "#0b0d10" -alpha remove -alpha off logo-dark.jpg

If the image is going onto an unknown background, JPEG is the wrong container and no flag fixes that. Keep the alpha and convert to WebP instead, which supports transparency and came out 72% smaller than PNG on a screenshot in our testing.

How do I convert PNG to JPG on a Mac?

Four routes. Nothing to install for the first three.

Preview is the shortest path for one file. Open the PNG, choose File → Export As…, pick JPEG in the Format menu, and use the Quality slider. Select several thumbnails in one window and that menu item becomes Export Selected Images…, which does the lot in one pass. Preview and sips both sit on ImageIO, and the two ImageIO routes we could script, sips and AppleScript’s Image Events, produced byte-identical 50,800-byte files with white behind the transparency.

sips is the one to script. Its default JPEG quality is equivalent to formatOptions 75, which we confirmed by producing both files and comparing them byte for byte:

# default quality, which is 75
mkdir -p jpg
sips -s format jpeg *.png --out jpg/

# explicit quality, 0-100
sips -s format jpeg -s formatOptions 90 shot.png --out shot.jpg

# convert and cap the long edge in one pass
sips -s format jpeg -Z 2000 *.png --out jpg/

One trap worth knowing, because it fails quietly. If the directory in --out does not exist, sips does not create it and does not error. Asked to write nodir/x.jpg with no nodir present, it exited 0 and left a single extension-less file called nodir containing JPEG data. Run mkdir -p first. Always.

Automator covers the Finder right-click case: a Quick Action containing Change Type of Images set to JPEG. It converts in place and deletes the originals, so accept Automator’s offer to add Copy Finder Items in front of it. Smol installs its own Finder Quick Action if you would rather not build one.

Does converting PNG to JPG actually make the file smaller?

Only if the PNG contains a photograph. Otherwise it can make things considerably worse, and this is the second reason people end up disappointed by this conversion.

Source PNGPNG bytessips JPEG (q75)Change
Photograph (Kodak 23), 768 × 512557,59685,392−84.7%
Logo with alpha, 1200 × 63068,06250,800−25.4%
App screenshot, 1440 × 90085,257114,953+34.8%

The screenshot row is the one to internalise. JPEG’s discrete cosine transform is built for the gradual tonal variation in a photograph, and a screenshot is the opposite of that: flat fills, hard edges and text. PNG stores flat fills almost for free. JPEG has to spend bits describing every sharp transition, then still leaves faint ringing around the letterforms. You pay more and get less.

Quality on the photograph, so you can see where the useful range sits:

sips formatOptionsBytesvs the 557,596-byte PNG
5042,328−92.4%
75 (the default)85,392−84.7%
90120,991−78.3%
100442,913−20.6%

Quality 100 is not lossless, it is just expensive. It still throws away chroma detail and still quantizes, and it costs five times the bytes of quality 75 to do it. If you want lossless, you already had it, and it was the PNG.

How do I convert a folder of PNGs at once?

Both routes work and the gap is process startup, not encoding. Sixty PNGs, 14 MB, a mix of the three fixtures above:

RouteWall clockPer file
sips in a shell loop12.55 s209 ms
Smol, one batch job2,645 ms44 ms

The loop spent 1.28 s of user CPU and eleven seconds waiting: sixty process launches, sixty ImageIO initialisations. One process that walks the list does the same work 4.7 times faster. For thirty files nobody cares. For three thousand it is the difference between a keystroke and a coffee.

Smol’s per-file results on the same fixtures were 557,596 → 149,126 on the photograph, 85,257 → 135,573 on the screenshot, and 68,062 → 81,946 on the logo. Larger than sips in every case, and higher fidelity in every case: 43.62 dB against 40.21 on the photograph, 51.34 dB against 43.50 on the screenshot. It converts conservatively. If you want the aggressive numbers you ask for them with a compression pass rather than a conversion.

For a repeatable pipeline rather than a one-off folder, the same operations are exposed over an MCP server that Claude Code, Codex and Google Antigravity drive directly, which is how every number on this page was collected.

When Smol is not the answer

If the PNG has transparency, do not use Smol for this. We measured our own output: it discards the alpha channel and leaves the raw RGB, so the badge came out on black at 3.21 dB against the composite-on-white reference. sips and Preview get this right for free. Flatten the image onto the background you want first, or use the built-in tools, or keep the alpha and go to WebP.

For one file, Preview is genuinely fine. It is installed, it has a quality slider, and it composites correctly. There is nothing an app can add to that transaction.

For a script or a build step, use sips. One line, no dependency, no GUI, and it ships on every Mac including the build agent.

Where Smol earns the $29 is the recurring mixed-format folder: a few hundred PNG, HEIC and TIFF files that all need to come out as JPEG at one consistent setting, from Finder, 4.7 times faster than a loop, with metadata stripped and nothing uploaded. If that is a weekly job rather than a one-off, it is a one-time purchase that runs entirely on your Mac.

Related reading: the reverse trip, and why it does not restore quality, HEIC to PNG, WebP to JPG, TIFF to JPG, and every format Smol reads and writes.

Frequently asked questions

How do I convert PNG to JPG on a Mac?

Run mkdir -p jpg && sips -s format jpeg *.png --out jpg/ in Terminal, or open the PNG in Preview and choose File then Export As with JPEG selected in the Format menu. Both are built into macOS. Preview gives you a quality slider; sips takes -s formatOptions followed by a number from 0 to 100.

Why does my PNG have a black background after converting to JPG?

Because JPEG has no alpha channel and the tool you used discarded the alpha instead of compositing it. ImageMagick, Pillow and ffmpeg all keep the raw RGB, which for transparent areas is usually black. sips and Preview composite onto white instead. Add -background white -alpha remove -alpha off in ImageMagick to fix it.

What causes the halo or dark fringe around a logo converted to JPG?

Partly transparent edge pixels. Anti-aliasing stores colour plus a low alpha value, so a pixel that is 7% visible still holds full-strength colour. Discard the alpha and that pixel is written at full opacity, producing an outline that was never in the design. On our fixture those edge pixels differed by 182 levels out of 255 between tools.

Is JPG smaller than PNG?

For photographs, dramatically. A 557,596-byte photographic PNG became 85,392 bytes as a quality 75 JPEG, an 84.7% cut. For a screenshot it went the other way: 85,257 bytes of PNG became 114,953 bytes of JPEG, 34.8% larger with visible ringing around the text. Content decides, not the format name.

Does sips have a default JPEG quality?

Yes, and it matches formatOptions 75. We converted the same PNG with and without an explicit quality of 75 and the two files were byte-identical. Pass -s formatOptions 90 for something closer to archival, or 50 if the image is a thumbnail. Quality 100 is still lossy and cost five times the bytes of 75.

Keep reading