Page 1 of 1

Extract low or high bits from an image using convert

Posted: 2012-12-20T13:00:28-07:00
by personalrobert
I have a 16-bit image file and want to create two images/files from it:
  • - the low 8 bits only
    - the high 8 bits only
How can I do this?

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T08:51:58-07:00
by snibgo
I haven't tried this, but I expect if you save a 16-bit image to a lossless 8-bit format, you'll get the high 8 bits. Then subtract this from the original to get the low 8 bits.

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T10:44:18-07:00
by glennrp
I think you could use -fx. I haven't figured out the exact syntax for the low byte, but this works for the high byte of a 16-bit grayscale image:

Code: Select all

    convert -colorspace rgb source.txt -fx "((p / 255) * 257)" -depth 8 high8.txt
I tried a few things for the low byte, but there is some weird stuff that makes shifting and masking fail.
Simply using -depth 8 without the -fx doesn't exactly get the high byte because the pixels are rounded somehow (expected 255 becomes 253).

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T11:27:06-07:00
by fmw42
I really do not understand much about bit-wise processing, but I would have thought something like the following (bit masking) would have worked (though it may need some kind of bit shift perhaps using -evaluate leftshift or rightshift). But unfortunately it only produces a binary result.

# create a 16-bit grayscale image
convert logo: -set colorspace RGB -colorspace gray -depth 16 logo_tmp.png

# use IM -fx with bit-wise and:

convert logo_tmp.png -fx "u & 0000000011111111" -depth 8 logo_tmp_hi.png

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T12:06:46-07:00
by snibgo
My initial thought was mistaken, because when an 8-bit image is promoted to 16-bit, the high byte is propagated into the low byte, rather than the low bytes being set to zero. Thus #aa becomes #aaaa, not #aa00.

Evaluating with "And" a bitmask seems to work. Windows script:

Code: Select all

>convert   -size 1x1   xc:#ffeeaa99bb88   xc:#ffee99aa8877   xc:#001122334455   -append   hilo8.tiff

>convert hilo8.tiff txt:

# ImageMagick pixel enumeration: 1,3,65535,srgb
0,0: (65518,43673,48008)  #FFEEAA99BB88  srgb(99.9741%,66.6407%,73.2555%)
0,1: (65518,39338,34935)  #FFEE99AA8877  srgb(99.9741%,60.0259%,53.3074%)
0,2: (   17, 8755,17493)  #001122334455  srgb(0.0259403%,13.3593%,26.6926%)

>rem Note: #ff00 is 65280; #00ff is 255.

>convert hilo8.tiff -evaluate And 65280 hi.tiff

>convert hi.tiff txt:
# ImageMagick pixel enumeration: 1,3,65535,srgb
0,0: (65280,43520,47872)  #FF00AA00BB00  srgb(99.6109%,66.4073%,73.048%)
0,1: (65280,39168,34816)  #FF0099008800  srgb(99.6109%,59.7665%,53.1258%)
0,2: (    0, 8704,17408)  #000022004400  srgb(0%,13.2815%,26.5629%)

>convert hilo8.tiff -evaluate And 255 lo.tiff

>convert lo.tiff txt:
# ImageMagick pixel enumeration: 1,3,65535,srgb
0,0: (  238,  153,  136)  #00EE00990088  srgb(0.363165%,0.233463%,0.207523%)
0,1: (  238,  170,  119)  #00EE00AA0077  srgb(0.363165%,0.259403%,0.181582%)
0,2: (   17,   51,   85)  #001100330055  srgb(0.0259403%,0.077821%,0.129702%)

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T13:37:23-07:00
by snibgo
Yes, this works for real files. Here's a Windows script that chops a file into low and high bytes, then combines them to reconstruct the original, and finally compares this with the orginal (and reports zero difference).

Code: Select all

set SRC=c:\pictures\20121113\AGA_0994_final.tiff

"%IMG%convert" %SRC% ^
  ( +clone -evaluate And 65280 -write hi.tiff +delete ) ^
  -evaluate And 255 lo.tiff

"%IMG%convert" ^
  lo.tiff  ^
  hi.tiff ^
  -compose Plus -composite ^
  combined.tiff

"%IMG%compare" %SRC% combined.tiff -metric RMSE null:

Re: Extract low or high bits from an image using convert

Posted: 2012-12-21T13:47:23-07:00
by glennrp
This worked. I couldn't get -fx to extract the low byte properly so used a combination of -evaluate and -fx:

Code: Select all

convert -size 256x1 \
          gradient:'#ff000000ff00'-'#00ff000000ff' \
          source.txt

# to test grayscale use  "gradient:'#ff00ff00ff00'-'#00ff00ff00ff'" instead.

convert source.txt -fx "(((p-(.5/256)) / 255) * 257)" -depth 8 high8.txt
convert source.txt -evaluate and 255 -fx "(p * 257)" -depth 8 low8.txt

echo high8.txt:
cat high8.txt
echo low8.txt:
cat low8.txt

Re: Extract low or high bits from an image using convert

Posted: 2012-12-22T03:47:51-07:00
by Bonzo
When I see posts like this I always think "Why would the poster want to do this".

Out of interest why would you want to do this?