<commit_before># encoding: utf-8

"""Image field which scales images on demand.

This acts like Django's ImageField but in addition can scale images on demand. Scaled Images are put in
<settings.MEDIA_ROOT>/,/<originalpath>. The avialable scaling factors are hardcoded in the dictionary _sizes.
If the dimensions there are followed by an '!' this means the images should be cropped to exactly this size.
Without this the images are scaled to fit in the given size without changing the aspect ratio of the image.

Scaled versions of the images are generated on the fly using PIL. 

In addition it also mangles the filename of the uploaded images to make sure they are unguessable and thus can
put without authentication on a public webserver as long as directory listings ar prohibitet on that
webserver.

Given a model like

class Image(models.Model):
    path       = ScaledImageField(verbose_name='Datei', upload_to='-/product/image')
    [...]

you can do  the following:

>>> img.path  
'-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg'
>>>img.get_path_url()
'/media/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg'
>>> img.get_path_size()
417119L
>>> img.get_path_width()
1584
>>> img.get_path_height()
2889

All well known metods from ImageField are supported. The new functionality is available via img.path_scaled - this returns an
Imagescaler instance beeing able to play some nifty tricks:

>>> img.path_scaled().svga()
'/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
>>> img.path_scaled().svga_path()
'/usr/local/web/media/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
>>> img.path_scaled().svga_dimensions()
(328, 600)
>>> img.path_scaled().svga_tag()
'<img src="/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg" width="328" height="600" />'
>>> img.path_scaled().thumb_dimensions()
(50, 91)
>>> img.path_scaled().square_dimensions()
(75, 76)

Created August 2006 by <NAME>. Consider it BSD licensed.
"""

import md5, time, os, urlparse
import Image 
from django.conf import settings
from django.utils.html import escape 
from django.utils.safestring import mark_safe 
from django.utils.functional import curry
from django.db.models import ImageField, signals

_sizes = {'mini':    "23x40",
          'thumb':   "50x200", 
          'sidebar': "179x600",
          'small':   "240x160",
          'medium':  "480x320", 
          'full':    "477x800",
          'svga':    "800x600", 
          'xvga':    "1024x768",
          'square':  "75x75!"} 

def _scaleImage(width, height, image):
    """
    This function will scale an image to a given bounding box. Image
    aspect ratios will be conserved and so there might be blank space
    at two sides of the image if the ratio isn't identical to that of
    the bounding box.
    """
    #from http://simon.bofh.ms/cgi-bin/trac-django-projects.cgi/file/stuff/branches/magic-removal/image.py
    lfactor = 1    
    width, height = int(width), int(height)
    (xsize, ysize) = image.size
    if xsize > width and ysize > height:
        lfactorx = float(width) / float(xsize)
        lfactory = float(height) / float(ysize)
        lfactor = min(lfactorx, lfactory)
    elif xsize > width:
        lfactor = float(width) / float(xsize)
    elif ysize > height:
        lfactor = float(height) / float(ysize)
    res = image.resize((int(float(xsize) * lfactor), int(float(ysize) * lfactor)), Image.ANTIALIAS)
    return res

def _cropImage(width, height, image):
    """
    This will crop the largest block out of the middle of an image
    that has the same aspect ratio as the given bounding box. No
    blank space will be in the thumbnail, but the image isn't fully
    visible due to croping.
    """
    #from http://simon.bofh.ms/cgi-bin/trac-django-projects.cgi/file/stuff/branches/magic-removal/image.py
    # moderately modified
    width, height = int(width), int(height)
    lfactor = 1
    (xsize, ysize) = image.size
    if xsize > width and ysize > height:
        lfactorx = float(width) / float(xsize)
        lfactory = float(height) / float(ysize)
        lfactor = max(lfactorx, lfactory)
    newx = int(float(xsize) * lfactor)
    newy = int(float(ysize) * lfactor)
    res = image.resize((newx, newy), Image.ANTIALIAS)
    leftx = 0
    lefty = 0
    rightx = newx
    righty = newy
    if newx > width:
        leftx += (newx - width) / 2
        rightx -= (newx - width) / 2
    elif newy > height:
        lefty += (newy - height) / 2
        righty -= (newy - height) / 2
    res = res.crop((leftx, lefty, rightx, righty))
    return res

