Skip to content

Commit 30fe24d

Browse files
committed
update docstring
1 parent 88f3f95 commit 30fe24d

File tree

5 files changed

+84
-55
lines changed

5 files changed

+84
-55
lines changed

README.rst

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ django-image-optimizer |pypi version|
22
---------------------------------------
33

44
.. |pypi version|
5-
image:: https://img.shields.io/pypi/v/django-image-optimizer.svg?style=flat-square
5+
image:: https://img.shields.io/pypi/v/django-image-optimizer.svg
66
:target: https://pypi.python.org/pypi/django-image-optimizer
77
8-
.. image:: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
8+
.. image:: https://img.shields.io/badge/license-MIT-blue.svg
99
:target: https://raw.githubusercontent.com/agusmakmun/django-image-optimizer/master/LICENSE
1010

11-
.. image:: https://img.shields.io/pypi/pyversions/django-image-optimizer.svg?style=flat-square
11+
.. image:: https://img.shields.io/pypi/pyversions/django-image-optimizer.svg
1212
:target: https://pypi.python.org/pypi/django-image-optimizer
1313

14-
.. image:: https://img.shields.io/badge/Django-1.8,%201.9,%201.10,%201.11,%202.0-green.svg?style=flat-square
14+
.. image:: https://img.shields.io/badge/Django-1.8%20%3E=%203.0-green.svg
1515
:target: https://www.djangoproject.com
1616

1717

@@ -80,13 +80,51 @@ file. Note: it is a good idea to keep this secret
8080
image = OptimizedImageField()
8181

8282

83+
class MyModel2(models.Model):
84+
"""
85+
If you using OPTIMIZED_IMAGE_METHOD = 'pillow'
86+
You can use this optional arguments.
87+
88+
This model represents a MyModel2 with a few
89+
fields including a `image` field which is an OptimizedImageField
90+
instance with `optimized_image_output_size` and
91+
`optimized_image_resize_method` arguments set.
92+
93+
This means that image would be a resized
94+
version of the source image, meant to keep a given screen resolution,
95+
in this case (400, 300) pixels.
96+
"""
97+
image = OptimizedImageField(
98+
upload_to='uploads/collaborators/%Y/%m/%d',
99+
optimized_image_output_size=(400, 300),
100+
optimized_image_resize_method='cover' # 'thumbnail', 'cover' or None
101+
)
102+
103+
83104
and saving images into it, the same way you would to a Django ``ImageField``.
84105
The optimized image will be saved into the ``url`` field in place of the
85106
unoptimized image.
86107

87108

109+
5. Or you can directly use the ``image_optimizer`` function from utils.
110+
111+
::
112+
113+
from image_optimizer.utils import image_optimizer
114+
115+
116+
def post_image(request):
117+
image_data = request.FILES.get('image')
118+
image_data = image_optimizer(image_data=image_data,
119+
output_size=(400, 300),
120+
resize_method='cover')
121+
....
122+
123+
124+
**P.S:**
125+
88126
Note about TinyPNG API keys: If you obtain the free TinyPNG API token, you are limited to 500
89127
image optimizations per month, so this function may fail if you have a
90128
lot of images. You may either obtain a paid API key, or wait until next month.
91129

92-
This project also taken from: https://github.com/dchukhin/django_optimized_image
130+
This project forked from: https://github.com/dchukhin/django_optimized_image

image_optimizer/fields.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import unicode_literals
33

44
from django.db.models import ImageField
5+
from .utils import image_optimizer
56

67

78
class OptimizedImageField(ImageField):
@@ -13,7 +14,6 @@ def save_form_data(self, instance, data):
1314
updating_image = True if data and getattr(instance, self.name) != data else False
1415

