Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: 'NoneType' object has no attribute 'containerSize'? #179

Closed
firefoxer22 opened this issue Jul 30, 2022 · 8 comments
Closed
Labels
question Further information is requested

Comments

@firefoxer22
Copy link

I'm working on my project to create patterns from svg code, but I have problem. It turns out that documentation doesn't provide explanation why SVGDOM is returning none. Anyway, I provide simple code that I'm working, just a note if I use simple svg code of shape or something, then it's working but when I use code from inkscape or something else, this happens.

I got this error...

width, height = svg.containerSize()
AttributeError: 'NoneType' object has no attribute 'containerSize'

And this is code....

import io
import skia
from PIL import Image


def image_from_svg(svg, element_size):
    stream = skia.MemoryStream()
    stream.setMemory(bytes(svg, 'UTF-8'))
    svg = skia.SVGDOM.MakeFromStream(stream)
    width, height = svg.containerSize()
    surface = skia.Surface(element_size, element_size)
    with surface as canvas:
        canvas.scale(element_size / width, element_size / height)
        svg.render(canvas)
    return surface.makeImageSnapshot()


def pattern_image_with_title(image_element, width, height, rotation):
    surface = skia.Surface(width, height)
    with surface as canvas:
        pattern(canvas, image_element, rotation)
    return surface.makeImageSnapshot()


def pattern(canvas, image_element, rotation):
    matrix = skia.Matrix()
    matrix.preRotate(rotation)
    canvas.drawPaint({
        'Shader': image_element.makeShader(
            skia.TileMode.kRepeat,
            skia.TileMode.kRepeat,
            matrix,
        )
    })


def write_png(file_name, skia_image):
    with io.BytesIO(skia_image.encodeToData()) as f:
        pil_image = Image.open(f)
        pil_image.save(file_name, 'PNG')


def write_jpeg(file_name, skia_image, background):
    with io.BytesIO(skia_image.encodeToData()) as f:
        pil_image = Image.open(f)
        new_image = Image.new("RGBA", pil_image.size, background)
        new_image.paste(pil_image, (0, 0), pil_image)
        new_image = new_image.convert('RGB')
        new_image.save(file_name, 'JPEG')

