#!/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 # generate a line report in the text file labels = True # label map load visualisation grid (time-consuming) cellcount = 10 # number of cells for map load visualization on the shortest dimension of the map # 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) # Pixel count recognition for selection and image pixels_selection = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)[3] pdb.gimp_selection_all(image) pixels_all = pdb.gimp_drawable_histogram(drawable, 0, 0, 1)[3] selected_all = pixels_selection == pixels_all is_transparent = pdb.gimp_drawable_has_alpha(drawable) # Edge detection using Sobel operator pdb.plug_in_edge(image, drawable, 1, 0, 0) # Converting to greyscale according to the value parameter r_gain = 0.299 g_gain = 0.587 b_gain = 0.114 pdb.plug_in_colors_channel_mixer(image, drawable, True, r_gain, r_gain, r_gain, g_gain, g_gain, g_gain, b_gain, b_gain, b_gain) # Converting to monochrome pdb.gimp_image_convert_grayscale(image) # Bit depth recognition bytres = drawable.bpp if is_transparent: 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 is_transparent): ml = histogram[0] * 100 / depth else: ml = histogram[0] * 100 # Grid creation pdb.gimp_selection_all(image) if sizewidth > sizeheight: cellsize = sizeheight // cellcount + (sizeheight % cellcount > 0) gridheight = cellcount gridwidth = int(sizewidth * gridheight / sizeheight) else: cellsize = sizewidth // cellcount + (sizewidth % cellcount > 0) gridwidth = cellcount gridheight = int(sizeheight * gridwidth / sizewidth) pdb.gimp_image_scale_full(image, gridwidth, gridheight, 1) cellsize_width = sizewidth / gridwidth cellsize_height = sizeheight / gridheight 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: mls = [] # map load values of cells trs = [] # transparencies of cells for grid_y in range(0, gridheight): for grid_x in range(0, gridwidth): pixelvalue = pdb.gimp_drawable_get_pixel(drawable, grid_x, grid_y) if bytres == 1: mls.append(pixelvalue[1][0] * 100 / depth) elif bytres == 2 and is_transparent: mls.append(pixelvalue[1][0] * 100 / depth) trs.append(pixelvalue[1][1] * 100 / depth) else: mls.append(pixelvalue[1][0] * 100) if len(mls) != 0: mean_ml = sum(mls) / len(mls) else: ctypes.windll.user32.MessageBoxW(0, unicode("Error in computing grid :-(", "utf-8"), u"ERROR", 0x10) exit() if is_transparent and (len(trs) != 0): mean_tr = sum(trs) / len(trs) / 100.0 # obtaining transparency ranging 0 (fully transparent) to 1 (fully covered) else: mean_tr = 1 # 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 is_transparent): 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 not selected_all: if not is_transparent: pdb.gimp_layer_add_alpha(drawable) pdb.gimp_image_insert_layer(image, layer1, None, -1) pdb.gimp_layer_set_opacity(layer1, 5) # Value notification message = "" if resolution != 100: message = "Warning: Image resolution is " + str(resolution) + " DPI while 100 DPI is recommended.\n\n" if selected_all: message = message + "Graphic map load value: " + str(round(ml, 1)) + " %" else: message = message + "Graphic map load value of your selection: " + str(round(ml, 1)) + " %" ctypes.windll.user32.MessageBoxW(0, unicode(message, "utf-8"), u"MEASUREMENT RESULTS", 0x40) # Grid labels if labels: position_y = sizeheight / gridheight / 3 arrayindex = 0 row = 1 while position_y < sizeheight: position_x = cellsize_width / 3 col = 1 while position_x < sizewidth: if mean_ml != 0: mls[arrayindex] = mls[arrayindex] * ml / mean_ml * mean_tr 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 = cellsize_width / 3 + col * cellsize_width arrayindex += 1 col += 1 position_y = cellsize_height / 3 + row * cellsize_height row += 1 pdb.gimp_floating_sel_anchor(pdb.gimp_image_get_floating_sel(image)) # 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("time_stamp\tfile_name\tmap_load_perc\tstd_dev_perc\tpixel_count\tresolution\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(pixels_selection))) reportfile.write("\t") if resolution == 100: reportfile.write("ok") else: reportfile.write(str(resolution)) reportfile.write("\n") reportfile.close() # Finishing merged steps pdb.gimp_image_undo_group_end(image) register( "MAPLOAD_1-4", "Experimental tool for graphic map load measurement based on edge detection", "Experimental tool for graphic map load measurement based on edge detection using Sobel operator, developed at the Department of Geoinformatics, Palacký University Olomouc (RGB images with resolution 100 DPI prefered)", "Radek Barvíř", "CC BY-SA", "v 1.4, build 221120, 2022", "GMLMT 1.4 en", "RGB*", [ (PF_IMAGE, "image", "takes current image", None), (PF_DRAWABLE, "drawable", "Input layer", None) ], [], mapload, menu="/Filters/Edge-Detect") main()