ImageMagick and spritesheet - image

I'm working on a little script that generates a sprite sheet. I have 6 spritesheets and I need to re-organize them and put their content (once ordered) in a unique file.
I logically chose to use ImageMagick. But here I'm stuck.
Here is what I have so far :
convert '%d.png[0-5]' \( -crop 456x912+0+0 -crop 3x6+0+0# +append \) -append test.png
This command line takes my 6 files (0.png to 5.png) crop them, and split them into 18 sprites. Once splited, the 18 sprites are aligned horizontally and then aligned vertically with the 18 previous one.
The problem is this command seems to only aligned them horizontally. Instead of being composed of 18x6 sprites, test.png is composed by 108x1 sprites.
Any idea how to perform this in one command ?

You might try another imagemagick tool, "montage," for this one.
$ for i in `seq 1 18 `; do convert -background none -fill black -size 32x32 -pointsize 14 caption:"$i" $i.png; done
$ montage `ls ?.png` `ls ??.png` -tile 6x3 -geometry 32x32 tile.jpg

Related

How to batch-resize PNG files?

I have a number of PNG image files that I'd like to increase in size. I do not want to rescale the image. I just want to extend the white background further down and to the right. In GIMP terms what I want is to increase the Canvas Size, and cover the increased area with white pixels, in a batch context. The input images may be different sizes, but the output images should all be a fixed size (e.g.: 1280 x 720 pixels).
I've tried this with various online tools, with GIMP, and with a very old version of Photoshop. Most of the tools I've tried to date do one of the following which I don't want:
Rescale the existing image to cover the new canvas size, or
Center the starting image and extend the canvas in all directions, or
Fail to perform this in a batch mode.
I just want to extend existing PNG images with additional white pixels down and to the right. What's the easiest way to do this to a large number of files?
imagemagick is a common tool for this. the -crop operation combined with -gravity can probably do what you want.
magick input.jpg -crop 1000x1000+0+0\! -background white -flatten output.png
source for the magick spell: https://legacy.imagemagick.org/Usage/crop/
In ImageMagick, you process a whole folder of images using mogrify. You can extend them using -extent. With mogrify, it is wise to first create a new empty directory to hold the results. So
cd image_directory
mogrify -format png -path path/to/new_directory -background white -gravity northwest -extent WxH *.png
Where WxH, is your desired final width and height after padding with the white. This assumes that all images will be padded to the same width and height
Expand By Size
cd test1
mogrify -format png -path ../test2 -background white -gravity northwest -extent 500x500 *.jpg
Expand By Percent
cd test1
mogrify -format png -path ../test2 -background white -gravity northwest -extent 150x150% *.jpg
For ImageMagick 7, add magick before mogrify. So "magick mogrify ..."
The ImageMagick command that did what I needed used "convert" with the -geometry and -composite arguments. In a Windows batch file context:
for %%a in (img*.png) do (
magick convert -size 1280x720 xc:white "%%a" -geometry 512x384+40+40 -composite "work-%%~na.pdf"
)

Copy a circle of image A into image B

I have two images:
a.jpg
b.jpg
Both images are square (100x100 pixel). I want to cut a circle with a radius of 50 from image a.jpg and paste it in the middle of image b.jpg. I want to save the result in c.jpg.
How can I do this with Linux command line tools? I need to do it within a shell script.
Many different techniques can be used. ImageMagick has FX language that can perform complex calculations.
convert a.jpg b.jpg -fx 'Wi=w/2; Hi=h/2; hypot(Wi-i, Hi-j) < 50 ? u : v' c.jpg
For example...
convert -size 100x100 PLASMA: a.jpg
convert -size 100x100 GRADIENT:LIME-ORANGE b.jpg
convert a.jpg b.jpg -fx 'hypot(50-i, 50-j) < 50 ? u : v' c.jpg
Update with another technique.
A faster approach can be leveraging image mask(s) of the shape you wish to crop, and compose/composite it between both images. It'll require a format that supports alpha channels, but only for the initial work. For example...
Create a circle mask, and copy values to alpha channel.
convert -size 100x100 xc:White -fill Black \
-draw 'circle 50 50 50 5' -alpha Copy mask.png
convert \( a.png mask.png -alpha Set -compose Dst_Out -composite \) \
b.png -compose Dst_Atop -composite c.png
Eric's approach is much more succinct, and probably preferable, but here is another way anyway. I am being very environmentally aware and recycling ;-) his start images:
magick b.jpg \( a.jpg \( +clone -threshold 101% -fill white -draw "circle 49,49, 49,99" \) -channel-fx '| gray=>alpha' \) -flatten result.png
That says... "Load b.jpg as the background. Load a.jpg and then create a transparency mask by cloning the entire a.jpg setting it black and drawing a white circle in it and pushing it into the alpha channel. Then flatten that over the top of b.jpg".
The result is the same as Eric's.

color pixel count with GraphicsMagick

I need to count pixels in an image that are not background color.
I am calling this from PHP (it's from ImageMagick):
gm convert test.png -fill black +opaque "rgb(255,255,255)" -fill white -opaque "rgb(255,255,255)" -print "pixels = %[fx:w*h*mean]\n"
But it does not give any result, nothing.
I tried using histogram instead:
gm convert test.png -define histogram:unique-colors=true -format %c histogram:info.txt
That works, but gives values for every color and more details, I just need a single number please.
You have got a couple of issues here. You seem to be trying to mix GraphicsMagick with ImageMagick when they are not the same thing.
Firstly, GraphicsMagick does not have the +opaque operator that ImageMagick has.
Secondly, it doesn't have the -fx operator that ImageMagick has for doing maths.
I would suggest you move to, the more powerful, ImageMagick. Then it will work as you expect:
# Create a test image
convert -size 200x200 xc:black xc:white xc:red +append image.png
# Count the white pixels
convert image.png -fill black +opaque "rgb(255,255,255)" -print "pixels = %[fx:w*h*mean]\n" nul:
pixels = 40000
If you really, really must do it with GraphicsMagick, I can only suggest the following - which is heavily based on #GlennRanders-Pehrson answer here:
gm convert image.png +matte -matte -transparent white -operator matte negate 1 result.png
gm identify -verbose result.png | grep -EA5 "Opacity:|Geometry:" | grep -E "Mean|Geometry"
Geometry: 600x200
Mean: 43690.00 (0.6667)
Mean: 43690.00 (0.6667)
And your answer will be:
600 * 200 * (1 - 0.667)

Count how many pixels with a specific color in an image?

I want to loop through a folder of images and output to console how many pixels are #333212, how many are #332211 etc. Is this possible in PHP? I found a package that manipulates images but not one that can detect colors of each pixel. Does such a tool or function exist in the PHP library?
EDIT: Doesn't have to be in PHP, the less packages I have to install the better.
You can do this quite easily with ImageMagick, like this. Say we want to count the red pixels...
# First create a little test strip with black, white, red, green and blue parts
convert -size 50x50 xc:black xc:white xc:red xc:lime xc:blue +append out.png
Now convert anything non-red to black so that only red pixels remain
convert out.png -fill black +opaque red n.png
Now count the red pixels by cloning the resulting picture and making the clone fully black (by setting everything to zero), and running a comparison to count how many pixels are not black
convert n.png \
\( +clone -evaluate set 0 \) \
-metric AE -compare \
-format "%[distortion]" info:
2500
And 2500 looks like 50px by 50px to me :-)
Note
The AE is the Absolute Error, i.e. a simple count of the number of differing pixels. The -format "%[distortion]" info: part causes ImageMagick to output the count (%distortion) as a number (info:) rather than as an image.
Obviously, you replace red with "#333212" for your problem.
You can also do all that in one visit, like this:
convert input.png \
-fill black +opaque red \
\( +clone -evaluate set 0 \) \
-metric AE -compare \
-format "%[distortion]" info:

Using ImageMagick to repeat or "tile" an image

How do I tile an image using ImageMagick? I don't think I can use montage because I want the columns displaced by 50% of the original image height.
It's probably easier to show an example of what I'm trying to do:
Start with:
End with:
Thanks!
In case you want plain tiles, without shifting down the second column and the rest of the even columns, you can use this script:
convert -size 800x600 tile:Ball.jpg Tiles.jpg
(probably the majority of people landing on this question want such plain tiles, like I did)
My "Ball.jpg" is 200 x 200 pixels, so this script creates a 4x3 tile image.
For ImageMagick 7 users, replace convert with magick.
Thanks to Fred at Fred's ImageMagick Scripts, here's the solution:
infile="tile.png"
h2=`convert $infile -format "%[fx:round(h/2)]" info:`
convert $infile \( -clone 0 -roll +0+$h2 \) +append -write mpr:sometile +delete -size 1000x500 tile:mpr:sometile output.png
This is exactly what I was looking for.
Even though you did not mention anything about context of usage, I will put it here so more people are aware. Fred's scripts are for non-commercial use. I ended with an alternative solution, however, principle is the same:
Creating shifted tile by:
convert _orange_270.jpg -roll +0+135 _orange_270_r.jpg
Create a column of regular tiles:
montage _orange_270.jpg +clone +clone +clone -tile x4 -geometry +0+0 _1col.jpg
Create a column of shifted tiles:
montage _orange_270_r.jpg +clone +clone +clone -tile x4 -geometry +0+0 _2col.jpg
Combined regular and shifted columns:
montage -geometry +0+0 _1col.jpg _2col.jpg _2cols.jpg
Created full tiled image using last output from point 4:
convert _2cols.jpg -write mpr:tile +delete -size 1920x1080 tile:mpr:tile _wallpap.jpg
Result:
If on a unix-like system with ImageMagick, you could just use my script, tileimage at http://www.fmwconcepts.com/imagemagick/tileimage/index.php.
It provides numerous variations on the flipping, rotation and offsets.
If non-commercial use, then it is free, If commercial use, then contact me for a license.
Information about tiling in ImageMagick can found at http://www.imagemagick.org/Usage/canvas/#tile

Resources