class Imagescaler:
    """Class whose instances scale an image on the fly to desired properties.
    
    For each set of dimensions defined in _sizes imagescaler has a set of functions, e.g. for 'small':
    
    o.small() = return the URL of the small version of the image
    o.small_path() - return the absolute  pathe in the filesystem for the  image
    o.small_dimensions() - return (width,  heigth)
    o.small_tag() - return a complete image tag for use in XHTML
    
    >>> img.path_scaled().svga()
    '/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
    >>> img.path_scaled().svga_path()
    '/usr/local/web/media/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
    >>> img.path_scaled().svga_dimensions()
    (328, 600)
    >>> img.path_scaled().svga_tag()
    '<img src="/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg" width="328" height="600" />'
    """
    def __init__(self, field, obj):
        self.field = field
        self.parent_obj = obj
        self.original_image = getattr(self.parent_obj, self.field.attname)
        self.original_image_path = os.path.join(settings.MEDIA_ROOT, self.original_image)
        self.scaled_image_dir = os.path.join(settings.MEDIA_ROOT, ',', self.original_image)
        self.broken_image = None
        # if broken.gif exists we sendd that if there are any problems during scaling
        if not os.path.exists(self.original_image_path):
            self.broken_image = os.path.join(settings.MEDIA_ROOT, 'broken.gif') <commit_msg>small fix: os.path.join(settings.MEDIA_ROOT, str(self.original_image))     instead of os.path.join(settings.MEDIA_ROOT, self.original_image)<commit_after># encoding: utf-8

"""Image field which scales images on demand.

This acts like Django's ImageField but in addition can scale images on demand. Scaled Images are put in
<settings.MEDIA_ROOT>/,/<originalpath>. The avialable scaling factors are hardcoded in the dictionary _sizes.
If the dimensions there are followed by an '!' this means the images should be cropped to exactly this size.
Without this the images are scaled to fit in the given size without changing the aspect ratio of the image.

Scaled versions of the images are generated on the fly using PIL. 

In addition it also mangles the filename of the uploaded images to make sure they are unguessable and thus can
put without authentication on a public webserver as long as directory listings ar prohibitet on that
webserver.

Given a model like

class Image(models.Model):
    path       = ScaledImageField(verbose_name='Datei', upload_to='-/product/image')
    [...]

you can do  the following:

>>> img.path  
'-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg'
>>>img.get_path_url()
'/media/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg'
>>> img.get_path_size()
417119L
>>> img.get_path_width()
1584
>>> img.get_path_height()
2889

All well known metods from ImageField are supported. The new functionality is available via img.path_scaled - this returns an
Imagescaler instance beeing able to play some nifty tricks:

>>> img.path_scaled().svga()
'/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
>>> img.path_scaled().svga_path()
'/usr/local/web/media/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
>>> img.path_scaled().svga_dimensions()
(328, 600)
>>> img.path_scaled().svga_tag()
'<img src="/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg" width="328" height="600" />'
>>> img.path_scaled().thumb_dimensions()
(50, 91)
>>> img.path_scaled().square_dimensions()
(75, 76)

Created August 2006 by <NAME>. Consider it BSD licensed.
"""

import md5, time, os, urlparse
import Image 
from django.conf import settings
from django.utils.html import escape 
from django.utils.safestring import mark_safe 
from django.utils.functional import curry
from django.db.models import ImageField, signals

_sizes = {'mini':    "23x40",
          'thumb':   "50x200", 
          'sidebar': "179x600",
          'small':   "240x160",
          'medium':  "480x320", 
          'full':    "477x800",
          'svga':    "800x600", 
          'xvga':    "1024x768",
          'square':  "75x75!"} 

