This is a problem I often face and it feels like there should be a trivial solution to it, but I can't figure it out (it probably doesn't help that I'm not a graphics designer either).

Step 1: Take a picture of a printed page. Typically some worksheet for school. Possibly badly photographed by another parent and sent to me on WhatsApp because my kid wasn't at school today.

Step 2: Try to print said page so that my kid can do the exercise.

Step 3: Notice that the print is awful since the photo is fifty shades of gray because of the lighting when taking it.

Now, as a human I can plainly distinguish the black letters/lines on the white page, even though at this point nothing is pure black or white there. So if I could alter the picture to contain only literally pure black and pure white pixels, all would be great.

But I just can't do it. No matter how I play around with curves and what not, no threshold is ever good enough, because the lighting on the page itself is uneven - one corner is usually much darker than the rest, and another brighter, so even though the text is perfectly legible, what counts as "white" in one place of the picture is the same as "black" in another.

How can this be done?

P.S. Since I don't do anything graphics related, I don't have a copy of Photoshop available. My usual weapon of choice is Paint.NET, but my daughter also has Krita installed, so I'd be most grateful for a solution in these programs. However I'll be happy to hear of other tools too or even of the general method itself, so that I can try to replicate it in my programs.

  • well you can try some highpass filtering.
    – joojaa
    Commented Feb 5 at 22:00
  • @joojaa What is that? Isn't that just a threshold? All pixels brighter than X are white; all darker than X are black. If so, then this doesn't work.
    – Vilx-
    Commented Feb 5 at 22:09
  • 3
    If the page has uneven tones, then nothing that is "global" will work well. You need to target areas and adjust areas as necessary. There's almost never "one button to fix it all" for images containing various tonal changes like you describe.
    – Scott
    Commented Feb 5 at 22:50
  • Highpass is definitely not a treshold. Its kind of inverse of blur. Or in fact image editors often use blur to implement highpass by doing original minus blur (so even if you dont have highpass you can still build it with a blur). But you could do it on the signal directly too.
    – joojaa
    Commented Feb 6 at 6:15
  • @joojaa - Ahh, ok, I think I got it. Thanks!
    – Vilx-
    Commented Feb 6 at 6:15

3 Answers 3


As mentioned in the first comment, here's how to do it in the simplest way in Krita.

This is your bad photo; no threshold is good:

enter image description here

High-pass filtering removes smooth brightness variations, but saves sharp ones. Apply Filter > Edge detection > Gaussian highpass:

enter image description here

The average brightness of result is 50% of the max.

Restore black-and-white by increasing the contrast with Filter > Adjust > Color curves:

enter image description here

Warning: A too steep curve (thresholding) will make it rough. Some greys are needed at the edges of the black shapes to make them look pleasant. If the photo has sharp shadow edges this method is useless. Something which really knows which feature is a shadow is needed.

Paint.NET has high-pass filter. I checked it's not preinstalled, one must load a filter plugin to get it. But the Gaussian Blur is available without expansion downloads. It works so well that it's well worth the effort to use it to build the high-pass filtering (as already suggested by others). There's also available blending mode Color Dodge, so the filtering and the contrast restoring curve treatment can be combined.

  1. Make a duplicate of the photo layer and invert the duplicate:

enter image description here

  1. Insert effect Gaussian Blur so that the text is totally unreadable, but the light variations are not remarkably smoothed. For this image blur radius about 50 px is good. Gamma exponent is set to the minimum to make the blurred text to have even less contrast. This parameter is not available in many other programs.

enter image description here

  1. Change the blending mode of the inverted and blurred duplicate to Color Dodge:

enter image description here

And that's it if the uneven light was this simple and caused only too dark white areas. Curves could still be used to increase the contrast, if needed.

If the shadow has sharp edges one could try to paint manually the needed top layer. It's difficult, but it's possible. One of the given comments suggests checking a dodge and burn tutorial. These names are inherited from the pro darkroom skill set from the era before computer photo editing. Professionals and advanced hobbyists used those methods to make local contrast adjustments manually.

  • 1
    Just tried this with a Paint.NET plugin. Had to fiddle around with the options a bit, but the result is perfect! Thank you! :)
    – Vilx-
    Commented Feb 6 at 10:17
  • 1
    Just verified the second method without the plugin. Works great as well! I wouldn't have thought of it (I don't even know what "Color Dodge" is).
    – Vilx-
    Commented Feb 7 at 15:19

In Krita find Levels.

Filters > Adjust > Levels

Or press Ctrl+L

enter image description here

On that window, play with the sliders, so you find a middle point between having clean white and dark text.

enter image description here

The same tool is on Paint.net Ctrl+L (This shortcut is almost standard across several applications)

Sometimes it is impossible to clean without comprehensive retouching. So the question is Is it worth it for homework?

If the answer is yes, then look for Dodge and Burn techniques, where you lighten or darken parts of the image "painting" over it. Lighten stains on the paper.

Dodge and Burn Tutorial and choose the application you use most.

But one fast correction is when the light has only a "fall off", for example, someone took a photo near a window, and the page "grades" to a darker zone (A)

Make two layers. On one adjust the levels so you have a decent contrast on the brighter zone (B)

The second layer uses levels to brighten up the dark zone. The other will be blown up (orange zone) (C)

enter image description here

Now make a transparent gradient on the top layer (D), so you merge the two adjustments on the two zones. (E)

enter image description here


Using image magick:

You can select a color, invert the selection, and then replace the pixels with another color. Select black pixels with a threshld of 40%, invert selection, make the selection white. You might need to play around with the threshold depending on the image.

magick snow.jpg -fuzz 40% -fill white +opaque black snow1.jpg

enter image description here

  • What does -fuzz do?
    – minseong
    Commented Feb 7 at 1:52
  • black only targets pure black RGB(0,0,0) fuzz tells it to also include neighboring colors within a 10% "color distance" from pure black. A detailed explanation is provided here: stackoverflow.com/a/64563233/2079345
    – chiliNUT
    Commented Feb 7 at 1:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.