-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathmakepyramid-scn
executable file
·210 lines (171 loc) · 6.17 KB
/
makepyramid-scn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/bin/bash
set -e
set -x
# Check if file is BigTIFF
# $1 file
bigtiff() {
if [ "0000000 4949 002b" != "$(dd if="$1" iflag=count_bytes count=4 | od -x | head -n1)" ]; then
return 1
fi
return 0
}
# Get fieldoffset for TIFF
# $1 file
fieldoffset() {
if bigtiff "$1"; then
echo 8
else
echo 2
fi
}
# Get fieldsize for TIFF
# $1 file
fieldsize() {
if bigtiff "$1"; then
echo 20
else
echo 12
fi
}
# Get IFD offsets
# $1=IFD number
# $2=file
diroffsets() {
tiffinfo "$dest" | grep "TIFF Directory at offset" | sed -e 's;.*(\(.*\))$;\1;'
}
# Get offset for IFD
# $1=IFD number
# $2=file
diroffset() {
diroffsets "$2" | head -n$(($1 + 1)) | tail -n1
}
# Get number of tags in directory
# $1=IFD offset
# $2=file
ntags() {
echo "od -j $1 -N 2 -d \"$2\"" >&2
od -j $1 -N 2 -d "$2" | head -n1 | sed -e 's;^[0-9]* *\(.*\);\1;'
}
# Offset of next pointer in IFD
# $1=IFD offset
# $2=file
nextoffset() {
echo "$(($1 + $(fieldoffset "$2") + ($(ntags $1 "$2") * $(fieldsize "$2"))))"
}
# Write uint64 little endian value to binary file
# $1=value
# $2=destination file
# $3=offset in file
update_uint64_le() {
if bigtiff "$2"; then
printf "$(printf %.16x $1 | sed -e 's;\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\)\(..\);\8\7\6\5\4\3\2\1;' | sed -e 's;\(..\);\\x\1;g')" | dd of="$2" conv=notrunc,nocreat oflag=seek_bytes seek=$3
else
printf "$(printf %.8x $1 | sed -e 's;\(..\)\(..\)\(..\)\(..\);\4\3\2\1;' | sed -e 's;\(..\);\\x\1;g')" | dd of="$2" conv=notrunc,nocreat oflag=seek_bytes seek=$3
fi
}
makeuuid() {
echo "urn:uuid:$(uuidgen)"
}
scnmeta() {
tiffcomment "$1" | egrep "<pixels|dimension" | sed -e 's;.*<dimension.* ifd="\([0-9][0-9]*\)".*;\1;' -e 's;.*<pixels.*;series;'
}
scnifds() {
scnmeta "$1" | grep -v "series"
}
scnmainifds() {
scnmeta "$1" | grep -h -A1 series | egrep -v "series|--"
}
scnsubifds() {
filter="series"
for ifd in $(scnmainifds "$1"); do
filter="$filter|$ifd"
done
scnmeta "$1" | egrep -v "^$filter\$"
}
scnseriessubifds() {
scnmeta "$1" | sed -n "/^$2\$/,/series/p" | egrep -v "^($2|series)\$"
}
src="$(ls -1 orig/*.scn)"
mkdir -p new
for srcfile in $src; do
echo "Processing $srcfile"
base="$(basename $srcfile)"
dest="new/${base%.scn}-subifds.tiff"
cp "$srcfile" "$dest"
if bigtiff "$dest"; then
echo "Using BigTIFF offsets"
fi
nifds=$(scnifds "$srcfile" | wc -l)
ifds=$(scnifds "$srcfile")
mainifds=$(scnmainifds "$srcfile")
subifds=$(scnsubifds "$srcfile")
nmainifds=$(echo "$mainifds" | wc -l)
echo "IFD count: $(echo $nifds)"
echo "IFDs: $(echo $ifds)"
echo "Main IFDs: $(echo $mainifds)"
echo "SUBIFDs: $(echo $subifds)"
# Main header
tiffset -d 0 -s 270 "OME Pyramid TIFF test (from $base)" "$dest"
tiffset -d 0 -s 305 "A gnarly shell script (makepyramid-scn)" "$dest"
tiffset -d 0 -s 315 "Roger Leigh <[email protected]>" "$dest"
# NewSubFileType
for ifd in $mainifds; do
tiffset -d $ifd -s 254 0 "$dest"
done
for ifd in $subifds; do
tiffset -d $ifd -s 254 1 "$dest"
done
# SubIFDs
for mainifd in $mainifds; do
subifds=$(scnseriessubifds "$srcfile" "$mainifd")
nsubifds=$(echo "$subifds" | wc -l)
subifds_start=$(echo "$subifds" | head -n1)
subifds_end=$(echo "$subifds" | tail -n1)
subifds_diroffs=$(echo $(tiffinfo "$dest" | grep "TIFF Directory at offset" | sed -e 's;.*(\(.*\))$;\1;' | head -n$(($subifds_end+1)) | tail -n$nsubifds))
echo "SubIFDs for series $mainifd: $subifds_diroffs"
tiffset -d $mainifd -s 330 $nsubifds $subifds_diroffs "$dest"
subifds_diroffs=$(echo $(tiffinfo "$dest" | grep "TIFF Directory at offset" | sed -e 's;.*(\(.*\))$;\1;' | head -n$(($subifds_end+1)) | tail -n$nsubifds))
echo "Updated SubIFDs for series $mainifd: $subifds_diroffs"
done
echo "New directories:"
diroffsets "$dest"
dest2="${dest%.tiff}-flat.tiff"
cp "$dest" "$dest2"
# Relink IFDs to elide SubIFDs. Run backward to keep the file readable between iterations.
nextdiroff=0
for mainifd in $(echo "$mainifds" | tac); do
subifds=$(scnseriessubifds "$srcfile" "$mainifd")
nsubifds=$(echo "$subifds" | wc -l)
subifds_start=$(echo "$subifds" | head -n1)
subifds_end=$(echo "$subifds" | tail -n1)
subifds_diroffs=$(echo $(tiffinfo "$dest" | grep "TIFF Directory at offset" | sed -e 's;.*(\(.*\))$;\1;' | head -n$(($subifds_end+1)) | tail -n$nsubifds))
for offset in $subifds_diroffs; do
noffset="$(nextoffset $offset "$dest")"
update_uint64_le 0 "$dest" $noffset
done
maindir="$(diroffset $mainifd "$dest")"
noffset="$(nextoffset $maindir "$dest")"
update_uint64_le $nextdiroff "$dest" $noffset
nextdiroff="$(diroffset $mainifd "$dest")"
done
tiffinfo "$dest"
# Create OME-XML metadata for the files.
dest_ometiff="${dest%.tiff}.ome.tiff"
dest2_ometiff="${dest2%.tiff}.ome.tiff"
cp "$dest" "$dest_ometiff"
cp "$dest2" "$dest2_ometiff"
bfomexml="$(showinf -nopix -noflat -omexml -omexml-only "$srcfile")"
# Add TiffData elements.
uuid="$(makeuuid)"
ome_attr="Creator=\"makepyramid-scn\" UUID=\"${uuid}\""
tiffdata_fmt="<TiffData FirstC=\"0\" FirstT=\"0\" FirstZ=\"0\" IFD=\"%d\" PlaneCount=\"1\"><UUID FileName=\"$(basename "${dest_ometiff}")\">${uuid}</UUID></TiffData>"
tiffdata_fmt_flat="<TiffData FirstC=\"0\" FirstT=\"0\" FirstZ=\"0\" IFD=\"%d\" PlaneCount=\"1\"><UUID FileName=\"$(basename "${dest2_ometiff}")\">${uuid}</UUID></TiffData>"
omexml_fmt="$(echo "$bfomexml" | sed -e "s;\(<OME.*\)\(\">\);\1\" ${ome_attr}>;" -e "s;<MetadataOnly\/>;${tiffdata_fmt};")"
omexml_fmt_flat="$(echo "$bfomexml" | sed -e "s;\(<OME.*\)\(\">\);\1\" ${ome_attr}>;" -e "s;<MetadataOnly\/>;${tiffdata_fmt_flat};")"
ifds="$(seq 0 $(($nmainifds - 1 )))"
omexml="$(printf "$omexml_fmt" $ifds)"
flatifds="$(echo $mainifds)"
omexml_flat="$(printf "$omexml_fmt" $flatifds)"
tiffset -d 0 -s 270 "$omexml" "$dest_ometiff"
tiffset -d 0 -s 270 "$omexml_flat" "$dest2_ometiff"
done