svg_code = """<svg
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg5"
   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
   sodipodi:docname="signiture.svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <sodipodi:namedview
     id="namedview7"
     pagecolor="#ffffff"
     bordercolor="#000000"
     borderopacity="0.25"
     inkscape:showpageshadow="2"
     inkscape:pageopacity="0.0"
     inkscape:pagecheckerboard="0"
     inkscape:deskcolor="#d1d1d1"
     inkscape:document-units="mm"
     showgrid="false"
     inkscape:zoom="0.67150344"
     inkscape:cx="276.24579"
     inkscape:cy="612.80401"
     inkscape:window-width="1366"
     inkscape:window-height="714"
     inkscape:window-x="0"
     inkscape:window-y="26"
     inkscape:window-maximized="1"
     inkscape:current-layer="layer1" />
  <defs
     id="defs2" />
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <path
       style="fill:#1a1a1a;stroke-width:0.264583"
       id="path1639"
       d="m 31.809965,176.45394 c 4.616897,-6.47799 10.696953,-11.76612 16.434704,-17.21024 2.32147,-2.17247 4.657291,-4.3297 6.96441,-6.5174 4.422794,-4.19388 9.225095,-8.84396 13.510578,-13.18857 5.541907,-5.61837 10.894594,-11.41832 16.244284,-17.21827 5.878605,-6.39375 11.41064,-13.09435 17.286379,-19.49 7.9e-4,-8e-4 1.49749,-1.6475 1.86882,-1.88108 0.0452,-0.0285 0.13405,0.15652 0.0847,0.1361 -1.54823,-0.64018 -2.94082,-1.843086 -4.608189,-2.006537 -0.583813,-0.05723 -0.647374,0.978647 -0.985205,1.458217 -0.540179,0.7668 -1.099005,1.5203 -1.648507,2.28045 -6.860855,9.48903 -13.083077,19.42316 -19.157191,29.42778 -4.661252,7.98334 -9.410597,15.97956 -13.030848,24.5082 -0.47711,1.12399 -0.882362,2.27714 -1.323541,3.41571 -0.326395,1.3637 -1.130361,3.70695 -0.67786,5.23824 0.789054,2.6702 6.304534,4.14811 7.398258,4.40635 1.557801,0.3678 5.871385,-1.50104 6.999713,-1.91874 3.908473,-1.81884 7.529986,-4.15701 10.852828,-6.89715 2.576761,-2.1249 4.881462,-4.51696 7.14924,-6.95836 0.492014,-0.59089 0.99728,-1.17099 1.476039,-1.77268 1.957279,-2.45984 1.802767,-2.79309 -3.657399,-3.99345 -0.491668,-0.10809 -0.754298,0.66792 -1.108821,1.02531 -0.506468,0.51057 -0.98165,1.05124 -1.472473,1.57687 -1.689245,1.94205 -3.298714,3.97143 -4.563602,6.22201 -0.64757,1.15221 -1.326615,2.56097 -1.586227,3.88258 -0.104384,0.53138 -0.06634,1.08104 -0.09951,1.62156 0.548235,1.29974 0.384257,1.54132 1.814084,2.19424 1.961539,0.89572 3.898805,1.936 6.001126,2.4158 0.889793,0.20307 1.813189,-0.23135 2.704187,-0.42907 2.382729,-0.52873 4.278013,-1.24651 6.592228,-2.03255 1.09511,-0.40816 2.19022,-0.81632 3.28533,-1.22447 0.99805,-0.38293 1.9933,-0.77323 2.99414,-1.14877 2.07703,-0.77936 4.18823,-1.65791 6.45593,-1.5819 0.46601,0.0156 0.92175,0.14151 1.38263,0.21227 1.63634,0.46682 2.99244,1.56309 4.6815,1.88325 1.37931,0.26145 1.96422,0.14023 3.37105,0.063 2.13245,-0.19548 4.14523,-1.12557 6.30942,-1.02887 1.12305,0.0502 1.5525,0.23982 2.63057,0.54422 3.3094,1.25515 6.80164,1.84817 10.253,2.56228 2.71003,0.60416 5.3216,1.55825 7.9868,2.32444 2.16133,0.67927 4.39795,0.9199 6.65303,0.88665 1.76813,-0.15363 0.87576,-0.0592 2.67684,-0.28551 0,0 -3.80996,-2.70129 -3.80996,-2.70129 v 0 c -1.80154,0.19255 -0.90788,0.12187 -2.68074,0.21497 -2.22552,-0.0398 -4.42898,-0.31524 -6.56157,-0.98257 -2.63537,-0.76453 -5.22722,-1.69699 -7.92491,-2.22909 -3.4823,-0.6829 -6.96276,-1.38037 -10.29774,-2.62792 -1.16194,-0.27413 -1.52184,-0.43413 -2.71669,-0.42457 -2.13083,0.0171 -4.11058,0.96255 -6.23338,1.06674 -1.47927,0.0168 -1.90572,0.11961 -3.33568,-0.2385 -1.65765,-0.41514 -3.04523,-1.53183 -4.74725,-1.81127 -0.45928,-0.0296 -0.91814,-0.11095 -1.37783,-0.0887 -2.19763,0.10649 -4.22928,1.07672 -6.22944,1.88527 -4.068117,1.64451 -1.86991,0.78791 -6.186038,2.40769 -2.49709,0.7999 -4.125296,1.42675 -6.707468,1.85107 -0.919181,0.15106 -2.448687,-0.62758 -2.784081,0.24145 -0.329668,0.8542 1.550676,1.11554 1.940653,1.94395 0.381013,0.80936 -2.922603,-1.68871 -2.029542,-1.75585 -0.0083,-0.51809 -0.09355,-1.04067 -0.02498,-1.55427 0.488067,-3.65554 3.58516,-7.32509 5.984394,-9.93393 0.528973,-0.48145 1.028395,-0.99753 1.586923,-1.44436 0.37021,-0.29617 1.458388,-0.38648 1.19077,-0.77783 -0.843732,-1.23382 -2.31286,-1.90595 -3.574335,-2.70775 -0.13208,-0.0839 0.101528,0.31957 0.04887,0.46695 -0.367525,1.02861 -1.421326,2.26467 -2.001814,3.04851 -1.659633,1.9314 -2.229075,2.66959 -4.10882,4.51711 -3.94644,3.87879 -8.421206,7.14318 -13.538671,9.31269 -1.279475,0.40711 -2.524546,0.94471 -3.838424,1.22131 -1.089954,0.22945 -2.553869,-0.51216 -3.329128,0.2876 -0.510267,0.5264 1.243153,0.96033 1.433026,1.66844 0.169264,0.63127 -1.110737,-0.80628 -1.363464,-1.40901 -0.611394,-1.45811 0.07952,-3.90706 0.314783,-5.24029 0.388604,-1.15825 0.735369,-2.3314 1.165817,-3.47476 3.263683,-8.66907 7.877075,-16.76057 12.487878,-24.76152 1.173184,-1.94168 2.318864,-3.90025 3.519549,-5.82505 4.999762,-8.01507 10.379022,-15.82185 16.445362,-23.07102 0.62365,-0.7175 1.2438,-1.43807 1.87095,-2.15251 0.39448,-0.4494 1.47676,-0.8121 1.19391,-1.33895 -3.16462,-5.894501 -2.94703,-4.069508 -4.208818,-2.344166 -0.33791,0.46205 -0.690301,0.913336 -1.03545,1.370006 -5.370422,6.74587 -10.767057,13.47393 -16.35117,20.04476 -3.964133,4.57174 -5.66126,6.58851 -9.846474,11.15404 -8.358685,9.11826 -17.166833,17.82402 -26.472573,25.9772 -2.250892,1.94354 -4.476355,3.91691 -6.752674,5.8306 -1.838995,1.54603 -3.763653,2.98876 -5.591937,4.54745 -2.106631,1.79598 -3.99505,3.81215 -5.923442,5.78981 0,0 4.259194,2.54563 4.259194,2.54563 z" />
  </g>
</svg>"""

