I've uploaded a fix in the bazaar repository. I've tested this only one image, so a lot of good testing is required now. Droopy, I count on you ;-) I'll upload it to my PPA where it will be available as Phatch-0.2.0.bzr656 or a later version. https://launchpad.net/~stani/+archive/ppa $ bzr diff === modified file 'phatch/core/api.py' --- phatch/core/api.py 2009-06-05 00:29:01 +0000 +++ phatch/core/api.py 2009-06-05 17:59:27 +0000 @@ -274,7 +274,7 @@ result['abort'] = False return photo, result -def flush_log(photo): +def flush_log(photo, image_file, action=None): if photo.log: log_error(photo.log,image_file,action,label='Warning') photo.log = '' @@ -285,7 +285,7 @@ result['skip'] = False result['abort'] = False #log non fatal errors/warnings - flush_log(photo) + flush_log(photo, image_file, action) return photo, result except Exception, details: folder, image = os.path.split(ensure_unicode(image_file)) @@ -382,7 +382,7 @@ for action_index, action in enumerate(actions): if action.flush_metadata_before: photo.flush_metadata() - flush_log(photo) + flush_log(photo, image_file) #update progress progress_result = {} send.progress_update_index(progress_result,image_index,action_index) @@ -397,7 +397,7 @@ elif result['skip']: break photo.flush_metadata() - flush_log(photo) + flush_log(photo, image_file, action) del photo, progress_result, action_index, action send.progress_close() === modified file 'phatch/core/lib/formField.py' --- phatch/core/lib/formField.py 2009-06-05 13:59:16 +0000 +++ phatch/core/lib/formField.py 2009-06-05 17:49:18 +0000 @@ -225,6 +225,7 @@ BYSIZE+'/'+SUBFOLDER, DEFAULT_FOLDER, FOLDER_PHATCH, + FOLDER+'/'+SUBFOLDER, FOLDER, ] STAMPS = [ === modified file 'phatch/core/pil.py' --- phatch/core/pil.py 2009-06-05 13:15:12 +0000 +++ phatch/core/pil.py 2009-06-05 17:54:49 +0000 @@ -39,6 +39,7 @@ pyexiv2 = None exif = False WWW_PYEXIV2 = 'http://tilloy.net/dev/pyexiv2/' +NEEDS_PYEXIV2 = _('pyexiv2 needs to be installed')+' (%s)'%WWW_PYEXIV2 try: from unicoding import ensure_unicode @@ -82,6 +83,13 @@ raise Exception('Libtiff tools are needed for "%s" compression'\ %compression) +def transpose(image, methods): + """Transpose with a sequence of transformations, mainly useful + for exif.""" + for method in methods: + image = image.transpose(method) + return image + def treshold(a): if a <= 128: return 255 @@ -144,6 +152,7 @@ def extract_info_pexif(info,image): """pexif = Pil EXIF""" + info['Pexif'] = 1 #check if exif information is available through pil if not hasattr(image,'_getexif'): return info @@ -345,6 +354,7 @@ self._rotate_exif_reverse = None self.metadata = {} self.init_info(layer,filename,image_index,save_metadata,folder) + self.rotate_exif() def flush_metadata(self): #is there something to be flushed? @@ -352,8 +362,7 @@ return #throw an error if pyexiv2 is not installed if not exif: - raise ImportError(_('pyexiv2 needs to be installed')\ - +' (%s)'%WWW_PYEXIV2) + raise ImportError(NEEDS_PYEXIV2) self.log += exif.flush(self.info['path'],self.metadata) #as metadata has changed, use new source self._exif_source = self.info['path'] @@ -403,7 +412,8 @@ def save(self,filename,**options): """Saves a flattened image""" #todo: flatten layers - image = self.get_layer().image + image = transpose(self.get_layer().image, + self._rotate_exif_reverse) if image.mode == 'CMYK' and filename.lower().endswith('.png'): self.log = \ _('CMYK has been converted to RGB to save as PNG.') @@ -467,13 +477,51 @@ def rotate_exif(self,reverse=False): if reverse: - if not(self._rotate_exif_reverse is None): - for layer in self.layers.values(): - layer.image = layer.image.transpose( - self._rotate_exif_reverse) - self._rotate_exif_reverse = None + rotation = self._rotate_exif_reverse + self._rotate_exif_reverse = () else: - pass + orientation = self.get_orientation() + #see EXIF.py + if orientation == 1: + rotation = self._rotate_exif_reverse = () + elif orientation == 2: + rotation = Image.FLIP_LEFT_RIGHT, + self._rotate_exif_reverse = Image.FLIP_LEFT_RIGHT, + elif orientation == 3: + rotation = Image.ROTATE_180, + self._rotate_exif_reverse = Image.ROTATE_180, + elif orientation == 4: + rotation = Image.FLIP_TOP_BOTTOM, + self._rotate_exif_reverse = Image.FLIP_TOP_BOTTOM, + elif orientation == 5: + rotation = Image.FLIP_LEFT_RIGHT,Image.ROTATE_90 + self._rotate_exif_reverse = Image.ROTATE_270,Image.FLIP_LEFT_RIGHT + elif orientation == 6: + self._rotate_exif_reverse = Image.ROTATE_270, + rotation = Image.ROTATE_90, + elif orientation == 7: + rotation = Image.FLIP_LEFT_RIGHT,Image.ROTATE_270 + self._rotate_exif_reverse = Image.ROTATE_90,Image.FLIP_LEFT_RIGHT + elif orientation == 8: + rotation = Image.ROTATE_90, + self._rotate_exif_reverse = Image.ROTATE_270, + else: + raise Exception(_('Unknown orientation value (%s)')%orientation) + if rotation: + for layer in self.layers.values(): + layer.image = transpose(layer.image,rotation) + + def get_orientation(self): + try: + return self.info['Pexif.Orientation'] + except KeyError: + if 'Pexif' in self.info: + return 1 + extract_info_pexif(self.info,layers[0]) + try: + orientation = self.info['Pexif.Orientation'] + except KeyError: + return 1 #---pil def apply_pil(self,function,*arg,**keyw): $ bzr commit -m "take exif orientation in account" Committing to: /home/stani/sync/python/phatch/trunk/ modified phatch/core/api.py modified phatch/core/pil.py modified phatch/core/lib/formField.py Committed revision 654.