1. Rémy HUBSCHER
  2. NGallery

Commits

Rémy HUBSCHER  committed 5ec2602

Création de la commande ngalerie, création du fichier setup.py et upload de la v1 sur pypi

  • Participants
  • Parent commits 5d79699
  • Branches default

Comments (0)

Files changed (8)

File .hgignore

View file
+syntax: glob
+
+*~
+*.pyc
+ngalerie.egg-info
+build
+dist

File GUI.py

-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from Tkinter import *
-import Tkconstants, tkFileDialog
-import os
-
-IMAGES_SIZES = [
-    {'title': u'Web 2.0 Gallery', 
-     'size': 600,},
-    {'title': u'Send by Mail', 
-     'size': 1024},
-    {'title': u'Large size',
-     'size': 1280},
-    {'title': u'Extra large size',
-     'size': 1440},
-    {'title': u'HD-Ready',
-     'size': 1600},
-    {'title': u'Hight Definition',
-     'size': 1920},
-]
-
-class GUI(Frame):
-    _input_dir = None
-    _output_dir = None
-
-    def __init__(self, root):
-        if os.name == 'nt':
-            self._input_dir = os.path.expanduser('~')
-            self._output_dir = os.path.expanduser('~\\site')
-        else:
-            self._input_dir = os.path.expanduser('~/Images')
-            self._output_dir = os.path.expanduser('~/Images/site')
-
-        # Define class attributes
-        self.root = root
-
-        # Launch the Frame constructor
-        Frame.__init__(self, root)
-        self.root.title('NGallery 1.0')
-
-        ##
-        # Create a simple Menu
-        gui_menu = Menu(self.root)
-
-        # File menu
-        fichier = Menu(gui_menu, tearoff=0)
-        gui_menu.add_cascade(label="Fichier",menu=fichier)
-        fichier.add_command(label="Quitter", command=self.quit)
-
-        # About menu
-        m_about = Menu(gui_menu, tearoff=0)
-        gui_menu.add_cascade(label="Help",menu=m_about)
-        m_about.add_command(label="About",command=self.about)
-        
-        # Display the menu
-        self.root.config(menu=gui_menu)
-
-        # Display the input_dir selector
-        input_frame = Frame(self)
-        Label(input_frame,text="Input dir:", width=10).pack(side="left")
-        self._input_entry = StringVar()
-        self._input_entry.set(self._input_dir)
-        Entry(input_frame, width=30, textvariable=self._input_entry).pack(side='left')
-        Button(input_frame, text="Select directory", command=self.askDirectoryInput).pack()
-        input_frame.pack()
-
-        # Display the output_dir selector
-        output_frame = Frame(self)
-        Label(output_frame,text="Output dir:", width=10).pack(side="left")
-        self._output_entry = StringVar()
-        self._output_entry.set(self._output_dir)
-        Entry(output_frame, width=30, textvariable=self._output_entry).pack(side='left')
-        Button(output_frame, text="Select directory", command=self.askDirectoryOutput).pack()
-        output_frame.pack()
-
-        # Display the normal size selector
-        self.select = Listbox(self, fg="red", bg="white", height=len(IMAGES_SIZES), width=30)
-
-        for f in IMAGES_SIZES:
-            self.select.insert(END,u'%(title)s - %(size)dx%(size)d' % f)
-        self.select.pack()
-
-        # Display the thumbnail checkbutton
-        self.with_thumbnails = IntVar()
-        Checkbutton(self, text="create thumbnails", variable=self.with_thumbnails).pack()
-
-        # Display the Ok button
-        Button(self, text='Ok', command=self.start_engine).pack()
-
-    def update_entry(self):
-        self._input_entry.set(self._input_dir)
-        self._output_entry.set(self._output_dir)
-
-    def update_dir(self):
-        self._input_dir = self._input_entry.get()
-        self._output_dir = self._output_entry.get()
-
-    def askDirectoryInput(self):
-        self.update_dir()
-        input = tkFileDialog.askdirectory(parent=self, initialdir=self._input_dir, title='Please select your pictures directory')
-        # If we didn't click on Cancel
-        if input:
-            self._input_dir = input
-        if not self._output_dir:
-            self._output_dir = os.path.join(self._input_dir,'site')
-        self.update_entry()
-
-    def askDirectoryOutput(self):
-        self.update_dir()
-        output = tkFileDialog.askdirectory(parent=self, initialdir=self._output_dir, title='Please select the directory to put thumbnails')
-        # If we didn't click on Cancel
-        if output:
-            self._output_dir = output
-
-        if self._output_dir == self._input_dir:
-            self._output_dir = os.path.join(self._input_dir,'site')
-        self.update_entry()
-
-    def start_engine(self):
-        self._input_dir = self._input_entry.get()
-        self._output_dir = self._output_entry.get()
-        print self._input_dir, self._output_dir
-        cur = map(int, self.select.curselection())[0]
-        if cur < len(IMAGES_SIZES):
-            print u'%(title)s - %(size)dx%(size)d' % IMAGES_SIZES[cur]
-        print "With Thumbnails ? ", self.with_thumbnails.get()
-
-    def about(self):
-        t1 = Toplevel(self)
-        t1.title("About NGallery")
-        f1 = Frame(t1)
-        Label(f1,text="NGallery helps to resize your picture with good quality efficiently.").pack()
-        Label(f1,text=u"NGallery was programmed by Rémy HUBSCHER <natim@users.sf.net>").pack()
-        Button(f1,text="Close",command=t1.destroy).pack()
-        f1.pack()
-
-    def quit(self, event=None):
-        print 'Je quitte'
-        try:
-            self.root.destroy()
-        except:
-            pass
-        self.root.quit()
-
-if __name__=='__main__':
-    root = Tk()
-    GUI(root).pack()
-    root.mainloop()

