How do I get graphicsmagick to draw a line inside a BMP file? - graphicsmagick

I've installed GraphicsMagick and the gm command responds inside the shell.
I have a BMP file of 400 by 400 white pixels.
I tried this
gm convert -draw 'line 10,10 200,200' blank_canvas.bmp
but all I got was
gm convert unable to open file (10,10)[No such file or directory]
I also tried
gm convert blank_canvas.bmp -draw 'line 10,10 200,200'
and got
gm convert: Non-conforming drawing primitive definition (line) [No such file or directory].
And while we are at it, how do I get it to draw a big number of lines, inputing the data from a text file?

Make a white BMP:
gm convert -size 400x400 xc:white white.bmp
Draw a red line on it, being careful to specify both an input and output image:
gm convert white.bmp -fill red -draw 'line 10,10 200,200' result.bmp
If you don't want to specify an input and an output file because you want the operation done "in-place", use mogrify:
gm mogrify -fill red -draw 'line 10,10 200,200' white.bmp
You can also use mogrify if you have hundreds of images to apply the drawing to, like this:
gm mogrify -fill red -draw 'line 10,10 200,200' *.bmp
Be careful - mogrify is a VERY POWERFUL command that can irreversibly alter lots of images very quickly.
If you want to do lots of lines, all listed in a text file, make it with a format like this and save as draw.txt:
fill red
line 10,10,200,200
fill blue
line 200,10,10,200
fill lime
line 80,120,300,400
And run it like this:
gm convert white.bmp -draw #draw.txt result.bmp
Alternatively, you could use an MVG file like this:
viewbox 0 0 400 400
fill white rectangle 0,0 400,400
fill red line 10,10,200,200
fill blue line 200,10,10,200
fill lime line 80,120,300,400
fill magenta circle 250,250 250,400
And run it like this:
gm convert mvg:lines.mvg result.png
Or, like this if you have a program that generates the lines:
cat lines.mvg | gm convert mvg:- result.png
Keywords: ImageMagick, GraphicsMagick, draw lines, multiple lines, multiple shapes, MVG.

Related

Quoting strings for use in command line

