5

I use ImageMagick and need to do conditional resize of images.

For that I store results of the identify tool into variables.

$infile='test.jpg'
width=$(identify -ping -format %w $infile)
height=$(identify -ping -format %h $infile)

But before resizing I want to do some transformations that change image size: -trim and -shave. So I need to calculate image size in between of trimming and resizing. And I'd like to do the trim operation only once to make a little optimization.

So, I'd like:

  1. to do trim and shave
  2. store [binary] result in a variable (for example: $data)
  3. pass $data variable value as input to identify tool and store its result for conditional resizing
  4. pass $data to convert tool and finish processing

Something like this:

data=$(convert logo: -shave 1x1 gif:-)
width=$(echo $data | identify -ping -format %w gif:-)
echo $data | convert -resize "$width"

But echo doesn't work as needed.

P. S. convert and identify are tools from ImageMagick suite

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
Valeria
  • 95
  • 6
  • 2
    Shell variables are not binary data safe. They cannot contain NUL for example. You cannot store raw binary in them. – Etan Reisner Jun 16 '15 at 18:15
  • 1
    As you are using `bash`, you can make another optimisation and avoid calling `identify` twice, once to read the width and once to read the height, like this `read w h < <(identify -ping -format "%w %h" wizard:)` – Mark Setchell Jun 17 '15 at 08:15
  • Thank you, @MarkSetchell. I've never used Bash before, so it looks like hell. But I'm trying. – Valeria Jun 17 '15 at 11:39
  • You can just run the contained part on its own to see the output that I feed into the `read` command. Run this to see the width and height of the built-in wizard file, or change `wizard:` to the name of one of your own images... `identify -ping -format "%w %h" wizard:` – Mark Setchell Jun 17 '15 at 11:44
  • Thanks! Output redirection and other bash features breaks my mind more than IM syntax. :) – Valeria Jun 17 '15 at 12:06

1 Answers1

8

Bash can not store blobs of data that may contain NULL terminating characters. But you can convert the data to base64, and use ImageMagick's fd: protocol.

# Store base64-ed image in `data'
data=$(convert logo: -shave 1x1 gif:- | base64)
# Pass ASCII data through decoding, and pipe to stdin file descriptor
width=$(base64 --decode <<< $data | identify -ping -format %w fd:0)
base64 --decode <<< $data | convert -resize "$width" -
emcconville
  • 23,800
  • 4
  • 50
  • 66
  • Nice approach - have my vote! For anyone else reading this, you can also just use a hyphen (`-`) for `stdin` instead of `fd:0`. – Mark Setchell Jun 17 '15 at 08:08
  • Ah yes, last line is missing the '-' symbol. Will update answer – emcconville Jun 17 '15 at 11:25
  • Thanks @MarkSetchell for the (-) tip! – emcconville Jun 17 '15 at 11:30
  • There is an error even with '-'. `base64 --decode <<< $data | convert -resize "$width" -` in OS X 10.8 (IM 6.9.1-4 Q16 x86_64) produces: http://pastebin.com/1MzVF3XN And `width=$(base64 --decode <<< $data | identify -ping -format %w fd:0)` in Ubuntu 14.04.2 (IM 6.7.7-10 2014-03-06 Q16) produces: http://pastebin.com/hwLtubUG I deleted my previous comment because of bad formatting. – Valeria Jun 17 '15 at 11:36
  • Sorry, it was stupid. Just needed to add output filename in the last line: `base64 --decode <<< $data | convert -resize "$width" - result.jpg` But what is wrong with Ubuntu? Strange version of base64 utility? – Valeria Jun 17 '15 at 11:46
  • Are you definitely using `bash`? You need to be using `bash` in order to use `<<<` and `$(...)` – Mark Setchell Jun 17 '15 at 11:49
  • @MarkSetchell Yes, it's bash. And I found a solution for Ubuntu, described [here](http://stackoverflow.com/a/9580720/4834319), [here](http://www.codedisqus.com/0iSqVPgVej/decode-base64-invalid-input.html), and [here](http://stackoverflow.com/a/15490765/4834319). `-i` flag added to `base64 --decode` solves the problem. Thanks to all! – Valeria Jun 17 '15 at 12:03