eggification
[Photo.git] / Products / Photo / static / gitweb.js
diff --git a/exif.py b/exif.py
deleted file mode 100755 (executable)
index 8120852..0000000
--- a/exif.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# -*- coding: utf-8 -*-
-#######################################################################################
-#   Photo is a part of Plinn - http://plinn.org                                       #
-#   Copyright © 2008  Benoît PIN <benoit.pin@ensmp.fr>                                #
-#                                                                                     #
-#   This program is free software; you can redistribute it and/or                     #
-#   modify it under the terms of the GNU General Public License                       #
-#   as published by the Free Software Foundation; either version 2                    #
-#   of the License, or (at your option) any later version.                            #
-#                                                                                     #
-#   This program is distributed in the hope that it will be useful,                   #
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of                    #
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                     #
-#   GNU General Public License for more details.                                      #
-#                                                                                     #
-#   You should have received a copy of the GNU General Public License                 #
-#   along with this program; if not, write to the Free Software                       #
-#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.   #
-#######################################################################################
-""" Exif version 2.2 read/write module.
-
-
-
-"""
-
-TYPES_SIZES = {
-         1: 1          # BYTE An 8-bit unsigned integer.,
-       , 2: 1          # ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.,
-       , 3: 2          # SHORT A 16-bit (2-byte) unsigned integer,
-       , 4: 4          # LONG A 32-bit (4-byte) unsigned integer,
-       , 5: 8          # RATIONAL Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator.,
-       , 7: 1          # UNDEFINED An 8-bit byte that can take any value depending on the field definition,
-       , 9: 4          # SLONG A 32-bit (4-byte) signed integer (2's complement notation),
-       , 10 : 8        # SRATIONAL Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
-}
-
-# tags for parsing metadata
-Exif_IFD_POINTER = 0x8769
-GPS_INFO_IFD_POINTER = 0x8825
-INTEROPERABILITY_IFD_POINTER = 0xA005
-
-# tags to get thumbnail
-COMPRESSION_SCHEME = 0x103
-COMPRESSION_SCHEME_TYPES = {1:'image/bmp', 6:'image/jpeg'}
-OFFSET_TO_JPEG_SOI = 0x201
-BYTES_OF_JPEG_DATA = 0x202
-STRIPOFFSETS = 0x111
-STRIPBYTECOUNTS = 0x117
-
-# constants for writing
-INTEROPERABILITY_FIELD_LENGTH = 12
-POINTER_TAGS = { Exif_IFD_POINTER:True
-                          , GPS_INFO_IFD_POINTER:True
-                          , INTEROPERABILITY_IFD_POINTER:True}
-
-
-class Exif(dict) :
-       
-       def __init__(self, f) :
-               # File Headers are 8 bytes as defined in the TIFF standard.
-               self.f = f
-               
-               byteOrder = f.read(2)
-               self.byteOrder = byteOrder
-               
-               if byteOrder == 'MM' :
-                       r16 = self.r16 = lambda:ib16(f.read(2))
-                       r32 = self.r32 = lambda:ib32(f.read(4))
-               elif byteOrder == 'II' :
-                       r16 = self.r16 = lambda:il16(f.read(2))
-                       r32 = self.r32 = lambda:il32(f.read(4))
-               else :
-                       raise ValueError, "Unkwnown byte order: %r" % byteOrder
-               
-               assert r16() == 0x002A, "Incorrect exif header"
-               
-               self.tagReaders = {
-                         1:  lambda c : [ord(f.read(1)) for i in xrange(c)]
-                       , 2:  lambda c : f.read(c)
-                       , 3:  lambda c : [r16() for i in xrange(c)]
-                       , 4:  lambda c : [r32() for i in xrange(c)]
-                       , 5:  lambda c : [(r32(), r32()) for i in xrange(c)]
-                       , 7:  lambda c : f.read(c)
-                       , 9:  lambda c : [r32() for i in xrange(c)]
-                       , 10: lambda c : [(r32(), r32()) for i in xrange(c)]
-               }
-               
-               self.tagInfos = {}
-               self.mergedTagInfos = {}
-               self.gpsTagInfos = {}
-               
-               ifd0Offset = r32()
-               
-               ifd1Offset = self._loadTagsInfo(ifd0Offset, 'IFD0')
-               others = [(lambda:self[Exif_IFD_POINTER], 'Exif'),
-                                 (lambda:self.get(GPS_INFO_IFD_POINTER), 'GPS'),
-                                 (lambda:self.get(INTEROPERABILITY_IFD_POINTER), 'Interoperability'),
-                                 (lambda:ifd1Offset, 'IFD1')]
-               
-               self.ifdnames = ['IFD0']
-               
-               for startfunc, ifdname in others :
-                       start = startfunc()
-                       if start :
-                               ret = self._loadTagsInfo(start, ifdname)
-                               assert ret == 0
-                               self.ifdnames.append(ifdname)
-               
-               
-       def _loadTagsInfo(self, start, ifdname) :
-               r16, r32 = self.r16, self.r32
-               
-               self.f.seek(start)
-               
-               numberOfFields = r16()
-               ifdInfos = self.tagInfos[ifdname] = {}
-               
-               for i in xrange(numberOfFields) :
-                       #  12 bytes of the field Interoperability
-                       tag = r16()
-                       typ = r16()
-                       count = r32()
-
-                       ts = TYPES_SIZES[typ]
-                       size = ts * count
-                       
-                       # In cases where the value fits in 4 bytes,
-                       # the value itself is recorded.
-                       # If the value is smaller than 4 bytes, the value is
-                       # stored in the 4-byte area starting from the left.
-                       if size <= 4 :
-                               offsetIsValue = True
-                               offset = self.tagReaders[typ](count)
-                               if count == 1:
-                                       offset = offset[0]
-                               noise = self.f.read(4 - size)
-                       else :
-                               offsetIsValue = False
-                               offset = r32()
-                       
-                       ifdInfos[tag] = (typ, count, offset, offsetIsValue)
-               
-               if ifdname == 'GPS' :
-                       self.gpsTagInfos.update(ifdInfos)
-               else :
-                       self.mergedTagInfos.update(ifdInfos)
-
-               # return nexf ifd offset
-               return r32()
-       
-       def getThumbnail(self) :
-               if hasattr(self, 'ifd1Offset') :
-                       comp = self[COMPRESSION_SCHEME]
-                       if comp == 6 :
-                               # TODO : handle uncompressed thumbnails
-                               mime = COMPRESSION_SCHEME_TYPES.get(comp, 'unknown')
-                               start = self[OFFSET_TO_JPEG_SOI]
-                               count = self[BYTES_OF_JPEG_DATA]
-                               f = self.f
-                               f.seek(start)
-                               data = f.read(count)
-                               return data, mime
-                       else :
-                               return None
-               else :
-                       return None
-       
-               
-       
-       #
-       # dict interface
-       #
-       def keys(self) :
-               return self.mergedTagInfos.keys()
-       
-       def has_key(self, key) :
-               return self.mergedTagInfos.has_key(key)
-       
-       __contains__ = has_key # necessary ?
-       
-       def __getitem__(self, key) :
-               typ, count, offset, offsetIsValue = self.mergedTagInfos[key]
-               if offsetIsValue :
-                       return offset
-               else :
-                       self.f.seek(offset)
-                       value = self.tagReaders[typ](count)
-                       if count == 1:
-                               return value[0]
-                       else :
-                               return value
-       
-       def get(self, key) :
-               if self.has_key(key):
-                       return self[key]
-               else :
-                       return None
-       
-       def getIFDNames(self) :
-               return self.ifdnames
-               
-               
-       def getIFDTags(self, name) :
-               tags = [tag for tag in self.tagInfos[name].keys()]
-               tags.sort()
-               return tags
-               
-
-       def save(self, out) :
-               byteOrder = self.byteOrder
-               
-               if byteOrder == 'MM' :
-                       w16 = self.w16 = lambda i : out.write(ob16(i))
-                       w32 = self.w32 = lambda i : out.write(ob32(i))
-               elif byteOrder == 'II' :
-                       w16 = self.w16 = lambda i : out.write(ol16(i))
-                       w32 = self.w32 = lambda i : out.write(ol32(i))
-               
-               tagWriters = {
-                         1:  lambda l : [out.write(chr(i)) for i in l]
-                       , 2:  lambda l : out.write(l)
-                       , 3:  lambda l : [w16(i) for i in l]
-                       , 4:  lambda l : [w32(i) for i in l]
-                       , 5:  lambda l : [(w32(i[0]), w32(i[1])) for i in l]
-                       , 7:  lambda l : out.write(l)
-                       , 9:  lambda l : [w32(i) for i in l]
-                       , 10: lambda l : [(w32(i[0]), w32(i[1])) for i in l]
-               }
-               
-               
-               # tiff header
-               out.write(self.byteOrder)
-               w16(0x002A)
-               tags = self.keys()
-               r32(8) # offset of IFD0
-               ifdStarts = {}
-               pointerTags = []
-               isPtrTag = POINTER_TAGS.has_key
-               
-               for ifdname in self.getIFDName() :
-                       ifdInfos = self.tagInfos[name]
-                       tags = ifdInfos.keys()
-                       tags.sort()
-                       
-                       ifdStarts[ifdname] = out.tell()
-                       
-                       tiffOffset = ifdStarts[ifdname] + INTEROPERABILITY_FIELD_LENGTH * len(tags) + 4
-                       moreThan4bytesValuesTags = []
-                       
-                       for tag, info in ifdInfos.items() :
-                               if isPtrTag(tag) :
-                                       pointerTags.append((tag, out.tell()))
-                               typ, count, offset, offsetIsValue = info
-
-                               w16(tag)
-                               w16(typ)
-                               w32(count)
-                               
-                               ts = TYPES_SIZES[typ]
-                               size = ts * count
-
-                               if size <= 4 :
-                                       if count == 1 : offset = [offset]                                       
-                                       tagWriters[typ](offset)
-                                       
-                                       # padding
-                                       for i in range(4 - size) : out.write('\0')
-                               else :
-                                       w32(tiffOffset)
-                                       tiffOffset += size
-                                       moreThan4bytesValuesTags.append(tag)
-                       
-                       for tag in moreThan4bytesValuesTags :
-                               typ, count, offset, offsetIsValue = ifdInfos[tag]
-                               self.f.seek(offset)
-                               size = TYPES_SIZES[typ] * count
-                               out.write(self.f.read(size))
-                       
-                       # write place-holder for next ifd offset (updated later)
-                       r32(0)
-                       
-
-def ib16(c):
-       return ord(c[1]) + (ord(c[0])<<8)
-def ob16(i) :
-       return chr(i >> 8 & 255) + chr(i & 255)
-       
-def ib32(c):
-       return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
-def ob32(c):
-       return chr(i >> 24 & 0xff) + chr(i >> 16 & 0xff) + chr(i >> 8 & 0xff) + chr(i & 0xff)
-
-
-def il16(c):
-       return ord(c[0]) + (ord(c[1])<<8)
-def ol16(i):
-       return chr(i&255) + chr(i>>8&255)
-       
-def il32(c):
-       return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
-def ol32(i):
-       return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
-
-
-
-
-def testRead(*paths) :
-       from PIL.Image import open as imgopen
-       from standards.exif import TAGS
-       from cStringIO import StringIO
-       
-       import os
-       paths = list(paths)
-       paths.extend(['testimages/%s'%name for name in os.listdir('testimages') \
-                                       if name.endswith('.jpg') and \
-                                          not name.endswith('_thumb.jpg')])
-       
-       for path in paths :
-               print '------------'
-               print path
-               print '------------'
-               im = imgopen(path)
-               applist = im.applist
-               exifBlock = [a[1] for a in applist if a[0] == 'APP1' and a[1].startswith("Exif\x00\x00")][0]
-               exif = exifBlock[6:]
-               sio = StringIO(exif)
-
-               e = Exif(sio)
-               for name in e.getIFDNames() :
-                       print '%s: ' %name
-                       for tag in e.getIFDTags(name) :
-                               print hex(tag), TAGS.get(tag), e[tag]
-                       print
-               
-               thumb = e.getThumbnail()
-               if thumb is not None :
-                       data, mime = thumb
-                       out = open('%s_thumb.jpg' % path[:-4], 'w')
-                       out.write(data)
-                       out.close()
-
-def testWrite(*paths) :
-       from PIL.Image import open as imgopen
-       from standards.exif import TAGS
-       from cStringIO import StringIO
-       
-#      import os
-#      paths = list(paths)
-#      paths.extend(['testimages/%s'%name for name in os.listdir('testimages') \
-#                                      if name.endswith('.jpg') and \
-#                                         not name.endswith('_thumb.jpg')])
-       
-       for path in paths :
-               print '------------'
-               print path
-               print '------------'
-               im = imgopen(path)
-               applist = im.applist
-               exifBlock = [a[1] for a in applist if a[0] == 'APP1' and a[1].startswith("Exif\x00\x00")][0]
-               exif = exifBlock[6:]
-               from cStringIO import StringIO
-               sio = StringIO(exif)
-
-               e = Exif(sio)
-               
-               out = StringIO()
-               e.save(out)
-               out.seek(0)
-               print '%r' % out.read()
-               
-
-if __name__ == '__main__' :
-       testRead('testMM.jpg', 'testII.jpg')
-       #testWrite('testMM.jpg', 'testII.jpg')