I have a for loop that builds up a string to be converted to a series of arguments for a command on the command line.
the loop looks like:
lineSpecs=""
for tripWire in {1..$numTrips}
do
lineSpec="-stroke ${colors[$tripWire+1]:0} -draw 'stroke-width 3 line $topX,$topY $botX,$botY'"
lineSpecs="${lineSpecs} ${lineSpec}"
done
I then want to execute this command with:
magick "$inputImage" $lineSpecs $outputImage
It should look like:
magick 'input.jpeg' -stroke purple -draw 'stroke-width 3 line 69,188 304,387' -stroke red -draw 'stroke-width 3 line 176,158 429,303' PaintedImage.jpg
but it fails because the string is parsed as:
magick 'input.jpeg' ' -stroke purple -draw '\''stroke-width 3 line 69,188 304,387'\'' -stroke red -draw '\''stroke-width 3 line 176,158 429,303'\' PaintedImage.jpg
How to remove the erroneous quoting?
This is what arrays are for.
lineSpecs=()
for tripWire in {1..$numTrips}
do
lineSpec+=(-stroke ${colors[$tripWire+1]:0} -draw "stroke-width 3 line $topX,$topY $botX,$botY"')
done
magic "$inputImage" $lineSpecs $outputImage
Of course using an array, as chepner suggested in his answer, is the most convenient approach, but if for whatever reason you have to stick with your string, you can peruse it with
magic $inputImage ${(z)lineSpecs} $outputImage
The (z) takes care of interpolating the string properly into the command line.

GraphicsMagick convert GIMP .xcf file to JPG

GraphicksMagick supports reading XCF files: http://www.graphicsmagick.org/formats.html
However, when I try to convert an XCF to JPG, I get the following error:
$ gm convert 00000680002.xcf -resize 2010 -unsharp 1+0.2+0.1 -background white -gravity center -extent 2100x2100 00000680002.jpg
gm convert: Request did not return an image.
If possible, I'd like to stay with GraphicsMagick because I'm also using GM to resize, sharpen, and modify the image in addition to converting it to a JPG.
How can I convert an XCF to JPG?

Overlay images and set transparency R

I have two images and I want to overlay one on top of the other such that the top layer is transparent and allows the features in the below layer to show to some extent.
I am searching for this functionality within magic and imager packages but can't seem to get it done. Found a good example at this link but it seems to be using some geographical packages (raster formatting) but the end result is what I want.
Image 1:
Image 2
Desired Result
With ImageMagick you can start with "input1.png" and overlay "input2.png" with a particular amount of transparency. This command in *nix shell format shows the basics...
magick input1.png \
\( input2.png -channel A -evaluate multiply 0.5 +channel \) \
-gravity center -composite result.png
First that reads in the base image. Then inside the parentheses it reads in the overlay image and reduces its alpha channel opacity to 50% with "-evaluate multiply 0.5". Then it composites the semi-transparent overlay onto the base image.
In that command the overlay will be centered. Setting the "-gravity ..." and specifying a horizontal and vertical offset with "-geometry +H+V" just before the composite allows you place the overlay anywhere you like on the base image.
To use this command from a Windows command line, the backslashes that escape the parentheses "\(...\)" should be removed "(...)", and the continued-line backslashes "\" need to be changed to carets "^".

Output percentage white content of image using imagemagick R

I am rendering two versions of the same web page and would like to know the most efficient use of space. I aim to do this by outputting the pages as images and looking at the percentage of the page that is white. The less white, the more efficient (my criteria!)
How can imagemagick in R be used to output the % white content of an image? I see it is possible through command line, but can't find anything on doing this inside R.
If you want exactly white (not lightgray or something, too), you can do it like this:
download.file("https://www.gravatar.com/avatar/b1cdf616876083f7c5ec1a49fc357530?s=328&d=identicon&r=PG", tf <- tempfile(fileext = ".png"), mode="wb")
f <- function(fn) {
require(magick)
img <- image_read(tf)
r <- as.raster(img)
sum(substr(tolower(r), 1, 7) == "#ffffff") / length(r) * 100
}
f(tf)
# [1] 44.33931
Sorry, I can't help you with the R side of things, but a suitable command for the command line that you may be able to adapt is as follows:
convert image.png -fill black +opaque white -format "%[fx:mean*100]" info:
That replaces with black (-fill black) everything that is not white (+opaque white) and then calculates the percentage white of the result.
Examples
convert -size 100x10 xc:white -bordercolor red -border 50 a.png # Generate test image
convert a.png -fill black +opaque white -format "%[fx:mean*100]" info: # Determine whites
4.5454
convert -size 100x10 xc:white -bordercolor blue -border 10 a.png # Generate test image
convert a.png -fill black +opaque white -format "%[fx:mean*100]" info: # Determine whites
27.7778
In ImageMagick command line, Mark's second line works without having to know the other color. So it works for both images without his first line of code.
convert VQZ9Y.png -fill black +opaque white -format "%[fx:100*mean]\%\n" info:
4.54545%
convert Qpdg8.png -fill black +opaque white -format "%[fx:100*mean]\%\n" info:
27.7778%

Conversion from Color image to 8-bit gray scale

I use R for image processing (packages EBImage)
I have an input 'jpeg' image, which upon reading in 'R' and trying print(Input_Image) gives me the following output Image
colorMode : Color
storage.mode : double
dim : 3888 2592 3
frames.total : 3
frames.render: 1
Now, I would like to convert this Color type input image to 8-bit Grayscale image type.
I am exhausted with manual and internet search but couldn't find a a solution. As I expect end result to be 8-bit, maximum value of the output grayscale image would be 255.
Using the functions readily available in R EBImage I am only able to get a Grayscale image of type double meaning values are in the range 0 and 1.
The image(s) can be converted into gray scale by modifying the attribute of colorMode. Using the file linked in the comments one could try :
library("EBImage")
img <- readImage("16_left.jpg")
With this the file has been read and stored in img (assuming that the JPEG file is in the working directory).
> img
Image
colorMode : Color
storage.mode : double
dim : 1279 853 3
frames.total : 3
frames.render: 1
...
Now the image can be converted into gray scale using
img#colormode <- Grayscale
or
colorMode(img) = Grayscale
The converted image can then be stored as a PNG file:
writeImage(img,file="16_left_bw.png")
In this example three images are stored in the working directory, 16_left_bw-0.png, 16_left_bw-1.png, and 16_left_bw-2.png
Here is the first of these images:
According to an analysis with a standard image viewer (here I used ubuntu's ImageMagick), the image is stored in 8-bit format. The data is still stored in double format and ranges from 0 to 1
> range(img#.Data)
[1] 0 1
but only 256 levels are used:
Hope this helps.

Resources