Menu

Search toolsChangelog

to move to openDescribe the problem, not the tool

Resize an image

Resizes a PNG, JPEG, WebP or GIF to a box, a width, a height, a percentage or an exact size, and writes it back as PNG or JPEG. The decoding, the resampling and the encoding all happen in this browser tab.

PNG, JPEG, WebP or GIF. The file is read in this tab and there is no server to send it to.

Fitting inside a box keeps the proportions and uses whichever of the two limits bites first.

Used when fitting inside a box, setting the width, or stretching to an exact size.

Used when fitting inside a box, setting the height, or stretching to an exact size.

Used when scaling by a percentage. 50 halves both sides, which is a quarter of the pixels.

Keeping the format writes a PNG back as PNG and a JPEG back as JPEG. A WebP or a GIF comes back as PNG.

New size
Width by height, in pixels, after rounding to whole pixels.
Original size
New file size
Smaller by
Written as

How it works

What this does

Makes an image smaller — or, if you insist, larger — without it leaving your computer. The size, the format and the JPEG quality are all yours to choose, and the proportions are kept unless you explicitly ask for them not to be.

Resizing sounds like it should be one line of arithmetic, and the arithmetic is in fact one line. The parts that go wrong are elsewhere: which dimensions to compute when a photo carries an EXIF rotation, how to reduce by a factor of ten without the browser’s resampler smearing the detail, what to do with transparency when the output format has none, and what to call the file so that it cannot overwrite the only copy that still has the pixels in it.

The method

Both sides are multiplied by one factor. Computing a width and a height separately, and rounding each, is how a 3:2 photograph comes out at 1.4999:1 — imperceptible on a screen and immediately visible when it is placed next to another one. In the box mode that factor is the smaller of the two the box allows, so the image fits inside rather than overflowing one edge. Only the exact-size mode uses two factors, and it does so because it has been told to.

The reduction is done in stages. A browser’s drawImage resamples with a small kernel, so asking it to go from 4000 pixels wide to 400 in one step reads about one input pixel in ten and discards the other nine: fine detail turns into aliasing and text shimmers. Halving repeatedly means every output pixel is the average of exactly four inputs, which is what a proper box filter would do. The ladder stops while both sides are still more than double the target, so the last draw is always a reduction of less than 2x — the size a small kernel handles correctly.

The EXIF orientation is asked for explicitly rather than left to the engine. A phone writes a landscape sensor image plus a tag saying “turn this a quarter turn”, and whether the decoder honours that tag by default has changed over the life of the specification and still differs between engines. Stating it means a portrait photo is 3000 by 4000 in every browser, not 4000 by 3000 in one of them and squashed in the output.

The size and the format are read out of the file’s own header before anything is decoded. That is what allows a 300-megapixel panorama to be refused with a sentence rather than by the tab running out of memory half way through, and it is why the message for a HEIC says HEIC instead of “unsupported file”.

Before you read on

A 4000 by 3000 photograph is fitted inside a 1200 by 1200 box. How many times is it actually drawn?

  • That is the four-line version, and it is why so many resized photographs shimmer.

  • Yes: halved to 2000 by 1500, then one final draw of 1.67x.

  • The ladder stops while both sides are still more than double the target, so the last draw does the remainder.

Twice — halved to 2000 by 1500, then a final 1.67x draw to 1200 by 900. A browser's drawImage resamples with a small kernel, so asking it to go from 4000 wide to 400 in one step reads about one input pixel in ten and discards the other nine: fine detail turns into aliasing and text shimmers. Halving means every output pixel is the average of exactly four inputs, which is what a proper box filter does, and stopping the ladder while both sides are still over double the target keeps the last draw under 2x — the size a small kernel handles correctly.

One factor, not two
  1. factor = min(1200 / 4000, 1200 / 3000)

    The box gives two limits. Both sides get multiplied by one of them, never by their own.

  2.        = min(0.30, 0.40) = 0.30

    The smaller, so the image fits inside the box rather than overflowing an edge. Here the height limit never bites, because the photograph is wider than it is tall.

  3. width  = round(4000 x 0.30) = 1200

    Computing a width and a height separately, and rounding each, is how a 3:2 photograph comes out at 1.4999:1.

  4. height = round(3000 x 0.30) =  900

    Imperceptible on its own, and immediately visible the moment it is placed next to another photograph.

A worked example

A 4000 by 3000 photograph, fitted inside a 1200 by 1200 box, with everything else left at its default:

factor = min(1200 / 4000, 1200 / 3000)
       = min(0.30, 0.40)
       = 0.30

width  = round(4000 x 0.30) = 1200
height = round(3000 x 0.30) =  900

The height limit never bites, because the photograph is wider than it is tall. It is drawn in two stages rather than one:

StageSizeReduction from the stage before
Decoded4,000 × 3,000
Halved2,000 × 1,5002.00x
Final1,200 × 9001.67x

and offered as photo-1200x900.png. These exact figures — the two stages, the final size and the filename — are asserted in this tool’s test file, so if the formula ever changes without this page changing with it, the build fails.