File NGalerie.py

-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright (C) 2008-2011 Rémy HUBSCHER <natim@users.sf.net> 
-#               http://www.trunat.fr/portfolio/python.html
-
-# 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.
-
-# Using :
-# - Python Imaging Library PIL http://www.pythonware.com/products/pil/index.htm
-# - pyexiv2                    http://tilloy.net/dev/pyexiv2/
-
-"""
- What is doing this script ?
-
-  1. Take a directory of picture from a Reflex Camera (Nikon D90 for example)
-  2. Use the EXIF Orientation information to turn the image
-  3. Remove the thumbnail from the EXIF Information
-  4. Create 2 image one maxi map in 600x600, one mini map in 200x200
-  5. Add a comment with the name of the Author and his Website
-  6. Copy the EXIF information to the maxi and mini image
-  7. Name the image files with a meanful name (Date of picture)
-
-"""
-import os, sys
-try:
-    import Image
-except ImportError:
-    print ("To use this program, you need to install Python Imaging Library"
-           "- http://www.pythonware.com/products/pil/")
-    sys.exit(1)
-
-try:
-    import pyexiv2
-except ImportError:
-    print ("To use this program, you need to install pyexiv2"
-           "- http://tilloy.net/dev/pyexiv2/")
-    sys.exit(1)
-
-############# Configuration ##############
-SIZE_MINI = (200, 200)
-SIZE_MAXI = (600, 600)
-
-# Information about the Photograph should be in ASCII
-COPYRIGHT = "Remy Hubscher - http://www.trunat.fr/"
-ARTIST = "Remy Hubscher"
-##########################################
-
-def list_jpeg(directory):
-    "Retourn a list of the JPEG files in the directory"
-    file_list = [os.path.normcase(f) for f in os.listdir(directory)]
-    file_list = [f for f in file_list 
-                        if os.path.splitext(f)[1]  in ('.png', '.jpg', '.JPG')]
-    file_list.sort()
-    return file_list
-
-def _mkdir(newdir):
-    """
-    works the way a good mkdir should :)
-      - already exists, silently complete
-      - regular file in the way, raise an exception
-      - parent directory(ies) does not exist, make them as well
-    """
-    if os.path.isdir(newdir):
-        pass
-    elif os.path.isfile(newdir):
-        raise OSError("a file with the same name as the desired "
-                      "dir, '%s', already exists." % newdir)
-    else:
-        head, tail = os.path.split(newdir)
-        if head and not os.path.isdir(head):
-            _mkdir(head)
-        if tail:
-            os.mkdir(newdir)
-
-if len(sys.argv) < 3:
-    print "USAGE : python %s indir outdir [comment]" % sys.argv[0]
-    sys.exit(1)
-
-INDIR  = sys.argv[1]
-OUTDIR = sys.argv[2]
-
-if len(sys.argv) == 4:
-    COMMENT = sys.argv[1]
-else:
-    COMMENT = COPYRIGHT
-
-AGRANDIE = os.path.join(OUTDIR, 'agrandie')
-MINIATURE = os.path.join(OUTDIR, 'miniature')
-
-print AGRANDIE, MINIATURE
-
-_mkdir(AGRANDIE)
-if MINIATURE:
-    _mkdir(MINIATURE)
-
-for infile in list_jpeg(INDIR):
-    if MINIATURE:
-        mini  = os.path.join(MINIATURE, infile)
-    grand = os.path.join(AGRANDIE, infile)
-    file_path = os.path.join(INDIR, infile).decode('utf-8')
-
-    metadata = pyexiv2.ImageMetadata(file_path)
-    metadata.read()
-
-    metadata['Exif.Image.Artist'] = ARTIST
-    metadata['Exif.Image.Copyright'] = COPYRIGHT
-
-    # I prefer not to modify the input file
-    # image.writeMetadata()
-
-    key = 'Exif.Image.DateTime'
-    # We look for a meanful name
-    if 'Exif.Photo.DateTimeOriginal' in metadata.exif_keys:
-        key = 'Exif.Photo.DateTimeOriginal'
-
-    if key in metadata.exif_keys:
-        filename = metadata[key].value\
-                        .strftime('%Y-%m-%d_%H-%M-%S.jpg')
-        if MINIATURE:
-            mini  = os.path.join(MINIATURE, filename)
-        grand = os.path.join(AGRANDIE, filename)
-        counter = 0
-        while os.path.isfile(grand):
-            # Il se peut qu'on prenne plusieurs photos à la même seconde ...
-            counter += 1
-            filename = metadata[key].value\
-                            .strftime('%Y-%m-%d_%H-%M-%S')+'_%d.jpg' % counter
-            if MINIATURE:
-                mini  = os.path.join(MINIATURE, filename)
-            grand = os.path.join(AGRANDIE, filename)
-
-    else:
-        #If no exif information, leave the old name
-        if MINIATURE:
-            mini  = os.path.join(MINIATURE, infile)
-        grand = os.path.join(AGRANDIE, infile)
-
-    # We create the thumbnail
-    #try:
-    im = Image.open(file_path)
-    im.thumbnail(SIZE_MAXI, Image.ANTIALIAS)
-
-    # We rotate regarding to the EXIF orientation information
-    if 'Exif.Image.Orientation' in image.exifKeys():
-        orientation = image['Exif.Image.Orientation']
-        if orientation == 1:
-            # Nothing
-            mirror = im.copy()
-        elif orientation == 2:
-            # Vertical Mirror
-            mirror = im.transpose(Image.FLIP_LEFT_RIGHT)
-        elif orientation == 3:
-            # Rotation 180°
-            mirror = im.transpose(Image.ROTATE_180)
-        elif orientation == 4:
-            # Horizontal Mirror
-            mirror = im.transpose(Image.FLIP_TOP_BOTTOM)
-        elif orientation == 5:
-            # Horizontal Mirror + Rotation 270°
-            mirror = im.transpose(Image.FLIP_TOP_BOTTOM)\
-                       .transpose(Image.ROTATE_270)
-        elif orientation == 6:
-            # Rotation 270°
-            mirror = im.transpose(Image.ROTATE_270)
-        elif orientation == 7:
-            # Vertical Mirror + Rotation 270°
-            mirror = im.transpose(Image.FLIP_LEFT_RIGHT)\
-                       .transpose(Image.ROTATE_270)
-        elif orientation == 8:
-            # Rotation 90°
-            mirror = im.transpose(Image.ROTATE_90)
-    
-        # No more Orientation information
-        image['Exif.Image.Orientation'] = 1
-    else:
-        # No EXIF information, the user has to do it
-        mirror = im.copy()
-
-    mirror.save(grand, "JPEG", quality=85)
-
-    img_grand = pyexiv2.ImageMetadata(grand)
-    img_grand.read()
-    metadata.copy(img_grand)
-    img_grand.write()
-    print grand
-
-    if MINIATURE:
-        mirror.thumbnail(SIZE_MINI, Image.ANTIALIAS)
-        mirror.save(mini, "JPEG", quality=85)
-        print mini
-    
-    print

