Imagemagick: Draw text in a bounding box with long ascenders and descenders - image-processing

I've got a bit of a weird question and, after parsing through ImageMagick's extensive documentation for hours, I cannot find an answer.
I have a program that creates text boxes within larger images. My current solution uses label: and caption: to create a temporary image sized appropriately, then later composites this image into the larger image. This has worked for me up until now.
convert \
-size 321x93 \
-font Carolyna-Pro-Black-Regular \
-pointsize 43 \
-fill #808080 \
-gravity center \
label:"Carolyna Pro Black\nis an obnoxious font." \
/tmp/generator20140421-7999-157xadf.png
However, recently I added some new fonts, and these fonts are a pain to work with because they have rather large ascenders and descenders (loopy, curly bits above and below the text.) In the case of these fonts, these ascenders and descenders are supposed to overflow their bounding box. I've tried a few things, but none produce the desired effect:
Making the bounding box larger: It seems like this would work, but when the -gravity is set to North, the text moves all the way to the top and clips the top anyway.
Various forms of the -draw command: These don't give me the ability to use -gravity to align my text within the bounding box, and don't seem to work with multi-line text.
Not specifying a -size argument and cropping the image later. This might be the only option, but it will take a lot of manual computation to get it to align text correctly, and adds an extra step to the process.
Essentially, my problem is that I need the text aligning capabilities that label: provides, but I don't want my text to be unnecessarily cut off.
Any ideas?

The solution turned out to be as simple as adding a newline character before and after the text, and adding the height of the text to the top and bottom of the bounding box.

Related

How to crop or chop the images at the L shaped corner edges with imagemagick

[]
I use imagemagick -6 for conversion.
I have an image like above. Actual image resides in the rectangular area. I need to remove the L shaped corner edges as you see. I tried with lots of options available in : https://imagemagick.org/Usage/crop/#splice . As crop/chop and shave options applicable symmetrical to both sides. I was thinking If I can just splice the un-wanted L shaped areas.
I tried with convert -background blue -gravity East -splice 10x10 +repage but of no luck. It basically adds a cross in horizontal and vertical in the middle of the image. Please advise if it possible just to erase/chop a particular area. e.g. some portion of an edge and not the complete edge. The reason here is I don't want to chop-off any part of rectangular shape but the L shapes above and below. Basically looking for removing/splicing with white color just L shaped one corner at a time if possible using Imagemagick-6. As I don't know about the pixel size in advance. I don't know if one liner solution will work.
Many thanks!
I think you mean this:
magick image.png -crop 305x365+232+58 result.png

How to identify fully formed rectangles?

I'm trying to identify the coordinates of the reactangles that are fully formed. I mean, that have 4 sides with white border line making fully box.
This is the input image I have.
In the below image I show, in yellow, the rectangles for which I'd like to get the coordinates.
In this input image there are 3 black rectangles with white border line and 1 rectangle that is all white.
My current convert code gives coordinates of all areas, including those white areas that generate noise for my purpose.
convert input.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=100 \
-connected-components 8 -auto-level out:null | grep "255,255,255"
7602: 233x81+295+192 411.0,232.0 18873 srgb(255,255,255)
31: 356x70+365+28 542.4,57.2 4602 srgb(255,255,255)
7604: 538x510+45+273 163.1,529.1 4394 srgb(255,255,255)
7605: 292x470+627+273 809.5,494.2 2116 srgb(255,255,255)
1393: 149x45+785+40 860.8,60.5 2040 srgb(255,255,255)
8449: 513x125+70+658 326.0,708.6 761 srgb(255,255,255)
7015: 43x27+291+110 312.5,122.1 620 srgb(255,255,255)
7599: 84x43+676+148 717.5,169.0 250 srgb(255,255,255)
So, my question is: is there a way to identify from the output given by convert command, which coordinates belong to rectangles fully formed? Thanks
A couple of ideas spring to mind. I haven't developed them into full solutions but may do so if time permits later.
You could maybe choose the centre of each connected component in your list as the seed point for a flood-fill with, say yellow, and then make everything not yellow black (with -fill black +opaque yellow) and run connected components again to see if you get a filled shape the correct area. So, for example, choosing your 4th output line:
7604: 538x510+45+273 163.1,529.1 4394 srgb(255,255,255)
And flood filling from the centre:
magick outlines.png -fill yellow -floodfill +314+478 black result.png
Or maybe go a little further:
magick outlines.png -fill yellow -floodfill +314+478 black -fill black +opaque yellow result.png
Then run another connected components analysis and see if you get a fully yellow-filled shape detected.
You could maybe run a Hit-or-Miss morphology, looking for line ends and follow them back to T-junctions and erase them to get rid of the "overshoot" lines that stick out beyond the ends of your rectangles.
By the way, if you are looking specifically for rectangles, you will probably be better off checking for 4-connected components rather than 8-connected as at present.

Trim image with transparency around and know it's location

I know it is possible to trim all transparency around image to make image smaller and contain only the image. But is it also possible to somehow know the location of "box", that contains the image?
For example I have 100x100 transparent image, which contains something at 10x10 box having topleft corner at x=15,y=15. Rest is all transparent.
I'd like to end up with 10x10 image, all transparency around trimmed, but also having that 15,15 information. Those are probably 2 separate actions. How do I do this in a script?
Just fyi - I am having bunch of images like this and they are layers, that I need to trim and stack onto eachother to make them clickable.
There are lots and lots of words but no image in your question so I am trying to guess what you want. I made this input image:
magick -size 100x100 xc:black -fill white -draw "rectangle 10,20 50,80" image.png
And I think you want to know the trim box, which is where it would trim to if you ran -trim:
magick image.png -format "%#" info:
41x61+10+20
So that's a 41x61 box with the top-left at (10,20).

Put image on top of other image, but resize to fit first

I have two pngs. One is of unknown size (but always square), the 2nd is 1024x1024 and mostly transparent. I want to put the 2nd on top of the first, but first scale it down to the size of the first.
E.g. image1.png is 100x100, overlay.png is 1024x1024. The resulting image size is 100x100 with the overlay scaled down to 100x100 and put on top of the source file.
So far I got this:
magick convert ~/Downloads/Test\ icon.png res/drawable/icon.png -gravity center -composite ~/result.png
But the resulting image is 1024x1024 and the original is tiny somewhere in the center.
This will read in both images, resize the second to fit within the dimensions of the first, then composite the second centered over the first.
magick img1.png img2.png \
-resize %[fx:u.w]x%[fx:u.h] -gravity center -composite output.png
If used in Windows, that continued line backslash "\" should be changed to a caret "^". If used in a Windows BAT script, the single percent signs "%" need to be doubles "%%".
EDITED TO ADD: The way that works is this... Two images are read into the command. The FX expressions "u.w" and "u.h" stand for the width and height of the first image. So to "-resize" first image to its own dimensions doesn't change it, of course. And the second gets resized to fit within the dimensions of the first.

Specify endpoints of lines by percentage of image size

I'm trying to draw the stretch bars on various sizes of ninepatch images. I'm doing this in a script, and I'd like to be able to specify a different master image or scale it to a different size without manually recalculating all the pixel coordinates of the lines I'm drawing on it. Is there a way to specify the endpoints of lines as a percentage of the image size? I tried this, which does not work:
convert -draw 'line 0,45% 0,55%' $myfile tmp~ && mv tmp~ $myfile
I had hoped this would draw a line along the middle 10% of the left side of the image. It does draw a line, but it ignores the percents and draws the line from 0,45 to 0,55 regardless of the image size.
If this is not possible with ImageMagick, is there another Linux command-line tool I could use?
I don't believe you can do that using percentages, but you can get it pretty succinct and avoid having to do any calculations using bash or bc or somesuch by using ImageMagick's built-in fx operator to calculate the line position as a function of the image height.
The best I can come up with is this:
linespec=$(convert image.jpg -format "0,%[fx:int(h*0.45)],0,%[fx:int(h*0.55)]" info:)
convert image.jpg -stroke red -strokewidth 32 -draw "line $linespec" image.jpg
Of course you can replace image.jpg with a variable, and you can also make it an (ugly) one-liner by putting the first command in the middle of the second if you really want to.
Note also, that there is no need to create a temporary image and rename like you do - you can just draw on your original like I have.

Resources