GraphicsMagick and FontMetrics - graphicsmagick

My aim is to create a text image and put it on top of other images. This is the command I use to create the text image:
String[] cp_img_arguments = {"convert",
"-size", width_size + "x",
"-background", background_colour,
"-pointsize", pointsize.toString(),
"-font", font_path,
"-fill",text_colour,
"caption:" + text,
destination};
In order to calculate the size of the image I need, I make use of FontsMetrics like this:
Font font = new Font(fontName, Font.PLAIN, pointsize);
Canvas canvas = new Canvas();
fontMetrics = canvas.getFontMetrics(font);
width_size = fontMetrics.stringWidth(toString());
Although I often generate images with the text truncated or multi-line, which means the width I calculate is not actually enough for the text.
The font comes from a .ttf file. I believe this miss-calculation happens because of the density/DPI parameter in GraphicsMagick. I am not currently using it (default is 55 I believe), but I wonder how that affects the actual font size, compared to what FontMetrics calculate.
Does anyone have experience generating images with text using gm? Any ideas how I can make the image dimension calculation more accurate?

Related

Is it possible to set a clip path on a QImage or save what a Qpainter paints?

I have a QImage I am able to clip out a QRegion of and successfully clip out the region using the QPainter class setClipRegion() function. However, I want to save what is drawn as a new QImage but am not seeing anything in the docs about saving what is actually displayed.
I've tried directly changing the images alpha channel to match the clipping region but my implementation is very inefficient. The setClipRegion() function was the only thing I learned that could efficiently display what I wanted. My end goal is to use the clipped image as a QOpenGLTexture so I somehow need to save the originally clipped image.
Thanks for any help.
You can simply specify a new file name when saving. so you do not overwrite the old one.
image = QtGui.QImage('orginal.png')
output = QtGui.QImage(image.size(), QtGui.QImage.Format_ARGB32)
output.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(output)
....
-> your clip path
....
painter.drawImage(QtCore.QPoint(), image)
painter.end()
output.save('new.png')

Load and Save opaque 8 bit PNG Files using ImageSharp

I am trying to Load -> Manipulate byte array directly -> Save an 8 bit png image.
I would like to use ImageSharp to compare its speeds to my current library, however in their code example they require the pixel type to be defined (they use Rgba32):
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
// Image.Load(string path) is a shortcut for our default type.
// Other pixel formats use Image.Load<TPixel>(string path))
using (Image<Rgba32> image = Image.Load("foo.jpg"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2)
.Grayscale());
image.Save("bar.jpg"); // Automatic encoder selected based on extension.
}
I looked through the pixel types: https://github.com/SixLabors/ImageSharp/tree/master/src/ImageSharp/PixelFormats
But there is no grayscale 8 bit pixel type.
As of 1.0.0-beta0005 There's no Gray8 pixel format because we couldn't decide what color model to use when converting from Rgb (We need that internally). ITU-R Recommendation BT.709 seems like the sensible solution because that is what png supports and what we use when saving an image as an 8bit grayscale png so it's on my TODO list.
https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
So... currently you need to use either Rgb24 or Rgba32 when decoding the images.
Update.
As of 1.0.0-dev002094 this is now possible! We have two new pixel formats. Gray8 and Gray16 that carry only the luminance component of a pixel.
using (Image<Gray8> image = Image.Load<Gray8>("foo.png"))
{
image.Mutate(x => x
.Resize(image.Width / 2, image.Height / 2));
image.Save("bar.png");
}
Note. The png encoder by default will save the image in the input color type and bit depth. If you want to encode the image in a different color type you will need to new up an PngEncoder instance with the ColorType and BitDepth properties set.

Windows Small System Icon Height Incorrect

I'm running on Windows 10, but using Delphi 7 (yes, I know it's quite old).
I want to use the system icons in Windows and have gone about this by defining a TImageList called SystemIcons which I initialize as follows:
var
fileInfo: TSHFileInfo;
begin
SystemIcons.Handle := ShGetFileInfo('', 0, fileInfo, SizeOf(fileInfo),
SHGFI_ICON or SHGFI_SMALLICON or SHGFI_SYSICONINDEX);
...
I have SystemIcons properties set statically as a TImageList component with width and height set to 16.
Elsewhere, I wish to retrieve an icon from this image list given a valid shell object's image index. Because these are "small system icons", I expect them to be 16x16. The result of calling GetSystemMetrics(SM_CYSMICON) yields 16. Oddly, the dimensions depend upon whether I retrieve them as a bitmap or an icon.
...
var
icon: TIcon;
bm: TBitmap;
begin
...
icon := TIcon.Create;
SystemIcons.GetIcon(imgIndex, icon);
bm := TBitmap.Create;
SystemIcons.GetBitmap(imgIndex, bm);
The imgIndex is correct and the same in both cases. The image retrieved is the same in each case, as expected. The dimensions of the bitmap (bm.Width and bm.Height) are also as expected: 16x16. However, the dimensions of the icon (icon.Width and icon.Height) are not. They are 32x32.
When I paint the icon on a canvas it appears as 16x16. So it's only its Height and Width values that appear incorrect. Very odd.
Why are these different?
The images are likely actually 32x32 to begin with.
Internally, TImageList.GetIcon() simply retrieves an HICON for the chosen image directly from the underlying Win32 ImageList API, using ImageList_GetIcon(), and assigns that to the TIcon.Handle property.
TImageList.GetBitmap(), on the other hand, is a bit different. It sizes the TBitmap to the dimensions of the TImageList (16x16), and then stretch draws the chosen image onto the TBitmap.Canvas using TImageList.Draw(), which in turn uses ImageList_DrawEx().

