~vmiklos/eoec/barcode-lo34

« back to all changes in this revision

Viewing changes to examples/Sharpen/binaries-windows-python23/SpiderImagePlugin.py

  • Committer: Darabos Daniel
  • Date: 2009-05-08 08:44:34 UTC
  • Revision ID: daniel@cyhawk-20090508084434-302s4hv6m42jotoo
3 new examples, docs for examples, translation credits in barcode, python26 compatibility, minor changes, sorry for the large commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# The Python Imaging Library.
 
3
#
 
4
# SPIDER image file handling
 
5
#
 
6
# History:
 
7
# 2004-08-02    Created BB
 
8
# 2006-03-02    added save method
 
9
# 2006-03-13    added support for stack images
 
10
#
 
11
# Copyright (c) 2004 by Health Research Inc. (HRI) RENSSELAER, NY 12144.
 
12
# Copyright (c) 2004 by William Baxter.
 
13
# Copyright (c) 2004 by Secret Labs AB.
 
14
# Copyright (c) 2004 by Fredrik Lundh.
 
15
#
 
16
 
 
17
##
 
18
# Image plugin for the Spider image format.  This format is is used
 
19
# by the SPIDER software, in processing image data from electron
 
20
# microscopy and tomography.
 
21
##
 
22
 
 
23
#
 
24
# SpiderImagePlugin.py
 
25
#
 
26
# The Spider image format is used by SPIDER software, in processing
 
27
# image data from electron microscopy and tomography.
 
28
#
 
29
# Spider home page:
 
30
# http://www.wadsworth.org/spider_doc/spider/docs/spider.html
 
31
#
 
32
# Details about the Spider image format:
 
33
# http://www.wadsworth.org/spider_doc/spider/docs/image_doc.html
 
34
#
 
35
 
 
36
import Image, ImageFile
 
37
import os, string, struct, sys
 
38
 
 
39
def isInt(f):
 
40
    try:
 
41
        i = int(f)
 
42
        if f-i == 0: return 1
 
43
        else:        return 0
 
44
    except:
 
45
        return 0
 
46
 
 
47
iforms = [1,3,-11,-12,-21,-22]
 
48
 
 
49
# There is no magic number to identify Spider files, so just check a
 
50
# series of header locations to see if they have reasonable values.
 
51
# Returns no.of bytes in the header, if it is a valid Spider header,
 
52
# otherwise returns 0
 
53
 
 
54
def isSpiderHeader(t):
 
55
    h = (99,) + t   # add 1 value so can use spider header index start=1
 
56
    # header values 1,2,5,12,13,22,23 should be integers
 
57
    for i in [1,2,5,12,13,22,23]:
 
58
        if not isInt(h[i]): return 0
 
59
    # check iform
 
60
    iform = int(h[5])
 
61
    if not iform in iforms: return 0
 
62
    # check other header values
 
63
    labrec = int(h[13])   # no. records in file header
 
64
    labbyt = int(h[22])   # total no. of bytes in header
 
65
    lenbyt = int(h[23])   # record length in bytes
 
66
    #print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt)
 
67
    if labbyt != (labrec * lenbyt): return 0
 
68
    # looks like a valid header
 
69
    return labbyt
 
70
 
 
71
def isSpiderImage(filename):
 
72
    fp = open(filename,'rb')
 
73
    f = fp.read(92)   # read 23 * 4 bytes
 
74
    fp.close()
 
75
    bigendian = 1
 
76
    t = struct.unpack('>23f',f)    # try big-endian first
 
77
    hdrlen = isSpiderHeader(t)
 
78
    if hdrlen == 0:
 
79
        bigendian = 0
 
80
        t = struct.unpack('<23f',f)  # little-endian
 
81
        hdrlen = isSpiderHeader(t)
 
82
    return hdrlen
 
83
 
 
84
 
 
85
class SpiderImageFile(ImageFile.ImageFile):
 
86
 
 
87
    format = "SPIDER"
 
88
    format_description = "Spider 2D image"
 
89
 
 
90
    def _open(self):
 
91
        # check header
 
92
        n = 27 * 4  # read 27 float values
 
93
        f = self.fp.read(n)
 
