You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

74 rivejä
2.3 KiB

  1. from PIL import Image
  2. # this neat function is based on easy-thumbnails
  3. def scale_and_crop(image, size, crop=False, upscale=False, quality=None):
  4. """
  5. Resize, crop and/or change quality of an image.
  6. :param image: Source image file
  7. :param type: :class:`django.core.files.images.ImageFile`
  8. :param size: Size as width & height, zero as either means unrestricted
  9. :type size: tuple of two int
  10. :param crop: Truncate image or not
  11. :type crop: bool
  12. :param upscale: Enable scale up
  13. :type upscale: bool
  14. :param quality: Value between 1 to 95, or None for keep the same
  15. :type quality: int or NoneType
  16. :return: Handled image
  17. :rtype: class:`PIL.Image`
  18. """
  19. # Open image and store format/metadata.
  20. image.open()
  21. im = Image.open(image)
  22. im_format, im_info = im.format, im.info
  23. if quality:
  24. im_info['quality'] = quality
  25. # Force PIL to load image data.
  26. im.load()
  27. source_x, source_y = [float(v) for v in im.size]
  28. target_x, target_y = [float(v) for v in size]
  29. if crop or not target_x or not target_y:
  30. scale = max(target_x / source_x, target_y / source_y)
  31. else:
  32. scale = min(target_x / source_x, target_y / source_y)
  33. # Handle one-dimensional targets.
  34. if not target_x:
  35. target_x = source_x * scale
  36. elif not target_y:
  37. target_y = source_y * scale
  38. if scale < 1.0 or (scale > 1.0 and upscale):
  39. im = im.resize((int(source_x * scale), int(source_y * scale)),
  40. resample=Image.ANTIALIAS)
  41. if crop:
  42. # Use integer values now.
  43. source_x, source_y = im.size
  44. # Difference between new image size and requested size.
  45. diff_x = int(source_x - min(source_x, target_x))
  46. diff_y = int(source_y - min(source_y, target_y))
  47. if diff_x or diff_y:
  48. # Center cropping (default).
  49. halfdiff_x, halfdiff_y = diff_x // 2, diff_y // 2
  50. box = [halfdiff_x, halfdiff_y,
  51. min(source_x, int(target_x) + halfdiff_x),
  52. min(source_y, int(target_y) + halfdiff_y)]
  53. # Finally, crop the image!
  54. im = im.crop(box)
  55. # Close image and replace format/metadata, as PIL blows this away.
  56. im.format, im.info = im_format, im_info
  57. image.close()
  58. return im