From 4d8cf8460ef35829041432a49c48c8d173b1822a Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 17 Aug 2016 10:49:31 +0200 Subject: [PATCH] Function for computing size of symbols --- gns3server/controller/drawing.py | 4 +- gns3server/utils/picture.py | 66 ++++++++++++++++++++------ tests/resources/gns3_icon_128x128.png | Bin 0 -> 7892 bytes tests/resources/gns3_icon_128x64.gif | Bin 0 -> 1759 bytes tests/resources/gns3_icon_128x64.jpg | Bin 0 -> 5082 bytes tests/resources/gns3_icon_128x64.png | Bin 0 -> 7650 bytes tests/utils/test_picture.py | 41 ++++++++++++++++ 7 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 tests/resources/gns3_icon_128x128.png create mode 100644 tests/resources/gns3_icon_128x64.gif create mode 100644 tests/resources/gns3_icon_128x64.jpg create mode 100644 tests/resources/gns3_icon_128x64.png create mode 100644 tests/utils/test_picture.py diff --git a/gns3server/controller/drawing.py b/gns3server/controller/drawing.py index b0c727ac..2675ce1b 100644 --- a/gns3server/controller/drawing.py +++ b/gns3server/controller/drawing.py @@ -72,8 +72,8 @@ class Drawing: try: return data.decode() except UnicodeError: - width, height = get_size(data) - return "\n\n".format(b64=base64.b64encode(data).decode(), extension=filename.split(".")[1], width=width, height=width) + width, height, filetype = get_size(data) + return "\n\n".format(b64=base64.b64encode(data).decode(), filetype=filetype, width=width, height=width) except OSError: log.warning("Image file %s missing", filename) return "" diff --git a/gns3server/utils/picture.py b/gns3server/utils/picture.py index abde33d2..34823113 100644 --- a/gns3server/utils/picture.py +++ b/gns3server/utils/picture.py @@ -15,16 +15,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import io import struct +from xml.etree.ElementTree import ElementTree - -def get_size(data): +def get_size(data, default_width=0, default_height=0): """ Get image size :param data: A buffer with image content - :return: Tuple (width, height) + :return: Tuple (width, height, filetype) """ + + height = default_height + width = default_width + filetype = None + # Original version: # https://github.com/shibukawa/imagesize_py # @@ -38,21 +44,20 @@ def get_size(data): # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - height = 0 - width = 0 - size = len(data) # handle GIFs if size >= 10 and data[:6] in (b'GIF87a', b'GIF89a'): # Check to see if content_type is correct try: width, height = struct.unpack("= 24 and data.startswith(b'\211PNG\r\n\032\n') and data[12:16] == b'IHDR': try: width, height = struct.unpack(">LL", data[16:24]) + filetype = "png" except struct.error: raise ValueError("Invalid PNG file") # Maybe this is for an older PNG version. @@ -60,12 +65,14 @@ def get_size(data): # Check to see if we have the right content type try: width, height = struct.unpack(">LL", data[8:16]) + filetype = "png" except struct.error: raise ValueError("Invalid PNG file") # handle JPEGs elif size >= 2 and data.startswith(b'\377\330'): try: - fhandle.seek(0) # Read 0xff next + # Not very efficient to copy data to a buffer + fhandle = io.BytesIO(data) size = 2 ftype = 0 while not 0xc0 <= ftype <= 0xcf: @@ -78,13 +85,44 @@ def get_size(data): # We are at a SOFn block fhandle.seek(1, 1) # Skip `precision' byte. height, width = struct.unpack('>HH', fhandle.read(4)) + filetype = "jpg" except struct.error: raise ValueError("Invalid JPEG file") - # handle JPEG2000s - elif size >= 12 and data.startswith(b'\x00\x00\x00\x0cjP \r\n\x87\n'): - fhandle.seek(48) + # End of https://github.com/shibukawa/imagesize_py + + # handle SVG + elif size >= 10 and data.startswith(b'LL', fhandle.read(8)) - except struct.error: - raise ValueError("Invalid JPEG2000 file") - return width, height + width = _svg_convert_size(root.attrib["width"]) + height = _svg_convert_size(root.attrib["height"]) + except IndexError: + raise ValueError("Invalid SVG file") + + return width, height, filetype + +def _svg_convert_size(size): + """ + Convert svg size to the px version + + :param size: String with the size + """ + + # https://www.w3.org/TR/SVG/coords.html#Units + conversion_table = { + "pt": 1.25, + "pc": 15, + "mm": 3.543307, + "cm": 35.43307, + "in": 90 + } + if len(size) > 3: + if size[-2:] in conversion_table: + return round(float(size[:-2]) * conversion_table[size[-2:]]) + + return round(float(size)) diff --git a/tests/resources/gns3_icon_128x128.png b/tests/resources/gns3_icon_128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..b7fc2a20a6430473dad996e895e8daeb6577d026 GIT binary patch literal 7892 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. + + +from gns3server.utils.picture import get_size + + +def test_get_size(): + with open("tests/resources/nvram_iou", "rb") as f: + res = get_size(f.read(), default_width=100, default_height=50) + assert res == (100, 50, None) + with open("tests/resources/gns3_icon_128x64.gif", "rb") as f: + res = get_size(f.read()) + assert res == (128, 64, "gif") + with open("tests/resources/gns3_icon_128x64.jpg", "rb") as f: + res = get_size(f.read()) + assert res == (128, 64, "jpg") + with open("tests/resources/gns3_icon_128x64.png", "rb") as f: + res = get_size(f.read()) + assert res == (128, 64, "png") + with open("gns3server/symbols/dslam.svg", "rb") as f: + res = get_size(f.read()) + assert res == (50, 53, "svg") + # Symbol using size with cm + with open("gns3server/symbols/cloud.svg", "rb") as f: + res = get_size(f.read()) + assert res == (159, 71, "svg")