Example #1
0
class CancelImageEditAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)

    name = _(u"Cancel")
    description = _(u"Cancel the current edit.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/process-stop.png"

    def on_setup(self):
        return """

function cancel_reload(data){
    var btn = $('#cancel-button');

    if(data.can_save){
        btn[0].disabled = false;
        btn.removeClass('disabled');
    }else{
        btn[0].disabled = true;
        btn.addClass('disabled');
    }
}
on('after_image_reload').accomplish(cancel_reload);
cancel_reload(IMAGE_INFORMATION);
        """

    def __call__(self, *args, **kwargs):
        self.editor.clear_edits()
Example #2
0
class UndoAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Undo")
    description = _(u"Go back to the previous change.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/edit-undo.png"

    def on_setup(self):
        return """
function undo_reload(data){
    var btn = $('#undo-button');

    if(data.can_undo){
        btn[0].disabled = false;
        btn.removeClass('disabled');
    }else{
        btn[0].disabled = true;
        btn.addClass('disabled');
    }
}

on('after_image_reload').accomplish(undo_reload);
undo_reload(IMAGE_INFORMATION);
        """

    def __call__(self, *args, **kwargs):
        self.editor.undo()
Example #3
0
class FlipOnHorizontalAxisAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Flip Horizontally")
    description = _(u"Flip the image on the horizontal axis.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/stock-tool-flip-16.png"

    def __call__(self, *args, **kwargs):
        original = self.editor.get_current_image()
        image = original.transpose(Image.FLIP_LEFT_RIGHT)

        self.editor.set_image(image, original.format)
Example #4
0
class FlipOnVerticalAxisAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Flip Vertical")
    description = _(u"Flip the image on vertically.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/stock-tool-rotate-16.png"

    def __call__(self, *args, **kwargs):
        original = self.editor.get_current_image()
        image = original.transpose(Image.FLIP_TOP_BOTTOM)

        self.editor.set_image(image, original.format)
Example #5
0
class RotateRightAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Rotate Right")
    description = _(u"Rotate the image right.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/stock-rotate-90-16.png"

    def __call__(self, *args, **kwargs):
        original = self.editor.get_current_image()
        image = original.rotate(270)

        self.editor.set_image(image, original.format)
Example #6
0
class SharpenAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(ISharpenOptions)
    options['amount'].custom_widget = SliderWidget
    name = _(u"Sharpen")
    description = _(u"Sharpen the image.")
    icon = u"++resource++imageeditor/icons/stock-tool-colorize-16.png"

    def __call__(self, amount, *args, **kwargs):
        image = self.editor.get_current_image()
        enhancer = ImageEnhance.Sharpness(image)
        newImage = enhancer.enhance(int(amount))

        self.editor.set_image(newImage, image.format)
Example #7
0
class ContrastAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(IContrastOptions)
    options['amount'].custom_widget = SliderWidget
    name = _(u"Contrast")
    description = _(u"Change the contrast of the image.")
    icon = u"++resource++imageeditor/icons/stock-tool-contrast-16.png"

    def __call__(self, amount, *args, **kwargs):
        image = self.editor.get_current_image()
        enhancer = ImageEnhance.Contrast(image)
        newImage = enhancer.enhance((float(amount) / 100) * 2.0)

        self.editor.set_image(newImage, image.format)
Example #8
0
class BrightnessAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(IBrightnessOptions)
    options['amount'].custom_widget = SliderWidget
    name = _(u"Brightness")
    description = _(u"Change the brightness of the image.")
    icon = u"++resource++imageeditor/icons/stock-tool-brightness-16.png"

    def __call__(self, amount, *args, **kwargs):
        image = self.editor.get_current_image()
        enhancer = ImageEnhance.Brightness(image)
        #can enhance from 0.0-2.0, 1.0 being original image
        newImage = enhancer.enhance((float(amount) / 100) * 2.0)

        self.editor.set_image(newImage, image.format)
Example #9
0
class BlurAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(IBlurOptions)
    options['amount'].custom_widget = SliderWidget
    name = _(u"Blur")
    description = _(u"Blur this image.")
    icon = u"++resource++imageeditor/icons/stock-tool-blur-16.png"

    def __call__(self, amount, *args, **kwargs):
        image = self.editor.get_current_image()
        fmt = image.format
        for x in range(0, int(amount)):
            image = image.filter(ImageFilter.BLUR)

        self.editor.set_image(image, fmt)
Example #10
0
class CompressAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(ICompressOptions)
    options['amount'].custom_widget = SliderWidget
    name = _(u"Compress")
    description = _(u"Compress this image to make it lower quality.")
    icon = u"++resource++imageeditor/icons/stock-template-16.png"

    def __call__(self, amount, *args, **kwargs):
        # if it is a png, convert it...
        image = self.editor.get_current_image().convert('RGB')
        try:
            self.editor.set_image(image, quality=float(amount))
        except TypeError:  # Pillow 2.2 will raise ValueError instead
            self.editor.set_image(image, quality=int(amount))
Example #11
0
class DropShadowAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(IDropShadowOptions)
    name = _(u"Drop Shadow")
    description = _(u"Adds a drop shadow to the image.")
    icon = u"++resource++imageeditor/icons/stock-transparency-16.png"

    def __call__(self, offset_x, offset_y, background_color, shadow_color,
                       border, iterations, *args, **kwargs):
        # convert to png if it isn't--shadow won't work without this.
        image = self.editor.get_current_image().convert('RGB')
        offset = (int(offset_x), int(offset_y))
        # precaution in case code is attempted to be injected
        background = eval("0x" + background_color[:6])
        # precaution in case code is attempted to be injected
        shadow = eval("0x" + shadow_color[:6])
        border = int(border)
        iterations = int(iterations)

        # Create the backdrop image -- a box in the background colour with a
        # shadow on it.
        totalWidth = image.size[0] + abs(offset[0]) + 2 * border
        totalHeight = image.size[1] + abs(offset[1]) + 2 * border
        back = Image.new(image.mode, (totalWidth, totalHeight), background)

        # Place the shadow, taking into account the offset from the image
        shadowLeft = border + max(offset[0], 0)
        shadowTop = border + max(offset[1], 0)
        back.paste(
            shadow,
            [shadowLeft, shadowTop,
             shadowLeft + image.size[0], shadowTop + image.size[1]]
        )

        # Apply the filter to blur the edges of the shadow. Since a small
        # kernel is used, the filter must be applied repeatedly to get a
        # decent blur.
        for n in range(0, iterations):
            back = back.filter(ImageFilter.BLUR)

        # Paste the input image onto the shadow backdrop
        imageLeft = border - min(offset[0], 0)
        imageTop = border - min(offset[1], 0)
        back.paste(image, (imageLeft, imageTop))

        self.editor.set_image(back)
Example #12
0
class SaveAsImageEditAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(ISaveAsOptions)

    name = _(u"Save As")
    description = _(u"Save the edited image as another content item.")
    icon = None

    def on_setup(self):
        return """
function redirect(data){
    if(data.previous_action == 'save-as'){
        window.location = data.new_type_location;
    }
}
on('after_image_reload').accomplish(redirect);
"""

    def __call__(self, type_to_save_as="Image", title=None,
                                                    *args, **kwargs):
        """
        create the new type, pass along the url to the client and then
        the javascript will redirect the browser
        """
        if not title:
            title = self.editor.context.Title()

        parent = self.editor.context.getParentNode()
        new_id = orig_id = queryUtility(IURLNormalizer).normalize(title)

        count = 1
        while new_id in parent.objectIds():
            new_id = orig_id + "-" + str(count)
            count += count

        parent.invokeFactory(
            type_to_save_as,
            new_id,
            title=title,
            image=self.editor.get_current_image_data()
        )

        return {
            'new_type_location': parent.absolute_url() + "/" + new_id + "/edit"
        }
Example #13
0
class SepiaAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(ISepiaOptions)
    options['red'].custom_widget = SliderWidget
    options['green'].custom_widget = SliderWidget
    options['blue'].custom_widget = SliderWidget

    name = _(u"Sepia")
    description = _(u"Applies the sepia effect to the image.")
    icon = None

    def make_linear_ramp(self, white):
        # putpalette expects [r,g,b,r,g,b,...]
        ramp = []
        r, g, b = white
        for i in range(255):
            ramp.extend((r * i / 255, g * i / 255, b * i / 255))
        return ramp

    def __call__(self, red, green, blue, *args, **kwargs):
        """
        found at http://effbot.org/zone/pil-sepia.htm
        """
        sepia = self.make_linear_ramp((int(red), int(green), int(blue)))
        image = self.editor.get_current_image()

        # convert to grayscale
        if image.mode != "L":
            image = image.convert("L")

        # optional: apply contrast enhancement here, e.g.
        image = ImageOps.autocontrast(image)

        # apply sepia palette
        image.putpalette(sepia)

        # convert back to RGB so we can save it as JPEG
        # (alternatively, save it in PNG or similar)
        image = image.convert("RGB")
        self.editor.set_image(image)
Example #14
0
class SaveImageEditAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)

    name = _(u"Save")
    description = _(u"Save the edited image.")
    skip_apply = True
    icon = u"++resource++imageeditor/icons/apply.png"

    def on_setup(self):
        return """
function save_reload(data){
    var btn = $('#save-button');

    if(data.can_save){
        btn[0].disabled = false;
        btn.removeClass('disabled');
    }else{
        btn[0].disabled = true;
        btn.addClass('disabled');
    }
}
on('after_image_reload').accomplish(save_reload);
save_reload(IMAGE_INFORMATION);
        """

    def __call__(self, *args, **kwargs):
        portal_repository = getToolByName(
            self.editor.context, 'portal_repository')
        if portal_repository.isVersionable(self.editor.context):
            portal_repository.save(
                self.editor.context, comment="saved from image editor")

        self.editor.save_edit()

        self.editor.context.reindexObject()  # stop image caching on browser
Example #15
0
    def get_options(self):
        html = ''
        for name, action in self.actions:
            html += '<div class="image-edit-action" id="%s-options">' % name
            widgets = form.setUpInputWidgets(
                action.options,
                name,
                self.context,
                self.request,
                ignore_request=True
            )

            for widget in widgets:
                html += """
<div class="edit-option">
    <label class="formQuestion" for="%s.%s">%s</label>
    <div class="formHelp">%s</div>
    %s
</div>
                """ % (
                    name,
                    widget.name,
                    widget.context.title.default,
                    widget.context.description.default,
                    widget()
                )

            if not action.skip_apply:
                html += """
<input type="button" id="%(name)s-apply-button"
       class="image-edit-apply-button" name="%(name)s"
       value="Apply"
/>
                """ % {'name': _(name)}

            html += '</div>'

        return html
Example #16
0
class CropAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Crop")
    description = _(u"Crop the image.")
    icon = u"++resource++imageeditor/icons/stock-selection-intersect-16.png"

    def on_setup(self):
        return """
function add_crop(){
    var w = $('#source-image').width(), h = $('#source-image').height();
    start_selection = {
        x1: w/4,
        y1: h/4,
        x2: w-w/4,
        y2: h-h/4
    };
    window.crop_selection = start_selection;

    function create_cropper(ratio){
        var options = {
            onSelectChange: function(image, selection){
                window.crop_selection = selection;
            },
            enable: true,
            border: 2,
            handles: true,
            show: true,
            parent: '#image-container',
            x1 : start_selection.x1,
            y1 : start_selection.y1,
            x2 : start_selection.x2,
            y2 : start_selection.y2
        }
        if(ratio != null){
            options.aspectRatio = ratio;
        }
        $('#source-image').imgAreaSelect(options);
    }
    create_cropper(null);

    $("#aspect-ratio-selector").dialog({
        position : 'right',
        title : "Aspect Ratio",
        autoOpen:true,
        resizable:false,
        modal: false,
        draggable: true,
        width:200,
        buttons: {
            "Manual" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true, hide: true});
                create_cropper(null);
            },
            "3:2" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true, hide: true});
                create_cropper("3:2");
            },
            "4:3" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true,hide: true});
                create_cropper("4:3");
            },
            "16:9" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true,hide: true});
                create_cropper("16:9");
            },
            "5:4" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true,hide: true});
                create_cropper("5:4");
            },
            "1:1" : function(){
                $('#source-image').imgAreaSelect({enable: false, remove: true,hide: true});
                create_cropper("1:1");
            }
        }
    });
}

function remove_crop(){
    $('#source-image').imgAreaSelect({ enable: false, remove: true, hide: true });
    try{
        $("#aspect-ratio-selector").dialog('destroy');
    }catch(e){
        //nothing
    }
}

on('action_button_clicked').accomplish(function(btn){

if($(btn).attr('id') == "crop-button"){
    add_crop();
}else{
    remove_crop();
}

});

on('before_image_reload').accomplish(function(){
    remove_crop();
});

on('before_image_zoom_change').accomplish(function(params){
    var active_btn = $('input.edit-button.active');
    if(active_btn.attr('id') == 'crop-button'){
        remove_crop();
    }
});
on('after_image_zoom_change').accomplish(function(params){
    var active_btn = $('input.edit-button.active');
    if(active_btn.attr('id') == 'crop-button'){
        add_crop();
    }
});
        """

    def action_parameters(self):
        return """(function(){
    var cs = {};
    var zoom = parseFloat(jQuery("#zoom-slider-value").attr('value'));
    cs['crop.x1'] = window.crop_selection.x1/zoom;
    cs['crop.x2'] = window.crop_selection.x2/zoom;
    cs['crop.y1'] = window.crop_selection.y1/zoom;
    cs['crop.y2'] = window.crop_selection.y2/zoom;
    return cs;
})"""

    def __call__(self, x1, y1, x2, y2, *args, **kwargs):
        image = self.editor.get_current_image()
        box = (int(float(x1)), int(float(y1)), int(float(x2)), int(float(y2)))
        new_image = image.crop(box=box)
        new_image.load()

        self.editor.set_image(new_image, image.format)
Example #17
0
from Products.ImageEditor import imageeditor_message_factory as _

Apply = _(u'Apply')
Example #18
0
class ResizeAction(BaseImageEditorAction):
    implements(IImageEditorAction)

    options = form.FormFields(INoOptions)
    name = _(u"Resize")
    description = _(u"Resize the image..")
    icon = u"++resource++imageeditor/icons/stock-resize-16.png"

    def on_setup(self):
        return """
function add_resize(){
    $('#image-container')[0].scrollTop = 5000;
    $('#image-container')[0].scrollLeft = 5000;

    function create_resizable(){
        var opts = {
            handles: 'all',
            resize: function(e, ui){
                //nothing
            }
        };
        var ar = $('#resize-ar');
        if(ar[0].checked){
            opts['aspectRatio'] =
                IMAGE_INFORMATION.width/IMAGE_INFORMATION.height;
        }
        $('#source-image').resizable(opts);
    }
    create_resizable();

    $('#resize-to-fields').dialog({
        autoOpen:true,
        resizable:false,
        modal: false,
        draggable: true,
        title: "Manual Resize",
        zindex: 999999,
        position: 'right',
        buttons: {
            Resize: function() {
                $('#source-image').resizable('destroy');
                var width = $('#resize-width').val();
                var height = $('#resize-height').val();
                if(isNaN(width) || isNaN(height)){
                    alert("You must enter a number for the width and height.");
                }else{
                    var zoom = parseFloat(
                        jQuery("#zoom-slider-value").attr('value'));
                    $('#source-image').width(
                        Math.floor(parseInt(width)*zoom) + "px");
                    $('#source-image').height(
                        Math.floor(parseInt(height)*zoom) + "px");
                }
                create_resizable();
            },
            Close: function() {
                $(this).dialog('close');
            }
        }
    });
    $('#resize-ar').change(function(){
        remove_resize();
        add_resize();
    });
}
function remove_resize(){
    try{
        $('#source-image').resizable('destroy');
    }catch(e){
        //nothing
    }
    try{
        $('#resize-to-fields').dialog('destroy');
    }catch(e){
        //nothing
    }
}
on('action_button_clicked').accomplish(function(btn){

if($(btn).attr('id') == "resize-button"){
    add_resize();
}else{
    remove_resize();
}

});

on('before_image_reload').accomplish(function(){
    remove_resize();
});

on('before_image_zoom_change').accomplish(function(params){
    var active_btn = $('input.edit-button.active');
    if(active_btn.attr('id') == 'resize-button'){
        remove_resize();
    }
});
on('after_image_zoom_change').accomplish(function(params){
    var active_btn = $('input.edit-button.active');
    if(active_btn.attr('id') == 'resize-button'){
        add_resize();
    }
});
            """

    def action_parameters(self):
        return """(function(){
    var res = {};
    var zoom = parseFloat(jQuery("#zoom-slider-value").attr('value'));
    res['resize.width'] = jQuery('#source-image').width()/zoom;
    res['resize.height'] = jQuery('#source-image').height()/zoom;
    return res;
})"""

    def __call__(self, width, height, *args, **kwargs):
        image = self.editor.get_current_image()
        size = (int(float(width)), int(float(height)))
        new_image = image.resize(size, Image.ANTIALIAS)
        self.editor.set_image(new_image, image.format)