File README

-NGallery
-========
-
-NGallery is a Python project that aim to fast management of Reflex
-Camera pictures.
-
-The picture are store in landscape way even if they shouldn't, there
-is a miniature file inside that we could remove.
-
-We also want to be able to resize them at a usable size, create
-external thumbnails and give them a meaningful name such as the date
-of picture's shots.
-
-This software want to be shipped as a exe software using py2exe and be
-spread over the Windows and Linux community of users.
-
-A Portable version will be add to the Framakey project.

File README.rst

View file
+NGalerie
+========
+
+NGalerie is a Python project that aim to enable fast management of
+Reflex Camera pictures.
+
+The picture are store in landscape way even if they shouldn't, there
+is a miniature file inside that we could remove.
+
+We also want to be able to resize them at a usable size, create
+external thumbnails and give them a meaningful name such as the date
+of picture's shots.
+
+NGalerie is a CLI software with useful function to make it do what we
+want.

File bin/ngalerie

View file
+#!/usr/bin/env python
+from ngalerie import main
+main()

File ngalerie/__init__.py

View file
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2008-2011 Rémy HUBSCHER <natim@users.sf.net> 
+#               http://www.trunat.fr/portfolio/python.html
+
+# 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.
+
+# Using :
+# - Python Imaging Library PIL http://www.pythonware.com/products/pil/index.htm
+# - pyexiv2                    http://tilloy.net/dev/pyexiv2/
+
+"""
+This command has the following behaviour
+
+"""
+__version__ = '1.0'
+
+import argparse
+import os
+import sys
+import errno
+import glob
+
+try:
+    import Image
+except ImportError:
+    print ("To use this program, you need to install Python Imaging Library"
+           "- http://www.pythonware.com/products/pil/")
+    sys.exit(1)
+
+try:
+    import pyexiv2
+except ImportError:
+    print ("To use this program, you need to install pyexiv2"
+           "- http://tilloy.net/dev/pyexiv2/")
+    sys.exit(1)
+
+############# DEFAULT Configuration ##############
+_SIZE_MINI = 200
+_SIZE_MAXI = 600
+
+_MINI_DIRNAME = None
+_MAXI_DIRNAME = ''
+
+# Information about the Photograph should be in ASCII
+_COPYRIGHT = "Remy Hubscher - http://www.trunat.fr/"
+_ARTIST = "Remy Hubscher"
+##########################################
+
+def list_jpeg(directory):
+    "Return a list of the JPEG files in the directory"
+    file_list = []
+    for ext in ('jpg', 'JPG'):
+        file_list += glob.glob(os.path.join(directory, '*.'+ext))
+    return [os.path.basename(f) for f in file_list]
+
+def _mkdir(path):
+    try:
+        os.makedirs(path)
+    except OSError as exc:
+        if exc.errno == errno.EEXIST:
+            pass
+        else: raise
+
+def main():
+
+    parser = argparse.ArgumentParser(description="A command interface to manage CAMERA JPG files",
+                                     prog='NGalerie')
+
+    parser.add_argument(dest='indir', nargs='?', help="Path where to find the raw pictures")
+    parser.add_argument(dest='outdir', nargs='?', help="Path where to put generated pictures")
+
+    parser.add_argument('-r', '--rename', dest='rename', action='store_true',
+                        help='Use EXIF.Image.DateTime information to rename the picture')
+
+    parser.add_argument('--resize', dest='resize', default=None, type=int,
+                        help="Ask to resize pictures eventually set the size")
+    parser.add_argument('-t', '--rotate', dest='rotate', action='store_true',
+                        help='Ask to force rotate the picture using EXIF information')
+    parser.add_argument('--max-dir', dest='max_dir', default=_MAXI_DIRNAME,
+                        help="The prefix directory for resized files")
+    parser.add_argument('--thumb-dir', dest='thumb_dir', default=_MINI_DIRNAME,
+                        help="The prefix directory for thumbnails")
+    parser.add_argument('--thumb-size', dest='thumb_size', default=_SIZE_MINI, type=int,
+                        help="The size for thumbnails if thumb-dir only works with --resize")
+    parser.add_argument('--artist', dest='artist', default=_ARTIST,
+                        help="Name of the artist")
+    parser.add_argument('--copyright', dest='copyright', default=_COPYRIGHT,
+                        help="Copyright of the pictures")
+    parser.add_argument('--version', action='version', version=__version__,
+            help='Print the NGalerie version and exit')
+    
+
+    args = parser.parse_args()
+
+    if not args.indir or not args.outdir:
+        print parser.print_help()
+        return 1
+
+    max_size = _SIZE_MAXI if args.resize is None else args.resize
+
+    max_dir = os.path.join(args.outdir, args.max_dir)
+    thumb_dir = os.path.join(args.outdir, args.thumb_dir) if args.thumb_dir else None
+
+    print max_dir, thumb_dir if thumb_dir else ''
+
+    _mkdir(max_dir)
+    if thumb_dir is not None:
+        _mkdir(thumb_dir)
+
+    for infile in list_jpeg(args.indir):
+        if thumb_dir is not None:
+            mini  = os.path.join(thumb_dir, infile)
+        grand = os.path.join(max_dir, infile)
+        file_path = os.path.join(args.indir, infile).decode('utf-8')
+
+        metadata = pyexiv2.ImageMetadata(file_path)
+        metadata.read()
+
+        metadata['Exif.Image.Artist'] = _ARTIST
+        metadata['Exif.Image.Copyright'] = _COPYRIGHT
+
+        if thumb_dir:
+            mini  = os.path.join(thumb_dir, infile)
+        grand = os.path.join(max_dir, infile)
+
+        if args.rename:
+            key = 'Exif.Image.DateTime'
+            # We look for a meanful name
+            if 'Exif.Photo.DateTimeOriginal' in metadata.exif_keys:
+                key = 'Exif.Photo.DateTimeOriginal'
+            
+            if key in metadata.exif_keys:
+                filename = metadata[key].value\
+                    .strftime('%Y-%m-%d_%H-%M-%S.jpg')
+            
+                if thumb_dir:
+                    mini  = os.path.join(thumb_dir, filename)
+                grand = os.path.join(max_dir, filename)
+                counter = 0
+                while os.path.isfile(grand):
+                    # Il se peut qu'on prenne plusieurs photos à la même seconde ...
+                    counter += 1
+                    filename = metadata[key].value\
+                        .strftime('%Y-%m-%d_%H-%M-%S')+'_%d.jpg' % counter
+                    if thumb_dir is not None:
+                        mini  = os.path.join(thumb_dir, filename)
+                    grand = os.path.join(max_dir, filename)
+
+        # We create the thumbnail
+        im = Image.open(file_path)
+        if args.resize:
+            size = (max_size, max_size)
+            im.thumbnail(size, Image.ANTIALIAS)
+
+        # We rotate regarding to the EXIF orientation information
+        if 'Exif.Image.Orientation' in metadata.exif_keys and args.rotate:
+            orientation = metadata['Exif.Image.Orientation']
+            if orientation == 2:
+                # Vertical Mirror
+                mirror = im.transpose(Image.FLIP_LEFT_RIGHT)
+            elif orientation == 3:
+                # Rotation 180°
+                mirror = im.transpose(Image.ROTATE_180)
+            elif orientation == 4:
+                # Horizontal Mirror
+                mirror = im.transpose(Image.FLIP_TOP_BOTTOM)
+            elif orientation == 5:
+                # Horizontal Mirror + Rotation 270°
+                mirror = im.transpose(Image.FLIP_TOP_BOTTOM)\
+                           .transpose(Image.ROTATE_270)
+            elif orientation == 6:
+                # Rotation 270°
+                mirror = im.transpose(Image.ROTATE_270)
+            elif orientation == 7:
+                # Vertical Mirror + Rotation 270°
+                mirror = im.transpose(Image.FLIP_LEFT_RIGHT)\
+                           .transpose(Image.ROTATE_270)
+            elif orientation == 8:
+                # Rotation 90°
+                mirror = im.transpose(Image.ROTATE_90)
+            else:
+                # Nothing
+                mirror = im.copy()
+        
+            # No more Orientation information
+            metadata['Exif.Image.Orientation'] = 1
+        else:
+            # No EXIF information, the user has to do it
+            mirror = im.copy()
+        
+        mirror.save(grand, "JPEG", quality=85)
+        
+        img_grand = pyexiv2.ImageMetadata(grand)
+        img_grand.read()
+        metadata.copy(img_grand)
+        img_grand.write()
+        print grand
+        
+        if thumb_dir:
+            size = (args.thumb_size, args.thumb_size)
+            mirror.thumbnail(size, Image.ANTIALIAS)
+            mirror.save(mini, "JPEG", quality=85)
+            print mini
+            print
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())

File setup.py

View file
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from setuptools import setup
+import sys
+
+VERSION = "1.0" # find a better way to do so.
+
+requires = ['PIL'] #pyexiv2
+if sys.version_info < (2,7):
+    requires.append('argparse')
+
+setup(
+    name = "ngalerie",
+    version = VERSION,
+    url = 'http://bitbucket.org/natim/ngallery/overview',
+    author = u'Rémy HUBSCHER',
+    author_email = 'remy.hubscher@ionyse.com',
+    description = "A tool to manage Camera pictures (Rotate, Resize, Rename using EXIF).",
+    long_description=open('README.rst').read(),
+    packages = ['ngalerie'],
+    include_package_data = True,
+    install_requires = requires,
+    scripts = ['bin/ngalerie'],
+    classifiers = ['Development Status :: 5 - Production/Stable',
+                   'Environment :: Console',
+                   'License :: OSI Approved :: GNU General Public License (GPL)',
+                   'Operating System :: OS Independent',
+                   'Programming Language :: Python',
+                   'Topic :: Multimedia :: Graphics :: Editors',
+                   'Topic :: Software Development :: Libraries :: Python Modules',
+                   ],
+)