|
|
@ -5,6 +5,8 @@ import seminar.models |
|
|
|
from django.db.models import Q |
|
|
|
from django.utils import timezone |
|
|
|
from django.utils.encoding import force_unicode |
|
|
|
from imagekit.models import ImageSpecField |
|
|
|
from imagekit.processors import ResizeToFit, Transpose |
|
|
|
|
|
|
|
from PIL import Image |
|
|
|
from PIL.ExifTags import TAGS |
|
|
@ -32,47 +34,32 @@ def get_exif(fn): |
|
|
|
ret[decoded] = value |
|
|
|
return ret |
|
|
|
|
|
|
|
def flip_horizontal(im): return im.transpose(Image.FLIP_LEFT_RIGHT) |
|
|
|
def flip_vertical(im): return im.transpose(Image.FLIP_TOP_BOTTOM) |
|
|
|
def rotate_180(im): return im.transpose(Image.ROTATE_180) |
|
|
|
def rotate_90(im): return im.transpose(Image.ROTATE_90) |
|
|
|
def rotate_270(im): return im.transpose(Image.ROTATE_270) |
|
|
|
def transpose(im): return rotate_90(flip_horizontal(im)) |
|
|
|
def transverse(im): return rotate_90(flip_vertical(im)) |
|
|
|
orientation_funcs = [None, |
|
|
|
lambda x: x, |
|
|
|
flip_horizontal, |
|
|
|
rotate_180, |
|
|
|
flip_vertical, |
|
|
|
transpose, |
|
|
|
rotate_270, |
|
|
|
transverse, |
|
|
|
rotate_90 |
|
|
|
] |
|
|
|
|
|
|
|
# tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují |
|
|
|
# až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat |
|
|
|
def obrazek_filename_maly(): |
|
|
|
pass |
|
|
|
def obrazek_filename_stredni(): |
|
|
|
pass |
|
|
|
def obrazek_filename_velky(): |
|
|
|
pass |
|
|
|
|
|
|
|
def obrazek_filename(self, filename): |
|
|
|
return obrazek_filename_obecny(self, filename, "velky") |
|
|
|
|
|
|
|
def obrazek_filename_stredni(self, filename): |
|
|
|
return obrazek_filename_obecny(self, filename, "stredni") |
|
|
|
|
|
|
|
def obrazek_filename_maly(self, filename): |
|
|
|
return obrazek_filename_obecny(self, filename, "maly") |
|
|
|
|
|
|
|
def obrazek_filename_obecny(self, filename, typ): |
|
|
|
gal = self.galerie |
|
|
|
cislo_gal = force_unicode(gal.pk) |
|
|
|
cesta = "" |
|
|
|
while(not gal.soustredeni): |
|
|
|
gal = gal.galerie_up |
|
|
|
return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, typ, force_unicode(self.nazev)) |
|
|
|
return os.path.join('Galerie', "soustredeni_" + force_unicode(gal.soustredeni.pk), "galerie_" + cislo_gal, "velky", force_unicode(self.nazev)) |
|
|
|
|
|
|
|
class Obrazek(models.Model): |
|
|
|
obrazek_velky = models.ImageField(upload_to=obrazek_filename, |
|
|
|
help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") |
|
|
|
obrazek_stredni = models.ImageField(upload_to=obrazek_filename_stredni, null = True, editable = False) |
|
|
|
obrazek_maly = models.ImageField(upload_to=obrazek_filename_maly, null = True, editable = False) |
|
|
|
obrazek_stredni = ImageSpecField(source='obrazek_velky', |
|
|
|
processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], |
|
|
|
options={'quality': 95}) |
|
|
|
obrazek_maly = ImageSpecField(source='obrazek_velky', |
|
|
|
processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], |
|
|
|
options={'quality': 95}) |
|
|
|
nazev = models.CharField('Název', max_length=50, blank = True, null = True) |
|
|
|
popis = models.TextField('Popis', blank = True, null = True) |
|
|
|
datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add = True) |
|
|
@ -89,56 +76,11 @@ class Obrazek(models.Model): |
|
|
|
original = Image.open(self.obrazek_velky) |
|
|
|
# vycteni EXIFu |
|
|
|
exif = get_exif(original) |
|
|
|
# otoceni podle EXIFu |
|
|
|
if exif['Orientation']: |
|
|
|
f = orientation_funcs[exif['Orientation']] |
|
|
|
original_otoceny = f(original) |
|
|
|
original_otoceny.format = original.format |
|
|
|
original = original_otoceny |
|
|
|
# datum podle EXIfu |
|
|
|
if exif['DateTimeOriginal']: |
|
|
|
datum_string = ":".join(exif['DateTimeOriginal'].split(' ')).split(":") |
|
|
|
datum_int = [] |
|
|
|
for retezec in datum_string: |
|
|
|
datum_int.append(int(retezec)) |
|
|
|
self.datum = datetime(datum_int[0], datum_int[1], datum_int[2], |
|
|
|
datum_int[3], datum_int[4], datum_int[5]) |
|
|
|
jmeno = os.path.basename(self.obrazek_velky.file.name) |
|
|
|
if not self.obrazek_stredni: |
|
|
|
Obrazek._vyrobMiniaturu(original, jmeno, 1024, self.obrazek_stredni) |
|
|
|
if not self.obrazek_maly: |
|
|
|
Obrazek._vyrobMiniaturu(original, jmeno, 200, self.obrazek_maly) |
|
|
|
datum_ints = map(int, ":".join(exif['DateTimeOriginal'].split(' ')).split(":")) |
|
|
|
self.datum = datetime(*datum_ints) |
|
|
|
super(Obrazek, self).save() |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def _vyrobMiniaturu(original, jmeno, maximum, field): |
|
|
|
zmensenina = Obrazek._zmensiObrazek(original, maximum) |
|
|
|
f = StringIO() |
|
|
|
try: |
|
|
|
zmensenina.save(f, format=original.format) |
|
|
|
data = ContentFile(f.getvalue()) |
|
|
|
finally: |
|
|
|
f.close() |
|
|
|
field.save(jmeno, data, save = False) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def _zmensiObrazek(original, maximum): |
|
|
|
"""Preskaluje obrazek tak, aby byl zachovan pomer stran a zadny rozmer |
|
|
|
nepresahoval maxRozmer. Pokud zadny rozmer nepresahuje maxRozmer, tak |
|
|
|
vrati puvodni obrazek (tj. nedojde ke zvetseni obrazku).""" |
|
|
|
novaVelikost = Obrazek._zmensiVelikost(original.size, maximum) |
|
|
|
return original.resize(novaVelikost, Image.ANTIALIAS) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def _zmensiVelikost(velikost, maximum): |
|
|
|
maximum = float(maximum) |
|
|
|
w, h = velikost |
|
|
|
soucasneMaximum = max(w, h) |
|
|
|
if soucasneMaximum <= maximum: |
|
|
|
return velikost |
|
|
|
pomer = maximum/soucasneMaximum |
|
|
|
return (int(w * pomer), int(h * pomer)) |
|
|
|
|
|
|
|
|
|
|
|
class Galerie(models.Model): |
|
|
|
nazev = models.CharField('Název', max_length=100) |
|
|
|