From 99b2660fb05ea5e057c69d3f6f0780448e9399c1 Mon Sep 17 00:00:00 2001 From: Tor-Einar Skog <tor-einar.skog@nibio.no> Date: Fri, 17 Feb 2023 10:50:55 +0100 Subject: [PATCH] Add methods for base64 encoding of images in desc --- src/vipscore_common/vips_model.py | 109 +++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 16 deletions(-) diff --git a/src/vipscore_common/vips_model.py b/src/vipscore_common/vips_model.py index 38e02f9..f4bab1c 100755 --- a/src/vipscore_common/vips_model.py +++ b/src/vipscore_common/vips_model.py @@ -1,21 +1,20 @@ #!/usr/bin/python3 """ -Copyright (c) 2023 NIBIO <http://www.nibio.no/>. - -This file is part of VIPSCore-Python-Common. -VIPSCore-Python-Common is free software: you can redistribute it and/or modify -it under the terms of the NIBIO Open Source License as published by -NIBIO, either version 1 of the License, or (at your option) any -later version. - -VIPSCore-Python-Common 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 -NIBIO Open Source License for more details. - -You should have received a copy of the NIBIO Open Source License -along with VIPSCore-Python-Common. If not, see <http://www.nibio.no/licenses/>. + Copyright (C) 2023 NIBIO + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. """ # All models in VIPSCore-Python must extend this abstract class @@ -24,6 +23,9 @@ along with VIPSCore-Python-Common. If not, see <http://www.nibio.no/licenses/>. from abc import ABC, abstractmethod, abstractproperty from .entities import Result, ModelConfiguration +import re, mimetypes, base64 +mimetypes.init() + class VIPSModel(ABC): # Default language is English @@ -90,4 +92,79 @@ class VIPSModel(ABC): """Technical manual for this model, in the specified language (<a href="http://www.loc.gov/standards/iso639-2/php/English_list.php">ISO-639-2</a>)""" pass - \ No newline at end of file + """ + Util methods to be able to serve images as part of the model description + """ + tag_matcher = None + attribute_matcher = None + image_path = None + + def get_tag_matcher(self): + """ + Get the regex matcher to find {{}} pseudotags + """ + if self.tag_matcher is None: + self.tag_matcher = re.compile("\\{\\{(.*?)\\}\\}",re.DOTALL) + return self.tag_matcher + + def get_attribute_matcher(self): + """ + Get the regex matcher to find attributes inside the {{}} pseudotag + """ + if self.attribute_matcher is None: + self.attribute_matcher = re.compile("([^=\\s]+)=\"([^\"]+)\"") + return self.attribute_matcher + + def replace_match(self, tag_match): + """ + Replace contents of pseudotags with <img/> element + """ + + ar = self.get_attribute_matcher() + tag_text = "<img" + tag_contents = tag_match.group(1) + file_attr_name_found = False + # Iterating the attributes ("filename", "description", "float"), adding to img tag + for attribute_match in ar.finditer(tag_contents): + attr_name = attribute_match.group(1) + attr_val = attribute_match.group(2) + # Analyzing each tag + if attr_name == "filename": + file_attr_name_found = True + file_path = "%s%s" % (self.image_path, attr_val ) + # https://docs.python.org/3/library/mimetypes.html + mime_type = mimetypes.guess_type("%s%s" % (self.image_path, attr_val ))[0] + f = open(file_path,"rb") + b64encoded = base64.b64encode(f.read()).decode("utf-8") + f.close() + tag_text = "%s src=\"data:%s;base64,%s\"" % (tag_text, mime_type, b64encoded) + if attr_name == "description": + tag_text = "%s alt=\"%s\" title=\"%s\"" % (tag_text, attr_val, attr_val) + if attr_name == "float": + tag_text = "%s style=\"float: %s\"" % (tag_text, attr_val) + tag_text = "%s class=\"img-responsive\"/>" % tag_text + + if file_attr_name_found: + return tag_text + else: + return "ERROR PARSING IMAGE PSEUDOTAG: MISSING filepath." + + def get_text_with_base64_encoded_images(self, text, image_path): + """ + Parsing text with reference to images. Image template tag format is: + {{filename="/path/to/filename.jpg" description="Sample description" float="[CSSFloat property]"}} + {{filename="/1348485230424.jpg" description="Chart for apple scab model" float="none"}} + + These tags are parsed and transformed to html <img/> tags, and the image files + are base64 encoded and embedded. The only mandatory parameter is filename. It refers to the + file relative to the Model jar in which it is placed. + @param text the description text + @param image_path the path where images are stored (absolute, must be figured out with pathlib.Path(__file__).parent in the calling VIPSModel) + @return The same text with embedded image(s) + """ + + self.image_path = image_path + return re.sub(self.get_tag_matcher(), self.replace_match, text) + + + \ No newline at end of file -- GitLab