DEV Community

Anuj Kabra
Anuj Kabra

Posted on

Shooting a signature on a phone so it doesn't come out grey

Upload forms that want a scanned signature usually mean "dark ink on a white background", within a pixel size and a KB range. A phone photo of a signature on white paper rarely looks like that. The paper comes out grey, often darker in one corner, and the file is bigger than it should be. Here's what I worked out about why, and how to fix it at the shooting step and afterwards, tested on dummy signature photos I generated (no real signatures).

Why white paper comes out grey

A phone camera sets its exposure so the scene averages out to a middle brightness. A sheet of white paper with a thin line of ink on it is almost all bright, so the camera turns the brightness down until the paper sits somewhere in the middle. Dim indoor light makes it worse: the paper gets darker, the camera raises its gain, and the grey picks up grain.

To see what that does to the file, I made two fake 4032 x 3024 phone photos of the same scribbled signature with Pillow and NumPy:

indoor.jpg    dim light: paper 48% to 63% grey, noisy, darker bottom right   2,261,328 bytes
daylight.jpg  window light: paper 87% to 92%, little noise                    1,273,147 bytes
Enter fullscreen mode Exit fullscreen mode

The percentages are the average brightness of 50 x 50 pixel patches of paper, measured like this:

$ magick indoor.jpg -colorspace Gray -crop 50x50+3950+2950 -format '%[fx:round(100*mean)]%%' info:
48%
Enter fullscreen mode Exit fullscreen mode

Same signature, same pixel count, and the indoor photo is 78% bigger. The ink didn't change. The noise did.

Shooting it so there's less to fix

  • Light: daylight near a window, not direct sun on the page. Turn the flash off; it leaves a bright spot in the middle and darker edges.
  • Exposure: after tapping to focus on the signature, drag the exposure control up a little (the sun icon next to the focus box on iPhone, a slider on most Android cameras) until the paper looks white on screen, but not so far that thin strokes start to fade.
  • Angle: hold the phone flat above the page, pointing straight down. A tilted shot turns a rectangle into a trapezoid and puts one side of the paper in more shadow than the other.
  • Your own shadow: with the light in front of you, the phone and your hand shade the page. Turn so the window is to one side.
  • Pen and paper: plain white paper with nothing showing through from the back, and a pen that gives a solid dark line. Ruled or textured paper adds lines and grain the file has to store.
  • Framing: fill a good part of the frame with the signature and leave some margin. You'll crop it anyway, and a signature that's 500 pixels wide in the photo holds up better than one that's 150.

Crop tight first

The rest of the photo is paper, and nobody asked for it. I cropped both photos to the same box around the signature (1569 x 559 pixels, starting at 1271, 1245) with a small margin. ImageMagick can find the ink for you if you threshold a copy first; %@ prints the bounding box of everything that isn't background:

$ magick indoor.jpg -colorspace Gray -threshold 30% -format '%@' info:
1489x479+1311+1285
Enter fullscreen mode Exit fullscreen mode

That's width x height + left + top. I added 40 pixels on each side for the crop:

$ magick indoor.jpg -crop 1569x559+1271+1245 +repage -colorspace Gray -quality 85 crop.jpg
Enter fullscreen mode Exit fullscreen mode

+repage drops the old canvas offset, so later steps treat the crop as a fresh image. -colorspace Gray keeps one channel instead of three, which suits a black or blue signature; skip it if the form insists the ink colour must show.

One thing that surprised me: at the same output width, cropping made the file bigger, not smaller.

600 px wide, quality 85
uncropped photo        600 x 450    10,851 bytes
cropped                600 x 214    16,456 bytes
Enter fullscreen mode Exit fullscreen mode

In the uncropped version the signature is only about 220 pixels wide and most of the image is blurred, smoothed-out paper. Cropping is about making the signature fill the pixels the form gives you. It's the next step that brings the size down.

Make the paper white: -level, not just brightness

Raising brightness lifts the ink along with the paper, so you get pale grey on pale grey. What you want is to set a black point and a white point: everything darker than one value becomes black, everything lighter than another becomes white, and the strokes' soft edges are stretched in between.

$ magick indoor.jpg -crop 1569x559+1271+1245 +repage -colorspace Gray -level 25%,45% -quality 85 clean.jpg
Enter fullscreen mode Exit fullscreen mode

My ink measured between 12% and 17% brightness and 99% of the pixels in the photo were above 46%, so 25% and 45% sit between the two. Check your own numbers with the fx:mean command above on a patch of paper near the darkest corner, and pick a white point a bit below it.

Here is what that does to the size. Same crop, same quality 85, the only difference is whether the paper is grey or white:

                          grey paper    white paper (-level)
