Generate image with variable size and get dimensions before image is created

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
tdv
Posts: 5
Joined: 2017-10-09T02:47:48-07:00
Authentication code: 1151

Generate image with variable size and get dimensions before image is created

Post by tdv »

I am writing a logo generator. The logo is simple - it is text of varying length (imagine a clothing store that has BRAND: WOMEN and BRAND: MEN etc.) surrounded by a black box. The black box has four gaps in it at the top, middle left, middle right and bottom. The width of these gaps is fixed.

I want to generate the black box with the gaps in it. To do this, I need to know what the midpoint of the image is so I can draw rectangles that leave the correct gap. So the top left rectangle, for example, would have co-ordinates 0,0 30,[verticalmidpoint - 60]. I'm using:

Code: Select all

leftmidpoint='convert xc: -format "%[fx:h/2]" info:'
But as the image doesn't exist yet, this fails.

How can I get the dimensions of an image before it is written to disk? I'm using ImageMagick 7.0.7-7 on Linux. Thanks for any help!
User avatar
GeeMack
Posts: 718
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Generate image with variable size and get dimensions before image is created

Post by GeeMack »

tdv wrote: 2017-10-09T02:57:41-07:00I want to generate the black box with the gaps in it. To do this, I need to know what the midpoint of the image is so I can draw rectangles that leave the correct gap. So the top left rectangle, for example, would have co-ordinates 0,0 30,[verticalmidpoint - 60]. I'm using:

Code: Select all

leftmidpoint='convert xc: -format "%[fx:h/2]" info:'
But as the image doesn't exist yet, this fails.

How can I get the dimensions of an image before it is written to disk? I'm using ImageMagick 7.0.7-7 on Linux. Thanks for any help!
It's not really clear what you're trying to accomplish. It would be helpful if you could post examples of the result you're trying to achieve. You can't upload directly to this forum, but there are several sites like Dropbox, for example, where you can upload files then post the links here.

Just a concept that might help get you started... ImageMagick can read in or create more than one image at a time. Working with stacks of images is one of IM's more powerful features. You can create and/or read several images, get various dimension information from one or more of them, then use that information to modify or create other images all in the same command. Then some or all the images in the stack can be deleted before the command completes, so even working with multiple images you can output just the data, or the one or more images that you want.
tdv
Posts: 5
Joined: 2017-10-09T02:47:48-07:00
Authentication code: 1151

Re: Generate image with variable size and get dimensions before image is created

Post by tdv »

Sure - here's an example of what I'm trying to create. You'll see that there is a black border around the text with a gap on each edge of the border. The size of the gap is fixed (or, at least, proportional only to the height of the text but that is fixed for my purposes), but its position varies depending on the width of the text.

I'm trying to do this without writing any images to disk unless I absolutely have to.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Generate image with variable size and get dimensions before image is created

Post by fmw42 »

Perhaps draw the text first and pad as desired using label:. Then get the dimensions of the image. Then draw you lines. Or after you create the image, put a black border around it of the desired thickness. Then draw short white (background color) lines in the middle of the border on all four sides to cover the black.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Generate image with variable size and get dimensions before image is created

Post by snibgo »

There are many ways of doing this. For example, we can create an image, then use "-chop" to remove a central set of columns and rows, then "-splice" to put them back, but white. This has also done the same to text, so we first save that in memory (mpr:), and composite that back afterwards.

Windows BAT syntax, with IM v6.

Code: Select all

convert ^
  -pointsize 30 ^
  label:"BRAND" ^
  -size 10x0 xc:white +size ^
  -fill Orange ^
  label:"SUB-BRAND" ^
  +append ^
  -bordercolor White -border 10 ^
  +write mpr:SAVED ^
  -bordercolor Black -border 5 ^
  -gravity Center -chop 8x5+0+0 ^
  -splice 8x5+0+0 ^
  mpr:SAVED ^
  -composite ^
  brandsb.png
Image
snibgo's IM pages: im.snibgo.com
tdv
Posts: 5
Joined: 2017-10-09T02:47:48-07:00
Authentication code: 1151

Re: Generate image with variable size and get dimensions before image is created