if __name__ == "__main__":
    img = image_from_svg(svg_code, 50)
    img = pattern_image_with_title(img, 300, 300, 45)
    write_png('result.png', img)
    write_jpeg('result.jpg', img, 'WHITE')

Any idea how to make this work is more then welcome. Thanks in advance!

@kyamagu
Copy link
Owner

kyamagu commented Aug 1, 2022

The current skia-python is based on m87 branch of Skia, and I remember that the SVGDOM API in that version is experimental and lacks support for many features in SVG spec.

@kyamagu kyamagu added the question Further information is requested label Aug 1, 2022
@firefoxer22
Copy link
Author

The current skia-python is based on m87 branch of Skia, and I remember that the SVGDOM API in that version is experimental and lacks support for many features in SVG spec.

Any idea how can I overcome this problem? Any alternative solutions?

@kyamagu
Copy link
Owner

kyamagu commented Aug 1, 2022

Use Inkscape or any other full-spec SVG renderer to rasterize.

@HinTak
Copy link
Collaborator

HinTak commented Jul 8, 2023

Commented in #192 (comment) , m88 (one milestone later) is when SkSVG becomes non-experimental . I need SVG functionality from m103+ myself.

@HinTak
Copy link
Collaborator

HinTak commented Jul 8, 2023

My investigation is trying alternatives to rsvg (which is cairo-based) which already works well - I just want another choice. It has stuff equivalent to m103+ so probably will suit you well.

@HinTak
Copy link
Collaborator

