1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 """
28 Config is a class containing all the configuration of the imagizer suite.
29 Technically it is a Borg (design Pattern) so every instance of Config has exactly the same contents.
30 """
31
32 import os, distutils.sysconfig, locale
33
34 installdir = os.path.join(distutils.sysconfig.get_python_lib(), "imagizer")
35
36 if os.name == 'nt':
37 ConfFile = [os.path.join(os.getenv("ALLUSERSPROFILE"), "imagizer.conf"), os.path.join(os.getenv("USERPROFILE"), "imagizer.conf"), "imagizer.conf"]
38 elif os.name == 'posix':
39 ConfFile = ["/etc/imagizer.conf", os.path.join(os.getenv("HOME"), ".imagizer"), ".imagizer"]
40 else:
41 raise OSError("Your platform does not seem to be an Unix nor a M$ Windows.\nI am sorry but the exiftran binary is necessary to run selector, and exiftran is probably not available for you plateform. If you have exiftran installed, please contact the developper to correct that bug, kieffer at terre-adelie dot org")
42
43
44
45
46
48 """this class is a Borg : always returns the same values regardless to the instance of the object"""
49 __shared_state = {}
51 """
52 This is a Borg, so the constructor is more or less empty
53 """
54 self.__dict__ = self.__shared_state
56 """
57 a kind of renamed constructor .... initializing default values
58 """
59 self.ScreenSize = 500
60 self.NbrPerPage = 20
61 self.PagePrefix = "page"
62 self.TrashDirectory = "Trash"
63 self.SelectedDirectory = "Selected"
64 self.Selected_save = ".selected-photos"
65 self.Extensions = [".jpg", ".jpeg", ".jpe", ".jfif"]
66 self.AutoRotate = False
67 self.DefaultMode = "664"
68 self.DefaultRepository = os.getcwd()
69 self.CommentFile = "index.desc"
70 self.Interpolation = 1
71 self.DefaultFileMode = int(self.DefaultMode, 8)
72 self.DefaultDirMode = self.DefaultFileMode + 3145
73 self.Filigrane = False
74 self.FiligraneSource = os.path.join(installdir, "signature.png")
75 self.FiligranePosition = 5
76 self.FiligraneQuality = 75
77 self.FiligraneOptimize = False
78 self.FiligraneProgressive = False
79 self.WebDirIndexStyle = "list"
80 self.MediaSize = 680
81 self.Burn = "grave-rep $Selected"
82 self.WebServer = "cp -r $Selected/* $WebRepository && generator"
83 self.WebRepository = "/var/www/imagizer"
84 self.Locale, self.Coding = locale.getdefaultlocale()
85 self.ExportSingleDir = False
86 self.GraphicMode = "Normal"
87 self.WebPageAnchor = "end"
88 self.SlideShowDelay = 5.0
89 self.SlideShowType = "chronological"
90 self.SynchronizeRep = "user@host:/mnt/photo"
91 self.SynchronizeType = "Newer"
92 self.ImageCache = 100000000
93 self.ImageWidth = None
94 self.ImageHeight = None
95 self.DEBUG = None
96 self.Thumbnails = {
97 "Size":160,
98 "Suffix": "thumb",
99 "Interpolation":1,
100 "Progressive":False,
101 "Optimize":False,
102 "ExifExtraction":True,
103 "Quality": 75
104 }
105 self.ScaledImages = {
106 "Size":800,
107 "Suffix": "scaled",
108 "Interpolation":1,
109 "Progressive":False,
110 "Optimize":False,
111 "ExifExtraction":False,
112 "Quality": 75
113 }
114
115 - def load(self, filenames):
116 """retrieves the the default options, if the filenames does not exist, uses the default instead
117 type filenames: list of filename
118 """
119 import ConfigParser
120 config = ConfigParser.ConfigParser()
121 self.default()
122 files = []
123 for i in filenames:
124 if os.path.isfile(i):files.append(i)
125 if len(files) == 0:
126 print "No configuration file found. Falling back on defaults"
127 return
128
129 config.read(files)
130 for i in config.items("Selector"):
131 j = i[0]
132 if j == "ScreenSize".lower(): self.ScreenSize = int(i[1])
133 elif j == "Interpolation".lower(): self.Interpolation = int(i[1])
134 elif j == "PagePrefix".lower(): self.PagePrefix = i[1]
135 elif j == "NbrPerPage".lower(): self.NbrPerPage = int(i[1])
136 elif j == "TrashDirectory".lower(): self.TrashDirectory = i[1]
137 elif j == "SelectedDirectory".lower():self.SelectedDirectory = i[1]
138 elif j == "Selected_save".lower(): self.Selected_save = i[1]
139 elif j == "AutoRotate".lower(): self.AutoRotate = config.getboolean("Selector", "AutoRotate")
140 elif j == "Filigrane".lower(): self.Filigrane = config.getboolean("Selector", "Filigrane")
141 elif j == "FiligraneSource".lower(): self.FiligraneSource = i[1]
142 elif j == "FiligranePosition".lower():self.FiligranePosition = int(i[1])
143 elif j == "FiligraneQuality".lower(): self.FiligraneQuality = int(i[1])
144 elif j == "FiligraneOptimize".lower():self.FiligraneOptimize = config.getboolean("Selector", "FiligraneOptimize")
145 elif j == "FiligraneProgressive".lower():self.FiligraneProgressive = config.getboolean("Selector", "FiligraneProgressive")
146 elif j == "CommentFile".lower(): self.CommentFile = i[1]
147 elif j == "WebDirIndexStyle".lower(): self.WebDirIndexStyle = i[1]
148
149 elif j == "DefaultFileMode".lower():
150 self.DefaultFileMode = int(i[1], 8)
151 self.DefaultDirMode = self.DefaultFileMode + 3145
152 elif j == "Extensions".lower(): self.Extensions = i[1].split()
153 elif j == "DefaultRepository".lower():self.DefaultRepository = i[1]
154 elif j == "MediaSize".lower(): self.MediaSize = float(i[1])
155 elif j == "Burn".lower(): self.Burn = i[1]
156 elif j == "WebServer".lower(): self.WebServer = i[1]
157 elif j == "WebRepository".lower(): self.WebRepository = i[1]
158 elif j == "Locale".lower(): self.Locale = i[1]
159 elif j == "Coding".lower(): self.Coding = i[1]
160 elif j == "ExportSingleDir".lower(): self.ExportSingleDir = config.getboolean("Selector", "ExportSingleDir")
161 elif j == "WebPageAnchor".lower(): self.WebPageAnchor = i[1]
162 elif j == "SlideShowDelay".lower(): self.SlideShowDelay = float(i[1])
163 elif j == "SlideShowType".lower(): self.SlideShowType = i[1]
164 elif j == "SynchronizeRep".lower(): self.SynchronizeRep = i[1]
165 elif j == "SynchronizeType".lower(): self.SynchronizeType = i[1]
166 elif j == "ImageCache".lower(): self.ImageCache = int(i[1])
167 elif j == "ImageWidth".lower(): self.ImageWidth = int(i[1])
168 elif j == "ImageHeight".lower(): self.ImageHeight = int(i[1])
169 else: print "unknown key " + j
170
171
172 for k in ["ScaledImages", "Thumbnails"]:
173 try:
174 dico = eval(k)
175 except:
176 dico = {}
177 for i in config.items(k):
178 j = i[0]
179 if j == "Size".lower():dico["Size"] = int(i[1])
180 elif j == "Suffix".lower():dico["Suffix"] = i[1]
181 elif j == "Interpolation".lower():dico["Interpolation"] = int(i[1])
182 elif j == "Progressive".lower():dico["Progressive"] = config.getboolean(k, "Progressive")
183 elif j == "Optimize".lower():dico["Optimize"] = config.getboolean(k, "Optimize")
184 elif j == "ExifExtraction".lower():dico["ExifExtraction"] = config.getboolean(k, "ExifExtraction")
185 elif j == "Quality".lower():dico["Quality"] = int(i[1])
186 exec("self.%s=dico" % k)
187
189
190 print("Size on the images on the Screen: %s pixels in the largest dimension" % self.ScreenSize)
191 print("Page prefix:\t\t\t %s" % self.PagePrefix)
192 print("Number of images per page:\t %s" % self.NbrPerPage)
193 print("Use Exif for Auto-Rotate:\t %s" % self.AutoRotate)
194 print("Default mode for files (octal):\t %o" % self.DefaultFileMode)
195 print("JPEG extensions:\t\t %s" % self.Extensions)
196 print("Default photo repository:\t %s" % self.DefaultRepository)
197 print("Add signature for exported images:%s" % self.Filigrane)
198 print("Backup media size (CD,DVD):\t %s MByte" % self.MediaSize)
199 print("Scaled imagesSize:\t\t %s pixels in the largest dimension" % self.ScaledImages["Size"])
200 print("Thumbnail Size:\t\t\t %s pixels in the largest dimension" % self.Thumbnails["Size"])
201 cache = ""
202 lenCache = len(str(self.ImageCache))
203 if lenCache in range(4, 7):
204 cache = "%.1f kByte" % (float(self.ImageCache) / 1024.0)
205 elif lenCache in range(7, 10):
206 cache = "%.1f MByte" % (float(self.ImageCache) / 1048576.0)
207 elif lenCache in range(10, 13):
208 cache = "%.1f GByte" % (float(self.ImageCache) / 1073741824.0)
209 else:
210 cache = "%i Byte" % self.ImageCache
211 print("Caching of PixBuffers size:\t %s" % cache)
212
214 """saves the default options"""
215 txt = "[Selector]\n"
216 txt += "#Size of the image on the Screen, by default\nScreenSize: %s \n\n" % self.ScreenSize
217 txt += "#Downsampling quality [0=nearest, 1=tiles, 2=bilinear, 3=hyperbolic]\nInterpolation: %s \n\n" % self.Interpolation
218 txt += "#Page prefix (used when there are too many images per day to fit on one web page)\nPagePrefix: %s \n\n" % self.PagePrefix
219 txt += "#Maximum number of images per web page\nNbrPerPage: %s\n\n" % self.NbrPerPage
220 txt += "#Trash sub-directory\nTrashDirectory: %s \n\n" % self.TrashDirectory
221 txt += "#Selected/processed images sub-directory\nSelectedDirectory: %s \n\n" % self.SelectedDirectory
222 txt += "#File containing the list of selected but unprocessed images\nSelected_save: %s \n\n" % self.Selected_save
223 txt += "#Use Exif data for auto-rotation of the images (canon cameras mainly)\nAutoRotate: %s\n\n" % self.AutoRotate
224 txt += "#Default mode for files (in octal)\nDefaultFileMode: %o\n\n" % self.DefaultFileMode
225 txt += "#Default JPEG extensions\nExtensions: "
226 for i in self.Extensions: txt += i + " "
227 txt += "\n\n"
228 txt += "#Default photo repository\nDefaultRepository: %s \n\n" % self.DefaultRepository
229 txt += "#Size of the backup media (in MegaByte)\nMediaSize: %s \n\n" % self.MediaSize
230 txt += "#Add signature to web published images\nFiligrane: %s \n\n" % self.Filigrane
231 txt += "#File containing the image of the signature for the filigrane\nFiligraneSource: %s\n\n" % self.FiligraneSource
232 txt += "#Position of the filigrane : 0=center 12=top center 1=upper-right 3=center-right...\nFiligranePosition: %s\n\n" % self.FiligranePosition
233 txt += "#Quality of the saved image in filigrane mode (JPEG quality)\nFiligraneQuality: %s\n\n" % self.FiligraneQuality
234 txt += "#Optimize the filigraned image (2 pass JPEG encoding)\nFiligraneOptimize: %s\n\n" % self.FiligraneOptimize
235 txt += "#Progressive JPEG for saving filigraned images\nFiligraneProgressive: %s\n\n" % self.FiligraneProgressive
236 txt += "#File containing the description of the day in each directory\nCommentFile: %s\n\n" % self.CommentFile
237 txt += "#Style of the dirindex web pages, either <<list>> or <<table>>, the latest includes thumbnail photos\nWebDirIndexStyle: %s\n\n" % self.WebDirIndexStyle
238 txt += "#System command to use to burn a CD or a DVD\n# $Selected will be replaced by the directory where the files are\nBurn: %s\n\n" % self.Burn
239 txt += "#System command to copy the selection to the server\n# $Selected will be replaced by the directory where the files are\n# $WebRepository will be replaced by the directory of the root of generator\nWebServer: %s\n\n" % self.WebServer
240 txt += "#The location of the root of generator\nWebRepository: %s\n\n" % self.WebRepository
241 txt += "#The localization code, fr_FR is suggested for unix or FR for win32\nLocale: %s\n\n" % self.Locale
242 txt += "#Default encoding for text files, latin-1 is suggested,UTF-8 should be possible\nCoding: %s\n\n" % self.Coding
243 txt += "#All selected photos should be exported in a single directory\nExportSingleDir: %s\n\n" % self.ExportSingleDir
244 txt += "#Where should the dirindex page start-up ? [begin/end] \nWebPageAnchor: %s\n\n" % self.WebPageAnchor
245 txt += "#Delay between imges in the slideshow? \nSlideShowDelay: %s\n\n" % self.SlideShowDelay
246 txt += "#Type of slideshow : chronological, anti-chronological or random ?\nSlideShowType: %s\n\n" % self.SlideShowType
247 txt += "#Remote repository to synchronize with (rsync like)\nSynchronizeRep: %s\n\n" % self.SynchronizeRep
248 txt += "#Synchronization type, acceptable values are Newer, Older, Selected and All\nSynchronizeType: %s\n\n" % self.SynchronizeType
249 txt += "#Allow the creation of a Cache of images with the given size in byte\nImageCache: %s\n\n" % self.ImageCache
250 if self.ImageWidth is not None:
251 txt += "#Width of the last image displayed ... should not be modified\nImageWidth:%s\n\n" % self.ImageWidth
252 if self.ImageHeight is not None:
253 txt += "#Height of the last image displayed ... should not be modified\nImageHeight:%s\n\n" % self.ImageHeight
254
255
256 for i in ["ScaledImages", "Thumbnails"]:
257 txt += "[%s]\n" % i
258 j = eval("self.%s" % i)
259 txt += "#%s size\nSize: %s \n\n" % (i, j["Size"])
260 txt += "#%s suffix\nSuffix: %s \n\n" % (i, j["Suffix"])
261 txt += "#%s downsampling quality [0=nearest, 1=antialias 2=bilinear, 3=bicubic]\nInterpolation: %s \n\n" % (i, j["Interpolation"])
262 txt += "#%s progressive JPEG files\nProgressive: %s \n\n" % (i, j["Progressive"])
263 txt += "#%s optimized JPEG (2 pass encoding)\nOptimize: %s \n\n" % (i, j["Optimize"])
264 txt += "#%s quality (in percent)\nQuality: %s \n\n" % (i, j["Quality"])
265 txt += "#%s image can be obtained by Exif extraction ?\nExifExtraction: %s \n\n" % (i, j["ExifExtraction"])
266 w = open(filename, "w")
267 w.write(txt)
268 w.close()
269