Use text instead of marker in nokia HERE map

I want to use text instead of StandardMarker in Nokia HERE map.
I tried using TextMarker but didn't work. May be I used incorrectly. Can you suggest me that how to do this?
TextMarker is not a built-in class of the API, rather the example in the API playground (http://developer.here.com/apiexplorer/examples/public/api-for-js/markers/extending-marker-to-text-marker.html) introduces this class by extending the Marker class. Take a look at the source code of the API explorer example.
The general idea is that you will need to produce a graphics (or graphics image) for the marker icon to use. There are multiple ways to do this but creating an SVG markup string with text is probably the easiest way to do it (as shown in the example code).
What the code in the example does it takes some variables and replaces parts of the SVG template string with the values.
var iconSVG = '<svg width="__WIDTH__" height="__HEIGHT__" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="__X__" y="__Y__" rx="5" ry="5" width="__RECT_WIDTH__" height="__RECT_HEIGHT__" ' +
'style="fill:__BRUSH__;stroke:__STROKE__;stroke-width:__STROKEWIDTH__;"/>' +
'<text x="__OFFSETX__" y="__OFFSETY__" fill="__TEXT_PEN__" style="font-weight:normal; ' +
'font-family:__FONTFAMILY__; font-size:__FONTSIZE__;" textContent="__TEXT__">__TEXT__</text>' +
'</svg>',
From the SVG markup string you can produce a graphics image:
icon = new nokia.maps.gfx.GraphicsImage(that.svgParser.parseSvg(iconSVG));
And this graphics image can be used as a marker icon.
marker.set("icon", icon)
The most important thing to note is that you need to figure out the size of your text (width and height) manually.

How to determine iTextSharp Basefont default style

I am creating a PDF using iTextSharp.
Part of the process adds straightforward text to the PDF and another part creates an outline of the same text.
For the straighforward text aspect I am using the ShowTextAligned method in iTextSharp; which requires a Basefont and has no way of setting the style.
For the outline I am creating a GDI GraphicsPath to get points, which are then translated into PDF curves/lines etc. The AddString method requires a Drawing.FontStyle
Now my issue is that I need to set the style of AddString to the same one being used by the BaseFont. I.E if the Basefont is rendering Regular, i need to set the AddString fontstyle to regular
How do I determine what style is being used by the BaseFont in ShowTextAligned?
Further info:
I have also tried using ColumnText; which allows you to set an iTextSharp Font, along with it's style. Though using this method results in a font that is rendered with the approximate style; I.E a font usually in regular and set to bold gives a slightly malformed bold font.
EDIT
When I say i need to pass in the BaseFont to ShowTextAligned, What I mean to say is that in order to use this method you have to set the font and size first using SetFontAndSize of the PdfContentByte - it is this method that requires the BaseFont.
I know I must be missing something obvious.. I just can't see the wood for the trees :)
You can try defining your base font beforehand and use it throughout your PDF doc.
See iTextSharp - Working with Fonts
Sample code:
BaseFont bfTimes = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
Font times = new Font(bfTimes, 12, Font.ITALIC, Color.RED);
The above lines create a BaseFont object and uses the built-in constant values to set the font family and encoding. It also specifies false for embedding the font within the PDF document. A new Font object is created using the BaseFont object, and further setting the font size in points, the style and the color - again, using iTextSharp's constants for these values.
For more info on BaseFont, see its class definition.
You can use SetColorFill method. Like this
content.BeginText();
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252,BaseFont.NOT_EMBEDDED);
content.SetFontAndSizebaseFont, 12);
BaseColor baseColor = new BaseColor(255, 0, 0);
content.SetColorFill(baseColor);
//or use predefined colors
content.SetColorFill(BaseColor.RED);
// use ShowTextAligned method
content.EndText();

Resources