Post by tdv »

snibgo wrote: 2017-10-09T12:55:10-07:00 There are many ways of doing this. For example, we can create an image, then use "-chop" to remove a central set of columns and rows, then "-splice" to put them back, but white. This has also done the same to text, so we first save that in memory (mpr:), and composite that back afterwards.
This is really helpful, thanks - saving to memory and then compositing them is so useful.
tdv
Posts: 5
Joined: 2017-10-09T02:47:48-07:00
Authentication code: 1151

Re: Generate image with variable size and get dimensions before image is created

Post by tdv »

fmw42 wrote: 2017-10-09T09:58:56-07:00 Perhaps draw the text first and pad as desired using label:. Then get the dimensions of the image. Then draw you lines. Or after you create the image, put a black border around it of the desired thickness. Then draw short white (background color) lines in the middle of the border on all four sides to cover the black.
This is more or less where I managed to get to so far. Because I'm after a transparent PNG I then converted the white to transparent. It works fine but with an intermediate image step.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Generate image with variable size and get dimensions before image is created

Post by fmw42 »

For transparent background, modify snibgo's code (with unix new line characters) as follows replacing white with "none" and adding the alpha and channel and compose additions.

Code: Select all

convert \
  -background none \
  -pointsize 30 \
  label:"BRAND" \
  -size 10x0 \
  xc:none +size \
  -fill Orange \
  label:"SUB-BRAND" \
  +append \
  -alpha on \
  -channel rgba \
  -bordercolor none \
  -compose copy -border 10 \
  +write mpr:SAVED \
  -bordercolor Black \
  -border 5 \
  -gravity Center \
  -chop 8x5+0+0 \
  -splice 8x5+0+0 \
  mpr:SAVED \
  -composite \
  brandsb.png
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Generate image with variable size and get dimensions before image is created

Post by snibgo »

As always, there are many ways to do the job. "-chop ... -splice" effectively paints a white cross on the image. The command is simple, but it is expensive as it needs two passes over the entire image. It would be quicker to explicitly draw a white cross. Better still, explicitly draw just the four small white rectangles, so this doesn't mess up the text, so we don't need to save it and composite at the end.

But calculating the coordinates of the four small rectangles is a pain in a script. In v7, I expect it could be done by:

Code: Select all

-draw "rectangle A,B C,D"
... where A..D are expressions.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Generate image with variable size and get dimensions before image is created

Post by fmw42 »

You could create 2 small white (or transparent) images and then use -gravity to composite them at the center top/bottom and center left/right sides over the black border.
tdv
Posts: 5
Joined: 2017-10-09T02:47:48-07:00
Authentication code: 1151

Re: Generate image with variable size and get dimensions before image is created

Post by tdv »

fmw42 wrote: 2017-10-09T15:27:41-07:00 You could create 2 small white (or transparent) images and then use -gravity to composite them at the center top/bottom and center left/right sides over the black border.
Thanks - I've tried that with the below script. It works well enough for my purposes for now. Thanks for the help!

Code: Select all

#!/bin/bash

FONT="Arial"
MAINBRAND="MAIN BRAND"
SUBBRAND="SUB BRAND"
MAINCOLOUR="#8ED1D9"
SUBCOLOUR="#D72A4E"
BORDERCOLOUR="#8ED1D9"

convert -size 120x120 canvas:white block.jpg
convert -font "$FONT" -background transparent -pointsize 257 -kerning 53 \
	-fill "$MAINCOLOUR" label:"$MAINBRAND " \
	-fill "$SUBCOLOUR" label:"$SUBBRAND" \
	+append -trim -matte -compose copy \
	-bordercolor transparent -border 200x200 \
	-bordercolor "$BORDERCOLOUR" -border 30x30 \
	-gravity north -draw "image over 0,0 0,0 'block.jpg'" \
	-gravity west -draw "image over 0,0 0,0 'block.jpg'" \
	-gravity south -draw "image over 0,0 0,0 'block.jpg'" \
	-gravity east -draw "image over 0,0 0,0 'block.jpg'" \
	-transparent white\
	final.png
rm block.jpg
Post Reply