Imagemagick: channel gets lighter after separate/combine operation - imagemagick

I'm trying to combine PBR normal/roughness/metallic map images (.png) into a single RGBA image (also .png), with the normal map in the red and green channels, the roughness map in the blue channel, and the metallic map in the alpha channel.
The following bash command line works, but for some reason the green channel is slightly lighter in the composite image than it is in the original normal image (e.g. a value of 0x7e in the original is raised to 0x87 in the composite). All three other channels keep their original values. If I switch the order of the red and green separation, it's the red channel in the final image that gets lighter. What could be causing that, and how do I avoid it?
convert ImageName_Normal.png -colorspace sRGB -write mpr:NORMAL_R -channel R -separate +channel \
-write mpr:NORMAL_G -channel G -separate +channel +delete \
ImageName_Roughness.png -colorspace Gray -flatten -write mpr:ROUGHNESS +delete \
ImageName_Metallic.png -colorspace Gray -flatten -write mpr:METALLIC +delete \
mpr:NORMAL_G mpr:NORMAL_R mpr:ROUGHNESS -combine -write mpr:RGBCOMP +delete \
mpr:RGBCOMP mpr:METALLIC -alpha off -compose Copy_Opacity -composite -depth 8 \
png32:ImageName_NormRoughMetal.png
ImageMagick version is 6.9.11-60
I tried different variations on it - using \( +clone , another copy of the normal map (with and without +delete after the first one), and so on. None of them worked any better (and some actually gave me two copies of the normal map's red channel even though green was specified on the command line for the second one).

I do not think your command is what you want in Imagemagick. I think you are not keeping the first two parts properly separate.
Try this
convert TestImage_Normal.png -colorspace sRGB -write mpr:NORMAL +delete \
\( mpr:normal -channel R -separate +channel -write mpr:NORMAL_R +delete \) \
\( mpr:normal -channel G -separate +channel -write mpr:NORMAL_G +delete \) \
\( TestImage_Roughness.png -colorspace Gray -flatten -write mpr:ROUGHNESS +delete \) \
\( TestImage_Metallic.png -colorspace Gray -flatten -write mpr:METALLIC +delete \) \
\( mpr:NORMAL_G mpr:NORMAL_R mpr:ROUGHNESS -combine -write mpr:RGBCOMP +delete \) \
mpr:RGBCOMP mpr:METALLIC -alpha off -compose Copy_Opacity -composite -depth 8 \
png32:TestImage_NormRoughMetal_fred.png

Related

Gradient over transparent png image with sparse-color has background color

I have this face source image. I'm tyring to add a gradient to the bottom of the picture so it fades out alpha transparent.
Problem is that the transparent source image is not transparent anymore after sparse-color transformation - the transparent area is now black.
This is my cmd so far:
magick convert face.png -alpha set -background none -channel A -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] none" +channel face-gradient.png
Here is how you have to do that in Imagemagick. Your image already has an alpha channel. So you have to create a new grayscale gradient image as a mask and combine that with the existing alpha channel. (The -sparse-color is going to write over your existing alpha channel.)
magick face.png \
\( -clone 0 -alpha extract \) \
\( -clone 0 -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] black" \) \
\( -clone 1,2 -compose multiply -composite \) \
-delete 1,2 \
-alpha off -compose copy_opacity -composite face-gradient.png

Treasure hunt for edges

I want to make a children's treasure hunt where the next location is given by a picture e.g.
To make a more suitable printable picture, I can use -canny like this:
convert hut.jpg -canny 0x1+10%+30% -negate hutCanny.jpg
To make it more interesting, I was thinking that I want to make two images -one with horizontal lines and one with vertical lines:
convert hut.jpg -colorspace gray -morphology Convolve Sobel -negate hutH.jpg
convert hut.jpg -colorspace gray -morphology Convolve Sobel:90 -negate hutV.jpg
I would like the location to be only guessable when both picture are found and can be combined using a light source. The problem is that Sobel not only detects vertical lines but also angled lines. As can be seen, the location is far too easy to recognise with just one picture. I have been trying with different kernels and trying to erode the pictures. -nothing woks.
How do I make two images that by themselves are not 'guessable' but can be combined to one. e.g. by making one image with only near horizontal lines and an other with only near vertical lines?
You could do something like the following in ImageMagick. Make a random mask and apply it to the image. Then invert the mask and do the same. The two images, when added together, will make the input.
Input:
convert \( hut.png -write mpr:img +delete \) \
\( mpr:img +noise random -channel g -separate +channel -blur 0x5 -threshold 50% +write mpr:mask +delete \) \
\( mpr:img mpr:mask -compose multiply -composite +write hut_out1.png \) \
\( mpr:img \( mpr:mask -negate \) -compose multiply -composite +write hut_out2.png \) \
null:
Output 1:
Output 2:
ADDITION
If it has to be grayscale, then you can do the above and make each output gray.
convert \( hut.png -write mpr:img +delete \) \
\( mpr:img +noise random -channel g -separate +channel -blur 0x5 -threshold 50% +write mpr:mask +delete \) \
\( mpr:img mpr:mask -compose multiply -composite -colorspace gray +write hut_out1.png \) \
\( mpr:img \( mpr:mask -negate \) -compose multiply -composite -colorspace gray +write hut_out2.png \) \
null:
Output 1:
Output 2:
Now add them together to reconstitute:
convert hut_out1.png hut_out2.png -evaluate-sequence add hut_out12.png

Trying to add a stroke around a PNG, can it be improved?

I'm trying to find a good way to add a 3px white stroke to a ton of png files, effectively to make them look like "stickers." I've got some sample code that does a decent job, but I can't seem to get the cropping right. Also, the stroke looks a bit pixelated and I wanted to know if it's possible to get cleaner edges!
I did a bunch of internet scouring, found some sample code, tweaked it around, and came to something that almost resembles what I'm looking for. The images are always going to be PNGs, so I looked into things like inkscape/gimp from the command line but realized I should be able to do this just using convert from the terminal.
convert in.png \
\( -clone 0 -alpha extract -threshold 0 \) \
\( -clone 1 -blur 10x65000 -threshold 0 \) \
\( -clone 2 -fill red -opaque white \) \
\( -clone 3 -clone 0 -clone 1 -alpha off -compose over -composite \) \
-delete 0,1,3 +swap -alpha off -compose copy_opacity -composite \
out.png
in:
out:
ideally:
Your main problem is it is that you do not have enough space bettween your object and the sides of the image. You just need to add your image with transparency and then remove any excess later.
In ImageMagick 6, this should do what you want.
1) read the input
2) add a larger border than you need to add
3) extract the alpha channel from the input and dilate it by the amount of border (in this case 10)
4) copy the previous image and color the white as red and the black as transparent
5) composite the original over the red/transparent image
6) delete the original and the red/transparent image
7) swap the composite with the dilated alpha channel and put the dilated alpha channel into the alpha channel of the previous image
8) trim the excess transparency from the border padding
9) save to output
convert img.png \
-bordercolor none -border 20 \
\( -clone 0 -alpha extract -morphology dilate diamond:10 \) \
\( -clone 1 -fuzz 30% -fill red -opaque white -fill none -opaque black \) \
\( -clone 2,0 -compose over -composite \) \
-delete 0,2 \
+swap -alpha off -compose copy_opacity -composite \
-trim +repage \
result.png
For ImageMagick 7, replace convert with magick.
If on a Unix-like system, you might be interested in my bash ImageMagick script, contour, at http://www.fmwconcepts.com/imagemagick/index.php
A better result can be achieved by replacing diamond:10 with disk:10

