mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 19:40:21 +01:00
* Refactored Img and Thumnail classes for new media storage.
This commit is contained in:
@@ -24,76 +24,49 @@
|
|||||||
|
|
||||||
from shutil import copy
|
from shutil import copy
|
||||||
from os import path, mkdir
|
from os import path, mkdir
|
||||||
|
from hashlib import sha512
|
||||||
|
from tempfile import mkstemp
|
||||||
|
|
||||||
|
from utils import EXIF
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
class Img(object):
|
class Img(object):
|
||||||
|
|
||||||
def __init__(self, filename=None, base=''):
|
def __init__(self, filename, base=''):
|
||||||
self.root = 'images'
|
self.root = 'images'
|
||||||
self.x = 160
|
self.x = 160
|
||||||
self.y = 160
|
self.y = 160
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.base = base
|
self.base = base
|
||||||
|
f = open(filename, "r")
|
||||||
|
self.sha512 = sha512(f.read()).hexdigest()
|
||||||
|
f.close()
|
||||||
|
|
||||||
def save(self, image_id):
|
def save(self):
|
||||||
"""Save image and asociated thumbnail into specific directory structure
|
"""Save image and asociated thumbnail into specific directory structure
|
||||||
return full path to the file and thumbnail or None"""
|
returns filename for image"""
|
||||||
|
|
||||||
base_path = self.__get_and_make_path(image_id)
|
|
||||||
ext = self.filename.split('.')[-1].lower()
|
|
||||||
image_filename = path.join(self.base, base_path + "." + ext)
|
|
||||||
|
|
||||||
thumbnail = path.join(self.base, base_path + "_t.jpg")
|
image_filename = path.join(self.base, self.sha512)
|
||||||
|
thumbnail = path.join(self.base, self.sha512 + "_t")
|
||||||
|
|
||||||
returncode = -1
|
# check wheter image already exists
|
||||||
|
if path.exists(image_filename) and path.exists(thumbnail):
|
||||||
|
if __debug__:
|
||||||
|
print "image", self.filename, "with hash", self.sha512, "already exist"
|
||||||
|
return self.sha512
|
||||||
|
|
||||||
im = self.__scale_image()
|
if not path.exists(thumbnail):
|
||||||
if im:
|
im = self.__scale_image()
|
||||||
im.save(thumbnail, "JPEG")
|
im.save(thumbnail, "JPEG")
|
||||||
returncode = 1
|
|
||||||
|
|
||||||
if returncode != -1:
|
# copy image
|
||||||
# copy image
|
if not path.exists(image_filename):
|
||||||
copy(self.filename, image_filename)
|
copy(self.filename, image_filename)
|
||||||
|
|
||||||
return thumbnail, image_filename, returncode
|
return self.sha512
|
||||||
|
|
||||||
# private class functions
|
# private class functions
|
||||||
def __get_and_make_path(self, img_id):
|
|
||||||
"""Make directory structure regards of id
|
|
||||||
and return filepath and img filename WITHOUT extension"""
|
|
||||||
t = path.join(self.base, self.root)
|
|
||||||
try: mkdir(t)
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
h = hex(img_id)
|
|
||||||
if len(h[2:])>6:
|
|
||||||
try: mkdir(path.join(t, h[2:4]))
|
|
||||||
except: pass
|
|
||||||
try: mkdir(path.join(t, h[2:4], h[4:6]))
|
|
||||||
except: pass
|
|
||||||
fpath = path.join(t, h[2:4], h[4:6], h[6:8])
|
|
||||||
try: mkdir(fpath)
|
|
||||||
except: pass
|
|
||||||
img = "%s" % h[8:]
|
|
||||||
elif len(h[2:])>4:
|
|
||||||
try: mkdir(path.join(t, h[2:4]))
|
|
||||||
except: pass
|
|
||||||
fpath = path.join(t, h[2:4], h[4:6])
|
|
||||||
try: mkdir(fpath)
|
|
||||||
except: pass
|
|
||||||
img = "%s" % h[6:]
|
|
||||||
elif len(h[2:])>2:
|
|
||||||
fpath = path.join(t, h[2:4])
|
|
||||||
try: mkdir(fpath)
|
|
||||||
except: pass
|
|
||||||
img = "%s" % h[4:]
|
|
||||||
else:
|
|
||||||
fpath = ''
|
|
||||||
img = "%s" % h[2:]
|
|
||||||
return(path.join(t, fpath, img))
|
|
||||||
|
|
||||||
def __scale_image(self):
|
def __scale_image(self):
|
||||||
"""create thumbnail. returns image object or None"""
|
"""create thumbnail. returns image object or None"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -22,189 +22,95 @@
|
|||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
from tempfile import gettempdir
|
from tempfile import mkstemp
|
||||||
|
from hashlib import sha512
|
||||||
from shutil import move
|
from shutil import move
|
||||||
from os import path, mkdir
|
from os import path
|
||||||
from datetime import datetime
|
import sys
|
||||||
|
|
||||||
from utils import EXIF
|
from utils import EXIF
|
||||||
import Image
|
import Image
|
||||||
|
|
||||||
class Thumbnail(object):
|
class Thumbnail(object):
|
||||||
|
"""Class for generate/extract thumbnail from image file"""
|
||||||
|
|
||||||
def __init__(self, filename=None, x=160, y=160,
|
def __init__(self, filename=None, base=''):
|
||||||
root='thumbnails', base=''):
|
self.thumb_x = 160
|
||||||
self.root = root
|
self.thumb_y = 160
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.base = base
|
self.base = base
|
||||||
|
self.sha512 = sha512(open(filename).read()).hexdigest()
|
||||||
|
self.thumbnail_path = path.join(self.base, self.sha512 + "_t")
|
||||||
|
|
||||||
def save(self, image_id):
|
def save(self):
|
||||||
"""Save thumbnail into specific directory structure
|
"""Save thumbnail into specific directory structure
|
||||||
return full path to the file and exif object or None"""
|
return filename base and exif object or None"""
|
||||||
filepath = path.join(self.base, self.__get_and_make_path(image_id))
|
exif = {}
|
||||||
f = open(self.filename, 'rb')
|
orientations = {2: Image.FLIP_LEFT_RIGHT, # Mirrored horizontal
|
||||||
exif = None
|
3: Image.ROTATE_180, # Rotated 180
|
||||||
returncode = -1
|
4: Image.FLIP_TOP_BOTTOM, # Mirrored vertical
|
||||||
|
5: Image.ROTATE_90, # Mirrored horizontal then
|
||||||
|
# rotated 90 CCW
|
||||||
|
6: Image.ROTATE_270, # Rotated 90 CW
|
||||||
|
7: Image.ROTATE_270, # Mirrored horizontal then
|
||||||
|
# rotated 90 CW
|
||||||
|
8: Image.ROTATE_90} # Rotated 90 CCW
|
||||||
|
flips = {7: Image.FLIP_LEFT_RIGHT, 5: Image.FLIP_LEFT_RIGHT}
|
||||||
|
|
||||||
|
image_file = open(self.filename, 'rb')
|
||||||
try:
|
try:
|
||||||
exif = EXIF.process_file(f)
|
exif = EXIF.process_file(image_file)
|
||||||
f.close()
|
|
||||||
if 'JPEGThumbnail' in exif:
|
|
||||||
thumbnail = exif['JPEGThumbnail']
|
|
||||||
f = open(filepath,'wb')
|
|
||||||
f.write(thumbnail)
|
|
||||||
f.close()
|
|
||||||
if 'Image Orientation' in exif:
|
|
||||||
orientation = exif['Image Orientation'].values[0]
|
|
||||||
if orientation > 1:
|
|
||||||
# TODO: replace silly datetime function with tempfile
|
|
||||||
ms = datetime.now().microsecond
|
|
||||||
t = path.join(gettempdir(), "thumb%d.jpg" % ms)
|
|
||||||
im_in = Image.open(filepath)
|
|
||||||
im_out = None
|
|
||||||
if orientation == 8:
|
|
||||||
# Rotated 90 CCW
|
|
||||||
im_out = im_in.transpose(Image.ROTATE_90)
|
|
||||||
elif orientation == 6:
|
|
||||||
# Rotated 90 CW
|
|
||||||
im_out = im_in.transpose(Image.ROTATE_270)
|
|
||||||
elif orientation == 3:
|
|
||||||
# Rotated 180
|
|
||||||
im_out = im_in.transpose(Image.ROTATE_180)
|
|
||||||
elif orientation == 2:
|
|
||||||
# Mirrored horizontal
|
|
||||||
im_out = im_in.transpose(Image.FLIP_LEFT_RIGHT)
|
|
||||||
elif orientation == 4:
|
|
||||||
# Mirrored vertical
|
|
||||||
im_out = im_in.transpose(Image.FLIP_TOP_BOTTOM)
|
|
||||||
elif orientation == 5:
|
|
||||||
# Mirrored horizontal then rotated 90 CCW
|
|
||||||
op = Image.FLIP_LEFT_RIGHT
|
|
||||||
rot = Image.ROTATE_90
|
|
||||||
im_out = im_in.transpose(op).transpose(rot)
|
|
||||||
elif orientation == 7:
|
|
||||||
# Mirrored horizontal then rotated 90 CW
|
|
||||||
op = Image.FLIP_LEFT_RIGHT
|
|
||||||
rot = Image.ROTATE_270
|
|
||||||
im_out = im_in.transpose(op).transpose(rot)
|
|
||||||
|
|
||||||
if im_out:
|
|
||||||
im_out.save(t, 'JPEG')
|
|
||||||
move(t, filepath)
|
|
||||||
else:
|
|
||||||
f.close()
|
|
||||||
returncode = 0
|
|
||||||
else:
|
|
||||||
im = self.__scale_image()
|
|
||||||
if im:
|
|
||||||
im.save(filepath, "JPEG")
|
|
||||||
returncode = 1
|
|
||||||
except:
|
except:
|
||||||
f.close()
|
if __debug__:
|
||||||
im = self.__scale_image()
|
print "exception", sys.exc_info()[0], "raised with file:"
|
||||||
if im:
|
print self.filename
|
||||||
im.save(filepath, "JPEG")
|
finally:
|
||||||
returncode = 2
|
image_file.close()
|
||||||
return filepath, exif, returncode
|
|
||||||
|
|
||||||
# private class functions
|
if path.exists(self.thumbnail_path):
|
||||||
def __get_and_make_path(self, image_id):
|
if __debug__:
|
||||||
"""Make directory structure regards of id
|
print "file", self.filename, "with hash", self.sha512, "exists"
|
||||||
and return filepath WITHOUT extension"""
|
return self.sha512, exif
|
||||||
t = path.join(self.base, self.root)
|
|
||||||
try: mkdir(t)
|
if 'JPEGThumbnail' in exif:
|
||||||
except: pass
|
if __debug__:
|
||||||
h = hex(image_id)
|
print self.filename, "exif thumb"
|
||||||
if len(h[2:])>6:
|
exif_thumbnail = exif['JPEGThumbnail']
|
||||||
try: mkdir(path.join(t, h[2:4]))
|
thumb_file = open(self.thumbnail_path, 'wb')
|
||||||
except: pass
|
thumb_file.write(exif_thumbnail)
|
||||||
try: mkdir(path.join(t, h[2:4], h[4:6]))
|
thumb_file.close()
|
||||||
except: pass
|
|
||||||
fpath = path.join(t, h[2:4], h[4:6], h[6:8])
|
if 'Image Orientation' in exif:
|
||||||
try: mkdir(fpath)
|
orient = exif['Image Orientation'].values[0]
|
||||||
except: pass
|
if orient > 1 and orient in orientations:
|
||||||
img = "%s.%s" % (h[8:], 'jpg')
|
temp_image_path = mkstemp()[1]
|
||||||
elif len(h[2:])>4:
|
|
||||||
try: mkdir(path.join(t, h[2:4]))
|
thumb_image = Image.open(self.thumbnail_path)
|
||||||
except: pass
|
tmp_thumb_img = thumb_image.transpose(orientations[orient])
|
||||||
fpath = path.join(t, h[2:4], h[4:6])
|
|
||||||
try: mkdir(fpath)
|
if orient in flips:
|
||||||
except: pass
|
tmp_thumb_img = tmp_thumb_img.transpose(flips[orient])
|
||||||
img = "%s.%s" % (h[6:], 'jpg')
|
|
||||||
elif len(h[2:])>2:
|
if tmp_thumb_img:
|
||||||
fpath = path.join(t, h[2:4])
|
tmp_thumb_img.save(temp_image_path, 'JPEG')
|
||||||
try: mkdir(fpath)
|
move(temp_image_path, self.thumbnail_path)
|
||||||
except: pass
|
return self.sha512, exif
|
||||||
img = "%s.%s" %(h[4:], 'jpg')
|
|
||||||
else:
|
else:
|
||||||
fpath = ''
|
if __debug__:
|
||||||
img = "%s.%s" %(h[2:], 'jpg')
|
print self.filename, "no exif thumb"
|
||||||
return(path.join(t, fpath, img))
|
thumb = self.__scale_image()
|
||||||
|
if thumb:
|
||||||
|
thumb.save(self.thumbnail_path, "JPEG")
|
||||||
|
return self.sha512, exif
|
||||||
|
return None, exif
|
||||||
|
|
||||||
def __scale_image(self):
|
def __scale_image(self):
|
||||||
"""create thumbnail. returns image object or None"""
|
"""create thumbnail. returns image object or None"""
|
||||||
try:
|
try:
|
||||||
im = Image.open(self.filename).convert('RGB')
|
image_thumb = Image.open(self.filename).convert('RGB')
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
x, y = im.size
|
it_x, it_y = image_thumb.size
|
||||||
if x > self.x or y > self.y:
|
if it_x > self.thumb_x or it_y > self.thumb_y:
|
||||||
im.thumbnail((self.x, self.y), Image.ANTIALIAS)
|
image_thumb.thumbnail((self.thumb_x, self.thumb_y), Image.ANTIALIAS)
|
||||||
return im
|
return image_thumb
|
||||||
|
|
||||||
def __scale_image_deprecated(self, factor=True):
|
|
||||||
"""generate scaled Image object for given file
|
|
||||||
args:
|
|
||||||
factor - if False, adjust height into self.y
|
|
||||||
if True, use self.x for scale portrait pictures height.
|
|
||||||
returns Image object, or None
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
im = Image.open(self.filename).convert('RGB')
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
x, y = im.size
|
|
||||||
|
|
||||||
if x > self.x or y > self.y:
|
|
||||||
if x==y:
|
|
||||||
# square
|
|
||||||
imt = im.resize((self.y, self.y), Image.ANTIALIAS)
|
|
||||||
elif x > y:
|
|
||||||
# landscape
|
|
||||||
if int(y/(x/float(self.x))) > self.y:
|
|
||||||
# landscape image: height is non standard
|
|
||||||
self.x1 = int(float(self.y) * self.y / self.x)
|
|
||||||
if float(self.y) * self.y / self.x - self.x1 > 0.49:
|
|
||||||
self.x1 += 1
|
|
||||||
imt = im.resize(((int(x/(y/float(self.y))), self.y)),
|
|
||||||
Image.ANTIALIAS)
|
|
||||||
elif x/self.x==y/self.y:
|
|
||||||
# aspect ratio ok
|
|
||||||
imt = im.resize((self.x, self.y), Image.ANTIALIAS)
|
|
||||||
else:
|
|
||||||
imt = im.resize((self.x, int(y/(x/float(self.x)))), 1)
|
|
||||||
else:
|
|
||||||
# portrait
|
|
||||||
if factor:
|
|
||||||
if y>self.x:
|
|
||||||
imt = im.resize(((int(x/(y/float(self.x))),self.x)),
|
|
||||||
Image.ANTIALIAS)
|
|
||||||
else:
|
|
||||||
imt = im
|
|
||||||
else:
|
|
||||||
self.x1 = int(float(self.y) * self.y / self.x)
|
|
||||||
if float(self.y) * self.y / self.x - self.x1 > 0.49:
|
|
||||||
self.x1 += 1
|
|
||||||
|
|
||||||
if x/self.x1==y/self.y:
|
|
||||||
# aspect ratio ok
|
|
||||||
imt = im.resize((self.x1,self.y),Image.ANTIALIAS)
|
|
||||||
else:
|
|
||||||
imt = im.resize(((int(x/(y/float(self.y))), self.y)),
|
|
||||||
Image.ANTIALIAS)
|
|
||||||
return imt
|
|
||||||
else:
|
|
||||||
return im
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user