#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import * 
import ctypes
import os
from datetime import datetime

def mapload(image, drawable):

    # Settings
    reportfile = TRUE   # generovat řádek záznamu v souboru s reportem
    labels = TRUE       # popsat hodnoty grafické náplně segmentů gridu
    cellcount = 10      # počet buněk na kratším rozměru mapy pro vizualizaci distribuce náplně

    # Merging steps
    pdb.gimp_image_undo_group_start(image)
    
    # Image size recognition and layer creation
    filename = pdb.gimp_layer_get_name(image.layers[0])
               
    sizewidth = drawable.width
    sizeheight = drawable.height
    
    select = pdb.gimp_selection_save(image)    
    layer1 = pdb.gimp_layer_new_from_drawable(drawable, image)
    floating_sel = pdb.gimp_image_get_floating_sel(image)
    
    # Pixel count recognition for selection and image
    px = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)[3]
    pdb.gimp_selection_all(image)
    px2 = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)[3]
       
    # Edge detection using Sobel operator       
    pdb.plug_in_edge(image, drawable, 1, 0, 0)

    # Converting to gryscale according to the value parameter
    monochrome = TRUE
    rr_gain = 0.299
    rg_gain = 0.299
    rb_gain = 0.299
    gr_gain = 0.587
    gg_gain = 0.587
    gb_gain = 0.587 
    br_gain = 0.114
    bg_gain = 0.114
    bb_gain = 0.114
    
    pdb.plug_in_colors_channel_mixer(image, drawable, monochrome, rr_gain, rg_gain, rb_gain, gr_gain, gg_gain, gb_gain, br_gain, bg_gain, bb_gain)

    # Converting to monochrome    
    pdb.gimp_image_convert_grayscale(image)

    # Bit depth recognition
    bytres = drawable.bpp
    if pdb.gimp_drawable_has_alpha(drawable):
        depth = (256 ** (bytres / 2)) - 1
    else:
        depth = (256 ** bytres) - 1
    
    resolution = (int(pdb.gimp_image_get_resolution(image)[0]) + int(pdb.gimp_image_get_resolution(image)[1])) / 2  
    
    # Map load calculation
    pdb.gimp_selection_load(select)        
    histogram = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)
    
    if bytres == 1 or (bytres == 2 and pdb.gimp_drawable_has_alpha(drawable)):
        ml = histogram[0] * 100 / depth
    else:
        ml = histogram[0] * 100
    
    # Grid creation
    pdb.gimp_selection_all(image)  
    if sizewidth > sizeheight:
        cellsize = int(sizeheight / cellcount) + (sizeheight % cellcount > 0)
        gridheight = cellcount
        gridwidth = int(1.0 * cellcount / sizeheight * sizewidth)
        pdb.gimp_image_scale_full(image, gridwidth, gridheight, 1)
    else:
        cellsize = int(sizewidth / cellcount) + (sizewidth % cellcount > 0)
        gridwidth = cellcount
        gridheight = int(1.0 * cellcount / sizewidth * sizeheight)
        pdb.gimp_image_scale_full(image, gridwidth, gridheight, 1)   
                                                                             
    pdb.plug_in_convmatrix(image, drawable, 25, [0,0,0,0,0, 0,1,2,1,0, 0,2,4,2,0, 0,1,2,1,0, 0,0,0,0,0], False, 16, 0, 5, [True,True,True,True,True], 0)
    
    # Map load calculation in grid
    if labels:
        grid_y = 0
        mls = []
        while (grid_y < gridheight):
            grid_x = 0
            while (grid_x < gridwidth):   
                pixelvalue = pdb.gimp_drawable_get_pixel(drawable, grid_x, grid_y)
                if bytres == 1 or (bytres == 2 and pdb.gimp_drawable_has_alpha(drawable)):
                    mls.append(pixelvalue[1][0] * 100 / depth)
                else:
                    mls.append(pixelvalue[1][0] * 100)            
                grid_x += 1   
            grid_y += 1
        
        mean = sum(mls) / len(mls)
    
    # SD recognition    
    pdb.gimp_selection_load(select)
    if reportfile:

        histogram2 = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)    
        if bytres == 1 or (bytres == 2 and pdb.gimp_drawable_has_alpha(drawable)):
            sd = histogram2[1] / depth * 100
        else:
            sd = histogram2[1] * 100
    
    # Visualisation
    pdb.gimp_image_scale_full(image, sizewidth, sizeheight, 0)
    pdb.gimp_image_convert_rgb(image) 
        
    if px != px2:           
        if not(pdb.gimp_drawable_has_alpha(drawable)):
            pdb.gimp_layer_add_alpha(drawable)
    
    pdb.gimp_image_insert_layer(image, layer1, None, -1)    
    pdb.gimp_layer_set_opacity(layer1, 5)
    
    # Writing a report file
    if reportfile:
        now = datetime.now()
        current_time = now.strftime("%Y%m%d_%H%M%S")       
        if not(os.path.isfile("gmlmt_report.txt") and os.path.getsize("gmlmt_report.txt") > 0):
            reportfile = open("gmlmt_report.txt","a")
            reportfile.write("cas_znacka\tnazev_souboru\tnapln_mapy_proc\tst_odch_proc\tpocet_pixelu\trozliseni\n")
            reportfile.close()
  
        reportfile = open("gmlmt_report.txt","a+")
        reportfile.write(current_time)
        reportfile.write("\t")
        reportfile.write(str(filename))
        reportfile.write("\t")
        reportfile.write(str(round(ml, 1)))
        reportfile.write("\t")
        reportfile.write(str(round(sd, 1)))
        reportfile.write("\t")
        reportfile.write(str(int(px)))
        reportfile.write("\t")
        if resolution == 100:
            reportfile.write("ok")
        else:
            reportfile.write(str(resolution))
        reportfile.write("\n")
        reportfile.close()
    
    # Value notification
    message = ""
    if resolution != 100:
        message = " Varování: Rozlišení obrazu je " + str(resolution) + " DPI, zatímco doporučeno je 100 DPI.\n\n"  
    message = message + " Grafická náplň mapy: " + str(round(ml, 1)) + " %"
    ctypes.windll.user32.MessageBoxW(0, unicode(message, "utf-8"), u"VÝSLEDKY MĚŘENÍ", 0x40) 
        
    # Grid labels
    if labels:
        position_y = sizeheight / gridheight / 3
        arrayindex = 0
        row = 1
        
        while (position_y < sizeheight):
            position_x = sizewidth / gridwidth / 3
            col = 1
            while (position_x < sizewidth):
                mls[arrayindex] = mls[arrayindex] * ml / mean
                if (mls[arrayindex] >= 50):
                    green = int(255 - (mls[arrayindex] - 50) * 5.1)
                    pdb.gimp_context_set_foreground((255,green,0))
                else:
                    blue = int(255 - mls[arrayindex] * 5.1)
                    pdb.gimp_context_set_foreground((255,255,blue))    
                text = pdb.gimp_text_fontname(image, drawable, position_x, position_y, int(mls[arrayindex]), -1, FALSE, cellsize / 3, 0, "Calibri")
                position_x = sizewidth / gridwidth / 3 + col * sizewidth / gridwidth
                arrayindex += 1
                col += 1
                
            position_y = sizeheight / gridheight / 3 + row * sizeheight / gridheight
            row += 1 
    
        pdb.gimp_floating_sel_anchor(pdb.gimp_image_get_floating_sel(image))   
       
    # Finishing merged steps
    pdb.gimp_image_undo_group_end(image)
    
register(
    "NAPLNMAPY_1-3",
    "Experimentální nástroj pro určování grafické náplně map založený na detekci hran",
    "Experimentální nástroj pro určování grafické náplně map založený na detekci hran pomocí Sobelova filtru, vyvinutý na Katedře geoinformatiky Univerzity Palackého v Olomouci v rámci výzkumu metrik pro výpočet grafické náplně map. Pro vzájemnou porovnatelnost se doporučuje využít rastry reprezentující mapu v originálních rozměrech a s rozlišením 100 DPI",
    "Radek Barvíř", "CC BY-SA", "v 1.3, build 210401, 2021",
    "GMLMT 1.3 cz",
    "RGB*", 
    [
        (PF_IMAGE, "image", "takes current image", None),
        (PF_DRAWABLE, "drawable", "Input layer", None)
    ],
    [],
    mapload, menu="<Image>/Filters/Edge-Detect")

main()