Index: favicon.py
==================================================================
--- favicon.py
+++ favicon.py
@@ -27,13 +27,15 @@
import os, os.path
from compat2and3 import xrange, urllib
import re
-from config import conf
+from config import *
from threading import Thread
import ahttp
+import compat2and3
+from PIL import Image
# ensure that we don't try to download a single favicon twice per session,
# if it's not available the first time, we won't get it after switching stations back and forth
@@ -155,35 +157,35 @@
google_ico2png(url)
if available(url) or only_google:
return
try: # look for /favicon.ico first
- #print("favicon.ico")
+ log.FAVICON("try /favicon.ico")
direct_download("http://"+domain(url)+"/favicon.ico", file(url))
except:
try: # extract facicon filename from website
- #print("html ")
+ log.FAVICON("html ")
html_download(url)
- except: # fallback
- #print("google ico2png")
+ except Exception as e: # fallback
+ log.ERR(e)
google_ico2png(url)
# retrieve PNG via Google ico2png
def google_ico2png(url):
-
- #try:
- GOOGLE = "http://www.google.com/s2/favicons?domain="
- (fn, headers) = urllib.urlretrieve(GOOGLE+domain(url), file(url))
-
- # test for stub image
- if delete_google_stub and (filesize(fn) in google_placeholder_filesizes):
- os.remove(fn)
+ log.FAVICON("google ico2png")
+
+ GOOGLE = "http://www.google.com/s2/favicons?domain="
+ (fn, headers) = urllib.urlretrieve(GOOGLE+domain(url), file(url))
+
+ # test for stub image
+ if delete_google_stub and (filesize(fn) in google_placeholder_filesizes):
+ os.remove(fn)
def filesize(fn):
return os.stat(fn).st_size
@@ -202,20 +204,20 @@
# favicon.ico
def direct_download(favicon, fn):
-# try:
# URL download
r = urllib.urlopen(favicon)
headers = r.info()
+ log.HTTP(headers)
# abort on
if r.getcode() >= 300:
- raise Error("HTTP error" + r.getcode())
+ raise Exception("HTTP error %s" % r.getcode())
if not headers["Content-Type"].lower().find("image/") == 0:
- raise Error("can't use text/* content")
+ raise Exception("can't use text/* content")
# save file
fn_tmp = fn+".tmp"
f = open(fn_tmp, "wb")
f.write(r.read(32768))
@@ -227,13 +229,10 @@
os.mv(fn_tmp, fn)
else:
ico2png(fn_tmp, fn)
os.remove(fn_tmp)
- # except:
- # "File not found" and False
-
# peek at URL, download favicon.ico
def html_download(url):
@@ -244,153 +243,43 @@
r = urllib.urlopen(url)
html = r.read(4096)
r.close()
rx = re.compile("""]+rel\s*=\s*"?\s*(?:shortcut\s+|fav)?icon[^<>]+href=["'](?P[^<>"']+)["'<>\s].""")
favicon = "".join(rx.findall(html))
+ log.DATA(favicon)
# url or
if favicon.startswith("http://"):
None
# just /pathname
else:
- favicon = ahttp.urlparse.urljoin(url, favicon)
+ favicon = compat2and3.urlparse.urljoin(url, favicon)
+ log.FAVICON(favicon)
#favicon = "http://" + domain(url) + "/" + favicon
# download
direct_download(favicon, file(url))
-
-
-#@obsolete since Pillow 2.1.x
-
-#
-# title: workaround for PIL.Image to preserve the transparency for .ico import
-#
-# http://stackoverflow.com/questions/987916/how-to-determine-the-transparent-color-index-of-ico-image-with-pil
-# http://djangosnippets.org/snippets/1287/
-#
-# Author: dc
-# Posted: January 17, 2009
-# Languag: Python
-# Django Version: 1.0
-# Tags: pil image ico
-# Score: 2 (after 2 ratings)
-#
-
-import operator
-import struct
-
-try:
- from PIL import BmpImagePlugin, PngImagePlugin, Image
-except Exception as e:
- print("no PIL", e)
- always_google = 1
- only_google = 1
-
-
-def load_icon(file, index=None):
- '''
- Load Windows ICO image.
-
- See http://en.wikipedia.org/w/index.php?oldid=264332061 for file format
- description.
- '''
- if isinstance(file, basestring):
- file = open(file, 'rb')
-
- try:
- header = struct.unpack('<3H', file.read(6))
- except:
- raise IOError('Not an ICO file')
-
- # Check magic
- if header[:2] != (0, 1):
- raise IOError('Not an ICO file')
-
- # Collect icon directories
- directories = []
- for i in xrange(header[2]):
- directory = list(struct.unpack('<4B2H2I', file.read(16)))
- for j in xrange(3):
- if not directory[j]:
- directory[j] = 256
-
- directories.append(directory)
-
- if index is None:
- # Select best icon
- directory = max(directories, key=operator.itemgetter(slice(0, 3)))
- else:
- directory = directories[index]
-
- # Seek to the bitmap data
- file.seek(directory[7])
-
- prefix = file.read(16)
- file.seek(-16, 1)
-
- if PngImagePlugin._accept(prefix):
- # Windows Vista icon with PNG inside
- image = PngImagePlugin.PngImageFile(file)
- else:
- # Load XOR bitmap
- image = BmpImagePlugin.DibImageFile(file)
- if image.mode == 'RGBA':
- # Windows XP 32-bit color depth icon without AND bitmap
- pass
- else:
- # Patch up the bitmap height
- image.size = image.size[0], image.size[1] >> 1
- d, e, o, a = image.tile[0]
- image.tile[0] = d, (0, 0) + image.size, o, a
-
- # Calculate AND bitmap dimensions. See
- # http://en.wikipedia.org/w/index.php?oldid=264236948#Pixel_storage
- # for description
- offset = o + a[1] * image.size[1]
- stride = ((image.size[0] + 31) >> 5) << 2
- size = stride * image.size[1]
-
- # Load AND bitmap
- file.seek(offset)
- string = file.read(size)
- mask = Image.fromstring('1', image.size, string, 'raw',
- ('1;I', stride, -1))
-
- image = image.convert('RGBA')
- image.putalpha(mask)
-
- return image
-
-
-
-
# convert .ico file to .png format
def ico2png(ico, png_fn):
- #print("ico2png", ico, png, image)
-
- try: # .ico
- image = load_icon(ico, None)
- except: # automatic img file type guessing
image = Image.open(ico)
-
- # resize
- if image.size[0] > 16:
- image.resize((16, 16), Image.ANTIALIAS)
-
- # .png format
- image.save(png_fn, "PNG", quality=98)
+ log.ICO2PNG(ico, png, image)
+ # resize
+ if image.size[0] > 16:
+ image.resize((16, 16), Image.ANTIALIAS)
+ # .png format
+ image.save(png_fn, "PNG", quality=98)
# resize an image
def pngresize(fn, x=16, y=16):
- image = Image.open(fn)
- if image.size[0] > x:
- image.resize((x, y), Image.ANTIALIAS)
- image.save(fn, "PNG", quality=98)
+ image = Image.open(fn)
+ if image.size[0] > x:
+ image.resize((x, y), Image.ANTIALIAS)
+ image.save(fn, "PNG", quality=98)
#-- test