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’
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
Guru
BruceSteers is in the usergroup ‘Guru’
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.