94
 
 
95
        try:
 
96
            self.bigendian = 1
 
97
            t = struct.unpack('>27f',f)    # try big-endian first
 
98
            hdrlen = isSpiderHeader(t)
 
99
            if hdrlen == 0:
 
100
                self.bigendian = 0
 
101
                t = struct.unpack('<27f',f)  # little-endian
 
102
                hdrlen = isSpiderHeader(t)
 
103
            if hdrlen == 0:
 
104
                raise SyntaxError, "not a valid Spider file"
 
105
        except struct.error:
 
106
            raise SyntaxError, "not a valid Spider file"
 
107
 
 
108
        h = (99,) + t   # add 1 value : spider header index starts at 1
 
109
        iform = int(h[5])
 
110
        if iform != 1:
 
111
            raise SyntaxError, "not a Spider 2D image"
 
112
 
 
113
        self.size = int(h[12]), int(h[2]) # size in pixels (width, height)
 
114
        self.istack = int(h[24])
 
115
        self.imgnumber = int(h[27])
 
116
 
 
117
        if self.istack == 0 and self.imgnumber == 0:
 
118
            # stk=0, img=0: a regular 2D image
 
119
            offset = hdrlen
 
120
            self.nimages = 1
 
121
        elif self.istack > 0 and self.imgnumber == 0:
 
122
            # stk>0, img=0: Opening the stack for the first time
 
123
            self.imgbytes = int(h[12]) * int(h[2]) * 4
 
124
            self.hdrlen = hdrlen
 
125
            self.nimages = int(h[26])
 
126
            # Point to the first image in the stack
 
127
            offset = hdrlen * 2
 
128
            self.imgnumber = 1
 
129
        elif self.istack == 0 and self.imgnumber > 0:
 
130
            # stk=0, img>0: an image within the stack
 
131
            offset = hdrlen + self.stkoffset
 
132
            self.istack = 2  # So Image knows it's still a stack
 
133
        else:
 
134
            raise SyntaxError, "inconsistent stack header values"
 
135
 
 
136
        if self.bigendian:
 
137
            self.rawmode = "F;32BF"
 
138
        else:
 
139
            self.rawmode = "F;32F"
 
140
        self.mode = "F"
 
141
 
 
142
        self.tile = [("raw", (0, 0) + self.size, offset,
 
143
                    (self.rawmode, 0, 1))]
 
144
        self.__fp = self.fp # FIXME: hack
 
145
 
 
146
    # 1st image index is zero (although SPIDER imgnumber starts at 1)
 
147
    def tell(self):
 
148
        if self.imgnumber < 1:
 
149
            return 0
 
150
        else:
 
151
            return self.imgnumber - 1
 
152
 
 
153
    def seek(self, frame):
 
154
        if self.istack == 0:
 
155
            return
 
156
        if frame >= self.nimages:
 
157
            raise EOFError, "attempt to seek past end of file"
 
158
        self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
 
159
        self.fp = self.__fp
 
160
        self.fp.seek(self.stkoffset)
 
161
        self._open()
 
162
 
 
163
    # returns a byte image after rescaling to 0..255
 
164
    def convert2byte(self, depth=255):
 
165
        (min, max) = self.getextrema()
 
166
        m = 1
 
167
        if max != min:
 
168
            m = depth / (max-min)
 
169
        b = -m * min
 
170
        return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
 
171
 
 
172
    # returns a ImageTk.PhotoImage object, after rescaling to 0..255
 
173
    def tkPhotoImage(self):
 
174
        import ImageTk
 
175
        return ImageTk.PhotoImage(self.convert2byte(), palette=256)
 
176
 
 
177
# --------------------------------------------------------------------
 
178
# Image series
 
179
 
 
180
# given a list of filenames, return a list of images
 
181
def loadImageSeries(filelist=None):
 
182
    " create a list of Image.images for use in montage "
 
183
    if filelist == None or len(filelist) < 1:
 
184
        return
 
185
 
 
186
    imglist = []
 
187
    for img in filelist:
 
188
        if not os.path.exists(img):
 
189
            print "unable to find %s" % img
 
190
            continue
 
191
        try:
 
192
            im = Image.open(img).convert2byte()
 