full crop, 1569 x 559      109,093         36,100
resized to 600 px wide      15,040          9,940
Enter fullscreen mode Exit fullscreen mode

At full size the white version is 67% smaller. JPEG stores each 8 x 8 block of pixels as a sum of patterns, and a block of flat white needs almost nothing. A block of grey paper with grain needs many patterns to describe the grain, so JPEG spends bytes on noise nobody wants. After -level, 93% of the pixels in the 600 px version were within 5 of pure white (250 or more); before it, none were.

The daylight photo shows that shooting well does most of the work:

600 px wide, quality 85, cropped, grey
indoor              15,040 bytes   (paper median 139 of 255)
daylight            10,054 bytes   (paper median 228)
daylight + -level    9,584 bytes
Enter fullscreen mode Exit fullscreen mode

Threshold works, but it's rougher

-threshold makes every pixel pure black or pure white. It's tempting for a signature, and it's small, but the order matters:

-threshold 35% then -resize 600x    10,360 bytes   edges softened by the resize
-resize 600x then -threshold 35%    11,448 bytes   hard stair-step edges on curves
-level 25%,45% then -resize 600x     9,940 bytes   smooth edges
Enter fullscreen mode Exit fullscreen mode

Thresholding after resizing gave the jaggiest result and was the biggest of the three, because hard edges are expensive for JPEG too. -level kept the smooth edges and came out smallest, so that's what I'd use.

One line, with automatic cropping

-trim removes borders that match the corner colour, and -fuzz sets how close counts as a match. On a grey, uneven photo it's useless on its own:

$ magick indoor.jpg -colorspace Gray -fuzz 10% -trim +repage -quality 85 out.jpg
1894 x 2943, 643,324 bytes
Enter fullscreen mode Exit fullscreen mode

It kept most of the photo, because the paper gets darker towards one corner and that gradient doesn't match the corner colour. After -level the paper is flat white and -trim works, as long as the white point is low enough to clear the darkest paper:

$ magick indoor.jpg -colorspace Gray -level 25%,40% -fuzz 10% -trim +repage \
    -bordercolor white -border 40 -resize 600x -quality 85 signature.jpg
600 x 213, 10,002 bytes
Enter fullscreen mode Exit fullscreen mode

With -level 25%,45% instead, a few noisy pixels in the dim corner stayed just below white, and -trim kept a 2723 x 1669 box to include them. At 40% it found the 1491 x 479 signature. If -trim returns something much bigger than the ink, lower the white point a little.

-border 40 puts a white margin back so the strokes don't touch the edge. If the form sets an exact size like 140 x 60 pixels, use -resize 140x60 -background white -gravity center -extent 140x60 so it fits inside and pads the rest with white rather than stretching. Some forms set a minimum KB as well as a maximum, and a clean signature can come out under it: that 140 x 60 version of my test signature was 1,551 bytes. Raising -quality, or the pixel size if the form allows a range, is the way back up.

Without the command line

  • Windows Photos: Edit image, then the crop tool to trim to the signature. The Adjustment panel has brightness, exposure, contrast, highlights and shadows; pushing exposure or highlights up until the paper turns white does roughly what -level does.
  • macOS Preview: draw a rectangle round the signature and use Tools > Crop. Tools > Adjust Color shows a histogram with sliders under it; dragging the right one left sets the white point and the left one right sets the black point, which is the same idea as -level. Saturation at zero makes it grey. Then File > Export as JPEG and watch the size as you move the quality slider.
  • Phone editors: most gallery apps can crop, and many have exposure, contrast and a black point slider in their adjust menu. Some also have a white point or highlights slider. A mono filter does the grey step.

I tested everything above on a Linux box with ImageMagick 7.1.2, so I haven't run these apps myself. The order is what carries over: shoot in good light, crop to the signature with a margin, set the paper to white, then resize and set the quality, and zoom in to check the thin strokes before uploading.

A browser option

I built ToolOcean, and its image-crop page does the crop step in the browser without uploading the photo. You drag a box on the image or type X, Y, width and height. I ran my indoor photo through the live page in headless Chrome with the same box as above: it saved cropped.png, 1569 x 559, pixel for pixel the same as ImageMagick's crop. As a PNG of grey, noisy paper that came to 1,278,084 bytes; the same crop of a copy I'd already put through -level was 155,733 bytes. So set the paper to white first (ToolOcean's image-filters page has brightness and contrast if you'd rather stay in the browser), and convert the result to JPEG at the end if the form wants one: toolocean.co/image-crop.

Drafted with AI help, tested and checked by me.

Top comments (0)