Back to index

moin  1.9.0~rc2
Public Member Functions | Public Attributes
MoinMoin.filter.EXIF.EXIF_header Class Reference

List of all members.

Public Member Functions

def __init__
def s2n
def n2s
def first_IFD
def next_IFD
def list_IFDs
def dump_IFD
def extract_TIFF_thumbnail
def decode_maker_note
def olympus_decode_tag
def canon_decode_tag

Public Attributes

 file
 endian
 offset
 fake_exif
 debug
 tags

Detailed Description

Definition at line 1146 of file EXIF.py.


Constructor & Destructor Documentation

def MoinMoin.filter.EXIF.EXIF_header.__init__ (   self,
  file,
  endian,
  offset,
  fake_exif,
  debug = 0 
)

Definition at line 1147 of file EXIF.py.

01147 
01148     def __init__(self, file, endian, offset, fake_exif, debug=0):
01149         self.file = file
01150         self.endian = endian
01151         self.offset = offset
01152         self.fake_exif = fake_exif
01153         self.debug = debug
01154         self.tags = {}


Member Function Documentation

def MoinMoin.filter.EXIF.EXIF_header.canon_decode_tag (   self,
  value,
  dict 
)

Definition at line 1444 of file EXIF.py.

01444 
01445     def canon_decode_tag(self, value, dict):
01446         for i in range(1, len(value)):
01447             x=dict.get(i, ('Unknown', ))
01448             if self.debug:
01449                 print i, x
01450             name=x[0]
01451             if len(x) > 1:
01452                 val=x[1].get(value[i], 'Unknown')
01453             else:
01454                 val=value[i]
01455             # it's not a real IFD Tag but we fake one to make everybody
01456             # happy. this will have a "proprietary" type
01457             self.tags['MakerNote '+name]=IFD_Tag(str(val), None, 0, None,
01458                                                  None, None)
01459 
01460 # process an image file (expects an open file object)
01461 # this is the function that has to deal with all the arbitrary nasty bits
# of the EXIF standard

Here is the caller graph for this function:

Definition at line 1365 of file EXIF.py.

01365 
01366     def decode_maker_note(self):
01367         note = self.tags['EXIF MakerNote']
01368         make = self.tags['Image Make'].printable
01369         # model = self.tags['Image Model'].printable # unused
01370 
01371         # Nikon
01372         # The maker note usually starts with the word Nikon, followed by the
01373         # type of the makernote (1 or 2, as a short).  If the word Nikon is
01374         # not at the start of the makernote, it's probably type 2, since some
01375         # cameras work that way.
01376         if make in ('NIKON', 'NIKON CORPORATION'):
01377             if note.values[0:7] == [78, 105, 107, 111, 110, 0, 1]:
01378                 if self.debug:
01379                     print "Looks like a type 1 Nikon MakerNote."
01380                 self.dump_IFD(note.field_offset+8, 'MakerNote',
01381                               dict=MAKERNOTE_NIKON_OLDER_TAGS)
01382             elif note.values[0:7] == [78, 105, 107, 111, 110, 0, 2]:
01383                 if self.debug:
01384                     print "Looks like a labeled type 2 Nikon MakerNote"
01385                 if note.values[12:14] != [0, 42] and note.values[12:14] != [42L, 0L]:
01386                     raise ValueError("Missing marker tag '42' in MakerNote.")
01387                 # skip the Makernote label and the TIFF header
01388                 self.dump_IFD(note.field_offset+10+8, 'MakerNote',
01389                               dict=MAKERNOTE_NIKON_NEWER_TAGS, relative=1)
01390             else:
01391                 # E99x or D1
01392                 if self.debug:
01393                     print "Looks like an unlabeled type 2 Nikon MakerNote"
01394                 self.dump_IFD(note.field_offset, 'MakerNote',
01395                               dict=MAKERNOTE_NIKON_NEWER_TAGS)
01396             return
01397 
01398         # Olympus
01399         if make.startswith('OLYMPUS'):
01400             self.dump_IFD(note.field_offset+8, 'MakerNote',
01401                           dict=MAKERNOTE_OLYMPUS_TAGS)
01402             # TODO
01403             #for i in (('MakerNote Tag 0x2020', MAKERNOTE_OLYMPUS_TAG_0x2020),):
01404             #    self.decode_olympus_tag(self.tags[i[0]].values, i[1])
01405             #return
01406 
01407         # Casio
01408         if make == 'Casio':
01409             self.dump_IFD(note.field_offset, 'MakerNote',
01410                           dict=MAKERNOTE_CASIO_TAGS)
01411             return
01412 
01413         # Fujifilm
01414         if make == 'FUJIFILM':
01415             # bug: everything else is "Motorola" endian, but the MakerNote
01416             # is "Intel" endian
01417             endian = self.endian
01418             self.endian = 'I'
01419             # bug: IFD offsets are from beginning of MakerNote, not
01420             # beginning of file header
01421             offset = self.offset
01422             self.offset += note.field_offset
01423             # process note with bogus values (note is actually at offset 12)
01424             self.dump_IFD(12, 'MakerNote', dict=MAKERNOTE_FUJIFILM_TAGS)
01425             # reset to correct values
01426             self.endian = endian
01427             self.offset = offset
01428             return
01429 
01430         # Canon
01431         if make == 'Canon':
01432             self.dump_IFD(note.field_offset, 'MakerNote',
01433                           dict=MAKERNOTE_CANON_TAGS)
01434             for i in (('MakerNote Tag 0x0001', MAKERNOTE_CANON_TAG_0x001),
01435                       ('MakerNote Tag 0x0004', MAKERNOTE_CANON_TAG_0x004)):
01436                 self.canon_decode_tag(self.tags[i[0]].values, i[1])
01437             return

