class Action(models.Action): """Defined variables: <filename> <type> <folder> <width> <height>""" label = _t('Write Tag') author = 'Stani' email = '*****@*****.**' version = '0.1' tags = [_t('metadata')] __doc__ = _t('Write new value to a tag') def interface(self, fields): fields[_t('Tag (Exif, Iptc)')] = self.ExifItpcField( 'Exif_Image_Copyright', choices=self.EXIF_IPTC) fields[_t('Value')] = self.CharField('Phatch') def apply(self, photo, setting, cache): info = photo.info tag = self.get_field('Tag (Exif, Iptc)', info) value = self.get_field('Value', info).strip() if value == '': value = None info[tag] = value return photo icon = \ 'x\xda\x01\xda\x0c%\xf3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def interface(self, action, fields): mapping_choices = (_t('Wrap Both'), _t('Separate')) fields[_t('Cover Color')] = action.ColorField('#FFFFFF') fields[_t('Page Mapping')] = action.ChoiceField(mapping_choices[0], choices=mapping_choices) fields[_t('Left Page')] = action.EmptyFileField(' ')
class Action(models.Action): label = _t('Convert Mode') author = 'Stani' email = '*****@*****.**' version = '0.1' init = staticmethod(init) tags = [_t('color')] __doc__ = _t('Convert the color mode of an image') def interface(self, fields): fields[_t('Mode')] = self.ImageModeField(self.IMAGE_MODES[4]) def apply(self, photo, setting, cache): #get info info = photo.info #get file values mode = self.get_field('Mode', info) if mode == 'P': photo.convert(mode, palette=Image.ADAPTIVE) else: photo.convert(mode) return photo icon = \ 'x\xda\x01B\x0c\xbd\xf3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def interface(self, fields): fields[_t('Text')] = self.CharField(choices=self.STAMPS) fields[_t('Font')] = self.FontFileField('Free Sans') fields[_t('Size')] = self.PixelField('5%', choices=self.SMALL_PIXELS) fields[_t('Color')] = self.ColorField('#000000') super(Action, self).interface(fields)
class Action(models.OffsetMixin, models.Action): """Draws text on an image.""" label = _t('Text') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(draw_text) version = '0.1' tags = [_t('default'), _t('filter')] __doc__ = _t('Write text at a given position') def interface(self, fields): fields[_t('Text')] = self.CharField(choices=self.STAMPS) fields[_t('Font')] = self.FontFileField('Free Sans') fields[_t('Size')] = self.PixelField('5%', choices=self.SMALL_PIXELS) fields[_t('Color')] = self.ColorField('#000000') super(Action, self).interface(fields) def get_relevant_field_labels(self): return ['Text', 'Font', 'Size', 'Color'] + \ super(Action, self).get_relevant_field_labels() def values(self, info, pixel_fields={}): x, y = info['size'] pixel_fields.update({'Size': (x + y) / 2}) return super(Action, self).values(info, pixel_fields=pixel_fields) icon = \ 'x\xda\x01\xcc\x043\xfb\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): """""" label = _t('Transpose') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(transpose) version = '0.1' tags = [_t('default'), _t('transform')] __doc__ = _t('Flip or rotate 90 degrees') def interface(self, fields): fields[_t('Method')] = self.ImageTransposeField('Orientation') fields[_t('Amount')] = self.SliderField(100, 1, 100) def apply(self, photo, setting, cache): #get info info = photo.info #dpi method = self.get_field('Method', info) #special case turn to its orientation if method == 'ORIENTATION': photo._exif_transposition_reverse = () info['orientation'] = 1 else: amount = self.get_field('Amount', info) layer = photo.get_layer() layer.image = transpose(layer.image, method, amount) return photo icon = \ 'x\xda\x01`\t\x9f\xf6\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def interface(self, fields): fields[_t('Command')] = \ self.CommandLineField(choices=COMMANDS) fields[_t('Verify Program')] = self.BooleanField(True) fields[_t('Verify Input')] = self.BooleanField(True) fields[_t('Verify Output')] = self.BooleanField(True) fields[_t('Allow as last action')] = self.BooleanField(False)
class Action(models.Action): label = _t('Color to Alpha') author = 'Nadia Alramli' email = '*****@*****.**' cache = False init = staticmethod(init) pil = staticmethod(color_to_alpha) version = '0.1' tags = [_t('color')] __doc__ = _t('Make selected color transparent') def get_relevant_field_labels(self): """If this method is present, Phatch will only show relevant fields. :returns: list of the field labels which are relevant :rtype: list of strings .. note:: It is very important that the list of labels has EXACTLY the same order as defined in the interface method. """ relevant = ['Select Color By'] if self.get_field_string('Select Color By') == OPTIONS[0]: relevant.append('Color Value') return relevant def interface(self, fields): fields[_t('Select Color By')] = self.ChoiceField(OPTIONS[0], choices=OPTIONS) fields[_t('Color Value')] = self.ColorField('#FFFFFF') icon = \ 'x\xda\x01o\x0c\x90\xf3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.LosslessSaveMixin, models.Action): """Defined variables: <filename> <type> <folder> <width> <height>""" label = _t('Save Tags') author = 'Stani' email = '*****@*****.**' version = '0.1' tags = [_t('file'), _t('metadata')] __doc__ = _t('Save only metadata (lossless)') def apply(self, photo, setting, cache): info = photo.info filename = self.get_lossless_filename(photo, info) #do it if info['path'] != filename: shutil.copy2(info['path'], filename) info.save(filename) if photo.modify_date: # Update file access and modification date os.utime(filename, (photo.modify_date, photo.modify_date)) photo.append_to_report(filename) return photo icon = \ 'x\xda\x01\xc7\x108\xef\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Contour') author = 'Nadia Alramli' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(put_contour) version = '0.1' tags = [_t('filter')] __doc__ = _t('Draw a contour around image edges') def interface(self, fields): fields[_t('Size')] = self.PixelField('1px', choices=['1', '2', '5']) fields[_t('Offset')] = self.PixelField('0px', choices=['0', '1', '2']) fields[_t('Contour Color')] = self.ColorField('#000000') fields[_t('Fill Color')] = self.ColorField('#FFFFFF') fields[_t('Opacity')] = self.SliderField(100, 0, 100) fields[_t('Include image')] = self.BooleanField(True) def values(self, info): #pixel fields x0, y0 = info['size'] dim = (x0 + y0) / 2 return super(Action, self).values(info, pixel_fields={ 'Size': dim, 'Offset': dim }) icon = \ 'x\xda\x01\x19\n\xe6\xf5\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Offset') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(offset) version = '0.1' tags = [_t('transform'), _t('filter')] __doc__ = _t('Offset by distance and wrap around') def interface(self, fields): fields[_t('Horizontal Offset')] = self.PixelField('50%', choices=self.PIXELS) fields[_t('Vertical Offset')] = self.PixelField('50%', choices=self.PIXELS) def values(self, info): #pixel fields x, y = info['size'] return super(Action, self).values(info, pixel_fields={ 'Horizontal Offset': x, 'Vertical Offset': y }) icon = \ 'x\xda\x01\xf5\x05\n\xfa\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Rename Tag') author = 'Juho Vepsäläinen' email = '*****@*****.**' version = '0.1' tags = [_t('metadata')] __doc__ = _t('Rename a tag') def interface(self, fields): fields[_t('From (Exif, Iptc)')] = self.ExifItpcField( 'Exif_Image_ImageDescription', choices=self.EXIF_IPTC) fields[_t('To (Exif, Iptc)')] = self.ExifItpcField( 'Exif_Image_ImageDescription', choices=self.EXIF_IPTC) def apply(self, photo, setting, cache): info = photo.info old_name = self.get_field('From (Exif, Iptc)', info).strip() new_name = self.get_field('To (Exif, Iptc)', info).strip() if not (new_name and old_name): return photo if old_name in info and old_name != new_name: info[new_name] = info[old_name] del info[old_name] return photo #FIXME: replace this icon with another one (Nadia?) icon = \ 'x\xda\x01j\x0c\x95\xf3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class CropMixin(object): crop_modes = (_t('All'), _t('Auto'), _t('Custom'), ) _choices = ('0', '1', '2', '5', '10', '20', ) def interface(self, fields, action=None): if action is None: action = self fields[_t('Mode')] = action.ChoiceField(self.crop_modes[0], choices=self.crop_modes) fields[_t('All')] = action.PixelField('30%', # works with jpegtran choices=self._choices) fields[_t('Left')] = action.PixelField('0px', choices=self._choices) fields[_t('Right')] = action.PixelField('0px', choices=self._choices) fields[_t('Top')] = action.PixelField('0px', choices=self._choices) fields[_t('Bottom')] = action.PixelField('0px', choices=self._choices) def get_relevant_field_labels(self, action=None): """If this method is present, Phatch will only show relevant fields. :returns: list of the field labels which are relevant :rtype: list of strings .. note:: It is very important that the list of labels has EXACTLY the same order as defined in the interface method. """ if action is None: action = self relevant = ['Mode'] if action.get_field_string('Mode') == 'All': relevant.extend(['All']) elif action.get_field_string('Mode') == 'Custom': relevant.extend(['Top', 'Left', 'Bottom', 'Right']) return relevant def values(self, info, pixel_fields=None, exclude=None, action=None): if action is None: action = self if pixel_fields is None: pixel_fields = {} # pixel fields width, height = info['size'] pixel_fields.update({ 'All': (width + height) / 2, 'Left': width, 'Right': width, 'Top': height, 'Bottom': height, }) # pass absolute reference for relative pixel values such as % # do NOT use super here or lossless jpegtran will fail return Action.values(action, info, pixel_fields, exclude)
class Action(models.Action): label = _t('Label') author = 'Author' email = '*****@*****.**' init = init version = '0.1' tags = [_t('tag')] __doc__ = _t('Description') def interface(self, fields): fields[_t('Boolean')] = self.BooleanField(True) fields[_t('String')] = self.CharField('hello world') fields[_t('Choice')] = self.ChoiceField(CHOICES[0], CHOICES) fields[_t('Color')] = self.ColorField('#FFFFFF') fields[_t('Resolution')] = self.DpiField('<dpi>') fields[_t('File')] = self.FileField('/home/images/logo.jpg') fields[_t('File Name')] = self.FileNameField('<filename>') fields[_t('In')] = self.FolderField('<folder>') # folder fields[_t('Float')] = self.FloatField(3.14) fields[_t('As')] = self.ImageTypeField('<type>') # png, jpg fields[_t('As')] = self.ImageReadTypeField('<type>') # png, jpg fields[_t('As')] = self.ImageWriteTypeField('<type>') # png, jpg fields[_t('Mode')] = self.ImageModeField('<mode>') # png, jpg fields[_t('Resample')] = self.ImageResampleField(_t('bicubic')) fields[_t('Integer')] = self.IntegerField(-4) fields[_t('Integer+')] = self.PositiveIntegerField(0) fields[_t('Integer+0')] = self.PositiveNoneZeroIntegerField(0) fields[_t('Horizontal')] = self.PixelField('5%') # accepts %, cm, inch fields[_t('Slider')] = self.SliderField(60, 1, 100) def apply(self, photo, setting, cache): # get info (always get this) info = photo.info # in case you use PixelField you can get width, height & dpi ... # ... from photo (use new_*) width, height = info['size'] dpi = info['dpi'] # ... or from user input (see actions/image_size.py) dpi = self.get_field('Resolution', info) horizontal = self.get_field_size('Horizontal Offset', info, width, dpi) # collect parameters parameters = { 'dpi': dpi, 'horizontal': horizontal, } # return manipulated photo photo.apply_pil(foo, **parameters) return photo # icon: 48x48pixels icon = 'ART_TIP'
def create_phatch_inspect_nautilus_action(): create_nautilus_extension( name="phatch_image_inspector", label='_("%s") + "..."' % _t("Inspect with Phatch"), command="phatch -n %s &", mimetypes=IMAGE_READ_MIMETYPES, tooltip='_("%s")' % _t("Inspect EXIF & IPTC tags"), preload=PRELOAD, )
def interface(self, fields): fields[_t('Text')] = self.CharField( choices=self.STAMPS) fields[_t('Font')] = self.FontFileField('Free Sans') fields[_t('Size')] = self.PixelField('5%', choices=self.SMALL_PIXELS) fields[_t('Color')] = self.ColorField('#000000') super(Action, self).interface(fields)
class Action(models.Action): label = _t('Tamogen') author = 'Juho Vepsäläinen' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(mosaic) version = '0.1' tags = [_t('filter')] __doc__ = _t('Tone altering mosaic generator') def interface(self, fields): fields[_t('Fill Type')] = self.ChoiceField(FILL_TYPES[0], choices=FILL_TYPES) fields[_t('Fill Image')] = self.ReadFileField('<path>') fields[_t('Fill Folder')] = self.FolderField('<folder>/<subfolder>', choices=self.FOLDERS) fields[_t('Rows')] = self.PositiveNonZeroIntegerField(10) fields[_t('Columns')] = self.PositiveNonZeroIntegerField(10) fields[_t('Canvas Width')] = self.PixelField('100%', choices=self.PIXELS) fields[_t('Canvas Height')] = self.PixelField('100%', choices=self.PIXELS) def values(self, info): #pixel fields width, height = info['size'] # pass absolute reference for relative pixel values such as % return super(Action, self).values(info, pixel_fields={ 'Canvas Width': width, 'Canvas Height': height }) def get_relevant_field_labels(self): relevant = [ 'Fill Type', ] action = self.get_field_string('Fill Type') if action == OTHER_IMAGE: relevant.append('Fill Image') elif action == FOLDER: relevant.append('Fill Folder') relevant.extend([ 'Rows', 'Columns', 'Canvas Width', 'Canvas Height', ]) return relevant icon = \ 'x\xda\x01\x98\x15g\xea\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def crop(image, mode=None, all=0, left=0, right=0, top=0, bottom=0): if mode == _t('Auto'): image = auto_crop(image) elif mode == _t('All'): image = ImageOps.crop(image, border=all) else: w, h = image.size box = (left, top, w - right, h - bottom) image = image.crop(box) return image
def create_phatch_inspect_nautilus_action(): create_nautilus_extension( name='phatch_image_inspector', label='_("%s") + "..."' % \ _t('Inspect with Phatch'), command='phatch -n %s &', mimetypes=IMAGE_READ_MIMETYPES, tooltip='_("%s")' % _t('Inspect EXIF & IPTC tags'), preload=PRELOAD, )
def interface(self, fields): fields[_t('Render Width')] = self.PixelField('800px') fields[_t('Render Height')] = self.PixelField('600px') fields[_t('Object')] = self.BlenderObjectField('Box') fields[_t('Image Size')] = self.ChoiceField(SIZE_CHOICES[0], choices=SIZE_CHOICES) self._objects.interface(self, fields) self._camera.interface(self, fields) self._background.interface(self, fields) self._floor.interface(self, fields)
def interface(self, action, fields): # Juho: space hacks. get rid of those with ids later fields[_t('Transformation ')] = action.ChoiceField( self.transformations[1], choices=self.transformations) fields[_t('Copy')] = action.ChoiceField(self.copy_choices[1], choices=self.copy_choices) fields[_t('Angle ')] = action.ChoiceField(ROTATE_AMOUNTS[0], choices=ROTATE_AMOUNTS) fields[_t('Direction ')] = action.ChoiceField(FLIP_DIRECTIONS[0], choices=FLIP_DIRECTIONS) super(Jpegtran, self).interface(fields, action)
class Action(models.Action): """Resize an image""" label = _t('Scale') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) version = '0.1' tags = [_t('default'), _t('transform'), _t('size')] __doc__ = _t('Make the image smaller or bigger') def interface(self, fields): fields[_t('Canvas Width')] = self.PixelField('800px', choices=self.PIXELS_X) fields[_t('Canvas Height')] = self.PixelField('800px', choices=self.PIXELS_Y) fields[_t('Resolution')] = self.DpiField(choices=self.DPIS) fields[_t('Constrain Proportions')] = self.BooleanField(True) fields[_t('Resample Image')] = self.ImageResampleAutoField('automatic') fields[_t('Scale Down Only')] = self.BooleanField(False) def apply(self, photo, setting, cache): #get info info = photo.info #dpi dpi = info['dpi'] = self.get_field('Resolution', info) #size x0, y0 = info['size'] x1 = self.get_field_size('Canvas Width', info, x0, dpi) y1 = self.get_field_size('Canvas Height', info, y0, dpi) #check if image size has changed scaleDownOnly = self.get_field('Scale Down Only', info) # check if image size has changed if (x0 != x1 or y0 != y1) and \ (not scaleDownOnly or (scaleDownOnly and (x1 < x0 or y1 < y0))): proportions = self.get_field('Constrain Proportions', info) method = self.get_field('Resample Image', info) #calculate proportions if proportions: x1, y1 = preserve_proportions(x0, y0, x1, y1) #in case of automatic choose antialias for smaller #and bicubic for bigger if method == 'AUTOMATIC': if x1 < x0 and y1 < y0: method = 'ANTIALIAS' else: method = 'BICUBIC' method = getattr(Image, method) #resize image photo.resize((x1, y1), method) return photo icon = \ 'x\xda\x01(\x0e\xd7\xf1\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): """Drops a reflection""" label = _t('Reflection') author = 'Stani' email = '*****@*****.**' cache = True init = staticmethod(init) pil = staticmethod(reflect) version = '0.1' tags = [_t('filter')] __doc__ = _t('Drops a reflection') def interface(self, fields): fields[_t('Depth')] = self.PixelField('10%', choices=self.PIXELS[:-1]) fields[_t('Gap')] = self.PixelField('0', choices=['0', '1', '2', '5']) fields[_t('Opacity')] = self.SliderField(60, 0, 100) fields[_t('Blur Reflection')] = self.BooleanField(False) fields[_t('Scale Reflection')] = self.BooleanField(False) fields[_t('Scale Method')] = self.ImageResampleField('antialias') fields[_t('Background Color')] = self.ColorField('#FFFFFF') fields[_t('Background Opacity')] = self.SliderField(90, 0, 100) def get_relevant_field_labels(self): """If this method is present, Phatch will only show relevant fields. :returns: list of the field labels which are relevant :rtype: list of strings .. note:: It is very important that the list of labels has EXACTLY the same order as defined in the interface method. """ relevant = [ 'Depth', 'Gap', 'Opacity', 'Blur Reflection', 'Scale Reflection' ] if self.get_field_string('Scale Reflection') in ('yes', 'true'): relevant.append('Scale Method') relevant.extend(['Background Color', 'Background Opacity']) return relevant def values(self, info): #pixel fields y = info['height'] return super(Action, self).values(info, pixel_fields={ 'Depth': y, 'Gap': y }) icon = \ 'x\xda\x01y\n\x86\xf5\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): """Resize an image""" label = _t('Fit') author = 'Stani' all_layers = True email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(fit) version = '0.1' tags = [_t('transform'), _t('size')] __doc__ = _t('Downsize and crop image with fixed ratio') def interface(self, fields): fields[_t('Canvas Width')] = self.PixelField('<min(width,height)>', choices=self.PIXELS_X) fields[_t('Canvas Height')] = self.PixelField('<min(width,height)>', choices=self.PIXELS_Y) fields[_t('Resolution')] = self.DpiField(choices=self.DPIS) fields[_t('Align Horizontal')] = self.SliderField(50, 0, 100) fields[_t('Align Vertical')] = self.SliderField(50, 0, 100) fields[_t('Bleed')] = self.SliderField(0, 0, 100) fields[_t('Resample Image')] = self.ImageResampleAutoField('automatic') def values(self, info): #dpi dpi = info['dpi'] = self.get_field('Resolution', info) #size x0, y0 = info['size'] x1 = self.get_field_size('Canvas Width', info, x0, dpi) y1 = self.get_field_size('Canvas Height', info, y0, dpi) new_size = (x1, y1) #method method = self.get_field('Resample Image', info) if method == 'AUTOMATIC': if x1 < x0 and y1 < y0: method = 'ANTIALIAS' else: method = 'BICUBIC' method = getattr(Image, method) #centering align_hor = self.get_field('Align Horizontal', info) / 100.0 align_ver = self.get_field('Align Vertical', info) / 100.0 #parameters return { 'size': new_size, 'method': method, 'centering': (align_hor, align_ver), 'bleed': self.get_field('Bleed', info) / 100.0, } icon = \ 'x\xda\x01(\x0e\xd7\xf1\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.CropMixin, models.Action): label = _t('Crop') author = 'Nadia Alramli' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(crop) version = '0.1' tags = [_t('transform'), _t('size')] __doc__ = _t('Crop the image') icon = \ 'x\xda\x01\x0f\t\xf0\xf6\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Border') author = 'Erich' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(border) version = '0.2' tags = [_t('filter')] __doc__ = _t('Draw border inside or outside') def interface(self, fields): fields[_t('Method')] = self.ChoiceField(OPTIONS[0], choices=OPTIONS) fields[_t('Border Width')] = self.PixelField('1px', choices=CHOICES) fields[_t('Left')] = self.PixelField('0px', choices=CHOICES) fields[_t('Right')] = self.PixelField('0px', choices=CHOICES) fields[_t('Top')] = self.PixelField('0px', choices=CHOICES) fields[_t('Bottom')] = self.PixelField('0px', choices=CHOICES) fields[_t('Color')] = self.ColorField('#000000') fields[_t('Opacity')] = self.SliderField(100, 1, 100) def values(self, info): #pixel fields width, height = info['size'] # pass absolute reference for relative pixel values such as % return super(Action, self).values(info, pixel_fields={ 'Border Width': (width + height) / 2, 'Left': width, 'Right': width, 'Top': height, 'Bottom': height, }) def get_relevant_field_labels(self): """If this method is present, Phatch will only show relevant fields. :returns: list of the field labels which are relevant :rtype: list of strings .. note:: It is very important that the list of labels has EXACTLY the same order as defined in the interface method. """ relevant = ['Method', 'Color', 'Opacity'] if self.get_field_string('Method') == OPTIONS[0]: relevant.append('Border Width') else: relevant.extend(['Left', 'Right', 'Top', 'Bottom']) return relevant icon = \ 'x\xda\x01x\x0b\x87\xf4\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def crop(image, mode=None, all=0, left=0, right=0, top=0, bottom=0): if mode == _t('Auto'): image = auto_crop(image) elif mode == _t('All'): image = ImageOps.crop(image, border=all) else: w, h = image.size box = ( left, top, w - right, h - bottom) image = image.crop(box) return image
class Action(models.StampMixin, models.Action): """Apply a watermark with tiling, scaling and opacity""" label = _t('Watermark') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(watermark) version = '0.1' tags = [_t('default'), _t('filter')] __doc__ = _t('Apply with tiling, scaling and opacity') icon = \ 'x\xda\x01\x95\nj\xf5\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): """Defined variables: <filename> <type> <folder> <width> <height>""" label = _t('Geotag') author = 'Robin Mills' email = '*****@*****.**' version = '0.1' tags = [_t('metadata')] init = staticmethod(init) __doc__ = _t('Add gps data') metadata = ['Exif_Image_DateTime'] def interface(self, fields): fields[_t('GPS Data (gpx)')] = self.GeoReadFileField(' ') fields[_t('GPS Report (csv)')] = self.CsvFileField(' ') fields[_t('Time Shift (seconds)')] = self.IntegerField( 0, choices=[-60, 0, 60]) def apply(self, photo, setting, cache): #get info info = photo.info # get timeshift # construct timedict if necessary if not ('gps_timedict' in cache): cache['gps_timeshift'] = \ self.get_field('Time Shift (seconds)', info) gpx_file = self.get_field('GPS Data (gpx)', info) csv_file = self.get_field('GPS Report (csv)', info).strip() if csv_file: csv_file = open(csv_file, 'w') gps.write_header(csv_file) cache['gps_report'] = csv_file cache['gps_timedict'] = gps.read_gpx(gpx_file) # get the geoTags gps_data = gps.get_metadata(info['Exif_Image_DateTime'], cache['gps_timedict'], cache['gps_timeshift'], info['path'], cache['gps_report']) # do not use update as info does not support it for key, value in gps_data.items(): info[key.replace('.', '_')] = value # writable return photo icon = \ 'x\xda\x01\xaa\x0eU\xf1\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class LabelFileCtrl(FileCtrl): _label = _t('Selection') _all_files = _t('All files') def GetWildcard(self): if self._extensions: if len(self._extensions) < 5: label = '%s (%s)' % (self._label, ','.join(self._extensions)) else: label = self._label menu = [wildcard_list(self._to_local(label), self._extensions)] else: menu = [] menu.append(self._all_files + '|*') return '|'.join(menu)
class Action(models.Action): label = _t('Saturation') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(saturation) version = '0.1' tags = [_t('color')] __doc__ = _t('Adjust saturation from grayscale to high') def interface(self, fields): fields[_t('Amount')] = self.SliderField(-100, -100, 100) icon = \ 'x\xda\x01\xe1\r\x1e\xf2\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Brightness') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(brightness) version = '0.1' tags = [_t('color')] __doc__ = _t('Adjust brightness from black to white') def interface(self, fields): fields[_t('Amount')] = self.SliderField(50, -100, 100) icon = \ 'x\xda\x01p\x0b\x8f\xf4\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
class Action(models.Action): label = _t('Invert') author = 'Stani' email = '*****@*****.**' init = staticmethod(init) pil = staticmethod(invert) version = '0.1' tags = [_t('color')] __doc__ = _t('Invert the colors of an image') def interface(self, fields): fields[_t('Amount')] = self.SliderField(100, 1, 100) icon = \ 'x\xda\x01\x91\nn\xf5\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\
def interface(self, fields): super(UtilityMixin, self).interface(fields) names = self.utilities.keys() fields[_t('Utility')] = self.ChoiceField(names[0], choices=names) for utility in self.utilities.values(): utility.interface(self, fields)
def interface(self, fields): fields[_t('Change')] = self.ChoiceField(OPTIONS[2], choices=OPTIONS) fields[_t('Use exif datetime')] = self.BooleanField(True) fields[_t('Seconds')] = self.IntegerField(0) fields[_t('Minutes')] = self.IntegerField(0) fields[_t('Hours')] = self.IntegerField(0) fields[_t('Days')] = self.IntegerField(0) fields[_t('Months')] = self.IntegerField(0) fields[_t('Years')] = self.IntegerField(0)
def interface(self, fields): fields[_t('Method')] = self.ChoiceField(OPTIONS[0], choices=OPTIONS) fields[_t('Border Width')] = self.PixelField('1px', choices=CHOICES) fields[_t('Left')] = self.PixelField('0px', choices=CHOICES) fields[_t('Right')] = self.PixelField('0px', choices=CHOICES) fields[_t('Top')] = self.PixelField('0px', choices=CHOICES) fields[_t('Bottom')] = self.PixelField('0px', choices=CHOICES) fields[_t('Color')] = self.ColorField('#000000') fields[_t('Opacity')] = self.SliderField(100, 1, 100)
def interface(self, fields): fields[_t('Radius')] = self.PixelField('2%', choices=self.SMALL_PIXELS) fields[_t('Same Method for All Corners')] = self.BooleanField(True) fields[_t('Method')] = self.ChoiceField(CORNERS[0], CORNERS) fields[_t('Top Left Corner')] = self.ChoiceField(CORNERS[0], CORNERS) fields[_t('Top Right Corner')] = self.ChoiceField(CORNERS[0], CORNERS) fields[_t('Bottom Left Corner')] = self.ChoiceField( CORNERS[0], CORNERS) fields[_t('Bottom Right Corner')] = self.ChoiceField( CORNERS[0], CORNERS) fields[_t('Background Color')] = self.ColorField('#FFFFFF') fields[_t('Opacity')] = self.SliderField(100, 1, 100)
def create_phatch_recent_nautilus_action(): create_nautilus_extension( name="phatch_recent", label='_("%s") + "..."' % _t("Process with recent Phatch action list"), command="phatch -d recent %s &", mimetypes=IMAGE_READ_MIMETYPES, tooltip=TOOLTIP, preload=PRELOAD, )
def interface(self, fields): fields[_t('Depth')] = self.PixelField('10%', choices=self.PIXELS[:-1]) fields[_t('Gap')] = self.PixelField('0', choices=['0', '1', '2', '5']) fields[_t('Opacity')] = self.SliderField(60, 0, 100) fields[_t('Blur Reflection')] = self.BooleanField(False) fields[_t('Scale Reflection')] = self.BooleanField(False) fields[_t('Scale Method')] = self.ImageResampleField('antialias') fields[_t('Background Color')] = self.ColorField('#FFFFFF') fields[_t('Background Opacity')] = self.SliderField(90, 0, 100)
def interface(self, fields): fields[_t("Canvas Width")] = self.PixelField("<max(width, height)> px", choices=self.PIXELS_X) fields[_t("Canvas Height")] = self.PixelField("<max(width, height)> px", choices=self.PIXELS_Y) fields[_t("Resolution")] = self.DpiField(choices=self.DPIS) fields[_t("Align Horizontal")] = self.SliderField(50, 0, 100) fields[_t("Align Vertical")] = self.SliderField(50, 0, 100) fields[_t("Background Color")] = self.ColorField("#FFFFFF") fields[_t("Opacity")] = self.SliderField(0, 0, 100)
def interface(self, action, fields): fields[_t('Transformation')] = action.ChoiceField( self.transformations[0], choices=self.transformations) fields[_t('Angle')] = action.ChoiceField(ROTATE_AMOUNTS[0], choices=ROTATE_AMOUNTS) fields[_t('Direction')] = action.ChoiceField(FLIP_DIRECTIONS[0], choices=FLIP_DIRECTIONS) fields[_t('Preserve Timestamp')] = action.BooleanField(True) fields[_t('Show Advanced Options')] = action.BooleanField(False) fields[_t('Update JPEG')] = action.BooleanField(True) fields[_t('Update Exif Thumbnail')] = action.BooleanField(True) fields[_t('Update Orientation Tag')] = action.BooleanField(True)
def create_phatch_nautilus_action(actionlist): name = os.path.splitext(os.path.basename(actionlist))[0] title = system.title(name) create_nautilus_extension( name="phatch_actionlist_" + name.encode("ascii", "ignore"), label='_("%s") + "..."' % _t("Phatch with %s") % title, command='phatch -d "%s" %%s &' % actionlist, mimetypes=IMAGE_READ_MIMETYPES, tooltip=TOOLTIP, preload=PRELOAD, )
def interface(self, fields): fields[_t('Canvas Width')] = self.PixelField( '<max(width, height)> px', choices=self.PIXELS_X) fields[_t('Canvas Height')] = self.PixelField( '<max(width, height)> px', choices=self.PIXELS_Y) fields[_t('Resolution')] = self.DpiField(choices=self.DPIS) fields[_t('Align Horizontal')] = self.SliderField(50, 0, 100) fields[_t('Align Vertical')] = self.SliderField(50, 0, 100) fields[_t('Background Color')] = self.ColorField('#FFFFFF') fields[_t('Opacity')] = self.SliderField(0, 0, 100)
def interface(self, fields): fields[_t('Canvas Width')] = self.PixelField('<min(width,height)>', choices=self.PIXELS_X) fields[_t('Canvas Height')] = self.PixelField('<min(width,height)>', choices=self.PIXELS_Y) fields[_t('Resolution')] = self.DpiField(choices=self.DPIS) fields[_t('Align Horizontal')] = self.SliderField(50, 0, 100) fields[_t('Align Vertical')] = self.SliderField(50, 0, 100) fields[_t('Bleed')] = self.SliderField(0, 0, 100) fields[_t('Resample Image')] = self.ImageResampleAutoField('automatic')
def interface(self, fields): fields[_t('Size')] = self.PixelField('1px', choices=['1', '2', '5']) fields[_t('Offset')] = self.PixelField('0px', choices=['0', '1', '2']) fields[_t('Contour Color')] = self.ColorField('#000000') fields[_t('Fill Color')] = self.ColorField('#FFFFFF') fields[_t('Opacity')] = self.SliderField(100, 0, 100) fields[_t('Include image')] = self.BooleanField(True)
def interface(self, fields): fields[_t('Angle')] = self.SliderField(45, 1, 360) fields[_t('Resample Image')] = self.ImageFilterField('bicubic') fields[_t('Expand')] = self.BooleanField(False) fields[_t('Amount')] = self.SliderField(100, 1, 100) fields[_t('Background Color')] = self.ColorField('#000000') fields[_t('Background Opacity')] = self.SliderField(0, 0, 100)
def __init__(self, info, info_to_dump=None): self.modify_date = None # for time shift action self.report_files = [] # for reports self._exif_transposition_reverse = None #layer path = info['path'] name = self.current_layer_name = _t('background') layer = Layer(path, load=True) self.layers = {name: layer} #info self.info = InfoPhoto(info, info_to_dump, self.get_flattened_image, layer.image) self.rotate_exif()
def interface(self, fields): fields[_t('Horizontal Offset')] = self.PixelField('2%', choices=self.SMALL_PIXELS) fields[_t('Vertical Offset')] = self.PixelField('2%', choices=self.SMALL_PIXELS) fields[_t('Border')] = self.PixelField('4%', choices=[str(int(x) * 2) for x in self.SMALL_PIXELS]) fields[_t('Shadow Blur')] = self.SliderField(3, 1, 20) fields[_t('Background Color')] = self.ColorField('#FFFFFF') fields[_t('Shadow Color')] = self.ColorField('#444444') fields[_t('Force Background Color')] = self.BooleanField(True)
def get_date(info): return datetime( year=info[_t('year')], month=info[_t('month')], day=info[_t('day')], hour=info[_t('hour')], minute=info[_t('minute')], second=info[_t('second')])
def interface(self, fields): fields[_t('Fill Type')] = self.ChoiceField( FILL_TYPES[0], choices=FILL_TYPES) fields[_t('Fill Image')] = self.ReadFileField('<path>') fields[_t('Fill Folder')] = self.FolderField( '<folder>/<subfolder>', choices=self.FOLDERS) fields[_t('Rows')] = self.PositiveNonZeroIntegerField(10) fields[_t('Columns')] = self.PositiveNonZeroIntegerField(10) fields[_t('Canvas Width')] = self.PixelField('100%', choices=self.PIXELS) fields[_t('Canvas Height')] = self.PixelField('100%', choices=self.PIXELS)
def interface(self, action, fields): fields[_t('Camera')] = action.BlenderRotationField('Hori -30 Vert 0') fields[_t('Camera Horizontal Rotation')] = \ action.SliderField(30, -180, 180) fields[_t('Camera Vertical Rotation')] = action.SliderField(0, 0, 90) fields[_t('Camera Roll')] = action.SliderField(0, -90, 90) fields[_t('Camera Lens Angle')] = action.SliderField(51, 8, 172) # TODO: provide bigger range for distance with 0.5 or 0.25 steps? fields[_t('Camera Distance')] = action.SliderField(2, 0, 10)
def interface(self, fields): fields[_t('Canvas Width')] = self.PixelField('800px', choices=self.PIXELS_X) fields[_t('Canvas Height')] = self.PixelField('800px', choices=self.PIXELS_Y) fields[_t('Resolution')] = self.DpiField(choices=self.DPIS) fields[_t('Constrain Proportions')] = self.BooleanField(True) fields[_t('Resample Image')] = self.ImageResampleAutoField('automatic') fields[_t('Scale Down Only')] = self.BooleanField(False)
def interface(self, fields): fields[_t('Text')] = self.CharField( choices=self.STAMPS) fields[_t('Font')] = self.FontFileField('Free Sans') fields[_t('Size')] = self.PixelField('5%', choices=self.SMALL_PIXELS) fields[_t('Color')] = self.ColorField('#000000') fields[_t('Opacity')] = self.SliderField(255,0, 255) fields[_t('Hallo')] = self.BooleanField(False) #opacity = int((self.get_field('Opacity') / 100.0) * 255) super(Action, self).interface(fields)
def interface(self, fields): fields[_t('Orientation')] = \ self.OrientationField(self.ORIENTATION[0]) fields[_t('Position')] = self.ChoiceField(self.POSITION[0], self.POSITION) fields[_t('Offset')] = self.PixelField('5%', choices=self.OFFSET_PIXELS) fields[_t('Horizontal Offset')] = self.PixelField('50%', choices=self.OFFSET_PIXELS) fields[_t('Vertical Offset')] = self.PixelField('50%', choices=self.OFFSET_PIXELS) fields[_t('Horizontal Justification')] = self.ChoiceField( self.HORIZONTAL_JUSTIFICATION[1], \ self.HORIZONTAL_JUSTIFICATION) fields[_t('Vertical Justification')] = self.ChoiceField( self.VERTICAL_JUSTIFICATION[1], self.VERTICAL_JUSTIFICATION)
def interface(self, fields, action=None): if action is None: action = self fields[_t('Mode')] = action.ChoiceField(self.crop_modes[0], choices=self.crop_modes) fields[_t('All')] = action.PixelField('30%', # works with jpegtran choices=self._choices) fields[_t('Left')] = action.PixelField('0px', choices=self._choices) fields[_t('Right')] = action.PixelField('0px', choices=self._choices) fields[_t('Top')] = action.PixelField('0px', choices=self._choices) fields[_t('Bottom')] = action.PixelField('0px', choices=self._choices)
def interface(self, fields): fields[_t('Tag (Exif, Iptc)')] = self.ExifItpcField( 'Exif_Image_Copyright', choices=self.EXIF_IPTC) fields[_t('Value')] = self.CharField('Phatch')