No file size is published here on purpose. The bytes that come out depend on the browser’s PNG and JPEG encoders, which differ between engines and between versions, and a number quoted on this page would be wrong for most readers.

What it does not do

It does not crop, rotate, or pad. Every mode scales the whole image; the exact-size mode changes the proportions by stretching rather than by cutting anything off. It does not target a file size — you choose the pixels and the JPEG quality, and the bytes are whatever the encoder produces. It reads PNG, JPEG, WebP and GIF, and writes PNG and JPEG, which leaves out HEIC, AVIF, TIFF, SVG and raw camera formats. It takes one file at a time. And it keeps only the first frame of anything animated.

It also will not change format for you. Converting PNG to JPEG is a separate decision with its own trade-off, and making it after the resize is the order that produces the smaller file.

How it is done

  1. Read the first bytes of the chosen file and work out from them alone whether it is a PNG, a JPEG, a WebP or a GIF, and how many pixels it claims to contain. The file's declared type is not consulted, because Safari reports a HEIC with no type at all.
  2. Refuse anything above 80 megapixels here, before allocating a byte. A decoded image costs four bytes a pixel whatever the file size, so a 100-megapixel panorama is 400 MB of memory that a browser tab does not have.
  3. Decode the image with the browser's own decoder, asking explicitly for the EXIF orientation to be applied, so a photo shot in portrait is measured the way it looks rather than the way the sensor recorded it.
  4. Work out one scale factor from the decoded dimensions and multiply both sides by it, rounding each to a whole pixel. Only the exact-size mode uses two factors, and only because it has been told to ignore the proportions.
  5. Halve the image repeatedly until one more halving would overshoot, then draw the last step straight to the target. A browser resamples with a small kernel, so a single 10x reduction samples about one pixel in ten and throws the rest away.
  6. Fill the canvas with the matte colour first when the output is JPEG, because JPEG has no alpha channel and a transparent pixel has to become something.
  7. Encode the final canvas as PNG or JPEG, read back the type the browser says it actually wrote, and offer it as a download named after the original with the new dimensions appended.

What it assumes

  • Both sides are scaled by one factor and then rounded to whole pixels, so the proportions can shift by up to half a pixel. On a 4000-pixel photo that is a change of about 0.01%, and it is the only way to avoid a much larger drift from rounding the two sides independently.
  • EXIF orientation is applied. A photo whose file header says 4000 by 3000 but which carries a quarter-turn tag is treated as 3000 by 4000, because that is what you see in your photo viewer and what every dimension below it has to agree with.
  • The toggle called "Never make it bigger" applies to the box, width and height modes, which describe a target the image must fit inside. A percentage or an exact size is taken literally, so 200% does enlarge.
  • Only the first frame of an animated GIF or WebP survives. A canvas holds one frame, and re-assembling an animation would need an encoder the browser does not expose.
  • An embedded colour profile is usually dropped. Most engines convert a wide-gamut photo to sRGB when it is drawn to a canvas, so an Adobe RGB image can come back looking slightly flatter than the original.
  • A JPEG is decoded and re-encoded, never copied. Even at 100% quality that loses a little more detail, which is why "keep the original format" writes a WebP or a GIF out as lossless PNG rather than as JPEG.
  • KB means 1,024 bytes and MB means 1,024 KB, which is what a desktop file manager shows and therefore what the figure gets compared against.

Common questions

Is my image uploaded anywhere?

No. The file is read in this browser tab and resized by a worker running on your own machine, using the same image decoder the browser uses to display a photograph on any other page. There is no server to send it to, and the automated test for this page fails if any request leaves this site while an image is loaded.

Why is my animated GIF now a single frame?

Because a canvas holds one frame at a time. The first frame is decoded, resized and written out, and the rest are discarded. Resizing an animation properly needs an encoder that can write the frames back with their timings, and a browser does not expose one for GIF or for WebP.

Why did the file get bigger instead of smaller?

Usually because a photograph was written out as PNG. PNG is lossless, so a photograph re-encoded as PNG can be several times the size of the JPEG it came from even at a fraction of the pixels. Choose JPEG under "Write it as" and the file will be far smaller. The other cause is a very small image, where the format's fixed overhead is most of the file.

Why will it not make my small photo bigger?

"Never make it bigger" is on by default, and the box, width and height modes respect it. Enlarging invents pixels: a 600-pixel photo stretched to 1920 is a bigger, blurrier file with no more detail in it. Turn the toggle off under "More options" if you want it anyway, or use the percentage mode, which is taken literally.

Can I resize a HEIC photo from my iPhone?

Not here. HEIC and AVIF are refused with a message saying so, because the browser's canvas cannot reliably decode either one and a half-decoded photo is worse than a refusal. Export the photo as JPEG from the Photos app, or set the camera to "Most Compatible", and it will resize normally.

Do the colours change?

Slightly, if the original carried a wide-gamut colour profile. Drawing an image to a canvas converts it to the canvas colour space, which is sRGB in most engines, so an Adobe RGB or Display P3 photo can come back looking a little flatter. An sRGB image, which is nearly everything from the web, is unaffected.

Sources