Here is the call graph for this function:

def MoinMoin.filter.EXIF.EXIF_header.dump_IFD (   self,
  ifd,
  ifd_name,
  dict = EXIF_TAGS,
  relative = 0,
  name = 'UNDEF' 
)

Definition at line 1203 of file EXIF.py.

01203 
01204     def dump_IFD(self, ifd, ifd_name, dict=EXIF_TAGS, relative=0, name='UNDEF'):
01205         entries=self.s2n(ifd, 2)
01206         for i in range(entries):
01207             # entry is index of start of this IFD in the file
01208             entry = ifd + 2 + 12 * i
01209             tag = self.s2n(entry, 2)
01210 
01211             # ignore certain tags for faster processing
01212             if not (tag in IGNORE_TAGS and not detailed):
01213                 # get tag name.  We do it early to make debugging easier
01214                 tag_entry = dict.get(tag)
01215                 if tag_entry:
01216                     tag_name = tag_entry[0]
01217                 else:
01218                     tag_name = 'Tag 0x%04X' % tag
01219 
01220                 field_type = self.s2n(entry + 2, 2)
01221                 if not 0 < field_type < len(FIELD_TYPES):
01222                     # unknown field type
01223                     raise ValueError('unknown type %d in tag 0x%04X' % (field_type, tag))
01224                 typelen = FIELD_TYPES[field_type][0]
01225                 count = self.s2n(entry + 4, 4)
01226                 offset = entry + 8
01227                 if count * typelen > 4:
01228                     # offset is not the value; it's a pointer to the value
01229                     # if relative we set things up so s2n will seek to the right
01230                     # place when it adds self.offset.  Note that this 'relative'
01231                     # is for the Nikon type 3 makernote.  Other cameras may use
01232                     # other relative offsets, which would have to be computed here
01233                     # slightly differently.
01234                     if relative:
01235                         tmp_offset = self.s2n(offset, 4)
01236                         offset = tmp_offset + ifd - self.offset + 4
01237                         if self.fake_exif:
01238                             offset = offset + 18
01239                     else:
01240                         offset = self.s2n(offset, 4)
01241                 field_offset = offset
01242                 if field_type == 2:
01243                     # special case: null-terminated ASCII string
01244                     if count != 0:
01245                         self.file.seek(self.offset + offset)
01246                         values = self.file.read(count)
01247                         values = values.strip().replace('\x00', '')
01248                     else:
01249                         values = ''
01250                 else:
01251                     values = []
01252                     signed = (field_type in [6, 8, 9, 10])
01253                     for dummy in range(count):
01254                         if field_type in (5, 10):
01255                             # a ratio
01256                             value = Ratio(self.s2n(offset, 4, signed),
01257                                           self.s2n(offset + 4, 4, signed))
01258                         else:
01259                             value = self.s2n(offset, typelen, signed)
01260                         values.append(value)
01261                         offset = offset + typelen
01262                 # now "values" is either a string or an array
01263                 if count == 1 and field_type != 2:
01264                     printable=str(values[0])
01265                 else:
01266                     printable=str(values)
01267                 # compute printable version of values
01268                 if tag_entry:
01269                     if len(tag_entry) != 1:
01270                         # optional 2nd tag element is present
01271                         if callable(tag_entry[1]):
01272                             # call mapping function
01273                             printable = tag_entry[1](values)
01274                         else:
01275                             printable = ''
01276                             for i in values:
01277                                 # use lookup table for this tag
01278                                 printable += tag_entry[1].get(i, repr(i))
01279 
01280                 self.tags[ifd_name + ' ' + tag_name] = IFD_Tag(printable, tag,
01281                                                           field_type,
01282                                                           values, field_offset,
01283                                                           count * typelen)
01284                 if self.debug:
01285                     print ' debug:   %s: %s' % (tag_name,
01286                                                 repr(self.tags[ifd_name + ' ' + tag_name]))
01287 
01288             if tag_name == name:
01289                 break

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1293 of file EXIF.py.

