Page 1 of 1
Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T19:18:15-07:00
by GiantCowFilms
I'm trying to figure out a way to find the largest value in a given channel, and set it to a particular value. Note that the largest value could be different to the possible maximum (for example it could only be 202 instead of 255 in an eight bit image). I would then like to assign it a particular value (for example if it is 202 set it to 235). I found a way to identify the maximum using
, but have been unable to figure out how to set a particular value on a particular channel to a different value while ignoring the other channel. The -fill option seems to be specifically designed for multi-channel operations. Combining all this into one command would be ideal.
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T19:47:47-07:00
by fmw42
What is your IM version and platform? Please always provide that with questions, since syntax differs. It can be done in one command if using IM 7, but not IM 6.
You will have to convert your new value to QuantumRange for your IM compile, since that is what is produce by %[max], i.e. 0-255 for Q8, 0-65535 for Q16, etc, or use "%[fx:100*max]" as a percent value between 0 and 100 (as a float) and -fuzz XXX% to ensure you stay within the equivalent quantum range equivalent integer value.
For IM 6 and Unix, this should work (untested)
Code: Select all
oldmax=`convert image -format "%[max]" info:
newmax=your (integer) value in quantum range
convert image -channel X -fill newmax -opaque oldmax +channel result
where X is R or G or B for an RGB image.
In IM 7 and Unix, try
Code: Select all
magick image -set option:oldmax "%[max]" -channel X -fill newmax -opaque "%[oldmax]" +channel result
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T19:49:13-07:00
by GiantCowFilms
Platform: Windows 10. Version 7 something, I can always install a new one as needed.
Note: I meant the max for the channel. "%[max]" will give you the greatest of the three channel. I want to use the max for the channel I'm manipulating.
Also, your all-in-one command fails. I think newmax and "%[oldmax]" might be in the wrong places . . .
Further -fill doesn't work with just an integer value, at least not on my end:
Code: Select all
magick: unable to open image '65535': No such file or directory @ error/blob.c/OpenBlob/3094.
magick: no decode delegate for this image format `' @ error/constitute.c/ReadImage/509.
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T20:21:25-07:00
by fmw42
Sorry, my error, since I did not test. You must use "gray(value)" for the old and new values where value is in the range 0-255. So this works with the IM internal image logo:
In unix replacing 200 for the red max (which is 255):
Code: Select all
magick logo: -set option:oldmax "%[fx:round(255*maxima.r)]" -separate +channel \
\( -clone 0 -fill "gray(200)" -opaque "gray(%[oldmax])" \) \
-swap 0,3 +delete -combine result.png
In windows replacing 200 for the red max (which is 255):
Code: Select all
magick logo: -set option:oldmax "%[fx:round(255*maxima.r)]" -separate +channel ^
( -clone 0 -fill "gray(200)" -opaque "gray(%[oldmax])" ) ^
-swap 0,3 +delete -combine result.png
%[fx:maxima] is in the range 0 to 1. So I must multiply by 255 and round to an integer. The suffix .r means get the red maximum value
This could have been simpler, but it seems that -fill ... -opaque ... is not channel sensitive.
Code: Select all
im7 magick logo: -channel r -fill "gray(200)" -opaque "gray(255)" +channel tmp2.png
But this must be a bug, since it works in IM 6
Code: Select all
convert logo: -channel r -fill "gray(200)" -opaque "gray(255)" +channel tmp2.png
I will report this.
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T20:42:14-07:00
by GiantCowFilms
Still get an error, Invalid swap index. Also, what values would I need to get that to work for any of the other channels if I needed?
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-06T20:56:50-07:00
by fmw42
Are you running my command in a bat file? If so, then you must double % to %%. Otherwise, I do not know why it should fail. I do not use Windows, so am not sure what is the issue. Try taking out the ^ at the end of the lines and make it into one long line. Perhaps a copy and paste from my command is not keeping the proper ^ end of line character without spaces after it.
Code: Select all
magick logo: -set option:oldmax "%[fx:round(255*maxima.r)]" -separate +channel ( -clone 0 -fill "gray(200)" -opaque "gray(%[oldmax])" ) -swap 0,3 +delete -combine result.png
For other channels replace maxima.r with maxima.g or maximal.b. Then change -clone 0 to -clone 1 or -clone 2 correspondingly. Then you have to use -swap 1,3 or -swap 2,3 correspondingly
Code: Select all
magick logo: -set option:oldmax "%[fx:round(255*maxima.g)]" -separate +channel ( -clone 1 -fill "gray(200)" -opaque "gray(%[oldmax])" ) -swap 1,3 +delete -combine result.png
Code: Select all
magick logo: -set option:oldmax "%[fx:round(255*maxima.b)]" -separate +channel ( -clone 2 -fill "gray(200)" -opaque "gray(%[oldmax])" ) -swap 2,3 +delete -combine result.png
see
http://www.imagemagick.org/Usage/basics/#clone
http://www.imagemagick.org/Usage/basics/#swap
http://www.imagemagick.org/Usage/color_basics/#separate
http://www.imagemagick.org/Usage/color_basics/#combine
What I am doing is:
separate into 3 channel
clone the color channel desired
modify the cloned channel
swap the old color channel with the new cloned one
delete the swapped old channel, which is now the last image in the command line sequence
then recombine the 3 color channels
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-07T08:55:48-07:00
by GiantCowFilms
Round doesn't seem to work correctly on 32 bit images, giving this output for the value 67335:
6733567335.
I'm currently using this on 32 bit tiffs. Which might also explain why swap wasn't working...
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-07T08:55:49-07:00
by GiantCowFilms
Round doesn't seem to work correctly on 32 bit images, giving this output for the value 67335:
6733567335.
I'm currently using this on 32 bit tiffs. Which might also explain why swap wasn't working...
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-07T09:11:46-07:00
by fmw42
Yes, you now have 4 channels from the -separate including the alpha channel. Do you need the alpha channel? If so, then you have a more complex issue of the combine followed by re-inserting the alpha channel.
In unix, if I make the logo: image transparent where it is white, then I have 32-bit image and need to do this to change the red value from 255 to 200
Code: Select all
magick \( logo: -transparent white \) \
-set option:oldmax "%[fx:round(255*maxima.r)]" -separate +channel \
\( -clone 0 -fill "gray(200)" -opaque "gray(%[oldmax])" \) \
-swap 0,4 +delete \( -clone 0-2 -combine \) \
-delete 0-2 +swap -alpha off -compose copy_opacity -composite \
result.png
In windows, if I remove the new line \ and make it one long line, then try
Code: Select all
magick ( logo: -transparent white ) -set option:oldmax "%[fx:round(255*maxima.r)]" -separate +channel ( -clone 0 -fill "gray(200)" -opaque "gray(%[oldmax])" ) -swap 0,4 +delete ( -clone 0-2 -combine ) -delete 0-2 +swap -alpha off -compose copy_opacity -composite result.png
If you are not using an RGBA TIFF (ie. CMYK) then you should convert to sRGB first, otherwise, you would now have to deal with colorspace difference in the combine step and if an alpha channel as well, then 5 channels rather than 4.
When posting questions, it is always a good idea to send your input images to avoid confusion and misunderstandings. They can be uploaded to some free hosting service such as dropbox.com and the URL posted here.
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-07T15:22:17-07:00
by GiantCowFilms
Sorry for not being clear, I mean 32 bits per channel. And yes, it also has an alpha, so 128 bits net total.
Re: Find Max value for a given channel and set it to a specific value.
Posted: 2017-04-07T15:48:56-07:00
by fmw42
What do you get from
Code: Select all
magick yourimage -format "%[maxima.r]" info:
it should still be between 0 and 1, even for 32bit IM compile.
What do you get from
Are you using 32bit IM and with or without HDRI?
Can you post your image to some free hosting service and put the URL here?