Strange effect using 'distort perspective' on multiple images using ImageMagick

I want to create a 3D effect on an image so it looks like a folder, using the +distort Perspective' commands from ImageMagick.
However, if I use the distort multiple times (on different layers) in ImageMagick the result doesn't look correct.
Please see the attached image, left is correct, but the top-right corner of the right image looks strange.
I have used the following commands:
convert square.jpg -brightness-contrast 0x0 -resize 700x700 \
\( -clone 0 -flip -crop 700x140+0-0 -size 700x140 gradient:gray60-black -compose CopyOpacity -composite \) \
-append front.png
convert square.jpg -brightness-contrast -50x0 -resize 700x700 \
\( -clone 0 -flip -crop 700x140+0-0 -size 700x140 gradient:gray60-black -compose CopyOpacity -composite \) \
-append inner.png
convert -background None -virtual-pixel transparent -background white \
\( inner.png +distort Perspective '0,0 0,0 700,0 735,-35 700,700 735,665 0,700 0,700' \) \
\( front.png +distort Perspective '0,0 0,0 700,0 665,35 700,700 665,735 0,700 0,700' \) \
-layers merge +repage 3dimage.jpg
I'm using ImageMagick v6.8
I'm not sure if I understand the layers in ImageMagick correctly.
Can someone see what's wrong? Thanks!
I'm not sure if I understand the layers in ImageMagick correctly. Can someone see what's wrong?
You're doing fine. Just need to repeat the -virtual-pixel transparent on the sub-image for front.png (and perhaps the inner.png too).
convert -background None -virtual-pixel transparent -background white \
\( inner.png +distort Perspective '0,0 0,0 700,0 735,-35 700,700 735,665 0,700 0,700' \) \
\( front.png -virtual-pixel transparent +distort Perspective '0,0 0,0 700,0 665,35 700,700 665,735 0,700 0,700' \) \
-layers merge +repage 3dimage.jpg

Setting opacity of each image drawn on canvas with imagemagick

I have the command below which takes multiple image sources and draw it onto 1 output.png file.
Convert img1.jpg -resize 1000x1000!
-draw "image over 169,555 875,109 'img1.png'"
-draw "image over 29,55 375,209 'img2.png'"
-draw "image over 129,525 15,29 'img3.png'"
png24:output.png
Is there a way to set the opacity of each of the images being drawn? where some might have opacity of 60% , while others have 100%
I tried this but doesn't work:
Convert img1.jpg -resize 1000x1000!
\( -alpha set -channel A -evaluate set 60% \) -draw "image over 169,555 875,109 'img1.png'"
\( -alpha set -channel A -evaluate set 100% \) -draw "image over 29,55 375,209 'img2.png'"
\( -alpha set -channel A -evaluate set 90% \) -draw "image over 129,525 15,29 'img3.png'"
png24:output.png
Thanks in advance
I think you want something like this...
convert img1.jpg -resize 1000x1000! \
\( img1.png -alpha set -channel A -evaluate set 60% -resize 707x447 \) -geometry +169+109 -composite \
\( img2.png -alpha set -channel A -evaluate set 100% -resize 347x155 \) -geometry +29+55 -composite \
\( img3.png -alpha set -channel A -evaluate set 90% -resize 115x497 \) -geometry +15+29 -composite \
png24:output.png

Resources