diff -dPNur happycamel-v1-beta3/HappyCamel/cli.py happycamel-v1-beta3-ds/HappyCamel/cli.py --- happycamel-v1-beta3/HappyCamel/cli.py 2008-04-17 21:25:10.000000000 +0200 +++ happycamel-v1-beta3-ds/HappyCamel/cli.py 2008-11-19 13:58:07.000000000 +0100 @@ -221,11 +221,16 @@ parser.addOption("--image-size", metavar = "pixels", var = "image_size", type = "int", default = defaults["image_size"], help = "The size of the long side of the photo in the KMZ file. Currently set to %default.") + parser.addOption("--icon-size", metavar = "pixels", var = "icon_size", + type = "int", default = defaults["icon_size"], + help = "The size of the long side of the icon in the KMZ file. Currently set to %default.") parser.addOption("--title", metavar = "title", var = "title", default = defaults["title"], help = "The title of your KMZ file. Currently set to \"%default\".") parser.addOption("--clickable", var = "clickable", type = "bool", bool_action = True, default = defaults["clickable"], help = "It true, make the images clickable so they are shown in your web browser. WARNING: When using disk photos, this is not portable across computers, unless the photo's are placed at exactly the same path as on the original machine. Currently set to %default.") + parser.addOption("--url", var = "url", + default = "", help = "Defines URL there the photos are published. Currently set to %default.") parser.addOption("--track", type = "bool", bool_action = True, var = "show_track", default = defaults["show_track"], help = "Show the GPS track in the KMZ file. Currently set to %default.") @@ -315,8 +320,10 @@ options["kmz_file"] = False options["order"] = False options["image_size"] = False + options["icon_size"] = False options["title"] = False options["clickable"] = False + options["url"] = False options["show_track"] = False options["track_color"] = False options["track_width"] = False diff -dPNur happycamel-v1-beta3/HappyCamel/config.py happycamel-v1-beta3-ds/HappyCamel/config.py --- happycamel-v1-beta3/HappyCamel/config.py 2008-04-17 21:25:10.000000000 +0200 +++ happycamel-v1-beta3-ds/HappyCamel/config.py 2008-11-19 13:54:41.000000000 +0100 @@ -78,8 +78,10 @@ "show_waypoints": [bool, "KMZ File", "Show waypoints", False], "order": [str, "KMZ File", "Order", "D"], "image_size": [int, "KMZ File", "Pixels", 200], + "icon_size": [int, "KMZ File", "Icon pixels", 0], "title": [str, "KMZ File", "Title", "Photo report"], - "clickable": [bool, "KMZ File", "Clickable", False] + "clickable": [bool, "KMZ File", "Clickable", False], + "url": [str, "KMZ File", "Photos URL", ""] } def __init__(self): @@ -133,7 +135,7 @@ if (type(value) == self.map[option][0]): self.values[option] = value else: - raise TypeError, "Expected %s, but got %s instead" % (self.map[options][0], type(value)) + raise TypeError, "Expected %s, but got %s instead for option %s" % (self.map[option][0], type(value), option) else: raise UnknownOptionError(option) diff -dPNur happycamel-v1-beta3/HappyCamel/kmlhandler.py happycamel-v1-beta3-ds/HappyCamel/kmlhandler.py --- happycamel-v1-beta3/HappyCamel/kmlhandler.py 2008-04-17 21:25:10.000000000 +0200 +++ happycamel-v1-beta3-ds/HappyCamel/kmlhandler.py 2008-11-19 13:57:31.000000000 +0100 @@ -27,7 +27,7 @@ def __init__(self, gpx_files, photo_list, thumbnail_names, logger, title = "Photo report", track_color = "ffffffff", track_width = 1.0, between_tracks_color = None, - between_tracks_width = None, photos_clickable = False): + between_tracks_width = None, photos_clickable = False, photos_url = "", use_icons = False): """ Initialize a new KML file. gpx_files is a list of GPXFile objects which should be drawn in the file. photo_list is a PhotoList object of photo's whose thumbnail should be included. thumbnail_names is an @@ -43,6 +43,8 @@ self.thumbnail_names = thumbnail_names self.title = title self.photos_clickable = photos_clickable + self.photos_url = photos_url + self.use_icons = use_icons # Check if the specified track colors and widths are ok self.track_color = self.__testColorFormat__(track_color) @@ -117,11 +119,28 @@ for photo in self.photo_list: if (photo in self.thumbnail_names): # Only process if there's a thumbnail location = photo.getLocation() + + if (self.use_icons): + out_fp.write(' \n') + out_fp.write(' \n') out_fp.write(' %s\n' % photo.getName()) out_fp.write(' ' % photo.getURL()) + if (self.photos_url): + out_fp.write('' % (self.photos_url, photo.getName())) + else: + out_fp.write('' % photo.getURL()) out_fp.write('' % self.thumbnail_names[photo]) if (self.photos_clickable): out_fp.write("") @@ -136,7 +155,11 @@ out_fp.write(' \n' % comment) else: out_fp.write(' %s\n' % photo.getName()) - out_fp.write(' #photo_mark\n') + + if (self.use_icons): + out_fp.write(' #photo_%s\n' % self.thumbnail_names[photo]) + else: + out_fp.write(' #photo_mark\n') out_fp.write(' \n') if (location[2]): out_fp.write(' clampToGround\n') @@ -275,10 +298,10 @@ NUM_THUMBNAILS = 25 def __init__(self, file_name, logger, gpx_files = None, photo_list = None, - sort_order = "D", thumbnail_size = 200, title = "Photo report", + sort_order = "D", thumbnail_size = 200, icon_size = 0, title = "Photo report", track_color = "ffffffff", track_width = 1.0, between_tracks_color = None, between_tracks_width = None, - photos_clickable = False): + photos_clickable = False, photos_url = ""): """ Create a new KMZ file with the disk path file_name. gpx_files is a list of GPXFile objects that need to be showed in the file. photo_list is a PhotoList object of photo's whose thumbnail should be included. @@ -286,8 +309,9 @@ presented ("D" is date and time, "A" is latitude, "O" is longitude. Lowercase means reverse sort. Multiple tokens may be specified in order of precedence). - thumbnail_size is the number of pixels the long size of each thumbnail - should have. + thumbnail_size is the number of pixels the long size of each thumbnail + should have. + icon_size is the number of pixels the long size of each icon should have. title is the title given to the report in Google Earth. track_color and between_tracks_color specify the color to give the tracks and the lines in between the tracks, respectively. They are @@ -309,12 +333,14 @@ self.gpx_files = gpx_files self.photo_list = photo_list self.thumbnail_size = thumbnail_size + self.icon_size = icon_size self.title = title self.track_width = track_width self.track_color = track_color self.between_tracks_width = between_tracks_width self.between_tracks_color = between_tracks_color self.photos_clickable = photos_clickable + self.photos_url = photos_url # Sort the photo's for index in range(len(sort_order)): @@ -366,7 +392,9 @@ file_names[photo] = "%s.jpg" % fn_base # Write the file - zip_file.writestr("images/%s.jpg" % fn_base, data) + zip_file.writestr("images/%s.jpg" % fn_base, data[0]) + if (data[1]): + zip_file.writestr("icons/%s.jpg" % fn_base, data[1]) else: self.logger.error("Couldn't make a thumbnail of image %s." % photo.getName()) @@ -391,7 +419,7 @@ # but we put it here in a separate thread here as well because at the same # time we need to start the processing thread. get_thread = threading.Thread(target = self.photo_list.getThumbnailData, - args = [self.thumbnail_size, tn_queue]) + args = [self.thumbnail_size, self.icon_size, tn_queue]) file_names = {} process_thread = threading.Thread(target = self.__processThumbnails__, args = [tn_queue, out_file, file_names]) @@ -410,7 +438,7 @@ kml = KML(self.gpx_files, self.photo_list, file_names, self.logger, self.title, self.track_color, self.track_width, self.between_tracks_color, self.between_tracks_width, - self.photos_clickable) + self.photos_clickable, self.photos_url, bool(self.icon_size)) kml_fp = StringIO.StringIO() kml.writeKML(kml_fp, write_photos, write_waypoints, write_track, write_between_tracks) diff -dPNur happycamel-v1-beta3/HappyCamel/main.py happycamel-v1-beta3-ds/HappyCamel/main.py --- happycamel-v1-beta3/HappyCamel/main.py 2008-04-17 21:25:10.000000000 +0200 +++ happycamel-v1-beta3-ds/HappyCamel/main.py 2008-11-19 14:22:55.000000000 +0100 @@ -254,12 +254,14 @@ self.writeKMZFile(self.geo_sources.getAllGPXFiles(), photo_list, kmz_file, self.conf.get("order"), self.conf.get("image_size"), + self.conf.get("icon_size"), self.conf.get("title"), self.conf.get("track_color"), self.conf.get("track_width"), self.conf.get("between_color"), self.conf.get("between_width"), self.conf.get("clickable"), + self.conf.get("url"), self.conf.get("show_waypoints"), self.conf.get("show_track"), self.conf.get("show_between_tracks")) @@ -525,16 +527,16 @@ if not (results[photo]): self.logger.message("Couldn't succesfully write metadata to photo %s." % photo.getName()) - def writeKMZFile(self, gpx_files, photo_list, file_path, order, image_size, + def writeKMZFile(self, gpx_files, photo_list, file_path, order, image_size, icon_size, title, track_color, track_width, between_color, - between_width, clickable, show_waypoints, show_track, + between_width, clickable, photos_url, show_waypoints, show_track, show_between_tracks): """ Write the KMZ file with the specified options. """ kmz = kmlhandler.KMZ(file_path, self.logger, gpx_files, - photo_list, order, image_size, title, track_color, - track_width, between_color, between_width, clickable) + photo_list, order, image_size, icon_size, title, track_color, + track_width, between_color, between_width, clickable, photos_url) kmz.writeFile(write_photos = True, write_waypoints = show_waypoints, write_track = show_track, diff -dPNur happycamel-v1-beta3/HappyCamel/photohandler.py happycamel-v1-beta3-ds/HappyCamel/photohandler.py --- happycamel-v1-beta3/HappyCamel/photohandler.py 2008-04-17 21:25:10.000000000 +0200 +++ happycamel-v1-beta3-ds/HappyCamel/photohandler.py 2008-11-19 14:22:55.000000000 +0100 @@ -164,7 +164,7 @@ if ((not self.ele) or overwrite): self.ele = ele - def __scalePhoto__(self, file_obj, max_side): + def __scalePhoto__(self, file_obj, max_side, icon_size = 0): """ Scale the photo referred to by the given file_obj so that the longest size is max_side. If the original is smaller than the required format, it isn't scaled. Return a JPEG-encoded string with data. """ @@ -195,7 +195,24 @@ self.logger.debug("Required thumbnail for %s is larger than the original - no scaling." % self.getName()) # Return a JPEG encoded string - return photo_data.tostring("jpeg", "RGB") + thumbnail = photo_data.tostring("jpeg", "RGB") + + if (icon_size): + if (photo_size[0] > photo_size[1]): + fraction = float(icon_size) / photo_size[0] + else: + fraction = float(icon_size) / photo_size[1] + + if (fraction < 1.0): + icon_size = [int(photo_size[0] * fraction), int(photo_size[1] * fraction)] + self.logger.debug("Resizing thumnail %s from %dx%d to %dx%d pixels." % (self.getName(), thumbnail_size[0], thumbnail_size[1], icon_size[0], icon_size[1])) + photo_data.thumbnail(icon_size, Image.BICUBIC) + + icon = photo_data.tostring("jpeg", "RGB") + else: + icon = None + + return thumbnail, icon return False @@ -543,7 +560,7 @@ results.update(self.__queue2Dict__(flickr_results)) return results - def getThumbnailData(self, max_side, queue): + def getThumbnailData(self, max_side, icon_size, queue): """ Load all the thumbnails from the images in the list and put a tuple of (photo object, JPEG-encoded thumbnail data) in the provided Queue.queue instance. This allows for a multithreaded processing of the images. @@ -558,9 +575,9 @@ # Process the pools self.__runThreaded__(self.DISK_THREAD_NUM, "getThumbnailData", - pools["disk"], queue, max_side = max_side) + pools["disk"], queue, max_side = max_side, icon_size = icon_size) self.__runThreaded__(self.FLICKR_THREAD_NUM, "getThumbnailData", - pools["flickr"], queue, max_side = max_side) + pools["flickr"], queue, max_side = max_side, icon_size = icon_size) def cleanup(self, check_date = False, check_location = False): """ Removes the photos from the list which don't comply to the specified @@ -757,7 +774,7 @@ return "file://%s" % os.path.join(os.getcwd(), self.getPath()) - def getThumbnailData(self, max_side = 200): + def getThumbnailData(self, max_side = 200, icon_size = 0): """ Convert the image to a thumbnail and return the data, JPEG-encoded, or False if we cannot convert this image. max_side specifies the number of pixels the long side of the thumbnail needs to have. """ @@ -767,7 +784,7 @@ if (ext in PIL_READ_FORMATS): self.logger.debug("Creating thumbnail for photo %s" % self.getName()) photo_data = open(self.getPath()) - return self.__scalePhoto__(photo_data, max_side) + return self.__scalePhoto__(photo_data, max_side, icon_size) else: self.logger.error("Can't create thumbnail for photo %s" % self.getName()) return False @@ -1270,7 +1287,7 @@ return True - def getThumbnailData(self, max_side = 200): + def getThumbnailData(self, max_side = 200, icon_size = 0): """ Convert the image to a thumbnail and return the data, JPEG-encoded, or False if we cannot convert this image. max_side specifies the number of pixels the long side of the thumbnail needs to have. """ @@ -1312,7 +1329,7 @@ # Download the photo and load it as a PIL image photo_data = StringIO.StringIO(urllib2.urlopen(best_fit["entry"]["source"]).read()) - return self.__scalePhoto__(photo_data, max_side) + return self.__scalePhoto__(photo_data, max_side, icon_size) def writeMetadata(self, write_coords = True, write_geo_names = False, correct_time = False):