You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.6 KiB

#!/usr/bin/env python3
# coding=utf-8
#
# Copyright (C) 2022 Mikael Nordin, hej@mic.ke
#
# 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., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
"""
Description of this extension
"""
import inkex
from inkex import Image as IImage
import gi
import io
import base64
from PIL import Image
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
from gi.repository import Gtk, Gdk # noqa: E402
class GeoReferencerPoint():
def __init__(self, x: int, y: int, to_x: int = 0, to_y: int = 0) -> None:
self.x: int = x
self.y: int = y
self.to_x: int = to_x
self.to_y: int = to_y
class GeoReferencer():
def __init__(self, window) -> None:
self.points: list[GeoReferencerPoint] = list()
self.window = window
def add_point(self, point: GeoReferencerPoint) -> None:
self.points.append(point)
def add_img(self, img) -> None:
self.img = img
def do_transform(self):
pass
class GeoReferencerWindow(Gtk.Window):
def __init__(self) -> None:
super().__init__(title="Georeferencer")
self.georeferencer: GeoReferencer = GeoReferencer(self)
self.set_events(Gdk.EventMask.POINTER_MOTION_MASK |
Gdk.EventMask.BUTTON_PRESS_MASK)
self.box: Gtk.Box = Gtk.Box()
self.add(self.box)
self.button: Gtk.Button = Gtk.Button(label="Georeference")
self.button.connect("clicked", self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.event_box: Gtk.EventBox = Gtk.EventBox()
self.event_box.set_above_child(above_child=True)
self.event_box.connect('motion-notify-event', self.on_motion_notify)
self.event_box.connect('enter-notify-event', self.on_motion_notify)
self.event_box.connect('button-press-event', self.on_mouse_click)
self.box.pack_start(self.event_box, True, True, 0)
self.connect("destroy", Gtk.main_quit)
def debug_box(self, message: str):
dialog = Gtk.MessageDialog(transient_for=self,
modal=False, destroy_with_parent=True,
message_type=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
text=message)
dialog.show_all()
dialog.run()
dialog.destroy()
def on_button_clicked(self, widget) -> None:
img = self.georeferencer.do_transform()
self.event_box.remove(self.image)
self.image = img
self.event_box.add(self.image)
self.image.show_all()
self.queue_draw()
# self.destroy()
def on_motion_notify(self, widget, event) -> None:
widget.set_tooltip_text("x:{}, y:{}".format(event.x, event.y))
def on_mouse_click(self, widget, event) -> None:
dialog = Gtk.MessageDialog(transient_for=self,
modal=True, destroy_with_parent=True,
message_type=Gtk.MessageType.QUESTION,
buttons=Gtk.ButtonsType.OK_CANCEL,
text="Set new coordinates")
point_box = dialog.get_content_area()
x_label = Gtk.Label()
y_label = Gtk.Label()
x_label.set_text("x:")
y_label.set_text("y:")
x_entry = Gtk.Entry()
y_entry = Gtk.Entry()
point_box.pack_start(x_label, True, True, 0)
point_box.pack_start(x_entry, True, True, 0)
point_box.pack_start(y_label, True, True, 0)
point_box.pack_start(y_entry, True, True, 0)
dialog.show_all()
response = dialog.run()
if response == Gtk.ResponseType.OK:
to_x = int(x_entry.get_text())
to_y = int(y_entry.get_text())
point = GeoReferencerPoint(event.x, event.y, to_x, to_y)
self.georeferencer.add_point(point)
dialog.destroy()
def add_image(self, img):
self.image = img
self.georeferencer.add_img(self.image)
self.event_box.add(self.image)
self.show_all()
class CoordinatesExtension(inkex.EffectExtension):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.window: GeoReferencerWindow = GeoReferencerWindow()
def effect(self) -> None:
images = self.svg.selection.get(IImage)
for elem in images:
xlink = elem.get("xlink:href")
if xlink is not None and xlink[:5] == "data:":
data = xlink[5:]
(mimetype, data) = data.split(";", 1)
(base, data) = data.split(",", 1)
if base != "base64":
self.debug_box(
"Unable to decode encoding {}.").format(base)
else:
imgdata = base64.b64decode(data)
image = Image.open(io.BytesIO(imgdata))
self.window.add_image(image)
self.window.show_all()
Gtk.main()
if __name__ == '__main__':
CoordinatesExtension().run()