1516
if updating_image:
16-
from .utils import image_optimizer
1717
data = image_optimizer(
1818
data,
1919
self.optimized_image_output_size,
@@ -34,6 +34,7 @@ def __init__(self, optimized_image_output_size=None,
3434
# Set the optimized_image_output_size specified on your
3535
# OptimizedImageField model instances
3636
self.optimized_image_output_size = optimized_image_output_size
37+
3738
# Set the optimized_image_resize_method specified on your
3839
# OptimizedImageField model instances
3940
self.optimized_image_resize_method = optimized_image_resize_method
@@ -49,10 +50,11 @@ def deconstruct(self):
4950
field but you need to exclude them from migrations.
5051
"""
5152
name, path, args, kwargs = super().deconstruct()
52-
if kwargs.get('optimized_image_output_size') is not None:
53-
del kwargs["optimized_image_output_size"]
5453

55-
if kwargs.get('optimized_image_resize_method') is not None:
56-
del kwargs["optimized_image_resize_method"]
54+
if kwargs.get('optimized_image_output_size'):
55+
del kwargs['optimized_image_output_size']
56+
57+
if kwargs.get('optimized_image_resize_method'):
58+
del kwargs['optimized_image_resize_method']
5759

5860
return name, path, args, kwargs

image_optimizer/utils.py

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
from resizeimage import resizeimage
77

88
import tinify
9+
import logging
910
import requests
1011

1112
from .settings import (OPTIMIZED_IMAGE_METHOD, TINYPNG_KEY)
1213

14+
1315
BACKGROUND_TRANSPARENT = (255, 255, 255, 0)
1416

1517

@@ -34,7 +36,13 @@ def get_image_extension(image):
3436

3537

3638
def image_optimizer(image_data, output_size=None, resize_method=None):
37-
"""Optimize an image that has not been saved to a file."""
39+
"""
40+
Optimize an image that has not been saved to a file.
41+
:param `image_data` is image data, e.g from request.FILES['image']
42+
:param `output_size` is float pixel scale of image (width, height) or None, e.g: (400, 300)
43+
:param `resize_method` is string resize method, choices are: None, "thumbnail", or "cover".
44+
:return optimized image data.
45+
"""
3846
if OPTIMIZED_IMAGE_METHOD == 'pillow':
3947
image = Image.open(image_data)
4048
bytes_io = BytesIO()
@@ -45,57 +53,31 @@ def image_optimizer(image_data, output_size=None, resize_method=None):
4553
# resize_method. 'thumbnail' is used by default
4654
if output_size is not None:
4755

48-
if resize_method is None:
49-
pass
56+
if resize_method not in ('thumbnail', 'cover', None):
57+
message = 'optimized_image_resize_method misconfigured, it\'s value must be \'thumbnail\', \'cover\' or None'
58+
raise Exception(message)
5059

5160
elif resize_method is 'thumbnail':
52-
image = resizeimage.resize_thumbnail(
53-
image,
54-
output_size,
55-
resample=Image.LANCZOS
56-
)
61+
image = resizeimage.resize_thumbnail(image, output_size, resample=Image.LANCZOS)
5762

5863
elif resize_method is 'cover':
59-
image = resizeimage.resize_cover(
60-
image,
61-
output_size,
62-
validate=False
63-
)
64-
65-
else:
66-
raise Exception(
67-
'optimized_image_resize_method misconfigured, it\'s value must be \'thumbnail\', \'cover\' or None'
68-
)
69-
70-
output_image = Image.new(
71-
'RGBA',
72-
output_size,
73-
BACKGROUND_TRANSPARENT
74-
)
75-
76-
output_image_center = (
77-
int((output_size[0] - image.size[0]) / 2),
78-
int((output_size[1] - image.size[1]) / 2)
79-
)
80-
81-
output_image.paste(
82-
image,
83-
output_image_center
84-
)
85-
86-
# If output_size is None the output_image would be the same as source
64+
image = resizeimage.resize_cover(image, output_size, validate=False)
65+
66+
output_image = Image.new('RGBA', output_size, BACKGROUND_TRANSPARENT)
67+
output_image_center = (int((output_size[0] - image.size[0]) / 2),
68+
int((output_size[1] - image.size[1]) / 2))
69+
70+
output_image.paste(image, output_image_center)
71+
8772
else:
73+
# If output_size is None the output_image would be the same as source
8874
output_image = image
8975

9076
# If the file extension is JPEG, convert the output_image to RGB
9177
if extension == 'JPEG':
92-
output_image = output_image.convert("RGB")
78+
output_image = output_image.convert('RGB')
9379

94-
output_image.save(
95-
bytes_io,
96-
format=extension,
97-
optimize=True
98-
)
80+
output_image.save(bytes_io, format=extension, optimize=True)
9981

10082
image_data.seek(0)
10183
image_data.file.write(bytes_io.getvalue())
@@ -105,9 +87,15 @@ def image_optimizer(image_data, output_size=None, resize_method=None):
10587
# disable warning info
10688
requests.packages.urllib3.disable_warnings()
10789

90+
# just info for people
91+
if any([output_size, resize_method]):
92+
message = '[django-image-optimizer] "output_size" and "resize_method" only for OPTIMIZED_IMAGE_METHOD="pillow"'
93+
logging.info(message)
94+
10895
tinify.key = TINYPNG_KEY
10996
optimized_buffer = tinify.from_buffer(image_data.file.read()).to_buffer()
11097
image_data.seek(0)
11198
image_data.file.write(optimized_buffer)
11299
image_data.file.truncate()
100+
113101
return image_data

image_optimizer_demo/image_optimizer_demo/settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"""
1212

1313
import os
14+
import tempfile
1415

1516
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
1617
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -27,7 +28,7 @@
2728

2829
ALLOWED_HOSTS = ['*']
2930

30-
OPTIMIZED_IMAGE_METHOD = 'tinypng' # 'pillow'
31+
OPTIMIZED_IMAGE_METHOD = 'pillow' # 'tinypng'
3132
TINYPNG_KEY = 'key-key-key-key'
3233

3334

@@ -123,7 +124,6 @@
123124
# Static files (CSS, JavaScript, Images)
124125
# https://docs.djangoproject.com/en/2.0/howto/static-files/
125126

126-
import tempfile
127127

128128
STATIC_URL = '/static/'
129129
MEDIA_URL = '/media/'

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from setuptools import (setup, find_packages)
44

5-
__VERSION__ = '1.0.0'
5+
__VERSION__ = '1.0.1'
66
__AUTHOR__ = 'Agus Makmun (Summon Agus)'
77
__AUTHOR_EMAIL__ = '[email protected]'
88

@@ -43,6 +43,7 @@
4343
'Programming Language :: Python :: 2.7',
4444
'Programming Language :: Python :: 3.3',
4545
'Programming Language :: Python :: 3.5',
46+
'Programming Language :: Python :: 3.7',
4647
'Topic :: Software Development :: Libraries :: Python Modules',
4748
'License :: OSI Approved :: MIT License',
4849
],

0 commit comments

Comments
 (0)