FreeToolio

JPG to WebP

Drop JPG photos here and get WebP copies back in this tab. The browser decodes the JPEG, draws those pixels onto a canvas at their own size and encodes them again as WebP at the quality you set. This is a second encode: the JPEG already approximated the picture once, so the sliders trade that first loss against file size rather than restoring anything. Each card reads the JPEG header before converting and reports what the source carried — baseline or progressive, chroma subsampling, EXIF orientation, GPS, ICC profile — because none of it survives the canvas. Nothing is uploaded.

Drop JPG images here

or choose files · up to 30 at a time · batch or single

    JPG in, WebP out · up to 30 files per batch · quality 30–100 · EXIF rotation applied · no upload · no account · no watermark

    JPG to WebP: What a Second Encode Costs, and Where the Format Wins

    A JPEG is an approximation before this page touches it. Converting it to WebP means decoding those approximated pixels and encoding them again. Width and height stay put; two separate things decide the number on the card: how much fidelity the new encode spends, and how tightly WebP packs the result. On a 12-megapixel photo saved at camera quality, quality 85 returned 776,980 bytes from 2,184,443 — 64% smaller. Written as JPEG instead, quality 60 landed at 856,245 bytes and 43.02 dB, against WebP's 42.64 dB. At equal fidelity the format's own edge was 9%, not 64%.

    Three horizontal bars for one 4,032 by 3,024 decoded JPEG photograph. WebP at quality 85 holds 776,980 bytes and measures 42.64 dB; JPEG at quality 85 holds 1,135,678 bytes and 50.83 dB; JPEG at quality 60 holds 856,245 bytes and 43.02 dB. A dashed line marks the 2,184,443-byte source JPEG.
    One decoded JPEG, three encodes. WebP at 85 and JPEG at 60 land within 0.4 dB of each other, and WebP is 9.3% smaller; the same nominal 85 in JPEG holds 50.83 dB and 359 KB more. Bars share one scale, with the source JPEG at 2,184,443 bytes marked by the dashed line.

    Two encodes, not one

    The JPEG decoder hands the canvas pixels that already carry the first encode's error: eight-by-eight blocks approximated, chroma often stored at half resolution. The WebP encoder then approximates those pixels a second time. Nothing in that pipeline looks at the original scene.

    Against the decoded JPEG, the quality-85 WebP measured 42.64 dB, and 95.6% of its pixels had moved by at least one level. That is the second encode doing its work. It is also why the direction of the size change depends on the source: a photograph saved at quality 50 grew from 833,627 bytes to 958,392 at the same setting, while a camera-quality file fell by nearly two thirds.

    The same number means different things in different codecs

    One decoded 4032 × 3024 photograph, three encodes from the same canvas:

    Encode Bytes PSNR vs the decoded JPG Pixels changed
    WebP, quality 85 776,980 42.64 dB 95.6%
    JPEG, quality 85 1,135,678 50.83 dB 40.4%
    JPEG, quality 60 856,245 43.02 dB 92.5%

    The JPEG column is flattered by the test: the source was itself a JPEG at quality 95, so the second JPEG encode lands back on the same block grid and reproduces much of it. Even allowing for that, the comparison makes the point the sliders hide. Quality 85 is a position on each encoder's own curve, not a unit of fidelity. Here WebP at 85 sat within 0.4 dB of JPEG at 60, for 9% fewer bytes. The rest of the 64% headline saving came from spending fidelity the source JPEG still had.

    That has a practical consequence. If a page weight target is the goal, either number works; if the JPG is the master copy, compare the card's PSNR before deciding that a small WebP is a free win.

    Where the bytes sit in the file

    Every WebP written here contains the same four parts:

    Part Bytes What it holds
    RIFF header 12 file signature and total length
    VP8X chunk 10 canvas flags: size, alpha, colour profile
    ICCP chunk 456 an sRGB profile written by the browser
    VP8 payload rest the compressed picture

    That is 478 bytes of container before a single pixel, and it appears on a 10 KB thumbnail as well as a 6 MB export. There is no ALPH chunk in any of these files: a JPEG has no alpha channel, so the encoder writes an opaque image and skips the transparency stream that a PNG-to-WebP conversion would carry. At quality 100 the payload chunk changes from VP8 to VP8L, the lossless codec.

    The source's metadata is not in that list. A 58-byte EXIF block holding the camera make and an orientation tag was read from one test file; the output contains none of it, and no GPS block either. The only profile in the output is the 456-byte sRGB one the browser adds.

    Eight JPGs at quality 85

    Every file below went through this page at the default setting. PSNR compares the WebP with the pixels the browser decoded from the JPEG; "changed" counts pixels where a colour channel moved.

    File Pixels JPG WebP q85 Change PSNR Pixels changed
    Photo, camera quality (4:4:4) 4032 × 3024 2,184,443 B 776,980 B −64.4% 42.64 dB 95.6%
    Same photo, saved at q50 4032 × 3024 833,627 B 958,392 B +15.0% 41.72 dB 95.8%
    Screenshot, q90 2560 × 1800 424,939 B 188,812 B −55.6% 42.78 dB 94.4%
    Thumbnail, q80 240 × 180 10,688 B 10,200 B −4.6% 39.11 dB 99.2%
    Phone photo, EXIF rotation 900 × 1200 220,452 B 140,222 B −36.4% 40.07 dB 98.1%
    Progressive JPEG 1600 × 1200 308,794 B 228,696 B −25.9% 40.55 dB 97.6%
    JPEG, 4:4:4 chroma 1200 × 900 216,793 B 137,956 B −36.4% 40.05 dB 98.0%
    Gradient, q90 1600 × 900 63,652 B 16,094 B −74.7% 47.04 dB 94.3%

    Three rows carry the argument. The q50 photo grew: the source had already spent its detail, and a second encode at 85 costs more bytes than the JPEG needed to say the same thing. The thumbnail barely moved at 4.6%: a small image carries so little data that the 478-byte container and block overhead eat the gain. The gradient fell 75% because smooth ramps are what a block encoder handles best, and this JPEG had little noise left to preserve.

    The quality curve starts on an already-lossy floor

    The 12-megapixel camera-quality photo at six settings:

    Quality Bytes vs the JPG PSNR Pixels changed
    30 251,270 −88.5% 36.65 dB 98.0%
    50 349,658 −84.0% 38.31 dB 97.3%
    70 465,510 −78.7% 39.70 dB 96.7%
    85 776,980 −64.4% 42.64 dB 95.6%
    95 1,497,538 −31.4% 46.56 dB 93.2%
    100 6,038,622 +176% lossless 0%

    Between 70 and 85 the file grows 67% for 2.94 dB. Between 95 and 100 the codec changes: 1,497,538 bytes of lossy data become 6,038,622 bytes of lossless data, 4.54 MB more, and every pixel of the decoded JPEG comes back exactly. On this source that is 2.8 times the JPEG's own size. Quality 100 does not restore what the JPEG discarded; it only stops adding a second loss on top.

    What the JPEG knows that the canvas forgets

    The rotated fixture was stored as 1200 × 900 with an EXIF Orientation value of 6, which means "display it turned 90° clockwise". The browser applied that rotation at decode, the card reported it, and the WebP came out 900 × 1200. Without handling that tag, every phone photo exported here would lie on its side.

    The same tag, the camera model and any GPS coordinates are not pixels, so they stop at the canvas. If the output is going to a client or an archive, that loss matters more than a few kilobytes: the date a photo was taken and the place it was taken are gone from the WebP. Keep the original JPG when those fields are part of the record.

    A progressive JPEG decodes exactly like a baseline one; the difference is how the file was stored, and the card says which you gave it. Chroma subsampling is reported for the same reason: a 4:2:0 source already stores colour at half resolution, so there is less colour detail for WebP to preserve than the pixel count suggests.

    How to convert JPG to WebP here

    1. Add the files. Drop JPGs on the box above, or choose files. Up to 30 at a time, 80 MB and 100 megapixels per file.
    2. Set the quality. The slider runs 30 to 100 and starts at 85. It re-encodes about a fifth of a second after you stop moving it; there is no run button. Each card reports the new size against the old one.
    3. Download. Every card has its own link, and the button under the panel packs the batch into one ZIP built in the tab.

    What the controls do

    The quality slider is the only setting, and it maps straight onto the encoder's quality factor: 85 sends 0.85. The number box beside it accepts a typed value and stays in step with the slider. Batch order follows the order you added files; names keep their stem and gain .webp. The page reads each file's JPEG markers before converting — baseline or progressive, chroma subsampling, EXIF orientation, ICC profile — and puts what it found on the card, because those are the facts that decide how much a second encode can keep.

    Why this page doesn't upload your JPG

    Decoding, the canvas and the WebP encoder all ship with the browser. A server would add a copy, a queue and a download, and none of that makes the picture smaller or the metadata survive.

    Two checks are open to you. Open DevTools (F12), switch to Network, then convert a file: no request carries the image. The harder test is to load this page, disconnect the network and convert anyway. Two files went through with the connection off and came back with the same SHA-256 as the online run.

    Check the result before deleting the JPG

    • Compare the two numbers on the card. If the WebP is not smaller, the source was already lean.
    • Zoom to 100% on the smallest text. A second encode softens edges that the JPEG had already softened once.
    • Look at a flat sky or a wall at 100%. The JPEG's blocks can become more visible after re-encoding.
    • Check the orientation on a phone photo: the card's pixel size should read the way the photo displays, not the way it is stored.
    • Keep the JPG if you need the capture date, the camera model or the GPS position.

    Questions that come up

    Why did my WebP come out bigger than the JPG?

    The JPG was probably saved at a lower quality than 85. A 4032 × 3024 photo saved at quality 50 grew 15% here, from 833,627 to 958,392 bytes, because the second encode spends more bits than the first one did. Drag the slider down until the card shows a decrease, or keep the original.

    Does a second encode make the photo blurrier?

    It adds error on top of the error the JPEG already carried; it cannot remove the first one. At quality 85 on a camera-quality photo the change was 42.64 dB against the decoded JPG, which is a mild second-generation loss. Repeated conversions compound, so convert from the original file rather than from an earlier WebP.

    Is quality 100 lossless for a JPG source too?

    Yes for the pixels the browser decoded: the encoder switches to VP8L and 0% of pixels changed here. It does not recover anything the JPEG threw away before this page saw the file, and on the test photo it produced 6,038,622 bytes, 2.8 times the source JPG.

    My phone photo came out rotated — why?

    It should come out upright. The page applies the EXIF orientation tag at decode: a file stored as 1200 × 900 with orientation 6 was written as 900 × 1200. If a photo still looks wrong, the rotation was baked into the pixels or stored in a tag this page did not see, and the card will show the stored dimensions.

    Where did the date and the GPS position go?

    They live in the JPEG's EXIF block, and a canvas exposes pixels only. The output WebP carries no EXIF, no GPS and no camera model; it carries the browser's 456-byte sRGB profile instead. Keep the original JPG if those fields matter.

    Can I turn the WebP back into a JPG later?

    You can, but each trip adds another encode. Converting this WebP to JPG would approximate the already-approximated pixels a third time. If the JPG is your master, archive it; the WebP is the copy you publish.