Four tools is three tools too many
Crop, rotate, flip and resize are sold as four separate products almost everywhere, which is a decision about search traffic rather than about the work. Nobody crops a photograph and then stops. You crop it and it is the wrong way up; you straighten it and it is 4000 pixels wide; you shrink it and the crop was a little tight. Four pages means exporting and re-importing three times, and every round trip through a lossy format costs a little more of the picture.
So this is one surface with all four on it, one live preview of the result, and one export at the end. The only thing you lose by combining them is the ability to rank for four keywords with four thin pages, which is not a loss.
The order matters, so it is written down
Transforms do not commute. Flipping an image horizontally and then turning it a quarter turn gives a different picture from turning it first and then flipping. An editor that does not tell you which order it uses is one you have to probe by experiment, and the probing is worse than the reading.
Here it is crop, then flip, then rotate, then resize. The crop rectangle is stored in the original image's own pixel coordinates, before anything else is applied, which is the part that matters in practice: it means the numbers in the crop boxes keep meaning the same edges after you press rotate. Store the crop after the rotation instead and x = 100 silently becomes a different side of the photograph every quarter turn.
One consequence is worth naming because it looks like a bug and is not. Since flip runs before rotate, the stored horizontal flip shows up as a vertical one once the image is at 90°. The buttons compensate — press "flip ↔" and the image flips the way it looks like it should, whatever the rotation — but underneath, the order never changes.
Why the resampler is named on the page
Shrinking an image is a resampling problem, and the browser's built-in answer is not a good one. Handing drawImage a smaller destination rectangle gets you whatever kernel that engine happens to use — Chrome and Firefox something Lanczos-like, Safari bicubic — with no way to ask for anything else and no way to find out what you got. On a reduction of more than about a third the difference is visible without pixel-peeping: hairlines break up, small type loses its counters, and detailed textures go flat.
A Lanczos3 pass computes each output pixel from a weighted window of source pixels rather than a cheap sample, which is why edges survive it. It is not magic and it is not new; it is just not what a canvas gives you by default. The whole cost is14 KB gzipped, loaded only when you open this page and run on a worker thread so dragging a handle stays smooth.
Going the other way, enlarging, the same resampler produces a clean result and invents nothing. That is worth stating plainly because the market for this term is dominated by "AI upscalers" promising recovered detail. They run a neural network that hallucinates plausible texture; it flatters landscapes and it wrecks faces and text. We measured what shipping one to a browser would cost — about 2.8 MB of runtime and an 800 KB model that compresses by 7% because float weights do not compress — and decided the honest 14 KB answer was the better product.
The blank-image failure, and why there is a ceiling
Browsers cap how large a canvas can be: roughly 8192 pixels on a side, and on older iOS about 16 megapixels in total regardless of shape. Go past either and the canvas does not throw, does not warn, and does not log. It hands back a blank image. You get a file of exactly the right dimensions containing nothing, and you usually find out later, on another device, with no idea which step lost it.
Every size this tool allocates is run through the same clamp first, including the intermediate canvas the crop and rotation are drawn onto — cropping a 12000-pixel scan to 11000 pixels is still over the ceiling, and checking only the final resize is how that case gets missed. When the clamp intervenes the readout says so and shows the size you are actually getting. A cap you are told about is a constraint; a cap you are not told about is a corrupt file.
What it will not do
No free-angle rotation. Anything that is not a multiple of 90° has to interpolate every pixel, softening the entire image to straighten a horizon by two degrees, and it needs a decision about what fills the corners. It is a real feature and it deserves a real treatment rather than a slider bolted on here. No HEIC input yet: decoding it needs a 450 KB LGPL-licensed WebAssembly build, which is a licensing decision rather than an install, and iOS usually hands over JPEG anyway. No AVIF output, because no browser can encode AVIF from a canvas — decoding is widely supported and routinely confused with it.
Questions people ask
Straight answers. Each one links directly: copy the address after opening it.
In what order are the crop, turn and resize applied?
Crop first, then flip, then rotate, then resize. The order is fixed and the page says so because it changes the result: flipping and then rotating is not the same as rotating and then flipping. The crop boxes always read in the original photograph’s coordinates, never the rotated ones, so a number you typed before pressing rotate still means the same edge afterwards. Resize runs last because there is no point resampling pixels a crop is about to discard.
Why does resizing here look sharper than dragging a corner in a photo app?
Because it does not use the browser’s built-in downscaler. `canvas.drawImage` with a smaller destination samples cheaply, and on a reduction of more than about a third it drops detail that sat between the pixels it sampled — fine rules go dotty, small text turns to mush, and hair and foliage go soft. You also cannot pick the kernel: Chrome and Firefox use something Lanczos-like, Safari uses bicubic, and nothing in the API lets you ask. This runs a Lanczos3 resample instead, which weighs a window of source pixels for every output pixel. It costs 14 KB, it is loaded only on this page, and it runs in a worker so the tab stays responsive.
Can it enlarge an image and add detail back?
It can enlarge, and it will be a clean enlargement, but no — and neither can anything else that is honest about it. Detail that was not captured is not in the file. The tools advertising “AI 4× upscaling” run a neural network that invents plausible detail; it can look good on photographs and it reliably mangles faces and text. Running one in a browser means roughly 2.8 MB of runtime plus an 800 KB model that barely compresses, which we measured and rejected. A properly resampled enlargement is the honest product.
Is there a size limit?
Yes, and it is the browser’s, not ours. A canvas is capped at about 8192 pixels on a side, and older iOS also caps the total at roughly 16 megapixels. Past either limit a canvas does not throw an error — it silently produces a blank image, which is the worst failure an editor can have because the download looks like a file and opens like a void. So this tool holds every canvas to 8,192 pixels a side and 16,777,216 pixels in total, in every browser, and when that scales your image down the Output panel tells you the size it used instead of the size you asked for.
Which format should I save as?
WebP for almost anything on the web: smaller than JPEG at the same visual quality and it keeps transparency. JPEG when something downstream refuses WebP, accepting that transparency gets flattened onto white. PNG for flat graphics, screenshots and anything with hard edges. “Smallest” encodes each one your browser can genuinely write, at your quality setting, keeps whichever produced the smallest file and lists the sizes it compared; it leaves JPEG out when the picture has see-through pixels. Whatever comes out, the file is named after what the browser actually wrote, because asking a canvas for a format it cannot encode returns a PNG with no error at all.
Can I crop without a mouse?
Yes. The four number boxes under the picture set the crop exactly — left, top, width and height, in source pixels — and they are the primary control, not an afterthought. The selection rectangle is also focusable: tab to it and the arrow keys nudge it a pixel at a time, or twenty with shift held. For an exact 1080 × 1080 the boxes are faster than dragging for everyone, pointer or not.
Does anything get uploaded?
No. The image is decoded, transformed and re-encoded in this tab, and there is no server in the path to upload it to. A side effect worth knowing in both directions: re-encoding drops EXIF, which removes the GPS coordinates a phone writes into every photograph, and also removes the copyright and camera fields if you needed them.