I have limited experience with programming and Linux and I need your help.

The situation I am in is that I have a stack of black and white .tiff images (approx. 400 of 10 Mb each one) which I need to convert into xyz coordinates plus grayscale values and to compile all those in ONLY a single text file with x,y,z,grayscale (the z coordinates, this way: first image of the folder z=0000, second image 0001...as many z coordinates as images in the folder).

I have a script (that I am pretty unfamiliar with, but I think it is done with Image Magick) which can do it but only for a single image at a time, and adds only the x, y coordinates and a value in grayscale, but no z.

The script is:

The exact format of the TXT image is defined by the convert command, then 'tail' is used to junk the header, 'tr' to character replace every non-number character with a single space, so that the later 'while' can read it easily, junking any comment numbers that may have been left.

convert -depth 8 -colorspace RGB $1 txt:- | tail -n +2 | tr -cs '0-9.\n' ' ' | while read x y Gray junk; do if [ "$Gray" -eq 0 ]; then echo "$x,$y $Gray" done

To run it I put in the Linux terminal:

chmod +x img.sh

And after that (I selected the same name as the image but with .txt as filename):

./img.sh pic0000.tif > pic0000.txt

Also I tried to change it to do it all at once, replacing the line convert -depth 8 -colorspace RGB $1 txt:- |


convert -depth 8 -colorspace RGB $* txt:- |

and putting this in the terminal

chmod +x ./img.sh ./img.sh *.tif > *.txt

And now it puts all the files in one with x y Grayscale, but I cannot add the z values.

By the way,it takes a long time to create the txt file.

The first lines of the final XYZ file must be, for example:

0 0 0 value in greyscale 1 0 0 value in greyscale `

and the last:

3095 2951 400 value in greyscale

Would you give me any clues, ideas or solutions to do it? Any help would be sincerely appreciated.


I'd use a simpler script in ImageMagick and then sed the output. The problem lies in determining your Z images.

Let's say that the image at Z=27 is DCM0027.tif and that you have images from 1 to 420.

Then you need to generate the filename from the number, and parse the file itself. For ease of use, the XYZ.txt file is generated incrementally:


 rm -f XYZ.txt
 for i in $( seq 1 420 ); do
      FILE=$( printf "DCM%04d.tif" )
      convert -depth 8 -colorspace gray $FILE txt:- \
         | sed -e "s/^\\([0-9]*\\),\\([0-9]*\\):.*gray(\\([0-9]*\\))/\1,\2,$i,\3/g' >> XYZ.txt

The above must be run as a script (saved into img.sh and so on). If you need the numbers 1 and 420 to be parameterized, you can do so by replacing them with $1 and $2. Then you would run img.sh 1 420.

Another possibility is to redirect the script itself:

 for i in $( seq $1 $2 ); do
      FILE=$( printf $3 )
      convert -depth 8 -colorspace gray $FILE txt:- \
         | sed -e "s/^\\([0-9]*\\),\\([0-9]*\\):.*gray(\\([0-9]*\\))/\1,\2,$i,\3/g'

The above would require both numbers and the filename structure, and redirection to save data:

 img.sh 1 500 "DCM%04d.tif" > XYZ.txt

"%04d" means "four digits, zero padded". So 0001, 0002, 0003. If the numbers are instead, say, DCM1FILE.tif, DCM9FILE.tif, DCM10FILE.tif etc, you would use "DCM%dFILE.tif" as a file pattern.

Finally, if you need the number of .tif files in a folder, you can use $( ls *.tif | wc -l ) (probably some easier way exists):

 img.sh 1 $( ls DCM*.tif | wc -l) "DCM%04d.tif" > XYZ.txt

Thank you @Iserni, I appreciate your effort, but I think that I don't understand your script.

By the way, In the end I solved the problem, I will post it here, maybe it will be useful to someone.

From .tiff grayscale to .txt in one file, with z coordinates, like this:

x y z Gray (always zero)

To know when one pic ends and another begins, see that the "z" value changes. To compile it: chmod +x ./script.sh and then:


Don't forget to have in the folder ONLY the pictures and the script.

for i in pic*; do
convert -depth 8 -colorspace Gray $i txt:- |
 tail -n +2 | tr -cs '0-9.\n' ' ' |
 while read x y Gray junk;
 do if [ "$Gray" -eq 0 ]; then 
echo "$x $y $z $Gray"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.