SVG scaling [SOLVED]

Post

Posted
Rating:
#1 (In Topic #1012)
Regular
JumpyVB is in the usergroup ‘Regular’
What is the best way to properly scale an svg graphic for use in Gambas IconView? Here's a hack I made to get the desired sharp result and and easier way which unfortunately yields a blurry result:

Code (gambas)

  1. Public Sub Form_Open()
  2.   Dim FilePath As String = "/usr/share/icons/Papirus/32x32/actions/home.svg"
  3.   Dim TmpDescription As String = File.Name(FilePath)
  4.   ' Method A = Sharp
  5.   Dim FileAsData As String = FixSvgResolution(FilePath, "64", "64")
  6.   Dim Pic_A As Picture = Picture.FromString(FileAsData)
  7.   IconView1.Add(0, TmpDescription, Pic_A)
  8.   ' Method B = Blurry
  9.   Dim Pic_B As Picture = Picture.Load(FilePath)
  10.   IconView1.Add(1, TmpDescription, Pic_B.Image.Stretch(64, 64).Picture)

Code (gambas)

  1. Private Function FixSvgResolution(SvgPath As String, Optional DesiredWidth As String = "32px", Optional DesiredHeight As String = "32px") As String
  2.   Dim FixedSvg As String
  3.   Dim doc As New XmlDocument(SvgPath)
  4.   Dim mainNode As XmlNode = doc.GetElementsByTagName("svg")[0] 'doc.All[0]
  5.   Dim OrigWidth As String = ""
  6.   Dim OrigHeight As String = ""
  7.   Dim Header As String = Split(mainNode.ToString(), ">")[0]
  8.   Dim Attributes As String[] = Split(Header, " ")
  9.   For i = 0 To Attributes.Count - 1
  10.     If Attributes[i] Like "*width=*" Then
  11.       OrigWidth = Split(Attributes[i], String.Chr(34))[1]
  12.     Else If Attributes[i] Like "*height=*" Then
  13.       OrigHeight = Split(Attributes[i], String.Chr(34))[1]
  14.     Endif
  15.     If OrigWidth = "" Or OrigHeight = "" Then
  16.         'Keep looking
  17.       Else
  18.         Exit 'For
  19.     Endif
  20.   Next
  21.   If OrigWidth = "" Or OrigHeight = "" Then Error.Raise("File did not contain width and height!")
  22.   mainNode.NewAttribute("width", DesiredWidth)
  23.   mainNode.NewAttribute("height", DesiredHeight)
  24.   ' mainNode.NewAttribute("viewBox", "0 0 16 16")
  25.   mainNode.NewAttribute("viewBox", "0 0 " & OrigWidth & " " & OrigHeight)
  26.   ' mainNode.NewAttribute("viewBox", "-0.2 -0.2 " & OrigWidth & ".4 " & OrigHeight & "16.4")
  27.   FixedSvg = doc.ToString()
  28.   Return FixedSvg
PS: DotNewAttribute does an update or replace to the existing attribute. But I could not find a proper way to read the xml attributes. So reading the original attribute values is another hack. I appreciate any advice in this regard aswell.
Online now: No Back to the top

Post

Posted
Rating:
#2
Avatar
Guru
cogier is in the usergroup ‘Guru’
cogier is in the usergroup ‘GambOS Contributor’
What is the best way to properly scale an svg graphic for use in Gambas IconView?

Well, I have just spent about an hour and a half on this and came up with the following that uses a little less code. Note that line 24 is needed as for some reason a SVG image saved at 128,128 ends up at 160,160!

Code (gambas)

  1. Public Sub Form_Open()
  2.  
  3.   Dim FilePath As String = "/usr/share/icons/Papirus/32x32/actions/home.svg"
  4.   Dim Pic_A As Picture = Picture.Load(FilePath)
  5.   Dim TmpDescription As String = File.Name(FilePath)
  6.  
  7.   ' Method A = Sharp
  8.   IconView1.Add(0, TmpDescription, LoadSVG(FilePath, 256, 256))
  9.  
  10.   ' Method B = Blurry
  11.   IconView1.Add(1, TmpDescription, Pic_A.Image.Stretch(256, 256).Picture)
  12.  
  13.  
  14. Public Sub LoadSVG(sPath As String, iWidth As Integer, iHeight As Integer) As Picture
  15.  
  16.   Dim hSVG As SvgImage = SvgImage.Load(sPath)
  17.   Dim pPic As Picture
  18.  
  19.   hSVG.Resize(iWidth, iHeight)
  20.   If Exist("/tmp/SVG.svg") Then Kill "/tmp/SVG.svg"
  21.   hSVG.Save("/tmp/SVG.svg")
  22.   pPic = Picture["/tmp/SVG.svg"]
  23.   pPic = pPic.Image.Resize(iWidth, iHeight).Picture 'Needed as the SVG file is bigger
  24.  
  25.   Return pPic
  26.  
  27.  

<IMG src="https://www.cogier.com/gambas/SVG1.png"> </IMG>
Online now: No Back to the top

Post

Posted
Rating:
#3
Regular
JumpyVB is in the usergroup ‘Regular’
 Thank you for your effort cogier. Makes me think I should take a peek at the source code of SvgImage.Resize. I will come back if I find something amazing.

It's a shame that using svgs in gambas is not a trivial task.
Online now: No Back to the top

Post

Posted
Rating:
#4
Banned
I guess with svg you can use resize and paint to make a Picture object.

Here's a function to create a Picture object from an svgimage using it's Resize and Paint methods


Code (gambas)

  1. '' convert an svg image to a picture
  2.  
  3. Public Sub SvgToPic(sPath As String, W As Integer, H As Integer) As Picture
  4.  
  5.   Dim sv As SvgImage = SvgImage.Load(sPath)  ' load svg
  6.  
  7.   Dim p As Picture = New Picture(W, H, True)  ' make a Picture object (transparent bg)
  8.  
  9.   sv.Resize(W, H)  ' resize svg
  10.  
  11.   Paint.Begin(p)  ' paint svg to the picture
  12.   sv.Paint(0, 0, W, H)
  13.   Paint.End
  14.   Return p
  15.  
  16.  
  17.  

PS. svgimage according to wiki is not great because qt svg methods are buggy.
/comp/gb.qt4/svgimage - Gambas Documentation
Online now: No Back to the top

Post

Posted
Rating:
#5
Regular
JumpyVB is in the usergroup ‘Regular’
 Thank you Bruce. It's elegant and it works.
Online now: No Back to the top
1 guest and 0 members have just viewed this.