Page 1 of 1

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

Posted: 2017-10-09T02:57:41-07:00
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!

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

Posted: 2017-10-09T08:06:49-07:00
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.

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

Posted: 2017-10-09T08:27:59-07:00
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.

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

Posted: 2017-10-09T09:58:56-07:00
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.

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

Posted: 2017-10-09T12:55:10-07:00
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

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

Posted: 2017-10-09T14:28:16-07:00
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.

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

Posted: 2017-10-09T14:44:38-07:00
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.

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

Posted: 2017-10-09T15:05:20-07:00
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

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

Posted: 2017-10-09T15:09:01-07:00
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.

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

Posted: 2017-10-09T15:27:41-07:00
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.

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

Posted: 2017-10-10T04:14:40-07:00
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