HinTak commented Jul 8, 2023

In particular I know the width, height retrieval with rsvg works - I am basically looking for skia-python equivalent of all the rsvg routines I use, and found the containerSize call in skia-python does not work.

@HinTak
Copy link
Collaborator

HinTak commented Jul 8, 2023

To use rsvg, you'll probably need to switch to drawing with pycairo too.

@HinTak
Copy link
Collaborator

HinTak commented Aug 16, 2023

Here is your code modified to work against current (117bX on my hard disk, but probably likely with 116b2 too):

import io
import skia
from PIL import Image


def image_from_svg(svg, element_size):
    doc = bytes(svg, 'UTF-8')
    data = skia.Data(doc)
    stream = skia.MemoryStream(data)
    svg = skia.SVGDOM.MakeFromStream(stream)
    width, height = svg.containerSize()
    if (svg.containerSize().isEmpty()):
        width, height = 1000, 1000
    surface = skia.Surface(element_size, element_size)
    with surface as canvas:
        canvas.scale(element_size / width, element_size / height)
        svg.render(canvas)
    return surface.makeImageSnapshot()


def pattern_image_with_title(image_element, width, height, rotation):
    surface = skia.Surface(width, height)
    with surface as canvas:
        pattern(canvas, image_element, rotation)
    return surface.makeImageSnapshot()


