def get(self, *args, **kwargs): orig_image = self.orig_image if orig_image: orig_w = getattr(orig_image, 'width', None) or 0 orig_h = getattr(orig_image, 'height', None) or 0 orig_image_name = getattr(orig_image, 'name', None) else: orig_w, orig_h = 0, 0 orig_image_name = None initial = { 'standalone': self.is_standalone, 'sizes': json.dumps(self.sizes), 'thumbs': json.dumps(dict([ (t['name'], t) for t in self.thumbs.queryset.values('id', 'name', 'width', 'height')])), 'image_id': getattr(self.db_image, 'pk', None) if orig_image else None, 'orig_image': orig_image_name, 'orig_w': orig_w, 'orig_h': orig_h, } FormSet = modelformset_factory(Thumb, form=ThumbForm, formset=ThumbFormSet, extra=0) thumb_formset = FormSet(queryset=self.thumbs, initial=[], prefix='thumbs') size_dict = dict([(s.name, s) for s in self.sizes]) for thumb_form in thumb_formset.initial_forms: name = thumb_form.initial['name'] if name in size_dict: thumb_form.initial['size'] = json.dumps(size_dict[name]) # The thumb being cropped and thumbs referencing it pk = thumb_form.initial['id'] thumb_group = self.thumbs.queryset.filter(Q(pk=pk) | Q(reference_thumb_id__exact=pk)) thumb_group_data = dict([(t['name'], t) for t in thumb_group.values('id', 'name', 'width', 'height')]) thumb_form.initial.update({ 'thumbs': json.dumps(thumb_group_data), 'changed': False, }) return render(self.request, 'cropduster/upload.html', { 'django_is_gte_19': (django.VERSION[:2] >= (1, 9)), 'is_popup': True, 'orig_image': '', 'parent_template': get_admin_base_template(), 'image': getattr(self.image_file.preview_image, 'url', u"%scropduster/img/blank.gif" % settings.STATIC_URL), 'standalone': self.is_standalone, 'upload_form': UploadForm(initial={ 'upload_to': self.upload_to, 'sizes': initial['sizes'], 'image_element_id': self.request.GET.get('el_id', ''), 'standalone': self.is_standalone, 'preview_width': self.preview_size[0], 'preview_height': self.preview_size[1], }), 'crop_form': CropForm(initial=initial, prefix='crop'), 'thumb_formset': thumb_formset, })
def generate_xmp(self, size, original_metadata=None): from cropduster.standalone.metadata import libxmp from cropduster.utils import json NS_MWG_RS = "http://www.metadataworkinggroup.com/schemas/regions/" NS_XMPMM = "http://ns.adobe.com/xap/1.0/mm/" NS_CROP = "http://ns.thealtantic.com/cropduster/1.0/" md5 = hashlib.md5() with open(self.image.filename, mode='rb') as f: md5.update(f.read()) digest = md5.hexdigest() md = original_metadata or libxmp.XMPMeta() md.register_namespace(NS_XMPMM, 'xmpMM') md.register_namespace(NS_MWG_RS, 'mwg-rs') md.register_namespace('http://ns.adobe.com/xap/1.0/sType/Dimensions#', 'stDim') md.register_namespace('http://ns.adobe.com/xmp/sType/Area#', 'stArea') md.register_namespace(NS_CROP, 'crop') md.set_property(NS_CROP, 'crop:size/stDim:w', '%s' % (size.width or '')) md.set_property(NS_CROP, 'crop:size/stDim:h', '%s' % (size.height or '')) md.set_property(NS_CROP, 'crop:size/crop:json', json.dumps(size)) md.set_property(NS_CROP, 'crop:md5', digest.upper()) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions', '', prop_value_is_struct=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions/stDim:w', six.text_type(self.image.size[0])) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions/stDim:h', six.text_type(self.image.size[1])) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList', '', prop_value_is_array=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Name', 'Crop') md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area', '', prop_value_is_struct=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:unit', "normalized") md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:w', "%.5f" % (self.box.w / self.bounds.w)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:h', "%.5f" % (self.box.h / self.bounds.h)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:x', "%.5f" % (self.box.x1 / self.bounds.w)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:y', "%.5f" % (self.box.y1 / self.bounds.h)) return md
def generate_xmp(self, size, original_metadata=None): from cropduster.standalone.metadata import libxmp from cropduster.utils import json NS_MWG_RS = "http://www.metadataworkinggroup.com/schemas/regions/" NS_XMPMM = "http://ns.adobe.com/xap/1.0/mm/" NS_CROP = "http://ns.thealtantic.com/cropduster/1.0/" md5 = hashlib.md5() with default_storage.open(self.image.filename, mode='rb') as f: md5.update(f.read()) digest = md5.hexdigest() md = original_metadata or libxmp.XMPMeta() md.register_namespace(NS_XMPMM, 'xmpMM') md.register_namespace(NS_MWG_RS, 'mwg-rs') md.register_namespace('http://ns.adobe.com/xap/1.0/sType/Dimensions#', 'stDim') md.register_namespace('http://ns.adobe.com/xmp/sType/Area#', 'stArea') md.register_namespace(NS_CROP, 'crop') md.set_property(NS_CROP, 'crop:size/stDim:w', '%s' % (size.width or '')) md.set_property(NS_CROP, 'crop:size/stDim:h', '%s' % (size.height or '')) md.set_property(NS_CROP, 'crop:size/crop:json', json.dumps(size)) md.set_property(NS_CROP, 'crop:md5', digest.upper()) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions', '', prop_value_is_struct=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions/stDim:w', six.text_type(self.image.size[0])) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:AppliedToDimensions/stDim:h', six.text_type(self.image.size[1])) # Clear out any existing <mwg-rs:RegionList> tags so they don't conflict # (for instance, iPhone face regions are stored in this tag) if md.does_property_exist(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList'): md.delete_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList') md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList', '', prop_value_is_array=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Name', 'Crop') md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area', '', prop_value_is_struct=True) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:unit', "normalized") md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:w', "%.5f" % (self.box.w / self.bounds.w)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:h', "%.5f" % (self.box.h / self.bounds.h)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:x', "%.5f" % (self.box.x1 / self.bounds.w)) md.set_property(NS_MWG_RS, 'mwg-rs:Regions/mwg-rs:RegionList[1]/mwg-rs:Area/stArea:y', "%.5f" % (self.box.y1 / self.bounds.h)) return md
def crop(request): if request.method == "GET": return json_error(request, 'crop', action="cropping image", errors=["Form submission invalid"]) crop_form = CropForm(request.POST, request.FILES, prefix='crop') if not crop_form.is_valid(): return json_error(request, 'crop', action='submitting form', forms=[crop_form], log=True, exc_info=full_exc_info()) crop_data = copy.deepcopy(crop_form.cleaned_data) if crop_data.get('image_id'): db_image = Image.objects.get(pk=crop_data['image_id']) else: db_image = Image(image=crop_data['orig_image']) try: with db_image.image as f: f.open() pil_image = PIL.Image.open(BytesIO(f.read())) pil_image.filename = f.name except IOError: pil_image = None FormSet = modelformset_factory(Thumb, form=ThumbForm, formset=ThumbFormSet) thumb_formset = FormSet(request.POST, request.FILES, prefix='thumbs') if not thumb_formset.is_valid(): return json_error(request, 'crop', action='submitting form', formsets=[thumb_formset], log=True, exc_info=full_exc_info()) cropped_thumbs = thumb_formset.save(commit=False) non_model_fields = set(ThumbForm.declared_fields) - set( [f.name for f in Thumb._meta.fields]) # The fields we will pull from when populating the ThumbForm initial data json_thumb_fields = ['id', 'name', 'width', 'height'] thumbs_with_crops = [t for t in cropped_thumbs if t.crop_w and t.crop_h] thumbs_data = [f.cleaned_data for f in thumb_formset] standalone_mode = crop_data['standalone'] # Address a standalone mode issue where, because the thumbs don't have a pk value, # Django no longer returns them in Formset.save() if they are in initial_forms if standalone_mode and not cropped_thumbs and len( thumb_formset.initial_forms): thumb_form = thumb_formset.initial_forms[0] obj = thumb_form.instance cropped_thumbs = [ thumb_formset.save_existing(thumb_form, obj, commit=False) ] for i, (thumb, thumb_form) in enumerate(zip(cropped_thumbs, thumb_formset)): changed_fields = set(thumb_form.changed_data) - non_model_fields thumb_form._changed_data = list(changed_fields) thumb_data = thumbs_data[i] size = thumb_data['size'] if changed_fields & set(['crop_x', 'crop_y', 'crop_w', 'crop_h']): # Clear existing primary key to force new thumb creation thumb.pk = None thumb.width = min(filter(None, [thumb.width, thumb.crop_w])) thumb.height = min(filter(None, [thumb.height, thumb.crop_h])) try: new_thumbs = db_image.save_size(size, thumb, tmp=True, standalone=standalone_mode) except CropDusterResizeException as e: return json_error(request, 'crop', action="saving size", errors=[force_text(e)]) if not new_thumbs: continue if standalone_mode: thumb = new_thumbs new_thumbs = {thumb.name: thumb} cropped_thumbs[i] = thumb = new_thumbs.get(thumb.name, thumb) update_props = [ 'crop_x', 'crop_y', 'crop_w', 'crop_h', 'width', 'height', 'id', 'name' ] for prop in update_props: thumbs_data[i][prop] = getattr(thumb, prop) thumbs_data[i].update({ 'changed': True, 'url': db_image.get_image_url(thumb.name), }) for name, new_thumb in six.iteritems(new_thumbs): thumb_data = dict([(k, getattr(new_thumb, k)) for k in json_thumb_fields]) thumb_data['url'] = db_image.get_image_url( name, tmp=not (new_thumb.image_id)) crop_data['thumbs'].update({name: thumb_data}) if new_thumb.reference_thumb_id: continue thumbs_data[i]['thumbs'].update({name: thumb_data}) elif thumb.pk and thumb.name and thumb.crop_w and thumb.crop_h: thumb_path = db_image.get_image_path(thumb.name, tmp=False) tmp_thumb_path = db_image.get_image_path(thumb.name, tmp=True) if default_storage.exists(thumb_path): if not thumb_form.cleaned_data.get( 'changed') or not default_storage.exists( tmp_thumb_path): with default_storage.open(thumb_path) as f: with default_storage.open(tmp_thumb_path, 'wb') as tmp_file: tmp_file.write(f.read()) if not thumb.pk and not thumb.crop_w and not thumb.crop_h: if not len(thumbs_with_crops): continue best_fit = thumb_form.cleaned_data['size'].fit_to_crop( thumbs_with_crops[0], original_image=pil_image) if best_fit: thumbs_data[i].update({ 'crop_x': best_fit.box.x1, 'crop_y': best_fit.box.y1, 'crop_w': best_fit.box.w, 'crop_h': best_fit.box.h, 'changed': True, 'id': None, }) for thumb_data in thumbs_data: if isinstance(thumb_data['id'], Thumb): thumb_data['id'] = thumb_data['id'].pk preview_url = db_image.get_image_url('_preview') preview_w = PREVIEW_WIDTH preview_h = PREVIEW_HEIGHT orig_width, orig_height = crop_data['orig_w'], crop_data['orig_h'] if (orig_width and orig_height): resize_ratio = min(PREVIEW_WIDTH / float(orig_width), PREVIEW_HEIGHT / float(orig_height)) if resize_ratio < 1: preview_w = int(round(orig_width * resize_ratio)) preview_h = int(round(orig_height * resize_ratio)) return HttpResponse(json.dumps({ 'crop': crop_data, 'thumbs': thumbs_data, 'initial': True, 'preview_url': preview_url, 'preview_w': preview_w, 'preview_h': preview_h }), content_type='application/json')
def upload(request): if request.method == 'GET': return index(request) # The data we'll be returning as JSON data = { 'warning': [], } form = UploadForm(request.POST, request.FILES) if not form.is_valid(): errors = form['image'].errors or form.errors return json_error(request, 'upload', action="uploading file", errors=[force_text(errors)]) form_data = form.cleaned_data is_standalone = bool(form_data.get('standalone')) orig_file_path = form_data['image'].name if six.PY2 and isinstance(orig_file_path, six.text_type): orig_file_path = orig_file_path.encode('utf-8') orig_image = get_relative_media_url(orig_file_path) with default_storage.open(orig_image, mode='rb') as f: img = PIL.Image.open(BytesIO(f.read())) img.filename = f.name (w, h) = (orig_w, orig_h) = img.size if is_animated_gif(img) and not has_animated_gif_support(): data['warning'].append( u"This server does not have animated gif support; your uploaded image " u"has been made static.") tmp_image = Image(image=orig_image) preview_w = form_data.get('preview_width') or PREVIEW_WIDTH preview_h = form_data.get('preview_height') or PREVIEW_HEIGHT # First pass resize if it's too large resize_ratio = min(preview_w / w, preview_h / h) def fit_preview(im): (w, h) = im.size if resize_ratio < 1: w = int(round(w * resize_ratio)) h = int(round(h * resize_ratio)) preview_img = im.resize((w, h), PIL.Image.ANTIALIAS) else: preview_img = im return preview_img if not is_standalone: preview_file_path = tmp_image.get_image_path('_preview') process_image(img, preview_file_path, fit_preview) data.update({ 'crop': { 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'image_id': None, }, 'url': tmp_image.get_image_url('_preview'), 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'width': w, 'height': h, }) if not is_standalone: return HttpResponse(json.dumps(data), content_type='application/json') size = Size('crop', w=img.size[0], h=img.size[1]) md5 = form_data.get('md5') try: standalone_image = StandaloneImage.objects.get(md5=md5) except StandaloneImage.DoesNotExist: standalone_image = StandaloneImage(md5=md5, image=orig_image) standalone_image.save() cropduster_image, created = Image.objects.get_or_create( content_type=ContentType.objects.get_for_model(StandaloneImage), object_id=standalone_image.pk) if not cropduster_image.image: cropduster_image.image = orig_image cropduster_image.save() elif cropduster_image.image.name != orig_image: data['crop']['orig_image'] = data[ 'orig_image'] = cropduster_image.image.name data['url'] = cropduster_image.get_image_url('_preview') with cropduster_image.image as f: f.open() img = PIL.Image.open(BytesIO(f.read())) img.filename = f.name preview_file_path = cropduster_image.get_image_path('_preview') if not default_storage.exists(preview_file_path): process_image(img, preview_file_path, fit_preview) thumb = cropduster_image.save_size(size, standalone=True, commit=False) sizes = form_data.get('sizes') or [] if len(sizes) == 1: size = sizes[0] else: size = Size('crop') data.update({ 'thumbs': [{ 'crop_x': thumb.crop_x, 'crop_y': thumb.crop_y, 'crop_w': thumb.crop_w, 'crop_h': thumb.crop_h, 'width': thumb.width, 'height': thumb.height, 'id': None, 'changed': True, 'size': json.dumps(size), 'name': thumb.name, }] }) data['crop'].update({ 'image_id': cropduster_image.pk, 'sizes': json.dumps([size]), }) return HttpResponse(json.dumps(data), content_type='application/json')
def get(self, *args, **kwargs): orig_image = self.orig_image try: orig_w = getattr(orig_image, 'width', None) or 0 orig_h = getattr(orig_image, 'height', None) or 0 orig_image_name = getattr(orig_image, 'name', None) except Exception: # If original image not found, allow it to be re-uploaded orig_w, orig_h = 0, 0 orig_image_name = None initial = { 'standalone': self.is_standalone, 'sizes': json.dumps(self.sizes), 'thumbs': json.dumps( dict([(t['name'], t) for t in self.thumbs.queryset.values( 'id', 'name', 'width', 'height')])), 'image_id': getattr(self.db_image, 'pk', None) if orig_image else None, 'orig_image': orig_image_name, 'orig_w': orig_w, 'orig_h': orig_h, } FormSet = modelformset_factory(Thumb, form=ThumbForm, formset=ThumbFormSet, extra=0) thumb_formset = FormSet(queryset=self.thumbs, initial=[], prefix='thumbs') size_dict = dict([(s.name, s) for s in self.sizes]) for thumb_form in thumb_formset.initial_forms: name = thumb_form.initial['name'] if name in size_dict: thumb_form.initial['size'] = json.dumps(size_dict[name]) # The thumb being cropped and thumbs referencing it pk = thumb_form.initial['id'] thumb_group = self.thumbs.queryset.filter( Q(pk=pk) | Q(reference_thumb_id__exact=pk)) thumb_group_data = dict([ (t['name'], t) for t in thumb_group.values('id', 'name', 'width', 'height') ]) thumb_form.initial.update({ 'thumbs': json.dumps(thumb_group_data), 'changed': False, }) return render( self.request, 'cropduster/upload.html', { 'django_is_gte_19': (django.VERSION[:2] >= (1, 9)), 'is_popup': True, 'orig_image': '', 'parent_template': get_admin_base_template(), 'image': getattr(self.image_file.preview_image, 'url', u"%scropduster/img/blank.gif" % settings.STATIC_URL), 'standalone': self.is_standalone, 'upload_form': UploadForm( initial={ 'upload_to': self.upload_to, 'sizes': initial['sizes'], 'image_element_id': self.request.GET.get('el_id', ''), 'standalone': self.is_standalone, 'preview_width': self.preview_size[0], 'preview_height': self.preview_size[1], }), 'crop_form': CropForm(initial=initial, prefix='crop'), 'thumb_formset': thumb_formset, })
def crop(request): if request.method == "GET": return json_error(request, 'crop', action="cropping image", errors=["Form submission invalid"]) crop_form = CropForm(request.POST, request.FILES, prefix='crop') if not crop_form.is_valid(): return json_error(request, 'crop', action='submitting form', forms=[crop_form], log=True, exc_info=full_exc_info()) crop_data = copy.deepcopy(crop_form.cleaned_data) db_image = Image(image=crop_data['orig_image']) try: pil_image = PIL.Image.open(db_image.image.path) except IOError: pil_image = None FormSet = modelformset_factory(Thumb, form=ThumbForm, formset=ThumbFormSet) thumb_formset = FormSet(request.POST, request.FILES, prefix='thumbs') if not thumb_formset.is_valid(): return json_error(request, 'crop', action='submitting form', formsets=[thumb_formset], log=True, exc_info=full_exc_info()) cropped_thumbs = thumb_formset.save(commit=False) non_model_fields = set(ThumbForm.declared_fields) - set([f.name for f in Thumb._meta.fields]) # The fields we will pull from when populating the ThumbForm initial data json_thumb_fields = ['id', 'name', 'width', 'height'] thumbs_with_crops = [t for t in cropped_thumbs if t.crop_w and t.crop_h] thumbs_data = [f.cleaned_data for f in thumb_formset] standalone_mode = crop_data['standalone'] # Address a standalone mode issue where, because the thumbs don't have a pk value, # Django no longer returns them in Formset.save() if they are in initial_forms if standalone_mode and not cropped_thumbs and len(thumb_formset.initial_forms): thumb_form = thumb_formset.initial_forms[0] obj = thumb_form.instance cropped_thumbs = [thumb_formset.save_existing(thumb_form, obj, commit=False)] for i, (thumb, thumb_form) in enumerate(zip(cropped_thumbs, thumb_formset)): changed_fields = set(thumb_form.changed_data) - non_model_fields thumb_form._changed_data = list(changed_fields) thumb_data = thumbs_data[i] size = thumb_data['size'] if changed_fields & set(['crop_x', 'crop_y', 'crop_w', 'crop_h']): # Clear existing primary key to force new thumb creation thumb.pk = None thumb.width = min(filter(None, [thumb.width, thumb.crop_w])) thumb.height = min(filter(None, [thumb.height, thumb.crop_h])) try: new_thumbs = db_image.save_size(size, thumb, tmp=True, standalone=standalone_mode) except CropDusterResizeException as e: return json_error(request, 'crop', action="saving size", errors=[force_text(e)]) if not new_thumbs: continue if standalone_mode: thumb = new_thumbs new_thumbs = {thumb.name: thumb} cropped_thumbs[i] = thumb = new_thumbs.get(thumb.name, thumb) update_props = ['crop_x', 'crop_y', 'crop_w', 'crop_h', 'width', 'height', 'id', 'name'] for prop in update_props: thumbs_data[i][prop] = getattr(thumb, prop) thumbs_data[i].update({ 'changed': True, 'url': db_image.get_image_url(thumb.name), }) for name, new_thumb in six.iteritems(new_thumbs): thumb_data = dict([(k, getattr(new_thumb, k)) for k in json_thumb_fields]) crop_data['thumbs'].update({name: thumb_data}) if new_thumb.reference_thumb_id: continue thumbs_data[i]['thumbs'].update({name: thumb_data}) elif thumb.pk and thumb.name and thumb.crop_w and thumb.crop_h: thumb_path = db_image.get_image_path(thumb.name, tmp=False) tmp_thumb_path = db_image.get_image_path(thumb.name, tmp=True) if os.path.exists(thumb_path): if not thumb_form.cleaned_data.get('changed') or not os.path.exists(tmp_thumb_path): shutil.copy(thumb_path, tmp_thumb_path) if not thumb.pk and not thumb.crop_w and not thumb.crop_h: if not len(thumbs_with_crops): continue best_fit = thumb_form.cleaned_data['size'].fit_to_crop( thumbs_with_crops[0], original_image=pil_image) if best_fit: thumbs_data[i].update({ 'crop_x': best_fit.box.x1, 'crop_y': best_fit.box.y1, 'crop_w': best_fit.box.w, 'crop_h': best_fit.box.h, 'changed': True, 'id': None, }) for thumb_data in thumbs_data: if isinstance(thumb_data['id'], Thumb): thumb_data['id'] = thumb_data['id'].pk return HttpResponse(json.dumps({ 'crop': crop_data, 'thumbs': thumbs_data, 'initial': True, }), content_type='application/json')
def upload(request): if request.method == 'GET': return index(request) # The data we'll be returning as JSON data = { 'warning': [], } form = UploadForm(request.POST, request.FILES) if not form.is_valid(): errors = form['image'].errors or form.errors return json_error(request, 'upload', action="uploading file", errors=[force_text(errors)]) form_data = form.cleaned_data is_standalone = bool(form_data.get('standalone')) orig_file_path = form_data['image'].name if six.PY2 and isinstance(orig_file_path, unicode): orig_file_path = orig_file_path.encode('utf-8') orig_image = get_relative_media_url(orig_file_path) img = PIL.Image.open(orig_file_path) (w, h) = (orig_w, orig_h) = img.size if is_animated_gif(img) and not has_animated_gif_support(): data['warning'].append( u"This server does not have animated gif support; your uploaded image " u"has been made static.") tmp_image = Image(image=orig_image) preview_w = form_data.get('preview_width') or PREVIEW_WIDTH preview_h = form_data.get('preview_height') or PREVIEW_HEIGHT # First pass resize if it's too large resize_ratio = min(preview_w / w, preview_h / h) def fit_preview(im): (w, h) = im.size if resize_ratio < 1: w = int(round(w * resize_ratio)) h = int(round(h * resize_ratio)) preview_img = im.resize((w, h), PIL.Image.ANTIALIAS) else: preview_img = im return preview_img if not is_standalone: preview_file_path = tmp_image.get_image_path('_preview') process_image(img, preview_file_path, fit_preview) data.update({ 'crop': { 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'image_id': None, }, 'url': tmp_image.get_image_url('_preview'), 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'width': w, 'height': h, }) if not is_standalone: return HttpResponse(json.dumps(data), content_type='application/json') size = Size('crop', w=img.size[0], h=img.size[1]) md5 = form_data.get('md5') try: standalone_image = StandaloneImage.objects.get(md5=md5) except StandaloneImage.DoesNotExist: standalone_image = StandaloneImage(md5=md5, image=orig_image) standalone_image.save() cropduster_image, created = Image.objects.get_or_create( content_type=ContentType.objects.get_for_model(StandaloneImage), object_id=standalone_image.pk) if not cropduster_image.image: cropduster_image.image = orig_image cropduster_image.save() elif cropduster_image.image.name != orig_image: data['crop']['orig_image'] = data['orig_image'] = cropduster_image.image.name data['url'] = cropduster_image.get_image_url('_preview') img = PIL.Image.open(cropduster_image.image.path) preview_file_path = cropduster_image.get_image_path('_preview') if not os.path.exists(preview_file_path): process_image(img, preview_file_path, fit_preview) thumb = cropduster_image.save_size(size, standalone=True) sizes = form_data.get('sizes') or [] if len(sizes) == 1: size = sizes[0] else: size = Size('crop') data.update({ 'thumbs': [{ 'crop_x': thumb.crop_x, 'crop_y': thumb.crop_y, 'crop_w': thumb.crop_w, 'crop_h': thumb.crop_h, 'width': thumb.width, 'height': thumb.height, 'id': None, 'changed': True, 'size': json.dumps(size), 'name': thumb.name, }] }) data['crop'].update({ 'image_id': cropduster_image.pk, 'sizes': json.dumps([size]), }) return HttpResponse(json.dumps(data), content_type='application/json')