Is it possible to easily determine whether or not an image has any actual content beyond just transparency using ImageMagick?
The back story is that I am cropping a image with unknown content, but a known area map (think game skins). The area I'm cropping for part of this will either contain something or it won't. If it contains something, I need to do something with it. If it doesn't, I need to scrap it and move on. Thanks!
I have a couple of ideas you could try, but I have not seen your images, so you will need to test them out.
Firstly, you could count the number of colours in the image, like this:
identify -format "%[k]" input.png
If there is only transparency, the number of colours will be 1, if there are other colours in the image, it will be greater than one. This cannot differentiate between a pure single colour image and a purely transparent image though. That may, or may not, be a problem. I don't speak Ruby, but I believe you access k like this in Ruby:
image["%[k]"]
Secondly, you could calculate the mean pixel colour of the image, like this:
identify -format "%[mean]" input.png
That will be zero in the case of a fully transparent image. However it will also be zero for a fully black image, which may or may not be a problem.
Both of these parameters can also be seen using
identify -verbose input.png
If you wanted a more robust test, for example to differentiate between a fully trasnparent image and a fully black image, you could use one of the tests above, and combine it with getting the value of a single pixel at top left of image to rule out the odd edge cases above, like this:
convert black.png -format "%[pixel:p{0,0}]" info:
black
convert transparent.png -format "%[pixel:p{0,0}]" info:
none
Another option would be to calculate the histogram, like this and see the colours:
convert input.png -format %c histogram:info:-
I ended up using the following code:
def transparent? image
solid_color = image['%[mean]'].to_i == 0 # transparent or solid color
not_opaque = !image['%[opaque]'].to_bool # no transparency remaining
solid_color && not_opaque
end
image['%[mean]'] gives me 0 for as single color or full on transparency, as Mark Setchell mentioned. This got me half way. In order to determine if the single color is transparent or not, I used image['%[opaque]']. If this was "true", then it is a color. Otherwise, transparent. The .to_bool method simply takes the resulting boolean string and converts it into an actual boolean.
I hope this helps someone else! And thanks again for the significant start toward figuring this out, Mark!
Related
We're doing a cognitive experiment that requires flashing 480 black-and-white images at high speed against a neutral-gray background. The image shown is detail at about 300% zoom; the full display is 932 x 612; there are actually other clusters similar to this one elsewhere on the screen.
We have to generate these images in a source app and later display them in the experimental app. At first, we were using 24-bit PNG's with the background color built in, but despite the size of each file hovering around 10KB, the total file payload of 480 is too large and takes way too long to preload. We can, however, set a default background color in the app and put up 1-bit images. Although we can change the background color in the source application, we don't have control over bit depth there, so we are stuck generating screen captures and then downsampling to binary. We have tried this with original images that sit on both a white background and the gray background. Using ImageMagick, both of these commands yield similar results:
magick gray.png -transparent "rgb(192,192,192)" -alpha set -depth 1 out\gray-out.bmp (or .png)
magick white.png -transparent white -alpha set -depth 1 out\white-out.bmp (or .png)
The PNGs are coming out to 1.5K to 5K, so this is where we want to be. However, we're stuck with that problem aliased edge whether we start with gray- or white-background images. We've also tried the -fuzz argument (1-99%) to no effect. The resulting pseudoalias artifact that we see in these 1-bit files is the same in multiple apps, so apparently it must be built into the output file generated by ImageMagick's attempt to filter the edge, and not an artifact of any single app or the OS.
We don't quite get how an alpha channel can even be attached to a 1-bit image if it is not strictly RGBA: an alpha channel with a 1-bit image doesn't even make sense. But if an alpha channel isn't being included, then where is the map coming from in a nonbinary image to distinguish that "white" edge from a nonwhite surface? It's not the destination apps. The output files must either not be strictly binary, or else ImageMagick is not computing the channel exactly to the contour edges. (When we remove the -alpha argument, ImageMagick generates a larger file; the aliasing (e.g., when we place into PowerPoint and select Transparent Color to white) may appear in slightly different places, but the effect is essentially the same.
The question is, how is it possible to remove this artifact in a 1-bit image using ImageMagick? We'd like to get the file sizes down to the minimum.
I have a series of images. What I wish to do is to literally superimpose these images on top of each other without any other manipulation. The actual example is below
This is the first image
This is the second image
There are five samples like this, each with a tooltip on top of the bar. Essentially, the final image needs have the bars in their full green color with the tool tips showing up on each bar.
The closest I've been able to come up with was using GraphicsMagick which unfortunately does the following with its "average" command.
Any other pointers on how to accomplish this?
Finally: While at this time I just want to get the job done, long term, I will ideally want to use some commandline tool like GraphicsMagick without the need to have a desktop software installed.
You could try using the darken blend mode in ImageMagick:
convert 1.png 2.png 3.png -compose darken -composite result.png
You'd have to tidy up your cropping first though!
On this similar thread they have been proposed solutions to convert the background color of some image to transparent.
But sometimes the background is a simple pattern, like in this case:
Note the square background pattern.
When processing images, the background does often need to be removed or changed, but firstly you need to detect it (i.e: change its color, or making it transparent). For example, on the above image example, I would like to obtain:
How can I detect/change a specified pattern inside an image?
GUI solutions accepted.
Open source solutions preferred (free at least required).
The simplest solution will be preferred (I would like to avoid installing some hundreds of MB program).
Note: I was thinking about posting this question at Photography
StackExchange site, but I would rather say the mind of a programmer (I
could need to edit dozens of such images) is more close to what I
want. I am not an artist.
This is not a fully developed answer, but it does go some way towards thinking about a method - maybe someone else would like to develop it...
If, as you say, your pattern is specified, you know what it is - good, aren't I? So, you could look for the "Minimum Repeating Unit" of your pattern in your image. In your case it is a 16x16 grid like this:
Now you can search for that pattern in your image. I am using ImageMagick at the command-line, but you can use other tools if you prefer. ImageMagick is installed on most Linux distros and is available for OSX and Windows for free. So, I search for that grid in your globe image and ImageMagick gives me an output image showing white dots at the top-left corner of every location where the two images match:
compare -metric ae -dissimilarity-threshold 1.0 -compose src -subimage-search globe.gif grid.png res.png
That gets me this in file res-1.png
Now the white dots are where the 16x16 "Minimum Repeating Unit" is found in the image, but at the top-left corner so I shift them right and down by 8 pixels to the centre of the matching area, then I create a new output image where each pixel is the maximum pixel of the 16x16 grid in which it existed before:
convert res-1.png -roll +8+8 -statistic maximum 16x16 z.png
I can now invert that mask and then use it to set the opacity of the original image, thereby blanking areas that matched the "Minimum Repeating Unit":
convert globe.gif \( z.png -negate \) -compose copy_opacity -composite q.png
No, it's not perfect, but it is an idea for an approach that could be refined...
My requirement is to convert a image with a transparent background to look like gold foil (the way it’s printed on leather etc.)
I've been using ImageMagick and am getting excellent results with certain kind of PNGs but not with others.
The Image Magick command I am using is:
composite foil.png tmp.png logog.png outputg.png
foil.png is just a gold foil image
tmp.png is a plain/empty transparent background png
logog.png is the logo with transparent background
outputg.png is the output (this is what I need)
However, this kind of result does not occur in most other images with transparent backgrounds.
Ex.
logom.png gives outputm.png which is all gold
logos.png gives outputs.png which is all gold and all wrong
Download all files as zip from here from here http://sdrv.ms/1h7QW4A or view from http://s.imgur.com/a/ExLRE
I checked the encodings of these all PNGs and they are all the same. What is wrong with logom and logos that the outputs are not as they should turn out to be?
If I am approaching the solution from the wrong direction, please suggest alternatives.
I have a requirement where I need to create a map flag based on a users avatar:
The users avatar can be any size and aspect ratio. The problem I'm having is getting the image to compose correctly, allowing me to get the transparency around the marker in order to support the tick at the bottom.
How can I do this?
It transpires that this is fairly straightforward with the correct approach.
First you need TWO overlay images. One of these is the size of the result image and is transparent everywhere for except where you want the avatar to show. The second is a simple transparent PNG of the surround on the image.
Then, this seems to work:
composite avatar.jpg -thumbnail 61x68^ -gravity center map_marker.png mask.png output.png