User:Pemu/CorrectDoubledLines

Python-2 script for Gimp to correct maps from Raremaps edit

Background edit

Different approaches exist in how-to transmit tiles for interactive web-based zoomable viewers. The majority of applications I encountered uses tiles that are laid out butting each other. In order to put them together to one huge image, one can harvest all tiles by some scripting methods (not described here). If the harvested tiles are JPEG ones and have a pixel size that is a multiple of 16, they can easily stitched losslessly by means of tool jpegtran (compiled with drop option).

Some, however, uses tiles that have a circumferential excess of 1 pixel. The application displays them overlapping by 2 pixels to compensate for the excess. If the tile’s size is a multiple of 16 plus 2 (e.g. 258×258), this is annoying when stitching them together, but, after all, is not that big problem. If, however, the tile’s size is just a plain multiple of 16 (like e.g. 256×256 as used by Raremaps.com), but contains nevertheless a circumferential excess of 1 pixel, one gets into dire straits. Stitching all tiles together losslessly yields a huge image with doubled lines at the borders of the former tiles.

To repair this fault or rather rework or finalise the stitching process, I developed this script which acts as a plugin to Gimp. So the underlying stitching works losslessly and is followed by removing the excess pixels. After this, when the image is saved as JPEG, only one generation loss is introduced.

Sorry, this is my first attempt in making a Gimp plugin. Albeit I’m now and then in the occasion to use Python, surely I’m far from thinking pythonesque. This script is for sure somewhat slipshod. Beware, consider this as alpha, please!

Usage edit

Install edit

Copy content of framed code window into clipboard and paste it into an empty text file. Save it. Rename it to something like CorrectDoubledLines.py (take care to also rename the filename ending). Maybe Gnu-Linux users must make the file executable. Move it into plug-ins subfolder of user’s Gimp directory. In Windows and with Gimp 2.8 this is usually found at C:\Users\YourUserName\.gimp-2.8\scripts, with Gimp 2.10 at C:\Users\YourUserName\AppData\Roaming\GIMP\2.10\scripts. In Gnu-Linux it is ~/.gimp-2.8/plug-ins. Its exact name vary with Gimp version, of course.

