# -*- coding: iso-8859-1 -*-
"""
   MoinMoin - Color2Grey Image Correction Effect

   Color2Grey image correction algorithm implemented according to
   http://www.e56.de/c2g.php, copyrights by Martin Faust

   Please note:
   Color2Grey Image Correction Effect needs
   * Python Image Library (PIL) from http://www.pythonware.com/products/pil/
   * NumPy from http://numpy.scipy.org/

   @copyright: 2008 by Oliver Siemoneit
               2008 refactored to an action for all jpeg images of a page by MoinMoin:ReimarBauer
   @license: GNU GPL, see COPYING for details.
"""

HELPERS = True
try:
    from PIL import Image
    import numpy
except ImportError:
    HELPERS = False

import colorsys, os, StringIO
from MoinMoin.Page import Page
from MoinMoin.action import AttachFile, cache

action_name = __name__.split('.')[-1]

def process_files(pagename, request, extension):
    files = AttachFile._get_files(request, pagename)
    attach_dir = AttachFile.getAttachDir(request, pagename)
    lightness_correction = True # Set lightness_correction by default to "True"!
    msg = "nothing done"
    state = "info"
    for attfile in files:
        if attfile.lower().endswith(extension):
            key = cache.key(request, itemname=pagename, attachname=attfile)
            # ToDo naming scheme for prefix wanted
            greyimage = 'G' + key
            if not cache.exists(request, greyimage):
                im = Image.open(os.path.join(attach_dir, attfile))
                if not im.mode in ('1', 'L'): # Don't process black/white or greyscale images
                    old_size = im.size
                    im.thumbnail((640, 640), Image.ANTIALIAS) # For the sake of speed: process thumbnail only
                    im = im.convert('RGB')
                    pix = im.load() # Load the image in memory so we don't need getpixel and putpixel

                    grey = numpy.zeros(im.size, float)
                    minimum = 100.0
                    maximum = -100.0
                    total = 0.0

                    for y_pos in range(im.size[1]):
                        for x_pos in range(im.size[0]):
                            red, green, blue = pix[x_pos, y_pos]
                            hue, saturation, lightness = colorsys.rgb_to_hsv(red, green, blue)
                            hue = hue * 360.0 # Algorithm expects value to be within <0;360>
                            if saturation == 0.0:
                                grey[x_pos][y_pos] = 1.5 * lightness
                            else:
                                grey[x_pos][y_pos] = lightness + lightness * saturation
                                minimum = min((grey[x_pos][y_pos], minimum))
                                maximum = max((grey[x_pos][y_pos], maximum))
                            total += grey[x_pos][y_pos]

                    mean = total / (float)(im.size[1] * im.size[0])
                    minimum = 0.0
                    maximum = (mean + maximum) * 0.5
                    for y_pos in range(im.size[1]):
                        for x_pos in range(im.size[0]):
                            if lightness_correction:
                                lightness = 0.9 * 255.0 * (grey[x_pos][y_pos] - minimum) / (maximum - minimum)
                            else:
                                lightness = 255.0 * (grey[x_pos][y_pos] - minimum) / (maximum - minimum)
                                lightness = max((min((lightness, 255)), 0.0))
                            pix[x_pos, y_pos] = (int(lightness), int(lightness), int(lightness))

                    buf = StringIO.StringIO()
                    im = im.resize(old_size, Image.ANTIALIAS)
                    im.save(buf, 'JPEG')
                    buf.flush()
                    buf.seek(0)
                    cache.put(request, greyimage, buf, filename=attfile)
                    buf.close()
                    state = "info"
                    msg = "file(s) processed"

    return msg, state

def execute(pagename, request):
    """ dispatcher for grey color conversion action. """
    _ = request.getText
    # XXX Why is this action restricted to jpg / jpeg? What about gif, png? Why restrict it at all?
    extension = '.jpg'
    msg = None
    if not HELPERS:
        msg = _('The action %(action)s needs Python Imaging Library (PIL) and numpy installed') % {'action': action_name}
        state = "error"
    if not msg:
        msg, state = process_files(pagename, request, extension)
    if msg:
        request.theme.add_msg(msg, state)
        Page(request, pagename).send_page()
    return

