Permalink
Browse files

add auto jpegoptim

fix tool.py for store new file
  • Loading branch information...
1 parent cd14d67 commit 042c4eee9f54cb8eef514267489b0231e7f0a6b4 @liut committed Jul 4, 2013
Showing with 65 additions and 13 deletions.
  1. +1 −0 config/imsto.ini
  2. +2 −0 imsto/_config.py
  3. +14 −5 imsto/_util.py
  4. +20 −3 imsto/image.py
  5. +27 −4 imsto/store.py
  6. +1 −1 imsto/tool.py
View
@@ -2,6 +2,7 @@
servers = mongodb://localhost
thumb_path = /t1
thumb_root = /opt/imsto/cache/thumb/
+temp_root = /opt/imsto/cache/temp/
;thumb_method = shell, wand, pil
thumb_method = wand
max_file_size = 102400
View
@@ -31,10 +31,12 @@ def __init__(self):
'fs_prefix': 'img',
'thumb_path': '/thumb',
'thumb_root': '/opt/imsto/cache/thumb/',
+ 'temp_root': '/opt/imsto/cache/temp/',
'thumb_method': 'shell', # shell, wand, pil
'url_prefix': 'http://m.imsto.net/',
'eggs_cache': '/opt/imsto/cache/eggs',
'max_file_size': '102400',
+ 'max_jpeg_quality': '88',
'support_size': '120,160,250,400',
'admin_name': 'imsto',
'admin_pass': '',
View
@@ -12,22 +12,24 @@
MagickGetImageFormat,MagickGetImageWidth,MagickGetImageHeight,MagickGetImageCompressionQuality
__all__ = [
-'check_dirs', 'save_file', 'identify_image', 'guessImageType',
+'check_dirs', 'save_file', 'identify_image', 'guessImageType',
'identify_image', 'thumb_image', 'watermark_image',
'guess_mimetype', 'guess_ext', 'password_hash',
-'encode_upload'
+'encode_upload', 'jpegoptim'
]
def check_dirs(filename):
dir_name = os.path.dirname(filename)
if not os.path.exists(dir_name):
os.makedirs(dir_name, 0777)
-def save_file(file, filename):
+def save_file(filename, file = None, blob = None):
check_dirs(filename)
+ if file is None and blob is None:
+ raise ValueError('invalid argument: file and blob are both None')
fp = open(filename, 'wb')
try:
- fp.write(file.read())
+ fp.write(blob if blob else file.read())
except Exception, e:
print('save file {} failed, error: {}'.format(filename, e))
finally:
@@ -247,6 +249,13 @@ def encode_upload(file=None, content=None, content_type=None, name=None, ext_dat
body.extend(['--' + BOUNDARY + '--', ''])
return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
-
+def jpegoptim(imagefile, max_quality = 88):
+ print 'jpegoptim {} (max {})'.format(imagefile, max_quality)
+ import subprocess
+ r = subprocess.call(["jpegoptim","--strip-all", "--max={}".format(max_quality), imagefile])
+ if r != 0:
+ print 'call jpegoptim failed {}'.format(r)
+ return False
+ return True
View
@@ -8,7 +8,7 @@
__all__ = ['SimpImage']
-import ctypes
+import ctypes,collections
from _wand import (NewMagickWand,DestroyMagickWand,CloneMagickWand,ClearMagickWand,
MagickReadImageBlob,MagickReadImage,MagickWriteImage,MagickGetImageBlob,
MagickGetImageFormat,MagickSetImageFormat,MagickGetImageWidth,MagickGetImageHeight,
@@ -24,15 +24,28 @@
import os
+# FORMAT_JPEG = 'JPEG'
+# FORMAT_PNG = 'PNG'
+# FORMAT_GIF = 'GIF'
+
class SimpImage(object):
_max_width, _max_height = 0, 0
"""docstring for ClassName"""
def __init__(self, file = None, image=None, blob=None):
if isinstance(image, SimpImage):
self._wand = CloneMagickWand(image.wand)
- elif blob:
- MagickReadImageBlob( self._wand, blob, len( blob ) )
+ elif blob is not None:
+ if not isinstance(blob, collections.Iterable):
+ raise TypeError( 'blob must be iterable, not {}'.format(repr(blob)) )
+ if not isinstance(blob, basestring):
+ blob = ''.join(blob)
+ elif not isinstance(blob, str):
+ blob = str(blob)
+ self._wand = NewMagickWand()
+ r = MagickReadImageBlob( self._wand, blob, len( blob ) )
+ if not r:
+ self.error()
else:
self._wand = NewMagickWand()
self.read(file)
@@ -138,6 +151,10 @@ def _get_size( self ):
return ( self.width, self.height )
size = property( _get_size, scale, None, 'A tuple containing the size of the image. Setting the size is the same as calling scale().' )
+ @property
+ def meta(self):
+ return {'format': self.format, 'width': self.width, 'height': self.height, 'quality': self.quality}
+
def save( self, file = None ):
''' Saves the image to a file. If no file is specified, the file is
saved with the original filename.'''
View
@@ -83,12 +83,35 @@ def store(self, file=None, ctype=None, content=None, name=None):
data = content if content is not None else file.read()
size = len(data)
- if (size > int(self.get_config('max_file_size'))):
- raise ValueError('file: {} too big'.format(name))
ext = guessImageType(data[:32])
if ext is None:
raise ValueError('invalid image file')
+ from image import SimpImage
+ im = SimpImage(blob=data)
+ if im.format == 'JPEG':
+ max_jpeg_quality = int(self.get_config('max_jpeg_quality'))
+ if im.quality > max_jpeg_quality:
+ print 'quality {} is too high'.format(im.quality)
+ from tempfile import NamedTemporaryFile
+ _tmp = NamedTemporaryFile('w+b',dir=self.get_config('temp_root'),delete=False)
+ _tmp.file.close()
+ save_file(_tmp.name, blob=data)
+ if jpegoptim(_tmp.name):
+ fp = open(_tmp.name)
+ data = fp.read()
+ size = len(data)
+ print 'new optimized size {}'.format(size)
+ fp.close()
+ _tmp.unlink(_tmp.name)
+ del im
+ im = SimpImage(blob=data)
+ meta = im.meta
+ del im
+
+ if (size > int(self.get_config('max_file_size'))):
+ raise ValueError('file: {} size {}, too big'.format(name, size))
+
hashed = md5(data).hexdigest()
print ('md5 hash: {}'.format(hashed))
@@ -119,7 +142,7 @@ def store(self, file=None, ctype=None, content=None, name=None):
raise NotImplementedError()
# save to mongodb
- spec = {'_id': id,'filename': filename, 'hash': hashed, 'content_type': ctype, 'content_length': size}
+ spec = {'_id': id,'filename': filename, 'hash': hashed, 'content_type': ctype, 'content_length': size, 'meta': 'meta'}
if name:
spec['name'] = name
rr = self._put(data, **spec)
@@ -221,7 +244,7 @@ def load(self, path):
if file is None:
print('fetch failed')
raise UrlError('id {} not found'.format(id))
- save_file(file, org_file)
+ save_file(org_file, file)
if not os.path.exists(org_file):
raise UrlError('file not found')
View
@@ -34,7 +34,7 @@ def store_file(filename):
from _util import guess_mimetype
ctype = guess_mimetype(filename)
with open(filename) as fp:
- ret = imsto.store(fp, ctype)
+ ret = imsto.store(fp, ctype, name=os.path.basename(filename))
print ret
else:
print 'image {} not found or access deny'.format(filename)

0 comments on commit 042c4ee

Please sign in to comment.