I have a grey scale image, from which I wish to convert all grey pixels into half transparent pixels, and white ones into transparent pixels.
How could I process a grey scale raster image via shell ?
Input :
Output (here made via Gimp):
Current Gimp process via GUI:
GIMP 2.6 > Load your shaded relief image (....shaded.tif : are grayscale)
or a screenshoot of your shaded relief (screenshot : RGB colors)
Force it to be RGB: Gimp > Image > Mode > RGB, click.
Delete the grey : Colors > "color to alpha" pop up > uncheck "preview", click on the horizontal color rectangle > "Color to alpha color picker" pop up> bottom right corner, click on the icon eyes dropper > choice you color of to delete (some grey pixel in a flat plain) > validate.
Delete an other color (white, black background) > same.
File > save as > ProjectName_relief_whitened.png (to keep transparency)
[note: SO images display, and image background CSS makes hard to see the subtile differences between files.]
Given the following gray scale input.png :
1a. To make black pixels of this image transparent and linearly keep the white pixels as they are, run this command:
convert source.png -alpha copy -fx '#fff' result.png
1b. To make white pixels transparent and linearly keep the black as they are, use:
convert source.png -alpha copy -channel alpha -negate +channel result.png
Manual:
convert – is the ImageMagic command (one of several)
source.png – is the greyscale source image.
-alpha copy – it copy contents of the previous file into the alpha channel.
-channel alpha – it specify that following operators only should affect the alpha channel.
-negate – it invert the current channel (channel alpha).
+channel – Specify that following operators only affect the opposite channel. For us, it switch focus from the alpha channel, to the color channel. (color channel is initially the default)
-fx '#000' – Replace current channel (for us, the color channel) contents with black pixels, so the end result actually fully depends on the alpha channel. If not included, all semi-transparent pixels in generated image will retain colors, from #FFF (white) to #000 (black).
Result of 1b:
Wiping out plains:
An additional processing could wipe out most of the flat plains, which appears around greys (#DDDDDD) with opacity:~50%. This could be done by :
convert input.png -fuzz 8% -transparent "#DDDDDD" grey_no.8pc.png
convert grey_no.8pc.png -alpha copy -channel alpha -negate +channel result.grey_no.png
so the plains avoid an useless #DDDDDD, opacity:50% overlay.
See also:
ImageMagick options: http://www.imagemagick.org/script/command-line-options.php
Related
Since it is hard to me to explain what I'm trying to do, I'm gonna show you this page to show you what I'm trying to reproduce and understand:
https://optifine.net/showCape?colTop=FF0000&colBottom=00FF00&colText=0000FF&colShadow=FD0000
which outputs this:
and this one https://optifine.net/showCape?colTop=FF00FF&colBottom=0034EE&colText=000000&colShadow=FF00E2 outputs this:
You can modify the hexadecimal colors, basically I'm trying to reproduce something like that. Basically you modify the colors and it gives you an image at the end with the colors you used.
I've tried to make the "possible" template that could be used on the page on Photoshop which can be downloaded here, it is a .psd file, that's because of the Alpha Channel, which I'm not even sure if done correctly. But based of these RGBA channels it should be possible to change the color. Can be downloaded here: https://workupload.com/file/4xYkgQMk
So what I know so far is that there is a template with RGBA channel. Each channel is indepedent so it apperantly doesn't matter if it's RGBA and at the end R channel is used to turn into another color other than red, where I'm not sure about that.
I've asked the developer he told me that these channels get interpolated with the real color after that, probably the one you choose.
Basically what is happening at showCape? and its URL parameters is that, lets assume colTop got assigned to the red channel then when you put a color in colTop it will get a fixed color that it will encode or something.
So the template has 4 Channels RGBA that can be made in Photoshop, the white color 255,255,255 means basically full and the black 0,0,0 means complete black. Like that you can setup brightness scales for the template.
I just don't know how to modify the channels and I don't understand how to use the Alpha channels properly or set them up.
I'm also not sure in which programming languages it is possible to peform and if you can test the template directly in something like Photoshop. Is it possible to do it in JavaScript or something to easy setup and if not on what then, to test it fast?
Ok, so here's how you can generate that sort of thing with ImageMagick, which is included in most Linux distros and is available for macOS and Windows. Note that there are Python, PHP, node.js and other bindings available.
First, generate a red rectangle:
magick -size 200x150 xc:red red.png
Now see how to do the same thing with hex codes:
magick -size 200x150 xc:"#ff0000" red.png
Now, draw a red rectangle with a blue one on top:
magick -size 200x150 xc:red -fill blue -draw "rectangle 10,10 80,140" redandblue.png
Now make the blue transparent:
magick -size 200x150 xc:red -fill blue -draw "rectangle 10,10 80,140" -transparent blue redandtrans.png
Now make a gradient from lime green to magenta:
magick -size 200x150 gradient:lime-magenta gradient.png
Now overlay the red rectangle with transparent window onto the gradient:
magick gradient.png redandtrans.png -composite overlay.png
Now add text:
magick overlay.png -fill "#0000ff" -pointsize 16 -draw "text 90,40 'Coloured text'" result.png
And now do the whole thing again, in one go:
magick -size 200x150 gradient:lime-magenta \
\( xc:red -fill blue -draw "rectangle 10,10 80,140" -transparent blue \) \
-composite \
-fill "#0000ff" -pointsize 16 -draw "text 90,40 'Coloured text'" result.png
Now you have provided a template, I can separate out the channels with ImageMagick like this and append them side-by-side with Red channel on the left, then Green, then Blue then the alpha/transparency channel on the right. I also added a red box around each one so you can see the extent on StackOverflow's white background.
magick template.png -separate -scale 100x +append channels.png
Keywords: ImageMagick, absolute basics, tutorial, transparency, compose, overlay, command line, image processing.
this sounds like indexed colors / palette effect from the VGA days (like plasma, water and fire) Where you change the palette (in a specific way) and image changes with it.
The idea is that Your image/sprite does not contain RGB colors directly but color indexes from palette instead. Where part of the palette for your image/sprite contains a color gradient so gradients on image are also gradients on index (neighboring shades have also neighboring indexes). Many old pixelart sprites and images from the old days are done this way (sorted palette).
Now you can simply chose few colors in that part of palette and interpolate the rest of the gradient (linearly or better).
To mimic this your need:
have a indexed color pixel art with sorted palette
For example You can convert your image into BMP or GIF with palette and sort the colors.
detect the part of palette with color gradient
change/update the gradient
re-render or recolor image.
I'm trying to make a capcha solver, but I have ran into some trouble. The captcha that I am trying to solve has different coloured backgrounds.
I need to convert it to black text on white background so that it could easily be recognised by tesseract-ocr
I have tried
convert *.png -threshold 50% *.png which only shows some of the digits.
The problem with simple 50% thresholding is that both colours may be lighter than 50% grey and will therefore come out as white. Or, conversely, both colours may be darker than mid-grey and therefore bith come out as black.
You need to do a 2-colour quantisation to get just 2 colours, then go to greyscale and normalize so the lighter colour goes white and the darker one goes black. I am not near a computer, to test, but that should be:
convert input.png -colors 2 -colorspace gray -normalize result.png
Now, you will find some images are inverted (black on white instead of white on black), so you can either test the top left corner pixel and if it is white, then invert the image. Or, you could get the mean of the image and if it is more than 0.5 that would indicate that the image is largely white and therefore needs inverting.
Invert with:
convert input.png -negate output.png
Get top-left pixel with:
convert image.png -format '%[pixel:p{0,0}]' info:-
Get mean value with:
convert image.png -format "%[mean]" info:-
This is general question (between programming and math):
How to replace a color by another in a bitmap?
I assume the bitmap is a 2D-array
Example : Let's replace RGB color [234,211,23] by RGB color [234,205,10].
How to do this color replacement, such that the neighbour colors are replaced as well ? I.e. a smooth color replacement.
I assume there exists methods like linear interpolation for neighbour colors, etc.
What are the classical ways to do this?
Here is an example of how to detect color RGB 234,211,23 and its neighbour colors in a 500x500px image bitmap array x:
for i in range(500):
for j in range(500):
if abs(x[i,j][0] - 234) < TRESH and abs(x[i,j][1] - 211) < TRESH and abs(x[i,j][2] - 23) < TRESH:
x[i,j] = ... # how to set the new color in a smooth way?
I think that a good approach that you can use is to change the whole image to a new color space, I'd rather use HSV color space instead of RGB, you can find some info here: HSV color Space.
When you wish to search for a specific color, RGB model is not the best option the principal reason is the large changes between brightness and darkness of the color. The thresholds on the RGB color space are not useful in this case.
In HSV color space you have a channel to select the color of your interest and the other 2 channels are for the saturation and brightness of the color. But you can get accurate results only using the Hue channel (the first). The only thing that you need to take care about is in realize that you need to work this channel as a circular buffer because the maximum and minimum value are very similar in color, both are the red color.
Once you have the detected color you can set the new one and you can keep the saturation and brightness properties of the old color, by doing this the color changes will look like smoother.
If you wish to replace the colours of pixel in a 2D - Array you do so as following:
Array[x][y] = new value
where x and y stand for the location of the pixel, but keep in mind that images use the right-handed system thus the values of y grow bottom to top while in computers you use the left handed system so y values grow from top to bottom. The exact syntax of assigning the value of the new colour depends on the programming language you are using (the example above works in ruby). Also some programming languages already offer image manipulation functions built in so make sure to read the documentation to avoid implementing an already implemented function.
New Answer
New answer coming - now I understand that you mean the neighbours in the colour sense rather than the geometric sense...
You could calculate the vector colour distance from each pixel of your image to the colour you want to change and use that as a mask. So, if we create the same image as below... say we have a red-yellow gradient as background with a blue square on it and we wish to replace the central orange colour across the middle.
# Make red-yellow gradient with blue square within
convert -size 500x500 gradient:red-yellow -fill none -stroke blue -strokewidth 10 -draw "rectangle 100,100 400,400" image.png
Now clone that image, and fill the clone with the orange tone we want to replace, then calculate the vector colour distance from each pixel to that orange tone:
convert image.png \( +clone -fill "rgb(255,128,0)" -colorize 100% \) \
-compose difference -composite \
-evaluate Pow 2 -separate \
-evaluate-sequence Add -evaluate pow 0.5 \
-negate \
colour_distance.png
You can then use this colour_distance.png as a mask for alpha-compositing, so if we decide to replace that orangey tone with pink, we can do this:
convert image.png \
\( +clone -fill fuchsia -colorize 100% \) \
\( colour_distance.png -sigmoidal-contrast 20 \) \
-composite z.png
Note that I changed the pow 0.5 to pow 0.3 to roll off the mask more sharply.
Original Answer
Here's one way to do it. Say we have a red-yellow gradient as background with a blue square on it and we wish to replace the blue with green...
First, extract all the blue pixels onto a transparent background, then change them to green and blur them so they spread into the neighbouring pixels. Then overlay the blurred green pixels onto the original image.
I choose to do it with ImageMagick but you seem happy to adapt to other languages and libraries...
#!/bin/bash
# Make red-yellow gradient with blue square within
convert -size 500x500 gradient:red-yellow -fill none -stroke blue -strokewidth 10 -draw "rectangle 100,100 400,400" image.png
# Make everything blue green, then everything else transparent, then blur the lot
convert image.png -fill green -opaque blue -fill white +opaque green -transparent white -blur x6 x.png
# Now overlay the blurred greeness onto the original after replacing blues with green
convert x.png \( image.png -fill green -opaque blue \) -compose overlay -composite result.png
Image.png
x.png (the blurred, colour-replaced image)
result.png
I have an icon with a fully transparent background and a semi-transparent, white foreground. I would like to make the foreground fully opaque, can this be achieved with ImageMagick?
I have tried juggling different combinations of these;
http://www.imagemagick.org/discourse-server/viewtopic.php?t=12619
http://www.imagemagick.org/discourse-server/viewtopic.php?t=18196
http://www.imagemagick.org/discourse-server/viewtopic.php?t=16718
, but cannot produce the desired result. Any tips?
It would be easier if you posted your icon, but my testing shows that this works for what I think you have:
convert icon.png -channel A -threshold 75% output.png
The above is somewhat coarse as it makes all partially transparent pixels fully opaque. If you wanted to be a bit more surgical, you could only set the opacity to fully opaque when the Red, Green and Blue pixels are greater than 90% and the original opacity (alpha) is between 40%-60% like this:
convert icon.png -channel A \
-fx "(r>0.9 && g>0.9 && b>0.9 && a>0.4 && a<0.6) ? 1.0 : a" output.png
I need to compose images in rmagick. If I put a png that has transparent regions on another image and set the opacity of that png to 50% the parts that where transparent become white (with 50% opacity). But I want these regions to stay transparent.
Here's my code:
canvas = Magick::Image.new(1024,768)
canvas.opacity = Magick::MaxRGB
image = Magick::ImageList.new('/tmp/trans.png').first
image.background_color = "none"
image.opacity = Magick::MaxRGB/2
canvas.composite!(image, 50, 50, Magick::OverCompositeOp)
canvas.write('/tmp/composite.png')
Any suggestions?
After 8 hours of Googling I came across this post which allowed me to come up with the answer.
http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=19169
convert FileIn.png -channel a -evaluate Multiply 0.5 +channel FileOut.png
-channel a forces the selection of the alpha channel
-evaluate Multiply 0.5 modifies the transparency of the image
+channel changes the selection to include all of the channels in the output
And then to merge the two transparent png's and end up with a 3rd transparent png
(Please note I'm using GraphicsMagick for this operation instead of ImageMagick)
gm convert FileIn1.png FileIn2.png -background transparent -mosaic FileOut.png