def __bobo_traverse__(self, REQUEST, name): """ helper to access image scales the old way during `unrestrictedTraverse` calls """ if name.startswith('image_capa'): field = self.getField('image_capa') image = None if name == 'image_capa': image = field.getScale(self) else: scalename = name[len('image_capa_'):] if scalename in field.getAvailableSizes(self): image = field.getScale(self, scale=scalename) if image is not None and not isinstance(image, basestring): # image might be None or '' for empty images return image if isinstance(REQUEST, dict): if '_' in name: fieldname, scale = name.split('_', 1) else: fieldname, scale = name, None field = self.getField(fieldname) handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(self, scale) if image is not None: return image return super(ATBlob, self).__bobo_traverse__(REQUEST, name)
def save_cropped(self, fieldname, scale, image_file): """ see interface """ field = self.get_image_field(fieldname) handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction="keep", **parameters): blob = Blob() result = blob.open("w") _, image_format, dimensions = scaleImage(data["data"], result=result, **parameters) result.close() return blob, image_format, dimensions # Avoid browser cache # calling reindexObject updates the modified metadate too self.context.reindexObject() # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, _millis) storage.scale(factory=crop_factory, fieldname=field.__name__, width=w, height=h)
def get_image_url(context, size='large'): # Look at the imaging view request = getattr(context, 'REQUEST', None) if request is not None: image_view = getMultiAdapter((context, request), name='images') # compatibility with collective.contentleadimage image_url = None for image_name in ['image', 'leadImage']: try: scale_attr = size and [size] or [] image = image_view.traverse(image_name, scale_attr) if image: # This returns an image tag, pull the src attribute image_url = ET.fromstring(image).attrib['src'] except (AttributeError, TraversalError): if IImageContent.providedBy(context): image = context.getImage() if image: image_url = image.absolute_url() if hasattr(context, 'getField'): field = context.getField('image') handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(context, size) if image: image_url = image.absolute_url() return image_url
def publishTraverse(self, request, name): """ Patched traverse method for plone.app.imaging.traverse.ImageTraverser """ lang = None lang_before, lang_set = None, 0 image = None schema = self.context.Schema() fieldname, scale = name, None if '___' in name: fieldname, lang, scalename = name.split('___') if scalename: scale = scalename[1:] elif '_' in name: fieldname, scale = name.split('_', 1) field = schema.get(fieldname) if lang is not None: lang_before, lang_set = field._v_lang, 1 field.setLanguage(lang) try: handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(self.context, scale) finally: if lang_set: field.setLanguage(lang_before) if image is not None: return image return self.fallback(request, name)
def save_cropped( self, fieldname, field, scale, image_file, interface=None): """ see interface """ handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale( self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage( data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, self.now_millis) storage.scale( factory=crop_factory, fieldname=field.__name__, width=w, height=h)
def _crop(self, fieldname, scale, box, interface=None): """interface just useful to locate field on dexterity types """ # https://github.com/plone/plone.app.imaging/blob/ggozad-cropping/src/ # plone/app/imaging/cropping.py field = self.context.getField(fieldname) if hasattr(field,'getHandler'): handler = field.getHandler() else: handler = IImageScaleHandler(field) # TODO this is archetype only value = field.get(self.context) data = getattr(aq_base(value), 'data', value) if isinstance(data, Pdata): data = str(data) original_file = StringIO(data) image = PIL.Image.open(original_file) image_format = image.format or self.DEFAULT_FORMAT cropped_image = image.crop(box) cropped_image_file = StringIO() cropped_image.save(cropped_image_file, image_format, quality=100) cropped_image_file.seek(0) sizes = field.getAvailableSizes(self.context) #regular scale if len(sizes[scale]) ==3: w, h, s = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=cropped_image_file.read()) else: w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=cropped_image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage(data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, self.now_millis) storage.scale(factory=crop_factory, fieldname=fieldname, width=w, height=h) # store crop information in annotations self._store(fieldname, scale, box)
def getScale(self, instance, scale=None, **kwargs): """ get scale by name or original """ if scale is None: return self.getUnwrapped(instance, **kwargs) handler = IImageScaleHandler(self, None) if handler is not None: return handler.getScale(instance, scale) return None
def getSize(self, instance, scale=None): """ get size of scale or original """ if scale is None: return self.getUnwrapped(instance).getSize() handler = IImageScaleHandler(self, None) if handler is not None: image = handler.getScale(instance, scale) if image is not None: return image.width, image.height return 0, 0
def createScales(self, instance, value=None): """ creates scales and stores them; largely based on the version from `Archetypes.Field.ImageField` """ sizes = self.getAvailableSizes(instance) handler = IImageScaleHandler(self) for name, size in sizes.items(): width, height = size data = handler.createScale(instance, name, width, height, data=value) if data is not None: handler.storeScale(instance, name, **data)
def patched_getScale(self, instance, scale=None, **kwargs): if scale is None: return self.getUnwrapped(instance, **kwargs) handler = IImageScaleHandler(self, None) if handler is not None: try: return handler.getScale(instance, scale) except POSKeyError: pass return None
def __blob__bobo_traverse__(self, REQUEST, name): """ helper to access multilanguage image scales the old way during `unrestrictedTraverse` calls the method to be patched is '__bobo_traverse__' """ field = self.getField(name.split('_')[0]) if not IMultilanguageField.providedBy(field) or not hasattr(REQUEST, 'get'): return BaseObject.__bobo_traverse__(self, REQUEST, name) last = REQUEST.get('ACTUAL_URL', '').endswith(name) fieldname, scale = name, None if '___' in name: fieldname, lang, scalename = name.split('___') if scalename: scale = scalename[1:] else: if '_' in name: fieldname, scale = name.split('_', 1) if last and REQUEST.get('HTTP_USER_AGENT', False): _scale = scale if _scale is not None: _scale = '_'+str(_scale) else: _scale = '' REQUEST.RESPONSE.redirect(self.absolute_url()+'/'+fieldname+'___'+field._getCurrentLanguage(self)+'___'+_scale) lang = field._getCurrentLanguage(self) lang_before = field._v_lang try: field.setLanguage(lang) handler = IImageScaleHandler(field, None) image = None if handler is not None: try: image = handler.getScale(self, scale) except AttributeError: # no image available, do not raise as there might be one available as a fallback pass if not image: # language fallback defaultLang = field.getDefaultLang(self) if defaultLang and not defaultLang == lang: field.setLanguage(defaultLang) if handler is not None: image = handler.getScale(self, scale) if image is not None: if last and REQUEST.get('HTTP_USER_AGENT', False): _scale = scale if _scale is not None: _scale = '_'+str(_scale) else: _scale = '' REQUEST.RESPONSE.redirect(self.absolute_url()+'/'+fieldname+'___'+defaultLang+'___'+_scale) finally: field.setLanguage(lang_before) if image is not None: return image return BaseObject.__bobo_traverse__(self, REQUEST, name)
def publishTraverse(self, request, name): schema = self.context.Schema() if "_" in name: fieldname, scale = name.split("_", 1) else: fieldname, scale = name, None field = schema.get(fieldname) handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(self.context, scale) if image is not None: return image return self.fallback(request, name)
def patched_getScale(self, instance, scale=None, **kwargs): """ Patch for getScale """ if scale is None: return self.getUnwrapped(instance, **kwargs) handler = IImageScaleHandler(self, None) if handler is not None: try: return handler.getScale(instance, scale) except POSKeyError: logger.error("BLOBWARNING: Could not get " "scale %r for %r", scale, instance) return None
def publishTraverse(self, request, name): schema = self.context.Schema() if '_' in name and name not in schema.keys(): fieldname, scale = name.rsplit('_', 1) else: fieldname, scale = name, None field = schema.get(fieldname) handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(self.context, scale) if image is not None: return image return self.fallback(request, name)
def __bobo_traverse__(self, REQUEST, name): """ helper to access image scales the old way during `unrestrictedTraverse` calls """ if isinstance(REQUEST, dict): if '_' in name: fieldname, scale = name.split('_', 1) else: fieldname, scale = name, None field = self.getField(fieldname) handler = IImageScaleHandler(field, None) if handler is not None: image = handler.getScale(self, scale) if image is not None: return image return super(ATBlob, self).__bobo_traverse__(REQUEST, name)
def save_cropped(self, fieldname, scale, image_file): """ see interface """ field = self.get_image_field(fieldname) handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage(data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # Avoid browser cache # calling reindexObject updates the modified metadate too self.context.reindexObject() # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, _millis) storage.scale(factory=crop_factory, fieldname=field.__name__, width=w, height=h)