#
# Dragan effect
# http://andrzejdragan.com/
#
# based on Sharon Lee Core's photoshop action
# http://www.atncentral.com/download.htm
# http://www.pbase.com/photofixer/draganizer_action
#
#
# tested with Gimp 2.4.5
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

from gimpfu import *

import pygtk
pygtk.require("2.0")
import gtk

def messBox(message, type, modal):
    if modal == 0:
      flag = gtk.DIALOG_DESTROY_WITH_PARENT
    else:
      flag = gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT
    msgBox = gtk.MessageDialog(None, flag, type, gtk.BUTTONS_OK, message)
    ret = msgBox.run()
    msgBox.destroy()

def smartSharpen_xy(InImage, InLayer):
    
  HSVimage = pdb.plug_in_decompose(InImage, InLayer, "Value", 1)[0] 
  V_layer = HSVimage.active_layer
  
  SharpenLayer = InLayer.copy(False)
  InImage.add_layer(SharpenLayer, -1)
  pdb.gimp_layer_set_mode(SharpenLayer, VALUE_MODE)
  pdb.gimp_edit_copy(V_layer)
  pdb.gimp_floating_sel_anchor(pdb.gimp_edit_paste(SharpenLayer, True))
  pdb.gimp_image_delete(HSVimage)
  
  mask = SharpenLayer.create_mask(ADD_BLACK_MASK)
  pdb.gimp_layer_add_mask(SharpenLayer, mask)
  
  LABimage = pdb.plug_in_decompose(InImage, InLayer, "LAB", 1)[0]
  L_layer = filter(lambda l: "L" in l.name, LABimage.layers)[0]
  
  pdb.gimp_levels_stretch(L_layer)
  pdb.plug_in_edge(LABimage, L_layer, 2.0, 0, 5, run_mode = 0)
  pdb.plug_in_gauss(LABimage, L_layer, 5.0, 5.0, 0, run_mode = 0)
  
  pdb.gimp_edit_copy(L_layer)
  pdb.gimp_floating_sel_anchor(pdb.gimp_edit_paste(mask, True))
  pdb.gimp_layer_set_edit_mask(SharpenLayer, False)
  
  pdb.gimp_image_delete(LABimage)
  
  pdb.plug_in_unsharp_mask(InImage, SharpenLayer, 1.0, 2.0, 0, run_mode = 0)
  SharpenLayer.opacity = 80.0
  messBox("""Make sure you're happy with the sharpening because we need to merge down the layers
Color > levels on the mask, painting some unwanted parts, perharps blur it a bit again ...

Then click OK in this box when ready to continue""", gtk.MESSAGE_INFO, 0)
  mergedlayer = pdb.gimp_image_merge_down(InImage, SharpenLayer, CLIP_TO_IMAGE)
  pdb.gimp_drawable_set_name(mergedlayer, "Sharp")
  return mergedlayer

def lazydraganEffect_xy(img, drawable):

    img.undo_group_start()
    origfgcolor = gimp.get_foreground()
    width = img.width
    height = img.height
    name = pdb.gimp_image_get_name(img)
    
    dup_image = pdb.gimp_image_duplicate(img)
    display = pdb.gimp_display_new(dup_image)
    dup_image.undo_group_start()
    dup_image.flatten()
    if not dup_image.base_type == RGB:
      pdb.gimp_image_convert_rgb(dup_image)
    dup_drawable = pdb.gimp_image_get_active_drawable(dup_image)
    
    messBox("""In the next dialogs, apply strong sharpening with smart Unsharp Mask (edges sharpening)""", gtk.MESSAGE_INFO, 1)
    dup_drawable = smartSharpen_xy(dup_image, dup_drawable)
    
    # saturation layer
    HSVimage = pdb.plug_in_decompose(dup_image, dup_drawable, "Saturation", 1)[0] 
    S_layer = HSVimage.active_layer
    saturationLayer= dup_drawable.copy()
    dup_image.add_layer(saturationLayer, -1)
    pdb.gimp_edit_copy(S_layer)
    pdb.gimp_floating_sel_anchor(pdb.gimp_edit_paste(saturationLayer, True))
    saturationLayer.mode = SATURATION_MODE
    pdb.gimp_image_delete(HSVimage)
    pdb.gimp_hue_saturation(saturationLayer, ALL_HUES, 0, 0, -50)
    pdb.gimp_layer_set_opacity(saturationLayer, 50.0)
    pdb.gimp_drawable_set_name(saturationLayer, "deSaturationAdj")
    
    # temp layer for mask
    tempLayer = dup_drawable.copy()
    dup_image.add_layer(tempLayer, -1)
    pdb.gimp_desaturate(tempLayer)
    pdb.gimp_levels_stretch(tempLayer)
    # copy invert layer in dodge_mode
    layer_copy = pdb.gimp_layer_copy(tempLayer, False)
    dup_image.add_layer(layer_copy, -1)
    pdb.gimp_invert(layer_copy)
    layer_copy.mode = DODGE_MODE
    messBox("""In the next dialog, adjust Gaussian blur for good black detail sketch.""", gtk.MESSAGE_INFO, 1)
    pdb.plug_in_gauss(dup_image, layer_copy, 5.0, 5.0, 0, run_mode = 0)
    # merge down
    templayer = pdb.gimp_image_merge_down(dup_image, layer_copy, CLIP_TO_IMAGE)
    # + layer in overlay_mode fill it with black
    newLayer = pdb.gimp_layer_new(dup_image, width, height, RGB_IMAGE, "new", 100, OVERLAY_MODE)
    dup_image.add_layer(newLayer, -1)
    gimp.set_foreground(0,0,0)
    pdb.gimp_drawable_fill(newLayer, FOREGROUND_FILL)
    # merge down name it "grungeMask" 
    grungeLayer = pdb.gimp_image_merge_down(dup_image, newLayer, CLIP_TO_IMAGE)
    pdb.gimp_drawable_set_name(grungeLayer, "grungeMask")
    pdb.plug_in_gauss(dup_image, grungeLayer, 03, 0.3, 0)
    messBox("""Color > level to increase contrast of grungeMask layer.

Then click OK when ready to continue """, gtk.MESSAGE_INFO, 0)
    pdb.gimp_drawable_set_visible(grungeLayer, False)
    
    #Highligths layer 
    curveLayer = dup_drawable.copy()
    dup_image.add_layer(curveLayer, -1)
    pdb.gimp_curves_spline(curveLayer, HISTOGRAM_VALUE, 6, [0,0,66,13,255,129])
    curveLayer.mode = MULTIPLY_MODE
    curveMask = pdb.gimp_layer_create_mask(curveLayer, ADD_WHITE_MASK)
    pdb.gimp_layer_add_mask(curveLayer, curveMask)
    pdb.gimp_edit_copy(grungeLayer)
    pdb.gimp_floating_sel_anchor(pdb.gimp_edit_paste(curveMask, True))
    
    pdb.gimp_drawable_set_name(curveLayer, "highlights CurveAdj")
    pdb.gimp_layer_set_opacity(curveLayer, 50.0)
    gimp.set_foreground(0,0,0)
    pdb.gimp_layer_set_edit_mask(curveLayer, False)
    messBox("""Move slightly the "highlights CurveAdj" layer according to the general direction of the light.
Blur the Mask a bit.

Then click OK when ready to continue""", gtk.MESSAGE_INFO, 0)
    
    #fake brightness contrast adjustment layer
    brightContrastLayer = dup_drawable.copy()
    dup_image.add_layer(brightContrastLayer, -1)
    pdb.gimp_brightness_contrast(brightContrastLayer, 22, 22)
    brightContrastLayer.mode = SCREEN_MODE
    pdb.gimp_drawable_set_name(brightContrastLayer, "brightContrastAdj")
    pdb.gimp_layer_set_opacity(brightContrastLayer, 20.0)
    
    # eyes layer
    EyesLayer= dup_drawable.copy()
    dup_image.add_layer(EyesLayer, -1)
    pdb.gimp_hue_saturation(EyesLayer, ALL_HUES, 0, 0, 40)
    EyesLayer.mode = SCREEN_MODE
    pdb.gimp_layer_set_opacity(EyesLayer, 70.0)
    eyesMask = pdb.gimp_layer_create_mask(EyesLayer, ADD_BLACK_MASK)
    pdb.gimp_layer_add_mask(EyesLayer, eyesMask)
    pdb.gimp_drawable_set_name(EyesLayer, "Eyes")
    gimp.set_foreground(255,255,255)
    messBox("""Using a soft white brush, paint only the eyes into the layer mask.

Then click OK when ready to continue""", gtk.MESSAGE_INFO, 0)
    
    # darken edges layer
    darkenEdgesLayer = pdb.gimp_layer_new(dup_image, width, height, RGB_IMAGE, "Darken Edges", 100, NORMAL_MODE)
    pdb.gimp_image_add_layer(dup_image, darkenEdgesLayer, -1)
    gimp.set_foreground(0,0,0)
    pdb.gimp_drawable_fill(darkenEdgesLayer, FOREGROUND_FILL)
    darkenEdgesMask = pdb.gimp_layer_create_mask(curveLayer, ADD_WHITE_MASK)
    pdb.gimp_layer_add_mask(darkenEdgesLayer, darkenEdgesMask)
    pdb.gimp_invert(grungeLayer)
    pdb.gimp_edit_copy(grungeLayer)
    pdb.gimp_floating_sel_anchor(pdb.gimp_edit_paste(darkenEdgesMask, True))
    pdb.gimp_image_remove_layer(dup_image, grungeLayer)
    pdb.gimp_layer_set_opacity(darkenEdgesLayer, 30.0)
    
    #blue Channel
    blueLayer= dup_drawable.copy()
    dup_image.add_layer(blueLayer, -1)
    pdb.plug_in_colors_channel_mixer(dup_image, blueLayer, False, 0, 0, 1, 0, 0, 1, 0, 0, 1)
    pdb.gimp_layer_set_opacity(blueLayer, 40.0)
    blueLayer.mode = SOFTLIGHT_MODE
    pdb.gimp_drawable_set_name(blueLayer, "Blue channel")
    
    
    #final color correction layer
    colorLayer= dup_drawable.copy()
    dup_image.add_layer(colorLayer, -1)
    colorLayer.mode = HARDLIGHT_MODE
    pdb.gimp_layer_set_opacity(colorLayer, 50.0)
    colorMask = pdb.gimp_layer_create_mask(colorLayer, ADD_WHITE_MASK)
    pdb.gimp_layer_add_mask(colorLayer, colorMask)
    pdb.gimp_drawable_set_name(colorLayer, "ColorAdj")
    pdb.gimp_layer_set_edit_mask(colorLayer, False)
    messBox("""Finished !
Use Color tools to adjust hue, brightness, saturation on ColorAdj layer.
Adjust opacity.
Paint the mask in black if you want to retain some details (eyes, ...)

Adjust all layers opacity to your will, tweak ...

click OK to finish""", gtk.MESSAGE_INFO, 0)
    pdb.gimp_image_set_filename(dup_image, "Draganized_" + name)
    
    gimp.displays_flush()
    gimp.set_foreground(origfgcolor)
    dup_image.undo_group_end()
    img.undo_group_end()

register(
        "lazydraganEffect_xy",
        "lazy Dragan Effect",
        "lazy Dragan Effect",
        "xy",
        "xy",
        "2008",
        "<Image>/Python-Fu/xy/lazydraganEffect_xy",
        "RGB*",
        [
        ],
        [],
        lazydraganEffect_xy)

main()