Page 1 of 1

Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-15T17:27:38-07:00
by personalrobert
Can I use convert to write only the upper (or lower) 8 bits of a 16-bit grayscale TIF? That is, will the following work?

Code: Select all

convert original.tif -evaluate and 255 -depth 8 lower.png
convert original.tif -evaluate RightShift 8 -evaluate and 255 -depth 8 upper.png
I don't want any normalization to occur. When I go from 16 to 8, how do I know which 8 bits it will use?

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-15T18:31:56-07:00
by snibgo
Can I use convert to write only the upper (or lower) 8 bits of a 16-bit grayscale TIF?
Yes.
That is, will the following work?
No.

The main difficulty with your approach is that when converting 16-bit=>8-bit, the important bits are the ones at the top, not the bottom. And we can't just strip the bottom bits, because 16-bit=>8-bit(#9ABC) = #99, not #9A.

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-15T19:46:20-07:00
by personalrobert
16-bit=>8-bit(#9ABC) = #99, not #9A
I give up. How do you get #99 from the top bits of #9ABC?

Is there documentation of the rules for converting from 16 to 8 bit?

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-15T20:09:56-07:00
by snibgo
Sorry, I meant to say 16-bit=>8-bit(#9A00) = #99, not #9A.

Yes, it's documented somewhere. I forget where; you'll have to look around. And it is in the source code, of course.

To get the correct spread of values, when converting from 8-bit to 16, the 8 bits must be replicated. To ensure symmetry, the conversion is the same in the other direction.

16-bit <=> 8-bit
#0000 <=> #00
#0101 <=> #01
#0202 <=> #02
#0303 <=> #03
#0404 <=> #04
:
#9898 <=> #98
#9999 <=> #99
#9A9A <=> #9A
#9B9B <=> #9B
;
#FFFF <=> #FF

You can see that #9A00 is closer to #9999 than to #9A9A, so it converts to #99.

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T08:22:28-07:00
by personalrobert
So it looks to me that if I want to force #XXYY to convert to #XX (regardless of YY), I should first modify it to #XXXX.
Do you agree?

Thanks a ton for your assistance!

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T10:14:59-07:00
by snibgo
Yes, I think that's right. This seems to be a general solution (not thoroughly tested, and there may be neater/faster solutions):

Code: Select all

convert x.tif -evaluate And 255 -evaluate Multiply 256 ( +clone -evaluate Divide 256 ) -compose Add -composite -depth 8 lower.png

convert x.tif -evaluate RightShift 8 -evaluate LeftShift 8 ( +clone -evaluate Divide 256 ) -compose Add -composite -depth 8 upper.png

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T10:24:20-07:00
by personalrobert
I was thinking:

Code: Select all

-fx "(u & #ff00) | (u >> 8)" -depth 8 upper.png
-fx "(u & #00ff) | (u << 8)" -depth 8 lower.png

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T10:34:21-07:00
by snibgo
Have you tried it? Does it work?

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T10:46:19-07:00
by personalrobert
I tried it. It doesn't seem to work.

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-16T10:58:22-07:00
by snibgo
I'm not an FX expert, but I think the values of "u" are floating point in the range zero to one. Bit-wise manipulations, and coping with rounding errors, is messy.

Re: Decompose 16-bit TIF into two 8-bit PNGs

Posted: 2013-04-23T14:06:50-07:00
by pipe
If you really must do this with imagemagick you can use this trick. It assumes that you know the image dimensions and that you are running on a platform with working pipes (that is, linux/bsd/osx/cygwin..). If you run this in windows you can create a temporary file instead. (GRAY:foo.raw instead of GRAY:-)

You must replace 2*W and H in the commands with the actual double source width and the real source height. If your source image is 320x240 you would write 640x240.
convert gray.tiff -depth 16 GRAY:- | convert -size 2*WxH -depth 8 GRAY:- -define sample:offset=25x50 -sample 50%x100%\! upper.png
convert gray.tiff -depth 16 GRAY:- | convert -size 2*WxH -depth 8 GRAY:- -define sample:offset=75x50 -sample 50%x100%\! lower.png
Upper and lower depends on the endianess of your machine.

If you're a real ImageMagick pro (Anthony), you may figure out a way to do this in one command, or at least calculate the image size in the second convert from the source image.