def pattern(canvas, image_element, rotation):
    matrix = skia.Matrix()
    matrix.preRotate(rotation)
    canvas.drawPaint({
        'Shader': image_element.makeShader(
[Hin-Tak@localhost examples]$ cat issue-179.py
import io
import skia
from PIL import Image


def image_from_svg(svg, element_size):
    doc = bytes(svg, 'UTF-8')
    data = skia.Data(doc)
    stream = skia.MemoryStream(data)
    svg = skia.SVGDOM.MakeFromStream(stream)
    width, height = svg.containerSize()
    if (svg.containerSize().isEmpty()):
        width, height = 1000, 1000
    surface = skia.Surface(element_size, element_size)
    with surface as canvas:
        canvas.scale(element_size / width, element_size / height)
        svg.render(canvas)
    return surface.makeImageSnapshot()


def pattern_image_with_title(image_element, width, height, rotation):
    surface = skia.Surface(width, height)
    with surface as canvas:
        pattern(canvas, image_element, rotation)
    return surface.makeImageSnapshot()


def pattern(canvas, image_element, rotation):
    matrix = skia.Matrix()
    matrix.preRotate(rotation)
    canvas.drawPaint({
        'Shader': image_element.makeShader(
            skia.TileMode.kRepeat,
            skia.TileMode.kRepeat,
            skia.SamplingOptions(),
            matrix,
        )
    })


def write_png(file_name, skia_image):
    with io.BytesIO(skia_image.encodeToData()) as f:
        pil_image = Image.open(f)
        pil_image.save(file_name, 'PNG')


def write_jpeg(file_name, skia_image, background):
    with io.BytesIO(skia_image.encodeToData()) as f:
        pil_image = Image.open(f)
        new_image = Image.new("RGBA", pil_image.size, background)
        new_image.paste(pil_image, (0, 0), pil_image)
        new_image = new_image.convert('RGB')
        new_image.save(file_name, 'JPEG')

svg_code = """<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" width="210mm" height="297mm" viewBox="0 0 210 297" version="1.1" id="svg5" inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" sodipodi:docname="signiture.svg">
  <defs id="defs2"></defs>
  <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1">
    <path style="fill:#1a1a1a;stroke-width:0.264583"
       id="path1639"
       d="m 31.809965,176.45394 c 4.616897,-6.47799 10.696953,-11.76612 16.434704,-17.21024 2.32147,-2.17247 4.657291,-4.3297 6.96441,-6.5174 4.422794,-4.19388 9.225095,-8.84396 13.510578,-13.18857 5.541907,-5.61837 10.894594,-11.41832 16.244284,-17.21827 5.878605,-6.39375 11.41064,-13.09435 17.286379,-19.49 7.9e-4,-8e-4 1.49749,-1.6475 1.86882,-1.88108 0.0452,-0.0285 0.13405,0.15652 0.0847,0.1361 -1.54823,-0.64018 -2.94082,-1.843086 -4.608189,-2.006537 -0.583813,-0.05723 -0.647374,0.978647 -0.985205,1.458217 -0.540179,0.7668 -1.099005,1.5203 -1.648507,2.28045 -6.860855,9.48903 -13.083077,19.42316 -19.157191,29.42778 -4.661252,7.98334 -9.410597,15.97956 -13.030848,24.5082 -0.47711,1.12399 -0.882362,2.27714 -1.323541,3.41571 -0.326395,1.3637 -1.130361,3.70695 -0.67786,5.23824 0.789054,2.6702 6.304534,4.14811 7.398258,4.40635 1.557801,0.3678 5.871385,-1.50104 6.999713,-1.91874 3.908473,-1.81884 7.529986,-4.15701 10.852828,-6.89715 2.576761,-2.1249 4.881462,-4.51696 7.14924,-6.95836 0.492014,-0.59089 0.99728,-1.17099 1.476039,-1.77268 1.957279,-2.45984 1.802767,-2.79309 -3.657399,-3.99345 -0.491668,-0.10809 -0.754298,0.66792 -1.108821,1.02531 -0.506468,0.51057 -0.98165,1.05124 -1.472473,1.57687 -1.689245,1.94205 -3.298714,3.97143 -4.563602,6.22201 -0.64757,1.15221 -1.326615,2.56097 -1.586227,3.88258 -0.104384,0.53138 -0.06634,1.08104 -0.09951,1.62156 0.548235,1.29974 0.384257,1.54132 1.814084,2.19424 1.961539,0.89572 3.898805,1.936 6.001126,2.4158 0.889793,0.20307 1.813189,-0.23135 2.704187,-0.42907 2.382729,-0.52873 4.278013,-1.24651 6.592228,-2.03255 1.09511,-0.40816 2.19022,-0.81632 3.28533,-1.22447 0.99805,-0.38293 1.9933,-0.77323 2.99414,-1.14877 2.07703,-0.77936 4.18823,-1.65791 6.45593,-1.5819 0.46601,0.0156 0.92175,0.14151 1.38263,0.21227 1.63634,0.46682 2.99244,1.56309 4.6815,1.88325 1.37931,0.26145 1.96422,0.14023 3.37105,0.063 2.13245,-0.19548 4.14523,-1.12557 6.30942,-1.02887 1.12305,0.0502 1.5525,0.23982 2.63057,0.54422 3.3094,1.25515 6.80164,1.84817 10.253,2.56228 2.71003,0.60416 5.3216,1.55825 7.9868,2.32444 2.16133,0.67927 4.39795,0.9199 6.65303,0.88665 1.76813,-0.15363 0.87576,-0.0592 2.67684,-0.28551 0,0 -3.80996,-2.70129 -3.80996,-2.70129 v 0 c -1.80154,0.19255 -0.90788,0.12187 -2.68074,0.21497 -2.22552,-0.0398 -4.42898,-0.31524 -6.56157,-0.98257 -2.63537,-0.76453 -5.22722,-1.69699 -7.92491,-2.22909 -3.4823,-0.6829 -6.96276,-1.38037 -10.29774,-2.62792 -1.16194,-0.27413 -1.52184,-0.43413 -2.71669,-0.42457 -2.13083,0.0171 -4.11058,0.96255 -6.23338,1.06674 -1.47927,0.0168 -1.90572,0.11961 -3.33568,-0.2385 -1.65765,-0.41514 -3.04523,-1.53183 -4.74725,-1.81127 -0.45928,-0.0296 -0.91814,-0.11095 -1.37783,-0.0887 -2.19763,0.10649 -4.22928,1.07672 -6.22944,1.88527 -4.068117,1.64451 -1.86991,0.78791 -6.186038,2.40769 -2.49709,0.7999 -4.125296,1.42675 -6.707468,1.85107 -0.919181,0.15106 -2.448687,-0.62758 -2.784081,0.24145 -0.329668,0.8542 1.550676,1.11554 1.940653,1.94395 0.381013,0.80936 -2.922603,-1.68871 -2.029542,-1.75585 -0.0083,-0.51809 -0.09355,-1.04067 -0.02498,-1.55427 0.488067,-3.65554 3.58516,-7.32509 5.984394,-9.93393 0.528973,-0.48145 1.028395,-0.99753 1.586923,-1.44436 0.37021,-0.29617 1.458388,-0.38648 1.19077,-0.77783 -0.843732,-1.23382 -2.31286,-1.90595 -3.574335,-2.70775 -0.13208,-0.0839 0.101528,0.31957 0.04887,0.46695 -0.367525,1.02861 -1.421326,2.26467 -2.001814,3.04851 -1.659633,1.9314 -2.229075,2.66959 -4.10882,4.51711 -3.94644,3.87879 -8.421206,7.14318 -13.538671,9.31269 -1.279475,0.40711 -2.524546,0.94471 -3.838424,1.22131 -1.089954,0.22945 -2.553869,-0.51216 -3.329128,0.2876 -0.510267,0.5264 1.243153,0.96033 1.433026,1.66844 0.169264,0.63127 -1.110737,-0.80628 -1.363464,-1.40901 -0.611394,-1.45811 0.07952,-3.90706 0.314783,-5.24029 0.388604,-1.15825 0.735369,-2.3314 1.165817,-3.47476 3.263683,-8.66907 7.877075,-16.76057 12.487878,-24.76152 1.173184,-1.94168 2.318864,-3.90025 3.519549,-5.82505 4.999762,-8.01507 10.379022,-15.82185 16.445362,-23.07102 0.62365,-0.7175 1.2438,-1.43807 1.87095,-2.15251 0.39448,-0.4494 1.47676,-0.8121 1.19391,-1.33895 -3.16462,-5.894501 -2.94703,-4.069508 -4.208818,-2.344166 -0.33791,0.46205 -0.690301,0.913336 -1.03545,1.370006 -5.370422,6.74587 -10.767057,13.47393 -16.35117,20.04476 -3.964133,4.57174 -5.66126,6.58851 -9.846474,11.15404 -8.358685,9.11826 -17.166833,17.82402 -26.472573,25.9772 -2.250892,1.94354 -4.476355,3.91691 -6.752674,5.8306 -1.838995,1.54603 -3.763653,2.98876 -5.591937,4.54745 -2.106631,1.79598 -3.99505,3.81215 -5.923442,5.78981 0,0 4.259194,2.54563 4.259194,2.54563 z"></path>
  </g>
</svg>
"""

if __name__ == "__main__":
    img = image_from_svg(svg_code, 50)
    img = pattern_image_with_title(img, 300, 300, 45)
    write_png('result.png', img)
    write_jpeg('result.jpg', img, 'WHITE')

There are three sets of modifications - the addition of skia.SamplingOptions() passed to Image.makeShader() is a documented m87 to m116 change; the other two, (1) the initialization of the memory stream seems to be quite picky - I am surprised that yours work at all, it does not at all for me; I have to go via the skia.Data() route, (2) your svg data itself seems to be invalid / truncated (it ends in the x co-ordinate of a point, without the y). I passes your svg through https://svg.enshrined.co.uk / https://github.com/darylldoyle/svg-sanitizer .

As you found, if skia is not happy with either the stream or the svg, there is not much feedback.

If you have more comments about why your memory stream initialization does not work, or how your svg data is invalid, I'd like to know. But for now, I'd suggest integrate the svg-sanitizer into your work :-) . Sorry can't be more constructive.

@HinTak HinTak closed this as completed Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants