How to get width/height of text - imagemagick

How to get width/height of written text in Imagemagick?
convert -font 'tahoma.ttf' -draw "text 10,10 'the text'" img.png

we can use queryFontMetrics function of imagick.
see this link (http://php.net/manual/en/imagick.queryfontmetrics.php)
checkout response of this function you will get width and height.

This is really late, but, from PHP.net:
Using:
Imagick::queryFontMetrics — Returns an array representing the font metrics
like this:
// Set font.
$font = PATH/TO/YOUR/CUSTOM/FONT
// Get dimensions.
// Create a new Imagick object.
$imTest = new Imagick();
// Create an ImagickDraw object.
$drawTest = new ImagickDraw();
// Set the font.
$drawTest->setFont($font);
// Set the local X and Y.
$localX = 0;
$localY = 0;
// Dump the font metrics, autodetect multiline
for ($i = 0; $i < strlen($yourText); $i++) {
if ($yourText[$i] === ' ') {
$tempX += $imTest->queryFontMetrics($drawTest, $yourText[$i])['textWidth'];
} else {
$tempX += $imTest->queryFontMetrics($drawTest, $yourText[$i])['originX'] + $imTest->queryFontMetrics($drawTest, $yourText[$i])['boundingBox']['x2'] + $imTest->queryFontMetrics($drawTest, $yourText[$i])['boundingBox']['x1'];
}
}
Where:
characterWidth and characterHeight
- These seem to be related to the size you have specified for the font and don't seem to differ from font to font (at the same size). As
such, they are not especially useful (to me, at least). They are not a
reliable indicator of how much space the font will use.
ascender
- The ascender is the part of the font that is above the baseline. It is not character related - the ascender value is the same for every
character in the font.
descender
- The descender is the part of the font that is below the baseline. It is represented as a negative figure. Adding the absolute values of the
ascender and the descender gives you the...
textHeight
- This is the total height available to the font. It is the same for every character in the font irrespective of its case or how much space
the character seems to occupy. This can be used to determined the line
height when outputting paragraphs, etc.
textWidth
- This value varies from character to character and is the width of the character. This is useful if the boundingBox does not provide
usable values (see boundingBox below). When positioning characters one
by one - don't use textWidth, use originX (see below).
maxHorizontalAdvance
- I'm afraid I haven't quite figured out the purpose of this. It is the same for every character in the font. For the font Arial Italic at
size 67, the value is 89 which is much wider than the advance reported
for the M or the W at the same size.
boundingBox
- This returns an associative array describing the four points (x1, y1, x2, y2) of a rectangle that contain the character. These values
are relative to the origin (i.e. the coordinates of where you are
drawing the character within an image). The returned rectangle is very
accurate and encloses all parts of the printed character completely -
but the boundingBox only works on single characters. It will not give
accurate figures for multiple characters (in my experience anyway).
When drawing a box you need to ADD "x" values to the origin and
SUBTRACT "y" values from the origin. You cannot rely on the
boundingBox for the SPACE character. It returns a boundingBox of
(0,0,0,0). textWidth (see above) comes in handy here.
originX and originY
- these are inaccurately titled. The values returned in originX and originY are actually advanceX and advanceY. These values give you the
position of the next character relative to the current one.
And afterwards you can generate the image with your text like this:
// Generate image.
$cmd = 'convert -size ' . $localX . 'x' . $maxY . ' xc:none -gravity Center -font ' . $font . ' -pointsize ' . $fontSize . ' -annotate +0+0 "' . $yourText . '" ' . FINAL/PATH/TO/YOUR/FILE.png';
$r = shell_exec($cmd);

Look at this page: http://www.imagemagick.org/ImageMagick-7.0.0/script/conjure.php
(3rd example)
The conjure binary lets you run XML based scripts written in the Magick Scripting Language (MSL). Those can make use of IMs "query-font-metrics"-command, that doesn't seem to be available by the other binaries.

Related

Remove unnecessary margin in epslatex/gnuplot

I would like to remove unnecessary margins (gray part in the figure below) in a PDF figure generated by epslatex (gnuplot).
Following are scripts and commands to create the figure.
set term epslatex standalone
set output "figure.tex"
set xlabel "\\LARGE $x$"
set ylabel "\\LARGE $y$"
set format x "\\Large{%.1f}"
set format y "\\Large{%.1f}"
set key left top Left
set size square
set xrange [0.0:1.0]
set yrange [0.0:1.0]
plot x with lines dt 1 lw 5.0 lc rgb "red" title "\\Large $y = x$",\
x*x with lines dt 2 lw 5.0 lc rgb "green" title "\\Large $y = x^2$",\
x*x*x with lines dt 3 lw 5.0 lc rgb "blue" title "\\Large $y = x^3$"
and commands
$ gnuplot sample.gp
$ pdflatex figure.tex
Instead of pdflatex, xelatex would also work. I would like to directly convert to PDF file.
It will be super good if we can remove these margins without too much effort (such as removing the margin manually one-by-one).
Thanks!
If you check help latex, it will tell you that default size is 5 x 3 inches.
Since you set size square, there will be for sure an "unwanted" left and right margin.
What you can do to at least minimize the margins is to set the terminal size to square size as well, e.g. to 3 x 3 inches.
However, keep in mind the graph size is square but x and y axes have tics and labels which require space depending on numbers and labels which might be different for x and y.
set term epslatex standalone size 3 in, 3 in
From help latex:
Syntax:
set terminal {latex | emtex} {default | {courier|roman} {<fontsize>}}
{size <XX>{unit}, <YY>{unit}} {rotate | norotate}
By default the plot will inherit font settings from the embedding
document. You have the option of forcing either Courier (cmtt) or
Roman (cmr) fonts instead. In this case you may also specify a
fontsize. Unless your driver is capable of building fonts at any size
(e.g. dvips), stick to the standard 10, 11 and 12 point sizes.
...
Maybe, there are LaTeX commands to crop the graph to its bounding box.
Thanks to #AlainMarigot help, I change the system to Lua tikz with the option tightboundingbox.
Looks good, but not exactly same as epslatex.

gnuplot pdfcairo matches latex font size

I plot a pdf figure using gnuplot 5.0 with pdfcairo terminal, and then insert this figure into a pdf file using latex. However, I found the font size in gunplot is different with the font size in latex, although I set them to be the same.
To make the font size consistent in gnuplot and latex, I have to set the fontscale in gnuplot as 0.75, as shown in the following codes.
gnuplot codes: plot an 'A' in blue (Helvetica, size 12, fontscale 0.75).
set terminal pdfcairo font 'Helvetica,12' size 1cm,1cm fontscale 0.75
set output 'test0.pdf'
set xrange [-1:1]
set yrange [-1:1]
unset xtics
unset ytics
unset border
set label 'A' at 0,0 textcolor 'blue'
p 1/0 notitle
Latex codes: insert the previous figure in original size, and write a black 'A' (Helvetica, size 12) next to the previous 'A'.
\documentclass[12pt]{standalone}
\usepackage{tikz}
\usepackage{helvet}
\usepackage{graphicx}
\begin{document}
\begin{tikzpicture}
\node at (0,0) {\includegraphics{test0.pdf}};
\node at (0.3, -0.025) {\textsf{A}};
\end{tikzpicture}
\end{document}
You can see the final pdf file here. Now we can see these two 'A' are exactly the same size under the gnuplot setting 'fontscale 0.75'. I don't understand why 'fontscale 0.75' should be used in gnuplot, not 'fontscale 1'?
Is this a problem of cairo? And is there any elegant way to deal with this font size issue?
Short answer: gnuplot uses 72dpi, while cairo uses 96dpi. (96/72=4/3)
Note: For the same reason, if using pngcairo, 'fontscale 0.75' should also be used to get the right font size.
Alternative solution: cairolatex. #user8153
I think this might be due to cairo rendering. In order to set the font size, Gnuplot calls function pango_font_description_set_size with the supplied size, i.e., 12 in your case. However, this is then translated into the cairo units:
the size of the font in points, scaled by PANGO_SCALE. (That is, a
size value of 10 * PANGO_SCALE is a 10 point font. The conversion
factor between points and device units depends on system configuration
and the output device. For screen display, a logical DPI of 96 is
common, in which case a 10 point font corresponds to a 10 * (96 / 72)
= 13.3 pixel font.
Moreveor, from the documentation of the function pango_cairo_font_map_set_resolution:
/**
* pango_cairo_font_map_set_resolution:
* #fontmap: a #PangoCairoFontMap
* #dpi: the resolution in "dots per inch". (Physical inches aren't actually
* involved; the terminology is conventional.)
*
* Sets the resolution for the fontmap. This is a scale factor between
* points specified in a #PangoFontDescription and Cairo units. The
* default value is 96, meaning that a 10 point font will be 13
* units high. (10 * 96. / 72. = 13.3).
*
* Since: 1.10
**/
So in summary, it seems that the supplied size is then for the purposes of the rendering multiplied by 96/72 = 4/3 which effectively yields a font of size 16 instead of 12. The scaling factor of 0.75 which you applied would then revert this.

How do I measure the real height of a rendered string?

I’m trying to measure a string to be drawn. I have tried sizeWithAttributes:, but that doesn’t make a difference between different characters:
NSLog(#"A: %#", NSStringFromCGSize([#"." sizeWithAttributes:labelAttributes]));
NSLog(#"B: %#", NSStringFromCGSize([#"X" sizeWithAttributes:labelAttributes]));
A: {6, 23}
B: {12, 23}
Note that the reported height is the same for both characters. Is there a call that would honour the height difference between . and X?
There's no such thing as "real height". Font metrics are a complex topic.
A string (consisting of characters) is converted to a bunch of glyphs. Those glyphs define what will be visible (rendered). This process involves endless subtleties that might change what you define as the "real height".
Examples:
Some characters extend very far over the normal line height.
Some (graphical) rendering options stretch out beyond the bounding box of all glyphs (like shadows or outlines).
Font metrics contain a myriad of different values for what could be considered the bounding box of a character (or glyph).
This image shows the string "abc f 123" rendered using the font Zapfino (in TextEdit.app on a Mac). The f character is selected (green box). The visual character stretches far beyond of what the selection considers the bounding box.
The red text has a shadow applied to it. It's not easy to calculate the bounding box of this part of the text either.
Your case sounds like you consider a "." character to have a smaller size than a "X". But has a space character a zero size then? It's really difficult to define the "real size" without exact knowledge of the use case. And even then there are often many undefined edge cases.
I had a use case where I wanted to convert strings to PNG images (stupid, I know). In that case the best option was to render the string into a large bitmap context and then search through the raw data bitplanes from the outside inwards until finding first non-transparent pixels.
Agree with Nikolai. I think the best you can do is to get smallest possible size like following.
self.myLabel.text = #".";
[self.myLabel setNeedsLayout];
[self.myLabel layoutIfNeeded];
NSLog(#"A: %#", NSStringFromCGSize([self.myLabel systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]));
self.myLabel.text = #"X";
[self.myLabel setNeedsLayout];
[self.myLabel layoutIfNeeded];
NSLog(#"B: %#", NSStringFromCGSize([self.myLabel systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]));
A: {5, 21}
B: {11, 21}
If you want the smallest possible size, pass UILayoutFittingCompressedSize; for the largest possible size, pass UILayoutFittingExpandedSize.

Word Wrap text in Argox OS214 - PPLA

I use PPLA language to print labels directly to an Argox OS-214.
How can I word wrap long texts?
Do I have to make the calculations or is there any function that does that for me?
If I have to calculate, do you hav any tips on how to do it?
In the PPLA language manual there are no functions to word wrap long text lines, so you have to calculate yourself where to insert the line breaks before sending the commands to the printer.
How to do it depends by the programming language that you are using; for example in the PHP language there is a wordwrap function that can do it for you (the C source code of the wordwrap function is here, at line 803).
A simple description of a word wrapping algorithm can be found on the wikipedia:
SpaceLeft := LineWidth
for each Word in Text
if (Width(Word) + SpaceWidth) > SpaceLeft
insert line break before Word in Text
SpaceLeft := LineWidth - Width(Word)
else
SpaceLeft := SpaceLeft - (Width(Word) + SpaceWidth)
First of all, you have to split the text in words, but I suppose that this is not a problem for you, so I won't elaborate further.
LineWidth should be calculated as the label width minus the left and right margins width.
Assuming that for your text you're using a single fixed-width (non proportional) font, you can convert the LineWidth to a number of characters by simply dividing it by the character width (or by simply printing a long line of text and then counting the number of characters that gets printed); this way each word length corresponds to the number of its characters.
Otherwise, if you're using a proportional font, calculating each word width is more difficult, unless you know each character width.
An idea could be using an image with the same pixel size of the label, just to simulate the printing and for calculating where to insert the line breaks, but this requires to have a function to calculate the pixel width of each word (for example in PHP there is the imagettfbbox function), and also to use exactly the same font on the printer and the PC.
Be aware that you could also have to handle some words that are longer than the label width; in this case you must simply split the word at LineWidth and continue on the next line.

Ruby & RMagick: determining real width & height of text

I'm using RMagick and I want to draw text vertically or horizontally (depends on user input) with background color set by user. I've ran into odd problem: get_type_metrics(text) returns invalid data. Actual width / height are smaller than returned by method.
I've been trying to play around with ascent / descent values, but no luck. Is there any way to determine real width / height of text string? I've seen couple solutions drawing text on empty image then determining width height then looking through whole image pixel by pixel, but imho thats stupid and really resource consumptive. Also as I've find out PHP GD has same issue and no solution.
P.S. I can't use Draw#annotate because user should be able to change background box size.
As I've found out, there's undocumented (in RMagick) bounds member of TypeMetric struct which is documented in FreeType Glyph Conventions and your real width & height of text is determined like this
gc = Magick::Draw.new { ... }
# *** setup gc with font, stroke, pointsize, ... *** THATS IMPORTANT!
metrics = gc.get_type_metrics("your text")
box_width = metrics.width # this one is ok by default
box_height = (metrics.bounds.y2 - metrics.bounds.y1).round # this is the actual heihgt

Resources