Bulk resize images
Give a batch of images one target box and download every result in a single archive.
How it works
Resizing one image is a decode, a resample and an encode. Resizing forty is those three steps forty times over, and the interesting question stops being how the pixels are filtered and becomes how much of the device the run occupies at its widest moment. A 12-megapixel photo is around 3 MB as a JPEG and 48 MB once expanded to raw RGBA, because a raw pixel is four bytes and bears no relation to the compressed size. Forty of those held open together is roughly 1.9 GB, which no phone browser will hand over, and the tab dies with no explanation.
So nothing here is held open together. One image is read, resampled, encoded into the archive and released before the next is opened, and each entry is written as it is produced rather than gathered up at the end. Peak memory therefore follows the single largest image, not the batch. The result panel reports both figures side by side so the gap is visible rather than asserted: on a mixed folder the together figure climbs into the hundreds of megabytes while the peak stays at the size of one photograph.
What limits a run instead is the archive, which does accumulate, plus the compressed originals the page holds while it works. Both are small next to raw pixels. A hundred 3 MB photos is 300 MB of input and perhaps 40 MB of output, against a 48 MB working set for the one image in hand. File count is rarely what breaks a batch; one enormous file is, so each arrival is checked on its own against a ceiling derived from what the device reports it has.
Three ways to fit a box
Width and height together describe a box, and there are three defensible things to do with an image that is not the same shape as it. Contain scales until the whole picture is inside, so a 3000×400 panorama aimed at an 800×800 box comes back 800×107 and one axis lands short of the number typed. Nothing is letterboxed: the box is a ceiling rather than a canvas, and no padding is added to make up the difference.
Cover scales until the box is full and crops the overflow from the centre, so that same panorama comes back exactly 800×800 with its two ends gone. Exact ignores the shape of the source and stretches to both numbers, which for the panorama means 3000×400 of picture squeezed into a square. Worth knowing before testing a setting: all three agree whenever the source already has the target's proportions, so a square photo into a square box cannot tell you which mode was picked.
Nothing is enlarged unless you ask
Leaving smaller images alone is the default, and it means no output dimension may exceed the source's. A 400×300 thumbnail sent to an 1800-pixel box stays 400×300, because a resampler asked to enlarge has nothing to work from beyond the pixels it was given and returns a bigger, softer copy of them. Under cover the crop shrinks with it, so the same thumbnail against an 800×800 target arrives 400×300 rather than stretched across an 800×800 frame.
With the output format left on keep, an image needing no resize is not re-encoded either. Its original bytes are copied into the archive untouched, so a JPEG that was already the right size does not come back a generation worse. The dimensions behind that decision are read out of the container header, which for PNG, JPEG, WEBP, GIF and BMP sits within the first few dozen bytes, so an image needing nothing costs no decode at all. Turn the toggle off and every file is resampled to the target.
One unreadable file does not lose the batch
A folder off a camera or a phone is rarely uniform. A truncated download, a screenshot saved under the wrong extension, a RAW file no browser opens: in a naive loop any of those throws on file nine and takes the eight already finished with it. Each file here is handled on its own terms. A failure is recorded against that filename with the reason, the loop moves to the next, and everything that worked is still in the archive. The panel lists failures first, and a _failed.txt entry travels inside the archive so the record outlives the download.
Formats and names inside the archive
Keeping the input format is the default, because a mixed folder should come back looking like itself. Choosing JPEG, PNG or WEBP converts the lot, and the quality setting then applies to the two lossy ones. Three inputs have no encoder here: GIF and BMP are lossless containers so they become PNG, while HEIC is a lossy photo format and becomes JPEG instead. An animated GIF contributes its first frame. A file copied through untouched keeps its own format, since nothing about it was rewritten.
Every entry is named for the file it came from plus the dimensions it ended up with, so photo.jpg against an 800-pixel box becomes photo-800x600.jpg, and the numbers make the setting used obvious months later. Two inputs sharing a name would otherwise overwrite each other inside the archive — the same folder dropped twice, or two cameras both writing IMG_0042.JPG — so the second gets -2 and the third -3. Extractors disagree about duplicate entries, and none of the answers is one to discover afterwards.
Questions
How many images can I do at once?
No cap is written into the tool, and file count is not the limiting quantity. Images are decoded one at a time, so adding files lengthens the queue and grows the archive without growing the working set. The real constraint is the largest single image: a 50-megapixel photo occupies roughly 200 MB as raw pixels by itself, and every file is measured against a per-file ceiling before it is accepted. A few hundred ordinary phone photos is a question of time rather than memory.
Why is an 800×800 target giving me 800×533 files?
Because contain treats the two numbers as a box the whole picture must fit inside. A 3:2 photo fitted into a square lands 800×533, with the shorter axis short of what you typed. Choose cover for exactly 800×800 with the sides cropped away, or exact for exactly 800×800 by stretching. Contain is the default because it is the only one of the three that neither discards nor invents any part of the picture.
One file came back with its original name and its original size.
That image was already inside the target box while the output format was on keep, so its bytes went into the archive rather than through the encoder. That is the outcome that loses nothing, since a JPEG re-saved at any quality is worse than the JPEG that went in. The per-file list marks those copied byte for byte. Turn off leaving smaller images alone and it will be resampled and re-encoded with the rest.
What happens to EXIF, GPS and colour profiles?
Resizing decodes to pixels and writes a new file from them, so camera tags, location and any embedded profile are not carried across. Orientation is the exception, and it is honoured rather than dropped: a portrait phone photo stores a landscape raster plus a rotation flag, and that rotation is applied during the decode so the output stands upright. Files copied through untouched keep everything, because nothing about them was rewritten.
Is any of this uploaded?
No. Decoding, resampling, encoding and the archive itself all happen in a Web Worker in this tab, using WebAssembly codecs the page fetches once. Open the Network tab and run a batch: you will see those codec chunks arrive and no request carrying an image. It is also why a batch keeps running after the page has loaded with the network disconnected.