I don’t know if the shebang line (first line with #!/…) is important an whether it should be modified according to the underlying operation system environment.

Finally (re)start Gimp in order to let it recognise the script. The Image menu contains now an additional menu entry Rework Raremaps.

Usage edit

There are two different modes of operation:

  1. Test mode
  2. Do mode

During test mode, all the overlapping lines are substracted. If the prerequisites are met – i.e. there are really doubled lines, and they are really at the tile borders –, this should result in a uniformly grey image. Due to the JPEG artefacts, this is not true in a strict sense. Nevertheless, it is distinctly and visibly, if the image doesn’t have doubled lines. The test mode – opposed to the do mode – can currently only handle either rows or columns, but not both simultaneously.

The do mode does achieve the desired effect.

There is currently no user interface; to control, one has to de-comment-out certain lines:

  • testx=False Do work on rows
  • #testx=False Don’t work on rows
  • testy=False Do work on columns
  • #testy=False Don’t work on columns
  • test=True Test mode
  • #test=True Do mode

It isn’t necessary to restart Gimp in order to let changes take effect, once it has discovered the script file.

According to experience, when dealing with stitched maps, due to their size, memory may at anytime suddenly an issue. My advise is to restart Gimp and reload the image after test mode. I had the case that I coulnd’t launch export savers, but I could save as xcf (not xcfbz2). After restart, launching JPEG export succeeded. In one case, first I had to disable work on columns. After processing on rows I saved the project, restarted Gimp and loaded it again, disbaled work on rows – and finally proceeded with working on columns.

Hint: Start Gimp from a console/terminal. Thus one can see output and error messages. Currently, the normal output is the pixel number of the left/top border of currently processed tile. Pitfall: As the right/bottom border will be processed, it is equitable to say that the numbers are to small by 256.

Code edit

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function
from gimpfu import *

def give_range(size, kachelgr):
	tile = size // kachelgr
#	return xrange (0,tile*kachelgr,kachelgr)         # Normally
	return xrange (kachelgr,tile*kachelgr,kachelgr)  # Not normally, this is used to omit the already manually corrected first tile border.

def fill_gray (drawa):
	background = pdb.gimp_palette_get_background()
	pdb.gimp_palette_set_background ((128,128,128)+background[3:])
	pdb.gimp_edit_fill (drawa,1)		
	pdb.gimp_palette_set_background (background)

def walk(timg, tdrawable, modrange, groesse, quer, overlap, kachelgr, y, test):
	i=1
	for a in modrange:
		print (a)
		a+=kachelgr

		# Cut away main part of first tile, in order to investigate only the interesting lines (test mode)
		if (i==1) and test:
			pdb.gimp_image_select_rectangle(timg, CHANNEL_OP_REPLACE, 0, 0, a-overlap if y else quer, quer if y else a-overlap) # select remaining part
			fill_gray (timg.layers[0])

		#Take one row, tranlate it about two pixels to the left, invert it (test mode) and combin eit with 50 % transparency.
		if (overlap+a < groesse):
			pdb.gimp_image_select_rectangle(timg, CHANNEL_OP_REPLACE, a if y else 0, 0 if y else a, overlap if y else quer, quer if y else overlap) # Spalte definieren
			pdb.gimp_edit_cut(timg.layers[0])                          # Cut out row
			se=pdb.gimp_edit_paste(timg.layers[0], True)               # Paste
			if test: pdb.gimp_invert(timg.floating_selection)          # Invertiert row (test mode)
			pdb.gimp_floating_sel_to_layer(se)                         # Floating selection to a new layer
			if not test:
				pdb.gimp_layer_translate(timg.layers[0], -overlap*i if y else 0, 0 if y else -overlap*i) # Translate to the left
			else:
				pdb.gimp_layer_translate(timg.layers[0], -overlap if y else 0, 0 if y else -overlap) # Translate to the left
			timg.layers[0].opacity = 50.0                              # Set layer to 50 % transparency
			pdb.gimp_image_merge_visible_layers(timg, 0)               # Combine visible layers

			if test: # Cut away main part of first tile, in order to investigate only the interesting lines (test mode)
				pdb.gimp_image_select_rectangle(timg, CHANNEL_OP_REPLACE, a if y else 0, 0 if y else a, (kachelgr-overlap) if y else quer, quer if y else (kachelgr-overlap)) # select remaining part
				fill_gray (timg.layers[0])
			else:
				pdb.gimp_image_select_rectangle(timg, CHANNEL_OP_REPLACE, (a+overlap) if y else 0, 0 if y else (a+overlap), (kachelgr-overlap) if y else quer, quer if y else (kachelgr-overlap)) # select remaining part
				pdb.gimp_edit_cut(timg.layers[0])                      # Cut away remainder tile
				se=pdb.gimp_edit_paste(timg.layers[0], True)           # Paste
				pdb.gimp_floating_sel_to_layer(se)                     # Floating selection to a new layer
				pdb.gimp_layer_translate(timg.layers[0], -overlap*i if y else 0, 0 if y else -overlap*i) # Translate to the left
				pdb.gimp_image_merge_visible_layers(timg, 0)           # Combine visible layers
			i+=1


def plugin_main(timg, tdrawable):
##	pdb.gimp_undo_push_group_start (timg) # Commented out due to out-of-memory-issues
	currentWidth = tdrawable.width
	currentHeight = tdrawable.height

	kachelgr=256
	xr = (give_range (currentWidth,  kachelgr), currentWidth, currentHeight)
	yr = (give_range (currentHeight, kachelgr), currentHeight, currentWidth)
	testx=True   # Remove x-doublings
	testy=True   # Remove y-doublings
	test=False   # Normal correction (no test mode)
	#testx=False # Remove only y-doublings
	#testy=False # Remove only x-doublings
	#test=True   # Test-Modus: Helps to tell whether the original really contains doublings. There should be produced a plain grey area. The produced stripes should only contain JPEG artifacts. Test mode works only either in x- or y-direction, but not in both directions at once.

	if (testx): walk (timg, tdrawable, xr[0], xr[1], xr[2], 2, kachelgr, True, test)
	if (testy): walk (timg, tdrawable, yr[0], yr[1], yr[2], 2, kachelgr, False,test)
	
	pdb.gimp_selection_clear (timg)
##	pdb.gimp_undo_push_group_end (timg)

register(
        "python_fu_Raremaps_nacharbeiten",
        "Removes the pixel doublings that happen each 256 pixel",
        "Removes the pixel doublings that happen each 256 pixel",
        "Pemu",
        "Pemu",
        "2019",
        "<Image>/Image/Rework Raremaps",
        "RGB*, GRAY*",
        [],
        [],
        plugin_main)

main()