fabio 0.1.1__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. Library/Python/2.7/site-packages/fabio/GEimage.py +334 -0
  2. Library/Python/2.7/site-packages/fabio/GEimage.pyc +0 -0
  3. Library/Python/2.7/site-packages/fabio/GEimage_old.py +501 -0
  4. Library/Python/2.7/site-packages/fabio/GEimage_old.pyc +0 -0
  5. Library/Python/2.7/site-packages/fabio/HiPiCimage.py +106 -0
  6. Library/Python/2.7/site-packages/fabio/HiPiCimage.pyc +0 -0
  7. Library/Python/2.7/site-packages/fabio/OXDimage.py +442 -0
  8. Library/Python/2.7/site-packages/fabio/OXDimage.pyc +0 -0
  9. Library/Python/2.7/site-packages/fabio/TiffIO.py +1197 -0
  10. Library/Python/2.7/site-packages/fabio/TiffIO.pyc +0 -0
  11. Library/Python/2.7/site-packages/fabio/__init__.py +10 -0
  12. Library/Python/2.7/site-packages/fabio/__init__.pyc +0 -0
  13. Library/Python/2.7/site-packages/fabio/adscimage.py +137 -0
  14. Library/Python/2.7/site-packages/fabio/adscimage.pyc +0 -0
  15. Library/Python/2.7/site-packages/fabio/binaryimage.py +87 -0
  16. Library/Python/2.7/site-packages/fabio/binaryimage.pyc +0 -0
  17. Library/Python/2.7/site-packages/fabio/bruker100image.py +96 -0
  18. Library/Python/2.7/site-packages/fabio/bruker100image.pyc +0 -0
  19. Library/Python/2.7/site-packages/fabio/brukerimage.py +195 -0
  20. Library/Python/2.7/site-packages/fabio/brukerimage.pyc +0 -0
  21. Library/Python/2.7/site-packages/fabio/byte_offset.so +0 -0
  22. Library/Python/2.7/site-packages/fabio/cbfimage.py +758 -0
  23. Library/Python/2.7/site-packages/fabio/cbfimage.pyc +0 -0
  24. Library/Python/2.7/site-packages/fabio/cf_io.so +0 -0
  25. Library/Python/2.7/site-packages/fabio/compression.py +388 -0
  26. Library/Python/2.7/site-packages/fabio/compression.pyc +0 -0
  27. Library/Python/2.7/site-packages/fabio/converters.py +54 -0
  28. Library/Python/2.7/site-packages/fabio/converters.pyc +0 -0
  29. Library/Python/2.7/site-packages/fabio/datIO.py +60 -0
  30. Library/Python/2.7/site-packages/fabio/datIO.pyc +0 -0
  31. Library/Python/2.7/site-packages/fabio/dm3image.py +219 -0
  32. Library/Python/2.7/site-packages/fabio/dm3image.pyc +0 -0
  33. Library/Python/2.7/site-packages/fabio/edfimage.py +924 -0
  34. Library/Python/2.7/site-packages/fabio/edfimage.pyc +0 -0
  35. Library/Python/2.7/site-packages/fabio/fabioimage.py +556 -0
  36. Library/Python/2.7/site-packages/fabio/fabioimage.pyc +0 -0
  37. Library/Python/2.7/site-packages/fabio/fabioutils.py +491 -0
  38. Library/Python/2.7/site-packages/fabio/fabioutils.pyc +0 -0
  39. Library/Python/2.7/site-packages/fabio/file_series.py +313 -0
  40. Library/Python/2.7/site-packages/fabio/file_series.pyc +0 -0
  41. Library/Python/2.7/site-packages/fabio/fit2dmaskimage.py +94 -0
  42. Library/Python/2.7/site-packages/fabio/fit2dmaskimage.pyc +0 -0
  43. Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.py +85 -0
  44. Library/Python/2.7/site-packages/fabio/fit2dspreadsheetimage.pyc +0 -0
  45. Library/Python/2.7/site-packages/fabio/kcdimage.py +131 -0
  46. Library/Python/2.7/site-packages/fabio/kcdimage.pyc +0 -0
  47. Library/Python/2.7/site-packages/fabio/mar345_IO.so +0 -0
  48. Library/Python/2.7/site-packages/fabio/mar345image.py +320 -0
  49. Library/Python/2.7/site-packages/fabio/mar345image.pyc +0 -0
  50. Library/Python/2.7/site-packages/fabio/marccdimage.py +309 -0
  51. Library/Python/2.7/site-packages/fabio/marccdimage.pyc +0 -0
  52. Library/Python/2.7/site-packages/fabio/openimage.py +162 -0
  53. Library/Python/2.7/site-packages/fabio/openimage.pyc +0 -0
  54. Library/Python/2.7/site-packages/fabio/pilatusimage.py +81 -0
  55. Library/Python/2.7/site-packages/fabio/pilatusimage.pyc +0 -0
  56. Library/Python/2.7/site-packages/fabio/pnmimage.py +165 -0
  57. Library/Python/2.7/site-packages/fabio/pnmimage.pyc +0 -0
  58. Library/Python/2.7/site-packages/fabio/readbytestream.py +86 -0
  59. Library/Python/2.7/site-packages/fabio/readbytestream.pyc +0 -0
  60. Library/Python/2.7/site-packages/fabio/tifimage.py +283 -0
  61. Library/Python/2.7/site-packages/fabio/tifimage.pyc +0 -0
  62. Library/Python/2.7/site-packages/fabio/xsdimage.py +134 -0
  63. Library/Python/2.7/site-packages/fabio/xsdimage.pyc +0 -0
  64. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/PKG-INFO +11 -0
  65. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/SOURCES.txt +114 -0
  66. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/dependency_links.txt +1 -0
  67. Library/Python/2.7/site-packages/fabio-0.1.1-py2.7.egg-info/top_level.txt +4 -0
@@ -0,0 +1,1197 @@
1
+ #/*##########################################################################
2
+ # Copyright (C) 2012 European Synchrotron Radiation Facility
3
+ #
4
+ # This file is part of the PyMca X-ray Fluorescence Toolkit developed at
5
+ # the ESRF by the Software group.
6
+ #
7
+ # This file is free software; you can redistribute it and/or modify it
8
+ # under the terms of the GNU Lesser General Public License as published by the Free
9
+ # Software Foundation; either version 2 of the License, or (at your option)
10
+ # any later version.
11
+ #
12
+ # PyMca is distributed in the hope that it will be useful, but WITHOUT ANY
13
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15
+ # details.
16
+ #
17
+ #############################################################################*/
18
+ __author__ = "V.A. Sole - ESRF Data Analysis"
19
+ __revision__ = 1501
20
+
21
+ import sys
22
+ import os
23
+ import struct
24
+ import numpy
25
+
26
+ DEBUG = 0
27
+ ALLOW_MULTIPLE_STRIPS = False
28
+
29
+ TAG_ID = { 256:"NumberOfColumns", # S or L ImageWidth
30
+ 257:"NumberOfRows", # S or L ImageHeight
31
+ 258:"BitsPerSample", # S Number of bits per component
32
+ 259:"Compression", # SHORT (1 - NoCompression, ...
33
+ 262:"PhotometricInterpretation", # SHORT (0 - WhiteIsZero, 1 -BlackIsZero, 2 - RGB, 3 - Palette color
34
+ 270:"ImageDescription", # ASCII
35
+ 273:"StripOffsets", # S or L, for each strip, the byte offset of the strip
36
+ 278:"RowsPerStrip", # S or L, number of rows in each back may be not for the last
37
+ 279:"StripByteCounts", # S or L, The number of bytes in the strip AFTER any compression
38
+ 305:"Software", # ASCII
39
+ 306:"Date", # ASCII
40
+ 320:"Colormap", # Colormap of Palette-color Images
41
+ 339:"SampleFormat", # SHORT Interpretation of data in each pixel
42
+ }
43
+
44
+ #TILES ARE TO BE SUPPORTED TOO ...
45
+ TAG_NUMBER_OF_COLUMNS = 256
46
+ TAG_NUMBER_OF_ROWS = 257
47
+ TAG_BITS_PER_SAMPLE = 258
48
+ TAG_PHOTOMETRIC_INTERPRETATION = 262
49
+ TAG_COMPRESSION = 259
50
+ TAG_IMAGE_DESCRIPTION = 270
51
+ TAG_STRIP_OFFSETS = 273
52
+ TAG_ROWS_PER_STRIP = 278
53
+ TAG_STRIP_BYTE_COUNTS = 279
54
+ TAG_SOFTWARE = 305
55
+ TAG_DATE = 306
56
+ TAG_COLORMAP = 320
57
+ TAG_SAMPLE_FORMAT = 339
58
+
59
+ FIELD_TYPE = {1:('BYTE', "B"),
60
+ 2:('ASCII', "s"), #string ending with binary zero
61
+ 3:('SHORT', "H"),
62
+ 4:('LONG', "I"),
63
+ 5:('RATIONAL', "II"),
64
+ 6:('SBYTE', "b"),
65
+ 7:('UNDEFINED', "B"),
66
+ 8:('SSHORT', "h"),
67
+ 9:('SLONG', "i"),
68
+ 10:('SRATIONAL', "ii"),
69
+ 11:('FLOAT', "f"),
70
+ 12:('DOUBLE', "d")}
71
+
72
+ FIELD_TYPE_OUT = { 'B': 1,
73
+ 's': 2,
74
+ 'H': 3,
75
+ 'I': 4,
76
+ 'II': 5,
77
+ 'b': 6,
78
+ 'h': 8,
79
+ 'i': 9,
80
+ 'ii': 10,
81
+ 'f': 11,
82
+ 'd': 12}
83
+
84
+ #sample formats (http://www.awaresystems.be/imaging/tiff/tiffflags/sampleformat.html)
85
+ SAMPLE_FORMAT_UINT = 1
86
+ SAMPLE_FORMAT_INT = 2
87
+ SAMPLE_FORMAT_FLOAT = 3 #floating point
88
+ SAMPLE_FORMAT_VOID = 4 #undefined data, usually assumed UINT
89
+ SAMPLE_FORMAT_COMPLEXINT = 5
90
+ SAMPLE_FORMAT_COMPLEXIEEEFP = 6
91
+
92
+
93
+
94
+ class TiffIO(object):
95
+ def __init__(self, filename, mode=None, cache_length=20, mono_output=False):
96
+ if mode is None:
97
+ mode = 'rb'
98
+ if 'b' not in mode:
99
+ mode = mode + 'b'
100
+ if 'a' in mode.lower():
101
+ raise IOError("Mode %s makes no sense on TIFF files. Consider 'rb+'" % mode)
102
+ if ('w' in mode):
103
+ if '+' not in mode:
104
+ mode += '+'
105
+ #if isinstance(filename, file): #does not work in python 3
106
+ if hasattr(filename, "seek"):
107
+ fd = filename
108
+ self._access = None
109
+ else:
110
+ #the b is needed for windows and python 3
111
+ fd = open(filename, mode)
112
+ self._access = mode
113
+
114
+ self._initInternalVariables(fd)
115
+ self._maxImageCacheLength = cache_length
116
+ self._forceMonoOutput = mono_output
117
+
118
+ def _initInternalVariables(self, fd=None):
119
+ if fd is None:
120
+ fd = self.fd
121
+ else:
122
+ self.fd = fd
123
+ # read the order
124
+ fd.seek(0)
125
+ order = fd.read(2).decode()
126
+ if len(order):
127
+ if order == "II":
128
+ #intel, little endian
129
+ fileOrder = "little"
130
+ self._structChar = '<'
131
+ elif order == "MM":
132
+ #motorola, high endian
133
+ fileOrder = "big"
134
+ self._structChar = '>'
135
+ else:
136
+ raise IOError("File is not a Mar CCD file, nor a TIFF file")
137
+ a = fd.read(2)
138
+ fortyTwo = struct.unpack(self._structChar + "H", a)[0]
139
+ if fortyTwo != 42:
140
+ raise IOError("Invalid TIFF version %d" % fortyTwo)
141
+ else:
142
+ if DEBUG:
143
+ print("VALID TIFF VERSION")
144
+ if sys.byteorder != fileOrder:
145
+ swap = True
146
+ else:
147
+ swap = False
148
+ else:
149
+ if sys.byteorder == "little":
150
+ self._structChar = '<'
151
+ else:
152
+ self._structChar = '>'
153
+ swap = False
154
+ self._swap = swap
155
+ self._IFD = []
156
+ self._imageDataCacheIndex = []
157
+ self._imageDataCache = []
158
+ self._imageInfoCacheIndex = []
159
+ self._imageInfoCache = []
160
+ self.getImageFileDirectories(fd)
161
+
162
+ def __makeSureFileIsOpen(self):
163
+ if not self.fd.closed:
164
+ return
165
+ if DEBUG:
166
+ print("Reopening closed file")
167
+ fileName = self.fd.name
168
+ if self._access is None:
169
+ #we do not own the file
170
+ #open in read mode
171
+ newFile = open(fileName, 'rb')
172
+ else:
173
+ newFile = open(fileName, self._access)
174
+ self.fd = newFile
175
+
176
+ def __makeSureFileIsClosed(self):
177
+ if self._access is None:
178
+ #we do not own the file
179
+ if DEBUG:
180
+ print("Not closing not owned file")
181
+ return
182
+
183
+ if not self.fd.closed:
184
+ self.fd.close()
185
+
186
+ def getNumberOfImages(self):
187
+ #update for the case someone has done anything?
188
+ self._updateIFD()
189
+ return len(self._IFD)
190
+
191
+ def _updateIFD(self):
192
+ self.__makeSureFileIsOpen()
193
+ self.getImageFileDirectories()
194
+ self.__makeSureFileIsClosed()
195
+
196
+ def getImageFileDirectories(self, fd=None):
197
+ if fd is None:
198
+ fd = self.fd
199
+ else:
200
+ self.fd = fd
201
+ st = self._structChar
202
+ fd.seek(4)
203
+ self._IFD = []
204
+ nImages = 0
205
+ fmt = st + 'I'
206
+ inStr = fd.read(struct.calcsize(fmt))
207
+ if not len(inStr):
208
+ offsetToIFD = 0
209
+ else:
210
+ offsetToIFD = struct.unpack(fmt, inStr)[0]
211
+ if DEBUG:
212
+ print("Offset to first IFD = %d" % offsetToIFD)
213
+ while offsetToIFD != 0:
214
+ self._IFD.append(offsetToIFD)
215
+ nImages += 1
216
+ fd.seek(offsetToIFD)
217
+ fmt = st + 'H'
218
+ numberOfDirectoryEntries = struct.unpack(fmt, fd.read(struct.calcsize(fmt)))[0]
219
+ if DEBUG:
220
+ print("Number of directory entries = %d" % numberOfDirectoryEntries)
221
+
222
+ fmt = st + 'I'
223
+ fd.seek(offsetToIFD + 2 + 12 * numberOfDirectoryEntries)
224
+ offsetToIFD = struct.unpack(fmt, fd.read(struct.calcsize(fmt)))[0]
225
+ if DEBUG:
226
+ print("Next Offset to IFD = %d" % offsetToIFD)
227
+ #offsetToIFD = 0
228
+ if DEBUG:
229
+ print("Number of images found = %d" % nImages)
230
+ return nImages
231
+
232
+ def _parseImageFileDirectory(self, nImage):
233
+ offsetToIFD = self._IFD[nImage]
234
+ st = self._structChar
235
+ fd = self.fd
236
+ fd.seek(offsetToIFD)
237
+ fmt = st + 'H'
238
+ numberOfDirectoryEntries = struct.unpack(fmt, fd.read(struct.calcsize(fmt)))[0]
239
+ if DEBUG:
240
+ print("Number of directory entries = %d" % numberOfDirectoryEntries)
241
+
242
+ fmt = st + 'HHI4s'
243
+ tagIDList = []
244
+ fieldTypeList = []
245
+ nValuesList = []
246
+ valueOffsetList = []
247
+ for i in range(numberOfDirectoryEntries):
248
+ tagID, fieldType, nValues, valueOffset = struct.unpack(fmt, fd.read(12))
249
+ tagIDList.append(tagID)
250
+ fieldTypeList.append(fieldType)
251
+ nValuesList.append(nValues)
252
+ if nValues == 1:
253
+ ftype, vfmt = FIELD_TYPE[fieldType]
254
+ if ftype not in ['ASCII', 'RATIONAL', 'SRATIONAL']:
255
+ vfmt = st + vfmt
256
+ actualValue = struct.unpack(vfmt, valueOffset[0: struct.calcsize(vfmt)])[0]
257
+ valueOffsetList.append(actualValue)
258
+ else:
259
+ valueOffsetList.append(valueOffset)
260
+ elif (nValues < 5) and (fieldType == 2):
261
+ ftype, vfmt = FIELD_TYPE[fieldType]
262
+ vfmt = st + "%d%s" % (nValues, vfmt)
263
+ actualValue = struct.unpack(vfmt, valueOffset[0: struct.calcsize(vfmt)])[0]
264
+ valueOffsetList.append(actualValue)
265
+ else:
266
+ valueOffsetList.append(valueOffset)
267
+ if DEBUG:
268
+ if tagID in TAG_ID:
269
+ print("tagID = %s" % TAG_ID[tagID])
270
+ else:
271
+ print("tagID = %d" % tagID)
272
+ print("fieldType = %s" % FIELD_TYPE[fieldType][0])
273
+ print("nValues = %d" % nValues)
274
+ #if nValues == 1:
275
+ # print("valueOffset = %s" % valueOffset)
276
+ return tagIDList, fieldTypeList, nValuesList, valueOffsetList
277
+
278
+
279
+
280
+ def _readIFDEntry(self, tag, tagIDList, fieldTypeList, nValuesList, valueOffsetList):
281
+ fd = self.fd
282
+ st = self._structChar
283
+ idx = tagIDList.index(tag)
284
+ nValues = nValuesList[idx]
285
+ output = []
286
+ ftype, vfmt = FIELD_TYPE[fieldTypeList[idx]]
287
+ vfmt = st + "%d%s" % (nValues, vfmt)
288
+ requestedBytes = struct.calcsize(vfmt)
289
+ if nValues == 1:
290
+ output.append(valueOffsetList[idx])
291
+ elif requestedBytes < 5:
292
+ output.append(valueOffsetList[idx])
293
+ else:
294
+ offset = fd.seek(struct.unpack(st + "I", valueOffsetList[idx])[0])
295
+ output = struct.unpack(vfmt, fd.read(requestedBytes))
296
+ return output
297
+
298
+ def getData(self, nImage, **kw):
299
+ if nImage >= len(self._IFD):
300
+ #update prior to raise an index error error
301
+ self._updateIFD()
302
+ return self._readImage(nImage, **kw)
303
+
304
+ def getImage(self, nImage):
305
+ return self.getData(nImage)
306
+
307
+ def getInfo(self, nImage, **kw):
308
+ if nImage >= len(self._IFD):
309
+ #update prior to raise an index error error
310
+ self._updateIFD()
311
+ current = self._IFD[nImage]
312
+ return self._readInfo(nImage)
313
+
314
+ def _readInfo(self, nImage, close=True):
315
+ if nImage in self._imageInfoCacheIndex:
316
+ if DEBUG:
317
+ print("Reading info from cache")
318
+ return self._imageInfoCache[self._imageInfoCacheIndex.index(nImage)]
319
+
320
+ #read the header
321
+ self.__makeSureFileIsOpen()
322
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList = self._parseImageFileDirectory(nImage)
323
+
324
+ #rows and columns
325
+ nColumns = valueOffsetList[tagIDList.index(TAG_NUMBER_OF_COLUMNS)]
326
+ nRows = valueOffsetList[tagIDList.index(TAG_NUMBER_OF_ROWS)]
327
+
328
+ #bits per sample
329
+ idx = tagIDList.index(TAG_BITS_PER_SAMPLE)
330
+ nBits = valueOffsetList[idx]
331
+ if nValuesList[idx] != 1:
332
+ #this happens with RGB and friends, nBits is not a single value
333
+ nBits = self._readIFDEntry(TAG_BITS_PER_SAMPLE,
334
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
335
+
336
+
337
+ if TAG_COLORMAP in tagIDList:
338
+ idx = tagIDList.index(TAG_COLORMAP)
339
+ tmpColormap = self._readIFDEntry(TAG_COLORMAP,
340
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
341
+ if max(tmpColormap) > 255:
342
+ tmpColormap = numpy.array(tmpColormap, dtype=numpy.uint16)
343
+ tmpColormap = (tmpColormap / 256.).astype(numpy.uint8)
344
+ else:
345
+ tmpColormap = numpy.array(tmpColormap, dtype=numpy.uint8)
346
+ tmpColormap.shape = 3, -1
347
+ colormap = numpy.zeros((tmpColormap.shape[-1], 3), tmpColormap.dtype)
348
+ colormap[:, :] = tmpColormap.T
349
+ tmpColormap = None
350
+ else:
351
+ colormap = None
352
+
353
+ #sample format
354
+ if TAG_SAMPLE_FORMAT in tagIDList:
355
+ sampleFormat = valueOffsetList[tagIDList.index(TAG_SAMPLE_FORMAT)]
356
+ else:
357
+ #set to unknown
358
+ sampleFormat = SAMPLE_FORMAT_VOID
359
+
360
+ # compression
361
+ compression = False
362
+ compression_type = 1
363
+ if TAG_COMPRESSION in tagIDList:
364
+ compression_type = valueOffsetList[tagIDList.index(TAG_COMPRESSION)]
365
+ if compression_type == 1:
366
+ compression = False
367
+ else:
368
+ compression = True
369
+
370
+ #photometric interpretation
371
+ interpretation = 1
372
+ if TAG_PHOTOMETRIC_INTERPRETATION in tagIDList:
373
+ interpretation = valueOffsetList[tagIDList.index(TAG_PHOTOMETRIC_INTERPRETATION)]
374
+ else:
375
+ print("WARNING: Non standard TIFF. Photometric interpretation TAG missing")
376
+ helpString = ""
377
+ if sys.version > '2.6':
378
+ helpString = eval('b""')
379
+
380
+ if TAG_IMAGE_DESCRIPTION in tagIDList:
381
+ imageDescription = self._readIFDEntry(TAG_IMAGE_DESCRIPTION,
382
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
383
+ if type(imageDescription) in [type([1]), type((1,))]:
384
+ imageDescription = helpString.join(imageDescription)
385
+ else:
386
+ imageDescription = "%d/%d" % (nImage + 1, len(self._IFD))
387
+
388
+ if sys.version < '3.0':
389
+ defaultSoftware = "Unknown Software"
390
+ else:
391
+ defaultSoftware = bytes("Unknown Software",
392
+ encoding='utf-8')
393
+ if TAG_SOFTWARE in tagIDList:
394
+ software = self._readIFDEntry(TAG_SOFTWARE,
395
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
396
+ if type(software) in [type([1]), type((1,))]:
397
+ software = helpString.join(software)
398
+ else:
399
+ software = defaultSoftware
400
+
401
+ if software == defaultSoftware:
402
+ try:
403
+ if sys.version < '3.0':
404
+ if imageDescription.upper().startswith("IMAGEJ"):
405
+ software = imageDescription.split("=")[0]
406
+ else:
407
+ tmpString = imageDescription.decode()
408
+ if tmpString.upper().startswith("IMAGEJ"):
409
+ software = bytes(tmpString.split("=")[0],
410
+ encoding='utf-8')
411
+ except:
412
+ pass
413
+
414
+ if TAG_DATE in tagIDList:
415
+ date = self._readIFDEntry(TAG_DATE,
416
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
417
+ if type(date) in [type([1]), type((1,))]:
418
+ date = helpString.join(date)
419
+ else:
420
+ date = "Unknown Date"
421
+
422
+ stripOffsets = self._readIFDEntry(TAG_STRIP_OFFSETS,
423
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
424
+ if TAG_ROWS_PER_STRIP in tagIDList:
425
+ rowsPerStrip = self._readIFDEntry(TAG_ROWS_PER_STRIP,
426
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)[0]
427
+ else:
428
+ rowsPerStrip = nRows
429
+ print("WARNING: Non standard TIFF. Rows per strip TAG missing")
430
+
431
+ if TAG_STRIP_BYTE_COUNTS in tagIDList:
432
+ stripByteCounts = self._readIFDEntry(TAG_STRIP_BYTE_COUNTS,
433
+ tagIDList, fieldTypeList, nValuesList, valueOffsetList)
434
+ else:
435
+ print("WARNING: Non standard TIFF. Strip byte counts TAG missing")
436
+ if hasattr(nBits, 'index'):
437
+ expectedSum = 0
438
+ for n in nBits:
439
+ expectedSum += int(nRows * nColumns * n / 8)
440
+ else:
441
+ expectedSum = int(nRows * nColumns * nBits / 8)
442
+ stripByteCounts = [expectedSum]
443
+
444
+ if close:
445
+ self.__makeSureFileIsClosed()
446
+
447
+ if self._forceMonoOutput and (interpretation > 1):
448
+ #color image but asked monochrome output
449
+ nBits = 32
450
+ colormap = None
451
+ sampleFormat = SAMPLE_FORMAT_FLOAT
452
+ interpretation = 1
453
+ #we cannot rely on any cache in this case
454
+ useInfoCache = False
455
+ if DEBUG:
456
+ print("FORCED MONO")
457
+ else:
458
+ useInfoCache = True
459
+
460
+ info = {}
461
+ info["nRows"] = nRows
462
+ info["nColumns"] = nColumns
463
+ info["nBits"] = nBits
464
+ info["compression"] = compression
465
+ info["compression_type"] = compression_type
466
+ info["imageDescription"] = imageDescription
467
+ info["stripOffsets"] = stripOffsets #This contains the file offsets to the data positions
468
+ info["rowsPerStrip"] = rowsPerStrip
469
+ info["stripByteCounts"] = stripByteCounts #bytes in strip since I do not support compression
470
+ info["software"] = software
471
+ info["date"] = date
472
+ info["colormap"] = colormap
473
+ info["sampleFormat"] = sampleFormat
474
+ info["photometricInterpretation"] = interpretation
475
+ infoDict = {}
476
+ if sys.version < '3.0':
477
+ testString = 'PyMca'
478
+ else:
479
+ testString = eval('b"PyMca"')
480
+ if software.startswith(testString):
481
+ #str to make sure python 2.x sees it as string and not unicode
482
+ if sys.version < '3.0':
483
+ descriptionString = imageDescription
484
+ else:
485
+ descriptionString = str(imageDescription.decode())
486
+ #interpret the image description in terms of supplied
487
+ #information at writing time
488
+ items = descriptionString.split('=')
489
+ for i in range(int(len(items) / 2)):
490
+ key = "%s" % items[i * 2]
491
+ #get rid of the \n at the end of the value
492
+ value = "%s" % items[i * 2 + 1][:-1]
493
+ infoDict[key] = value
494
+ info['info'] = infoDict
495
+
496
+ if (self._maxImageCacheLength > 0) and useInfoCache:
497
+ self._imageInfoCacheIndex.insert(0, nImage)
498
+ self._imageInfoCache.insert(0, info)
499
+ if len(self._imageInfoCacheIndex) > self._maxImageCacheLength:
500
+ self._imageInfoCacheIndex = self._imageInfoCacheIndex[:self._maxImageCacheLength]
501
+ self._imageInfoCache = self._imageInfoCache[:self._maxImageCacheLength]
502
+ return info
503
+
504
+ def _readImage(self, nImage, **kw):
505
+ if DEBUG:
506
+ print("Reading image %d" % nImage)
507
+ if 'close' in kw:
508
+ close = kw['close']
509
+ else:
510
+ close = True
511
+ rowMin = kw.get('rowMin', None)
512
+ rowMax = kw.get('rowMax', None)
513
+ if nImage in self._imageDataCacheIndex:
514
+ if DEBUG:
515
+ print("Reading image data from cache")
516
+ return self._imageDataCache[self._imageDataCacheIndex.index(nImage)]
517
+
518
+ self.__makeSureFileIsOpen()
519
+ if self._forceMonoOutput:
520
+ oldMono = True
521
+ else:
522
+ oldMono = False
523
+ try:
524
+ self._forceMonoOutput = False
525
+ info = self._readInfo(nImage, close=False)
526
+ self._forceMonoOutput = oldMono
527
+ except:
528
+ self._forceMonoOutput = oldMono
529
+ raise
530
+ compression = info['compression']
531
+ compression_type = info['compression_type']
532
+ if compression:
533
+ if compression_type != 32773:
534
+ raise IOError("Compressed TIFF images not supported except packbits")
535
+ else:
536
+ #PackBits compression
537
+ if DEBUG:
538
+ print("Using PackBits compression")
539
+
540
+ interpretation = info["photometricInterpretation"]
541
+ if interpretation == 2:
542
+ #RGB
543
+ pass
544
+ #raise IOError("RGB Image. Only grayscale images supported")
545
+ elif interpretation == 3:
546
+ #Palette Color Image
547
+ pass
548
+ #raise IOError("Palette-color Image. Only grayscale images supported")
549
+ elif interpretation > 2:
550
+ #Palette Color Image
551
+ raise IOError("Only grayscale images supported")
552
+
553
+ nRows = info["nRows"]
554
+ nColumns = info["nColumns"]
555
+ nBits = info["nBits"]
556
+ colormap = info["colormap"]
557
+ sampleFormat = info["sampleFormat"]
558
+
559
+ if rowMin is None:
560
+ rowMin = 0
561
+
562
+ if rowMax is None:
563
+ rowMax = nRows - 1
564
+
565
+ if rowMin < 0:
566
+ rowMin = nRows - rowMin
567
+
568
+ if rowMax < 0:
569
+ rowMax = nRows - rowMax
570
+
571
+ if rowMax < rowMin:
572
+ txt = "Max Row smaller than Min Row. Reverse selection not supported"
573
+ raise NotImplemented(txt)
574
+
575
+ if rowMin >= nRows:
576
+ raise IndexError("Image only has %d rows" % nRows)
577
+
578
+ if rowMax >= nRows:
579
+ raise IndexError("Image only has %d rows" % nRows)
580
+
581
+ if sampleFormat == SAMPLE_FORMAT_FLOAT:
582
+ if nBits == 32:
583
+ dtype = numpy.float32
584
+ elif nBits == 64:
585
+ dtype = numpy.float64
586
+ else:
587
+ raise ValueError("Unsupported number of bits for a float: %d" % nBits)
588
+ elif sampleFormat in [SAMPLE_FORMAT_UINT, SAMPLE_FORMAT_VOID]:
589
+ if nBits in [8, (8, 8, 8), [8, 8, 8]]:
590
+ dtype = numpy.uint8
591
+ elif nBits in [16, (16, 16, 16), [16, 16, 16]]:
592
+ dtype = numpy.uint16
593
+ elif nBits in [32, (32, 32, 32), [32, 32, 32]]:
594
+ dtype = numpy.uint32
595
+ elif nBits in [64, (64, 64, 64), [64, 64, 64]]:
596
+ dtype = numpy.uint64
597
+ else:
598
+ raise ValueError("Unsupported number of bits for unsigned int: %s" % (nBits,))
599
+ elif sampleFormat == SAMPLE_FORMAT_INT:
600
+ if nBits in [8, (8, 8, 8), [8, 8, 8]]:
601
+ dtype = numpy.int8
602
+ elif nBits in [16, (16, 16, 16), [16, 16, 16]]:
603
+ dtype = numpy.int16
604
+ elif nBits in [32, (32, 32, 32), [32, 32, 32]]:
605
+ dtype = numpy.int32
606
+ elif nBits in [64, (64, 64, 64), [64, 64, 64]]:
607
+ dtype = numpy.int64
608
+ else:
609
+ raise ValueError("Unsupported number of bits for signed int: %s" % (nBits,))
610
+ else:
611
+ raise ValueError("Unsupported combination. Bits = %s Format = %d" % (nBits, sampleFormat))
612
+ if hasattr(nBits, 'index'):
613
+ image = numpy.zeros((nRows, nColumns, len(nBits)), dtype=dtype)
614
+ elif colormap is not None:
615
+ #should I use colormap dtype?
616
+ image = numpy.zeros((nRows, nColumns, 3), dtype=dtype)
617
+ else:
618
+ image = numpy.zeros((nRows, nColumns), dtype=dtype)
619
+
620
+ fd = self.fd
621
+ st = self._structChar
622
+ stripOffsets = info["stripOffsets"] #This contains the file offsets to the data positions
623
+ rowsPerStrip = info["rowsPerStrip"]
624
+ stripByteCounts = info["stripByteCounts"] #bytes in strip since I do not support compression
625
+
626
+ rowStart = 0
627
+ if len(stripOffsets) == 1:
628
+ bytesPerRow = int(stripByteCounts[0] / rowsPerStrip)
629
+ fd.seek(stripOffsets[0] + rowMin * bytesPerRow)
630
+ nBytes = (rowMax - rowMin + 1) * bytesPerRow
631
+ if self._swap:
632
+ readout = numpy.fromstring(fd.read(nBytes), dtype).byteswap()
633
+ else:
634
+ readout = numpy.fromstring(fd.read(nBytes), dtype)
635
+ if hasattr(nBits, 'index'):
636
+ readout.shape = -1, nColumns, len(nBits)
637
+ elif info['colormap'] is not None:
638
+ readout = colormap[readout]
639
+ else:
640
+ readout.shape = -1, nColumns
641
+ image[rowMin:rowMax + 1, :] = readout
642
+ else:
643
+ for i in range(len(stripOffsets)):
644
+ #the amount of rows
645
+ nRowsToRead = rowsPerStrip
646
+ rowEnd = int(min(rowStart + nRowsToRead, nRows))
647
+ if rowEnd < rowMin:
648
+ rowStart += nRowsToRead
649
+ continue
650
+ if (rowStart > rowMax):
651
+ break
652
+ #we are in position
653
+ fd.seek(stripOffsets[i])
654
+ #the amount of bytes to read
655
+ nBytes = stripByteCounts[i]
656
+ if compression_type == 32773:
657
+ try:
658
+ bufferBytes = bytes()
659
+ except:
660
+ #python 2.5 ...
661
+ bufferBytes = ""
662
+ #packBits
663
+ readBytes = 0
664
+ #intermediate buffer
665
+ tmpBuffer = fd.read(nBytes)
666
+ while readBytes < nBytes:
667
+ n = struct.unpack('b', tmpBuffer[readBytes:(readBytes + 1)])[0]
668
+ readBytes += 1
669
+ if n >= 0:
670
+ #should I prevent reading more than the
671
+ #length of the chain? Let's python raise
672
+ #the exception...
673
+ bufferBytes += tmpBuffer[readBytes:\
674
+ readBytes + (n + 1)]
675
+ readBytes += (n + 1)
676
+ elif n > -128:
677
+ bufferBytes += (-n + 1) * tmpBuffer[readBytes:(readBytes + 1)]
678
+ readBytes += 1
679
+ else:
680
+ #if read -128 ignore the byte
681
+ continue
682
+ if self._swap:
683
+ readout = numpy.fromstring(bufferBytes, dtype).byteswap()
684
+ else:
685
+ readout = numpy.fromstring(bufferBytes, dtype)
686
+ if hasattr(nBits, 'index'):
687
+ readout.shape = -1, nColumns, len(nBits)
688
+ elif info['colormap'] is not None:
689
+ readout = colormap[readout]
690
+ readout.shape = -1, nColumns, 3
691
+ else:
692
+ readout.shape = -1, nColumns
693
+ image[rowStart:rowEnd, :] = readout
694
+ else:
695
+ if 1:
696
+ #use numpy
697
+ if self._swap:
698
+ readout = numpy.fromstring(fd.read(nBytes), dtype).byteswap()
699
+ else:
700
+ readout = numpy.fromstring(fd.read(nBytes), dtype)
701
+ if hasattr(nBits, 'index'):
702
+ readout.shape = -1, nColumns, len(nBits)
703
+ elif colormap is not None:
704
+ readout = colormap[readout]
705
+ readout.shape = -1, nColumns, 3
706
+ else:
707
+ readout.shape = -1, nColumns
708
+ image[rowStart:rowEnd, :] = readout
709
+ else:
710
+ #using struct
711
+ readout = numpy.array(struct.unpack(st + "%df" % int(nBytes / 4), fd.read(nBytes)),
712
+ dtype=dtype)
713
+ if hasattr(nBits, 'index'):
714
+ readout.shape = -1, nColumns, len(nBits)
715
+ elif colormap is not None:
716
+ readout = colormap[readout]
717
+ readout.shape = -1, nColumns, 3
718
+ else:
719
+ readout.shape = -1, nColumns
720
+ image[rowStart:rowEnd, :] = readout
721
+ rowStart += nRowsToRead
722
+ if close:
723
+ self.__makeSureFileIsClosed()
724
+
725
+ if len(image.shape) == 3:
726
+ #color image
727
+ if self._forceMonoOutput:
728
+ #color image, convert to monochrome
729
+ image = (image[:, :, 0] * 0.114 + \
730
+ image[:, :, 1] * 0.587 + \
731
+ image[:, :, 2] * 0.299).astype(numpy.float32)
732
+
733
+ if (rowMin == 0) and (rowMax == (nRows - 1)):
734
+ self._imageDataCacheIndex.insert(0, nImage)
735
+ self._imageDataCache.insert(0, image)
736
+ if len(self._imageDataCacheIndex) > self._maxImageCacheLength:
737
+ self._imageDataCacheIndex = self._imageDataCacheIndex[:self._maxImageCacheLength]
738
+ self._imageDataCache = self._imageDataCache[:self._maxImageCacheLength]
739
+
740
+ return image
741
+
742
+ def writeImage(self, image0, info=None, software=None, date=None):
743
+ if software is None:
744
+ software = 'PyMca.TiffIO'
745
+ #if date is None:
746
+ # date = time.ctime()
747
+
748
+ self.__makeSureFileIsOpen()
749
+ fd = self.fd
750
+ #prior to do anything, perform some tests
751
+ if not len(image0.shape):
752
+ raise ValueError("Empty image")
753
+ if len(image0.shape) == 1:
754
+ #get a different view
755
+ image = image0[:]
756
+ image.shape = 1, -1
757
+ else:
758
+ image = image0
759
+
760
+ if image.dtype == numpy.float64:
761
+ image = image.astype(numpy.float32)
762
+ fd.seek(0)
763
+ mode = fd.mode
764
+ name = fd.name
765
+ if 'w' in mode:
766
+ #we have to overwrite the file
767
+ self.__makeSureFileIsClosed()
768
+ fd = None
769
+ if os.path.exists(name):
770
+ os.remove(name)
771
+ fd = open(name, mode='wb+')
772
+ self._initEmptyFile(fd)
773
+ self.fd = fd
774
+
775
+ #read the file size
776
+ self.__makeSureFileIsOpen()
777
+ fd = self.fd
778
+ fd.seek(0, os.SEEK_END)
779
+ endOfFile = fd.tell()
780
+ if fd.tell() == 0:
781
+ self._initEmptyFile(fd)
782
+ fd.seek(0, os.SEEK_END)
783
+ endOfFile = fd.tell()
784
+
785
+ #init internal variables
786
+ self._initInternalVariables(fd)
787
+ st = self._structChar
788
+
789
+ #get the image file directories
790
+ nImages = self.getImageFileDirectories()
791
+ if DEBUG:
792
+ print("File contains %d images" % nImages)
793
+ if nImages == 0:
794
+ fd.seek(4)
795
+ fmt = st + 'I'
796
+ fd.write(struct.pack(fmt, endOfFile))
797
+ else:
798
+ fd.seek(self._IFD[-1])
799
+ fmt = st + 'H'
800
+ numberOfDirectoryEntries = struct.unpack(fmt, fd.read(struct.calcsize(fmt)))[0]
801
+ fmt = st + 'I'
802
+ pos = self._IFD[-1] + 2 + 12 * numberOfDirectoryEntries
803
+ fd.seek(pos)
804
+ fmt = st + 'I'
805
+ fd.write(struct.pack(fmt, endOfFile))
806
+ fd.flush()
807
+
808
+ #and we can write at the end of the file, find out the file length
809
+ fd.seek(0, os.SEEK_END)
810
+
811
+ #get the description information from the input information
812
+ if info is None:
813
+ description = info
814
+ else:
815
+ description = "%s" % ""
816
+ for key in info.keys():
817
+ description += "%s=%s\n" % (key, info[key])
818
+
819
+ #get the image file directory
820
+ outputIFD = self._getOutputIFD(image, description=description,
821
+ software=software,
822
+ date=date)
823
+
824
+ #write the new IFD
825
+ fd.write(outputIFD)
826
+
827
+ #write the image
828
+ if self._swap:
829
+ fd.write(image.byteswap().tostring())
830
+ else:
831
+ fd.write(image.tostring())
832
+
833
+ fd.flush()
834
+ self.fd = fd
835
+ self.__makeSureFileIsClosed()
836
+
837
+ def _initEmptyFile(self, fd=None):
838
+ if fd is None:
839
+ fd = self.fd
840
+ if sys.byteorder == "little":
841
+ order = "II"
842
+ #intel, little endian
843
+ fileOrder = "little"
844
+ self._structChar = '<'
845
+ else:
846
+ order = "MM"
847
+ #motorola, high endian
848
+ fileOrder = "big"
849
+ self._structChar = '>'
850
+ st = self._structChar
851
+ if fileOrder == sys.byteorder:
852
+ self._swap = False
853
+ else:
854
+ self._swap = True
855
+ fd.seek(0)
856
+ if sys.version < '3.0':
857
+ fd.write(struct.pack(st + '2s', order))
858
+ fd.write(struct.pack(st + 'H', 42))
859
+ fd.write(struct.pack(st + 'I', 0))
860
+ else:
861
+ fd.write(struct.pack(st + '2s', bytes(order, 'utf-8')))
862
+ fd.write(struct.pack(st + 'H', 42))
863
+ fd.write(struct.pack(st + 'I', 0))
864
+ fd.flush()
865
+
866
+ def _getOutputIFD(self, image, description=None, software=None, date=None):
867
+ #the tags have to be in order
868
+ #the very minimum is
869
+ #256:"NumberOfColumns", # S or L ImageWidth
870
+ #257:"NumberOfRows", # S or L ImageHeight
871
+ #258:"BitsPerSample", # S Number of bits per component
872
+ #259:"Compression", # SHORT (1 - NoCompression, ...
873
+ #262:"PhotometricInterpretation", # SHORT (0 - WhiteIsZero, 1 -BlackIsZero, 2 - RGB, 3 - Palette color
874
+ #270:"ImageDescription", # ASCII
875
+ #273:"StripOffsets", # S or L, for each strip, the byte offset of the strip
876
+ #278:"RowsPerStrip", # S or L, number of rows in each back may be not for the last
877
+ #279:"StripByteCounts", # S or L, The number of bytes in the strip AFTER any compression
878
+ #305:"Software", # ASCII
879
+ #306:"Date", # ASCII
880
+ #339:"SampleFormat", # SHORT Interpretation of data in each pixel
881
+
882
+ nDirectoryEntries = 9
883
+ imageDescription = None
884
+ if description is not None:
885
+ descriptionLength = len(description)
886
+ while descriptionLength < 4:
887
+ description = description + " "
888
+ descriptionLength = len(description)
889
+ if sys.version >= '3.0':
890
+ description = bytes(description, 'utf-8')
891
+ elif type(description) != type(""):
892
+ try:
893
+ description = description.decode('utf-8')
894
+ except UnicodeDecodeError:
895
+ try:
896
+ description = description.decode('latin-1')
897
+ except UnicodeDecodeError:
898
+ description = "%s" % description
899
+ if sys.version > '2.6':
900
+ description = description.encode('utf-8', errors="ignore")
901
+ description = "%s" % description
902
+ descriptionLength = len(description)
903
+ imageDescription = struct.pack("%ds" % descriptionLength, description)
904
+ nDirectoryEntries += 1
905
+
906
+ #software
907
+ if software is not None:
908
+ softwareLength = len(software)
909
+ while softwareLength < 4:
910
+ software = software + " "
911
+ softwareLength = len(software)
912
+ if sys.version >= '3.0':
913
+ software = bytes(software, 'utf-8')
914
+ softwarePackedString = struct.pack("%ds" % softwareLength, software)
915
+ nDirectoryEntries += 1
916
+ else:
917
+ softwareLength = 0
918
+
919
+ if date is not None:
920
+ dateLength = len(date)
921
+ if sys.version >= '3.0':
922
+ date = bytes(date, 'utf-8')
923
+ datePackedString = struct.pack("%ds" % dateLength, date)
924
+ dateLength = len(datePackedString)
925
+ nDirectoryEntries += 1
926
+ else:
927
+ dateLength = 0
928
+
929
+ nRows, nColumns = image.shape
930
+ dtype = image.dtype
931
+ bitsPerSample = int(dtype.str[-1]) * 8
932
+
933
+ #only uncompressed data
934
+ compression = 1
935
+
936
+ #interpretation, black is zero
937
+ interpretation = 1
938
+
939
+ #image description
940
+ if imageDescription is not None:
941
+ descriptionLength = len(imageDescription)
942
+ else:
943
+ descriptionLength = 0
944
+
945
+ #strip offsets
946
+ #we are putting them after the directory and the directory is
947
+ #at the end of the file
948
+ self.fd.seek(0, os.SEEK_END)
949
+ endOfFile = self.fd.tell()
950
+ if endOfFile == 0:
951
+ #empty file
952
+ endOfFile = 8
953
+
954
+ #rows per strip
955
+ if ALLOW_MULTIPLE_STRIPS:
956
+ #try to segment the image in several pieces
957
+ if not (nRows % 4):
958
+ rowsPerStrip = int(nRows / 4)
959
+ elif not (nRows % 10):
960
+ rowsPerStrip = int(nRows / 10)
961
+ elif not (nRows % 8):
962
+ rowsPerStrip = int(nRows / 8)
963
+ elif not (nRows % 4):
964
+ rowsPerStrip = int(nRows / 4)
965
+ elif not (nRows % 2):
966
+ rowsPerStrip = int(nRows / 2)
967
+ else:
968
+ rowsPerStrip = nRows
969
+ else:
970
+ rowsPerStrip = nRows
971
+
972
+ #stripByteCounts
973
+ stripByteCounts = int(nColumns * rowsPerStrip * bitsPerSample / 8)
974
+
975
+ if descriptionLength > 4:
976
+ stripOffsets0 = endOfFile + dateLength + descriptionLength + \
977
+ 2 + 12 * nDirectoryEntries + 4
978
+ else:
979
+ stripOffsets0 = endOfFile + dateLength + \
980
+ 2 + 12 * nDirectoryEntries + 4
981
+
982
+ if softwareLength > 4:
983
+ stripOffsets0 += softwareLength
984
+
985
+ stripOffsets = [stripOffsets0]
986
+ stripOffsetsLength = 0
987
+ stripOffsetsString = None
988
+
989
+ st = self._structChar
990
+
991
+ if rowsPerStrip != nRows:
992
+ nStripOffsets = int(nRows / rowsPerStrip)
993
+ fmt = st + 'I'
994
+ stripOffsetsLength = struct.calcsize(fmt) * nStripOffsets
995
+ stripOffsets0 += stripOffsetsLength
996
+ #the length for the stripByteCounts will be the same
997
+ stripOffsets0 += stripOffsetsLength
998
+ stripOffsets = []
999
+ for i in range(nStripOffsets):
1000
+ value = stripOffsets0 + i * stripByteCounts
1001
+ stripOffsets.append(value)
1002
+ if i == 0:
1003
+ stripOffsetsString = struct.pack(fmt, value)
1004
+ stripByteCountsString = struct.pack(fmt, stripByteCounts)
1005
+ else:
1006
+ stripOffsetsString += struct.pack(fmt, value)
1007
+ stripByteCountsString += struct.pack(fmt, stripByteCounts)
1008
+
1009
+ if DEBUG:
1010
+ print("IMAGE WILL START AT %d" % stripOffsets[0])
1011
+
1012
+ #sample format
1013
+ if dtype in [numpy.float32, numpy.float64] or\
1014
+ dtype.str[-2] == 'f':
1015
+ sampleFormat = SAMPLE_FORMAT_FLOAT
1016
+ elif dtype in [numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64]:
1017
+ sampleFormat = SAMPLE_FORMAT_UINT
1018
+ elif dtype in [numpy.int8, numpy.int16, numpy.int32, numpy.int64]:
1019
+ sampleFormat = SAMPLE_FORMAT_INT
1020
+ else:
1021
+ raise ValueError("Unsupported data type %s" % dtype)
1022
+
1023
+ info = {}
1024
+ info["nColumns"] = nColumns
1025
+ info["nRows"] = nRows
1026
+ info["nBits"] = bitsPerSample
1027
+ info["compression"] = compression
1028
+ info["photometricInterpretation"] = interpretation
1029
+ info["stripOffsets"] = stripOffsets
1030
+ info["rowsPerStrip"] = rowsPerStrip
1031
+ info["stripByteCounts"] = stripByteCounts
1032
+ info["date"] = date
1033
+ info["sampleFormat"] = sampleFormat
1034
+
1035
+ outputIFD = ""
1036
+ if sys.version > '2.6':
1037
+ outputIFD = eval('b""')
1038
+
1039
+ fmt = st + "H"
1040
+ outputIFD += struct.pack(fmt, nDirectoryEntries)
1041
+
1042
+ fmt = st + "HHII"
1043
+ outputIFD += struct.pack(fmt, TAG_NUMBER_OF_COLUMNS,
1044
+ FIELD_TYPE_OUT['I'],
1045
+ 1,
1046
+ info["nColumns"])
1047
+ outputIFD += struct.pack(fmt, TAG_NUMBER_OF_ROWS,
1048
+ FIELD_TYPE_OUT['I'],
1049
+ 1,
1050
+ info["nRows"])
1051
+
1052
+ fmt = st + 'HHIHH'
1053
+ outputIFD += struct.pack(fmt, TAG_BITS_PER_SAMPLE,
1054
+ FIELD_TYPE_OUT['H'],
1055
+ 1,
1056
+ info["nBits"], 0)
1057
+ fmt = st + 'HHIHH'
1058
+ outputIFD += struct.pack(fmt, TAG_COMPRESSION,
1059
+ FIELD_TYPE_OUT['H'],
1060
+ 1,
1061
+ info["compression"], 0)
1062
+ fmt = st + 'HHIHH'
1063
+ outputIFD += struct.pack(fmt, TAG_PHOTOMETRIC_INTERPRETATION,
1064
+ FIELD_TYPE_OUT['H'],
1065
+ 1,
1066
+ info["photometricInterpretation"], 0)
1067
+
1068
+ if imageDescription is not None:
1069
+ descriptionLength = len(imageDescription)
1070
+ if descriptionLength > 4:
1071
+ fmt = st + 'HHII'
1072
+ outputIFD += struct.pack(fmt, TAG_IMAGE_DESCRIPTION,
1073
+ FIELD_TYPE_OUT['s'],
1074
+ descriptionLength,
1075
+ info["stripOffsets"][0] - \
1076
+ 2 * stripOffsetsLength - \
1077
+ descriptionLength)
1078
+ else:
1079
+ #it has to have length 4
1080
+ fmt = st + 'HHI%ds' % descriptionLength
1081
+ outputIFD += struct.pack(fmt, TAG_IMAGE_DESCRIPTION,
1082
+ FIELD_TYPE_OUT['s'],
1083
+ descriptionLength,
1084
+ description)
1085
+
1086
+ if len(stripOffsets) == 1:
1087
+ fmt = st + 'HHII'
1088
+ outputIFD += struct.pack(fmt, TAG_STRIP_OFFSETS,
1089
+ FIELD_TYPE_OUT['I'],
1090
+ 1,
1091
+ info["stripOffsets"][0])
1092
+ else:
1093
+ fmt = st + 'HHII'
1094
+ outputIFD += struct.pack(fmt, TAG_STRIP_OFFSETS,
1095
+ FIELD_TYPE_OUT['I'],
1096
+ len(stripOffsets),
1097
+ info["stripOffsets"][0] - 2 * stripOffsetsLength)
1098
+
1099
+ fmt = st + 'HHII'
1100
+ outputIFD += struct.pack(fmt, TAG_ROWS_PER_STRIP,
1101
+ FIELD_TYPE_OUT['I'],
1102
+ 1,
1103
+ info["rowsPerStrip"])
1104
+
1105
+ if len(stripOffsets) == 1:
1106
+ fmt = st + 'HHII'
1107
+ outputIFD += struct.pack(fmt, TAG_STRIP_BYTE_COUNTS,
1108
+ FIELD_TYPE_OUT['I'],
1109
+ 1,
1110
+ info["stripByteCounts"])
1111
+ else:
1112
+ fmt = st + 'HHII'
1113
+ outputIFD += struct.pack(fmt, TAG_STRIP_BYTE_COUNTS,
1114
+ FIELD_TYPE_OUT['I'],
1115
+ len(stripOffsets),
1116
+ info["stripOffsets"][0] - stripOffsetsLength)
1117
+
1118
+ if software is not None:
1119
+ if softwareLength > 4:
1120
+ fmt = st + 'HHII'
1121
+ outputIFD += struct.pack(fmt, TAG_SOFTWARE,
1122
+ FIELD_TYPE_OUT['s'],
1123
+ softwareLength,
1124
+ info["stripOffsets"][0] - \
1125
+ 2 * stripOffsetsLength - \
1126
+ descriptionLength - softwareLength - dateLength)
1127
+ else:
1128
+ #it has to have length 4
1129
+ fmt = st + 'HHI%ds' % softwareLength
1130
+ outputIFD += struct.pack(fmt, TAG_SOFTWARE,
1131
+ FIELD_TYPE_OUT['s'],
1132
+ softwareLength,
1133
+ softwarePackedString)
1134
+
1135
+ if date is not None:
1136
+ fmt = st + 'HHII'
1137
+ outputIFD += struct.pack(fmt, TAG_DATE,
1138
+ FIELD_TYPE_OUT['s'],
1139
+ dateLength,
1140
+ info["stripOffsets"][0] - \
1141
+ 2 * stripOffsetsLength - \
1142
+ descriptionLength - dateLength)
1143
+
1144
+ fmt = st + 'HHIHH'
1145
+ outputIFD += struct.pack(fmt, TAG_SAMPLE_FORMAT,
1146
+ FIELD_TYPE_OUT['H'],
1147
+ 1,
1148
+ info["sampleFormat"], 0)
1149
+ fmt = st + 'I'
1150
+ outputIFD += struct.pack(fmt, 0)
1151
+
1152
+ if softwareLength > 4:
1153
+ outputIFD += softwarePackedString
1154
+
1155
+ if date is not None:
1156
+ outputIFD += datePackedString
1157
+
1158
+ if imageDescription is not None:
1159
+ if descriptionLength > 4:
1160
+ outputIFD += imageDescription
1161
+
1162
+ if stripOffsetsString is not None:
1163
+ outputIFD += stripOffsetsString
1164
+ outputIFD += stripByteCountsString
1165
+
1166
+ return outputIFD
1167
+
1168
+
1169
+ if __name__ == "__main__":
1170
+ filename = sys.argv[1]
1171
+ dtype = numpy.uint16
1172
+ if not os.path.exists(filename):
1173
+ print("Testing file creation")
1174
+ tif = TiffIO(filename, mode='wb+')
1175
+ data = numpy.arange(10000).astype(dtype)
1176
+ data.shape = 100, 100
1177
+ tif.writeImage(data, info={'Title':'1st'})
1178
+ tif = None
1179
+ if os.path.exists(filename):
1180
+ print("Testing image appending")
1181
+ tif = TiffIO(filename, mode='rb+')
1182
+ tif.writeImage((data * 2).astype(dtype), info={'Title':'2nd'})
1183
+ tif = None
1184
+ tif = TiffIO(filename)
1185
+ print("Number of images = %d" % tif.getNumberOfImages())
1186
+ for i in range(tif.getNumberOfImages()):
1187
+ info = tif.getInfo(i)
1188
+ for key in info:
1189
+ if key not in ["colormap"]:
1190
+ print("%s = %s" % (key, info[key]))
1191
+ elif info['colormap'] is not None:
1192
+ print("RED %s = %s" % (key, info[key][0:10, 0]))
1193
+ print("GREEN %s = %s" % (key, info[key][0:10, 1]))
1194
+ print("BLUE %s = %s" % (key, info[key][0:10, 2]))
1195
+ data = tif.getImage(i)[0, 0:10]
1196
+ print("data [0, 0:10] = ", data)
1197
+