0

How can I trim whitespace from an image but keep some padding with imagemagick?

I tried the -trim option but imagemagick crops down to the very edge of the content without leaving any padding.

Note, I don't want to add a border in some color but instead keep more of the original image.


Input

magick in.jpg -fuzz 5% -trim out.jpg

A paragraph of text surrounded by lots of whitespace

Expected Output

A paragraph of text with a little margin of whitespace

Actual Output

A paragraph of text with no margin of whitespace

7
  • 1
    See stackoverflow.com/a/35770591/2836621 You can get ImageMagick to tell you the trimbox, then edit it to be a little larger (with bash, awk or dc or even ImageMagick) then crop to it in a second ImageMagick invocation. Commented Aug 10, 2024 at 18:52
  • You didn't state your OS. It might be easier to help if you did. Commented Aug 10, 2024 at 20:22
  • 1
    Ok, cool. You need to use padded_trimbox in final command. Commented Aug 10, 2024 at 20:47
  • 1
    Note you can also read and split the trimbox by setting IFS in bash like this stackoverflow.com/a/28793278/2836621 Commented Aug 10, 2024 at 20:53
  • 1
    Well done! Go ahead and write it up and accept your own answer - you did the work. I only gave hints. Commented Aug 10, 2024 at 20:55

3 Answers 3

3

This ImageMagick v7 command is in Windows CLI syntax. (A version for IMv6 is described below.) It will read the input image, calculate the results of a "-trim" operation, adjust that geometry to provide for wider spacing all around, then create the output using "-extent" with the calculated dimensions and offsets...

magick input1.jpg -set page "%[@]" ^
   -set option:pad 0.15 ^
   -set option:wide "%[fx:page.width+(page.x*pad*2)]" ^
   -set option:high "%[fx:page.height+(page.y*pad*2)]" ^
   -set option:padx "%[fx:page.x-(page.x*pad)]" ^
   -set option:pady "%[fx:page.y-(page.y*pad)]" ^
   -extent "%[wide]x%[high]+%[padx]+%[pady]" ^
   +repage result1.png

Adjust the amount of extra space by changing the value of that "-set option:pad" variable. This is the result of running the above command on your example input image...

enter image description here

EDITED TO ADD: Nearly the same command can be made to work in ImageMagick v6 by applying those dimensions and offsets to a "-distort" viewport instead of using the "-extent" operation.

convert input1.jpg -set page "%[@]" ^
   -set option:pad 0.15 ^
   -set option:wide "%[fx:page.width+(page.x*pad*2)]" ^
   -set option:high "%[fx:page.height+(page.y*pad*2)]" ^
   -set option:padx "%[fx:page.x-(page.x*pad)]" ^
   -set option:pady "%[fx:page.y-(page.y*pad)]" ^
   -set option:distort:viewport "%[wide]x%[high]+%[padx]+%[pady]" ^
   -distort SRT 0 ^
   +repage resultv6.png

These commands can be easily converted to *nix shell commands by changing all the continued-line carets "^" to backslashes "\".

To use the commands in a Windows BAT script, double all the percent signs "%%".

Sign up to request clarification or add additional context in comments.

1 Comment

@GeeMack Clever use of -set page %@ and separating the w,h,ox,oy.
3

Here is a slightly shorter approach with fewer lines of code in bash unix.

The first line sets the padding.
The second line creates variables for ww, hh, ox, oy from the %@.
The third line uses the variables to do the crop.

padding=20

IFS=+ read -r ww hh ox oy <<< $(magick in.jpg -fuzz 5% -format "%@" info: | tr "x" "+")

magick in.jpg -crop "%[fx:$ww+2*$padding]x%[fx:$hh+2*$padding]+%[fx:$ox-$padding]+%[fx:$oy-$padding]" +repage out.jpg

resulting image

13 Comments

Thank you! I found your excellent script trim2detail for trimming with proper edge detection. I'm running it with the pad option like trim2detail -p 20 in.jpg out.jpg 2>/dev/null - the error suppression because it's logging some warnings that the convert command is deprecated in IMv7. What values would you recommend for the other options in this case of scanned text?
@mdcq. Sorry, the IM developers have deprecated convert. I will look into that. You could temporarily set up a symbolic link from magick to convert. Try copying magick to convert in the utilities folder of the download and then compile again. Does that work? I will check the script myself and see what is happening and get back to you.
What is your version of Imagemagick and what is your OS?
@mdcq Your command trim2detail -p 20 in.jpg out.jpg 2>/dev/null works fine for me with or without the 2>/dev/null on IM 6.9.13-14 or 7.1.1-36 on Mac OSX Ventura
@mdcq You could also edit the script and replace convert with magick. I don't know about suggestions. It worked fine for me on your image. The only thing to be aware is if the background is not nearly pure constant color. That is if it has dark specks that might affect the canny edge detector in the script. If so you could try the -an argument that uses connected component area to filter out small regions. As long as you get one large region for the text, you can make this nearly as big as the text to filter out smaller size regions.
|
2

This answer is a compilation of @MarkSetchell's answers 1, 2, 3 and thanks to his help in the comments.


ImageMagick does not support changing the geometry it trims to with -trim directly. However, it can output the geometry it would trim to using the %@ format and crop to a specified geometry with the -crop option.

So, we can first read out the trim geometry, manually add the padding, and then crop to it.

#!/usr/bin/env bash

trimbox=$(magick in.jpg -fuzz 5% -format "%@" info:)

IFS="x+" read width height x_offset y_offset <<< "$trimbox"

PADDING=30
padded_trimbox="$((width + 2 * PADDING))x$((height + 2 * PADDING))+$((x_offset - PADDING))+$((y_offset - PADDING))"

magick in.jpg -crop "$padded_trimbox" +repage out.jpg

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.