01293 
01294     def extract_TIFF_thumbnail(self, thumb_ifd):
01295         entries = self.s2n(thumb_ifd, 2)
01296         # this is header plus offset to IFD ...
01297         if self.endian == 'M':
01298             tiff = 'MM\x00*\x00\x00\x00\x08'
01299         else:
01300             tiff = 'II*\x00\x08\x00\x00\x00'
01301         # ... plus thumbnail IFD data plus a null "next IFD" pointer
01302         self.file.seek(self.offset+thumb_ifd)
01303         tiff += self.file.read(entries*12+2)+'\x00\x00\x00\x00'
01304 
01305         # fix up large value offset pointers into data area
01306         for i in range(entries):
01307             entry = thumb_ifd + 2 + 12 * i
01308             tag = self.s2n(entry, 2)
01309             field_type = self.s2n(entry+2, 2)
01310             typelen = FIELD_TYPES[field_type][0]
01311             count = self.s2n(entry+4, 4)
01312             oldoff = self.s2n(entry+8, 4)
01313             # start of the 4-byte pointer area in entry
01314             ptr = i * 12 + 18
01315             # remember strip offsets location
01316             if tag == 0x0111:
01317                 strip_off = ptr
01318                 strip_len = count * typelen
01319             # is it in the data area?
01320             if count * typelen > 4:
01321                 # update offset pointer (nasty "strings are immutable" crap)
01322                 # should be able to say "tiff[ptr:ptr+4]=newoff"
01323                 newoff = len(tiff)
01324                 tiff = tiff[:ptr] + self.n2s(newoff, 4) + tiff[ptr+4:]
01325                 # remember strip offsets location
01326                 if tag == 0x0111:
01327                     strip_off = newoff
01328                     strip_len = 4
01329                 # get original data and store it
01330                 self.file.seek(self.offset + oldoff)
01331                 tiff += self.file.read(count * typelen)
01332 
01333         # add pixel strips and update strip offset info
01334         old_offsets = self.tags['Thumbnail StripOffsets'].values
01335         old_counts = self.tags['Thumbnail StripByteCounts'].values
01336         for i in range(len(old_offsets)):
01337             # update offset pointer (more nasty "strings are immutable" crap)
01338             offset = self.n2s(len(tiff), strip_len)
01339             tiff = tiff[:strip_off] + offset + tiff[strip_off + strip_len:]
01340             strip_off += strip_len
01341             # add pixel strip to end
01342             self.file.seek(self.offset + old_offsets[i])
01343             tiff += self.file.read(old_counts[i])
01344 
01345         self.tags['TIFFThumbnail'] = tiff

Here is the call graph for this function:

Definition at line 1185 of file EXIF.py.

01185 
01186     def first_IFD(self):
01187         return self.s2n(4, 4)

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1194 of file EXIF.py.

01194 
01195     def list_IFDs(self):
01196         i=self.first_IFD()
01197         a=[]
01198         while i:
01199             a.append(i)
01200             i=self.next_IFD(i)
01201         return a

Here is the call graph for this function:

def MoinMoin.filter.EXIF.EXIF_header.n2s (   self,
  offset,
  length 
)

Definition at line 1174 of file EXIF.py.

01174 
01175     def n2s(self, offset, length):
01176         s = ''
01177         for dummy in range(length):
01178             if self.endian == 'I':
01179                 s = s + chr(offset & 0xFF)
01180             else:
01181                 s = chr(offset & 0xFF) + s
01182             offset = offset >> 8
01183         return s

Here is the caller graph for this function:

def MoinMoin.filter.EXIF.EXIF_header.next_IFD (   self,
  ifd 
)

Definition at line 1189 of file EXIF.py.

01189 
01190     def next_IFD(self, ifd):
01191         entries=self.s2n(ifd, 2)
01192         return self.s2n(ifd+2+12*entries, 4)

Here is the call graph for this function:

Here is the caller graph for this function:

def MoinMoin.filter.EXIF.EXIF_header.olympus_decode_tag (   self,
  value,
  dict 
)

Definition at line 1439 of file EXIF.py.

01439 
01440     def olympus_decode_tag(self, value, dict):
01441         pass

def MoinMoin.filter.EXIF.EXIF_header.s2n (   self,
  offset,
  length,
  signed = 0 
)

Definition at line 1159 of file EXIF.py.

01159 
01160     def s2n(self, offset, length, signed=0):
01161         self.file.seek(self.offset+offset)
01162         slice=self.file.read(length)
01163         if self.endian == 'I':
01164             val=s2n_intel(slice)
01165         else:
01166             val=s2n_motorola(slice)
01167         # Sign extension ?
01168         if signed:
01169             msb=1L << (8*length-1)
01170             if val & msb:
01171                 val=val-(msb << 1)
01172         return val

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 1152 of file EXIF.py.

Definition at line 1149 of file EXIF.py.

Definition at line 1151 of file EXIF.py.

Definition at line 1148 of file EXIF.py.

Definition at line 1150 of file EXIF.py.

Definition at line 1153 of file EXIF.py.


The documentation for this class was generated from the following file: