Most upload forms only set a ceiling: "under 50 KB". Some set a range instead, like a signature "between 10 KB and 20 KB". That catches people out in the other direction. A clean, tightly cropped signature resized to the requested pixels often comes out at a few KB, and the form rejects it as too small.
The usual instinct is to make the image worse or bigger until it weighs more. Neither is a good idea, and there's a cleaner option built into the JPEG format.
Why a clean signature is tiny
JPEG stores an image in 8 x 8 pixel blocks. A block that's flat white costs almost nothing. A signature is black strokes on a mostly white background at a small pixel size, so most of the image is cheap blocks. At a sensible quality it ends up at a few KB, and that's the correct result for that picture.
To check, I drew a simple black stroke on a 300 x 120 white image and saved it at JPEG quality 90. It came to 2,609 bytes.
Ways people push the size up, and why I wouldn't:
- Raising pixel dimensions. If the form specifies a pixel size, you've now broken that rule instead.
- Quality 100. Helps a bit. My test image went from 2,609 to 4,224 bytes, still nowhere near 10 KB.
- Adding noise or a grey background. Makes the size go up and the signature look worse. Forms that ask for black ink on white paper want it to look like that.
JPEG comments: bytes that don't change the picture
A JPEG file is a list of segments, each starting with an FF marker byte. One of them is the comment segment, marker FF FE. Decoders skip over it. It was meant for text notes, and one comment segment can hold up to 65,533 bytes (its 2-byte length field maxes out at 65,535 and counts itself).
So you can raise a JPEG's file size without touching a single pixel: insert a comment segment of the right length.
Here's a small Python script that does it. It puts the comment straight after the start-of-image marker:
import sys
src, dst, target = sys.argv[1], sys.argv[2], int(sys.argv[3])
data = open(src, "rb").read()
assert data[:2] == b"\xff\xd8", "not a JPEG"
need = target - len(data)
if need > 4:
payload = b" " * min(need - 4, 65533)
com = b"\xff\xfe" + (len(payload) + 2).to_bytes(2, "big") + payload
data = data[:2] + com + data[2:]
open(dst, "wb").write(data)
print(len(data), "bytes")
python3 pad_jpeg.py signature.jpg signature-padded.jpg 11264 # 11 KB
The 4 extra bytes are the marker plus the length field. On my 2,609 byte test image this produced a file of exactly 11,264 bytes. ImageMagick's compare -metric AE between the original and the padded file reported 0 different pixels, identify still read it as a normal 300 x 120 JPEG, and Pillow opened it without complaint.
If the target is more than about 64 KB above the current size, one segment isn't enough; the script caps the padding at one segment, so check the printed size.
If you'd rather not write code, exiftool -Comment="..." can add a comment too, but you have to build a string of the right length yourself.
Aim inside the range, not at the edges
Ranges have two edges and both can be ambiguous.
The top edge. "20 KB" might mean 20,480 bytes (1 KB = 1024) or 20,000 bytes (1 KB = 1000). A file of 20,300 bytes passes the first reading and fails the second. Staying a little under the limit avoids the question.
The bottom edge. Padding lands exactly on the number you give it. If a validator checks "more than 10 KB" instead of "at least 10 KB", a file of exactly 10,240 bytes could fail. I don't know which validators do which, so I pad to about 1 KB above the stated minimum. That's why the example uses 11 KB, not 10.
Will a portal strip the comment or complain?
I don't know of one that does, but I can't promise none will. The padding is standard JPEG structure, not a change to the image data. If a portal re-encodes uploads on its side after the size check, the padding just disappears, which doesn't affect you.
The gotcha: pad last
Order matters. Any resize or recompression after padding re-encodes the image, and the size moves again. In my test, ImageMagick and Pillow both kept the comment when I resized the padded file slightly, but the ImageMagick result still shrank from 11,264 to 10,973 bytes, under the 11 KB I'd aimed for. Other editors and phone apps may drop comments entirely.
So do the crop, the pixel resize and any compression first. Pad last, then check the exact byte count in file properties before you upload.
I built ToolOcean, a set of browser-based file tools. Its exact-size image pages have an "Optional minimum (JPEG padding only)" field that adds this kind of comment padding when a JPEG comes out under the minimum, and the result note says how many bytes are padding. The image stays in your browser tab: https://toolocean.co/compress-image-to-50kb
Drafted with AI help, tested and checked by me.
Top comments (0)