| DICOM_Sorter |

    package ij.plugin;
    import ij.*;
    import ij.process.*;
    import ij.gui.*;
    import java.awt.*;
    import ij.util.*;

    /* Sorts a DICOM stack by image number. */
    public class DICOM_Sorter implements PlugIn {
        static final int MAX_DIGITS = 5;

        public void run(String arg) {
            ImagePlus imp = IJ.getImage();
            if (!isDicomStack(imp)) {
                IJ.showMessage("DICOM Sorter", "This command requires a DICOM stack");
                return;
            }
            int stackSize = imp.getStackSize();
            ImageStack stack = imp.getStack();
            String[] strings = getSortStrings(stack, "0020,0013");
            StringSorter.sort(strings);
            ImageStack stack2 = sortStack(stack, strings);
            if (stack2!=null)
                imp.setStack(null, stack2);
        }

        public ImageStack sort(ImageStack stack) {
            if (IJ.debugMode) IJ.log("DICOM_Sorter: sorting by image number");
            if (stack.getSize()==1) return stack;
            String[] strings = getSortStrings(stack, "0020,0013");
            if (strings==null) return stack;
            StringSorter.sort(strings);
            ImageStack stack2 = sortStack(stack, strings);
            return stack2!=null?stack2:stack;
        }

        ImageStack sortStack(ImageStack stack, String[] strings) {
            ImageProcessor ip = stack.getProcessor(1);
            ImageStack stack2 = new ImageStack(ip.getWidth(), ip.getHeight(), ip.getColorModel());
            for (int i=0; i<stack.getSize(); i++) {
                int slice = (int)Tools.parseDouble(strings[i].substring(strings[i].length()-MAX_DIGITS), 0.0);
                if (slice==0) return null;
                stack2.addSlice(stack.getSliceLabel(slice), stack.getPixels(slice));
            }
            stack2.update(stack.getProcessor(1));
            return stack2;
        }

        String[] getSortStrings(ImageStack stack, String tag) {
            double series = getSeries(stack.getSliceLabel(1));
            int n = stack.getSize();
            String[] values = new String[n];
            for (int i=1; i<=n; i++) {
                String tags = stack.getSliceLabel(i);
                if (tags==null) return null;
                double value = getNumericTag(tags, tag);
                if (Double.isNaN(value)) {
                    if (IJ.debugMode) IJ.log("  "+tag+"  tag missing in slice "+i);
                    return null;
                }
                if (getSeries(tags)!=series) {
                    if (IJ.debugMode) IJ.log("  all slices must be part of the same series");
                    return null;
                }
                values[i-1] = toString(value, MAX_DIGITS) + toString(i, MAX_DIGITS);
            }
            return values;
        }

        String toString(double value, int width) {
            String s = "       " + IJ.d2s(value,0);
            return s.substring(s.length()-MAX_DIGITS);
        }

        boolean isDicomStack(ImagePlus imp) {
            if (imp.getStackSize()==1)
                return false;
            ImageStack stack = imp.getStack();
            String label = stack.getSliceLabel(1);
            return label!=null && label.lastIndexOf("7FE0,0010")>0;
        }

        double getSeries(String tags) {
            double series = getNumericTag(tags, "0020,0011");
            if (Double.isNaN(series)) series = 0;
            return series;
        }

        double getNumericTag(String hdr, String tag) {
            String value = getTag(hdr, tag);
            if (value.equals("")) return Double.NaN;
            int index3 = value.indexOf("\\");
            if (index3>0)
                value = value.substring(0, index3);
            return Tools.parseDouble(value);
        }

        String getTag(String hdr, String tag) {
            if (hdr==null) return "";
            int index1 = hdr.indexOf(tag);
            if (index1==-1) return "";
            //IJ.log(hdr.charAt(index1+11)+"   "+hdr.substring(index1,index1+20));
            if (hdr.charAt(index1+11)=='>') {
                // ignore tags in sequences
                index1 = hdr.indexOf(tag, index1+10);
                if (index1==-1) return "";
            }
            index1 = hdr.indexOf(":", index1);
            if (index1==-1) return "";
            int index2 = hdr.indexOf("\n", index1);
            String value = hdr.substring(index1+1, index2);
            return value;
        }

    }

| DICOM_Sorter |