193
        except:
 
194
            if not isSpiderImage(img):
 
195
                print img + " is not a Spider image file"
 
196
            continue
 
197
        im.info['filename'] = img
 
198
        imglist.append(im)
 
199
    return imglist
 
200
 
 
201
# --------------------------------------------------------------------
 
202
# For saving images in Spider format
 
203
 
 
204
def makeSpiderHeader(im):
 
205
    nsam,nrow = im.size
 
206
    lenbyt = nsam * 4  # There are labrec records in the header
 
207
    labrec = 1024 / lenbyt
 
208
    if 1024%lenbyt != 0: labrec += 1
 
209
    labbyt = labrec * lenbyt
 
210
    hdr = []
 
211
    nvalues = labbyt / 4
 
212
    for i in range(nvalues):
 
213
        hdr.append(0.0)
 
214
 
 
215
    if len(hdr) < 23:
 
216
        return []
 
217
 
 
218
    # NB these are Fortran indices
 
219
    hdr[1]  = 1.0           # nslice (=1 for an image)
 
220
    hdr[2]  = float(nrow)   # number of rows per slice
 
221
    hdr[5]  = 1.0           # iform for 2D image
 
222
    hdr[12] = float(nsam)   # number of pixels per line
 
223
    hdr[13] = float(labrec) # number of records in file header
 
224
    hdr[22] = float(labbyt) # total number of bytes in header
 
225
    hdr[23] = float(lenbyt) # record length in bytes
 
226
 
 
227
    # adjust for Fortran indexing
 
228
    hdr = hdr[1:]
 
229
    hdr.append(0.0)
 
230
    # pack binary data into a string
 
231
    hdrstr = []
 
232
    for v in hdr:
 
233
        hdrstr.append(struct.pack('f',v))
 
234
    return hdrstr
 
235
 
 
236
def _save(im, fp, filename):
 
237
    if im.mode[0] != "F":
 
238
        im = im.convert('F')
 
239
 
 
240
    hdr = makeSpiderHeader(im)
 
241
    if len(hdr) < 256:
 
242
        raise IOError, "Error creating Spider header"
 
243
 
 
244
    # write the SPIDER header
 
245
    try:
 
246
        fp = open(filename, 'wb')
 
247
    except:
 
248
        raise IOError, "Unable to open %s for writing" % filename
 
249
    fp.writelines(hdr)
 
250
 
 
251
    rawmode = "F;32NF"  #32-bit native floating point
 
252
    ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))])
 
253
 
 
254
    fp.close()
 
255
 
 
256
def _save_spider(im, fp, filename):
 
257
    # get the filename extension and register it with Image
 
258
    fn, ext = os.path.splitext(filename)
 
259
    Image.register_extension("SPIDER", ext)
 
260
    _save(im, fp, filename)
 
261
 
 
262
# --------------------------------------------------------------------
 
263
 
 
264
Image.register_open("SPIDER", SpiderImageFile)
 
265
Image.register_save("SPIDER", _save_spider)
 
266
 
 
267
if __name__ == "__main__":
 
268
 
 
269
    if not sys.argv[1:]:
 
270
        print "Syntax: python SpiderImagePlugin.py Spiderimage [outfile]"
 
271
        sys.exit()
 
272
 
 
273
    filename = sys.argv[1]
 
274
    if not isSpiderImage(filename):
 
275
        print "input image must be in Spider format"
 
276
        sys.exit()
 
277
 
 
278
    outfile = ""
 
279
    if len(sys.argv[1:]) > 1:
 
280
        outfile = sys.argv[2]
 
281
 
 
282
    im = Image.open(filename)
 
283
    print "image: " + str(im)
 
284
    print "format: " + str(im.format)
 
285
    print "size: " + str(im.size)
 
286
    print "mode: " + str(im.mode)
 
287
    print "max, min: ",
 
288
    print im.getextrema()
 
289
 
 
290
    if outfile != "":
 
291
        # perform some image operation
 
292
        im = im.transpose(Image.FLIP_LEFT_RIGHT)
 
293
        print "saving a flipped version of %s as %s " % (os.path.basename(filename), outfile)
 
294
        im.save(outfile, "SPIDER")