def _scaleImage(width, height, image):
    """
    This function will scale an image to a given bounding box. Image
    aspect ratios will be conserved and so there might be blank space
    at two sides of the image if the ratio isn't identical to that of
    the bounding box.
    """
    #from http://simon.bofh.ms/cgi-bin/trac-django-projects.cgi/file/stuff/branches/magic-removal/image.py
    lfactor = 1    
    width, height = int(width), int(height)
    (xsize, ysize) = image.size
    if xsize > width and ysize > height:
        lfactorx = float(width) / float(xsize)
        lfactory = float(height) / float(ysize)
        lfactor = min(lfactorx, lfactory)
    elif xsize > width:
        lfactor = float(width) / float(xsize)
    elif ysize > height:
        lfactor = float(height) / float(ysize)
    res = image.resize((int(float(xsize) * lfactor), int(float(ysize) * lfactor)), Image.ANTIALIAS)
    return res

def _cropImage(width, height, image):
    """
    This will crop the largest block out of the middle of an image
    that has the same aspect ratio as the given bounding box. No
    blank space will be in the thumbnail, but the image isn't fully
    visible due to croping.
    """
    #from http://simon.bofh.ms/cgi-bin/trac-django-projects.cgi/file/stuff/branches/magic-removal/image.py
    # moderately modified
    width, height = int(width), int(height)
    lfactor = 1
    (xsize, ysize) = image.size
    if xsize > width and ysize > height:
        lfactorx = float(width) / float(xsize)
        lfactory = float(height) / float(ysize)
        lfactor = max(lfactorx, lfactory)
    newx = int(float(xsize) * lfactor)
    newy = int(float(ysize) * lfactor)
    res = image.resize((newx, newy), Image.ANTIALIAS)
    leftx = 0
    lefty = 0
    rightx = newx
    righty = newy
    if newx > width:
        leftx += (newx - width) / 2
        rightx -= (newx - width) / 2
    elif newy > height:
        lefty += (newy - height) / 2
        righty -= (newy - height) / 2
    res = res.crop((leftx, lefty, rightx, righty))
    return res

class Imagescaler:
    """Class whose instances scale an image on the fly to desired properties.
    
    For each set of dimensions defined in _sizes imagescaler has a set of functions, e.g. for 'small':
    
    o.small() = return the URL of the small version of the image
    o.small_path() - return the absolute  pathe in the filesystem for the  image
    o.small_dimensions() - return (width,  heigth)
    o.small_tag() - return a complete image tag for use in XHTML
    
    >>> img.path_scaled().svga()
    '/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
    >>> img.path_scaled().svga_path()
    '/usr/local/web/media/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg'
    >>> img.path_scaled().svga_dimensions()
    (328, 600)
    >>> img.path_scaled().svga_tag()
    '<img src="/,/-/product/image/0e99d6be8ec0259df920c2d273d1ad6f.jpg/svga.jpeg" width="328" height="600" />'
    """
    def __init__(self, field, obj):
        self.field = field
        self.parent_obj = obj
        self.original_image = getattr(self.parent_obj, self.field.attname)
        self.original_image_path = os.path.join(settings.MEDIA_ROOT, str(self.original_image))
        self.scaled_image_dir = os.path.join(settings.MEDIA_ROOT, ',', str(self.original_image))
        self.broken_image = None
        # if broken.gif exists we sendd that if there are any problems during scaling
        if not os.path.exists(self.original_image_path):
            self.broken_image = os.path.join(settings.MEDIA_ROOT, 'broken.gif') 
{'fraction_non_alphanumeric': 0.11522666881391416, 'fraction_numerical': 0.04090506482003382, 'mean_word_length': 3.2418032786885247, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5698212', 'n_tokens_mistral': 4513, 'n_tokens_neox': 4139, 'n_words': 1167}