'How to convert SVG to PNG in flutter
I am looking to convert SVG from assets to png and write it to File.
I have managed to write SVG to file, but I want to write the image to a file as a PNG
code that writes SVG to file :
final bytes = await rootBundle.load('assets/images/example.svg');
final String tempPath = (await getTemporaryDirectory()).path;
final File file = File('$tempPath/profile.svg');
await file.writeAsBytes(
bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));
return file;
}
Solution 1:[1]
I found a solution to your problem on another answer.
You will need to add flutter_svg
as a dependency of your project.
This is almost a copy past of the code given on the referenced answer:
Future<Uint8List> svgToPng(BuildContext context, String svgString,
{int svgWidth, int svgHeight}) async {
DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, null);
// to have a nice rendering it is important to have the exact original height and width,
// the easier way to retrieve it is directly from the svg string
// but be careful, this is an ugly fix for a flutter_svg problem that works
// with my images
String temp = svgString.substring(svgString.indexOf('height="') + 8);
int originalHeight =
svgHeight ?? int.parse(temp.substring(0, temp.indexOf('p')));
temp = svgString.substring(svgString.indexOf('width="') + 7);
int originalWidth =
svgWidth ?? int.parse(temp.substring(0, temp.indexOf('p')));
// toPicture() and toImage() don't seem to be pixel ratio aware, so we calculate the actual sizes here
double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
double width = originalHeight *
devicePixelRatio; // where 32 is your SVG's original width
double height = originalWidth * devicePixelRatio; // same thing
// Convert to ui.Picture
final picture = svgDrawableRoot.toPicture(size: Size(width, height));
// Convert to ui.Image. toImage() takes width and height as parameters
// you need to find the best size to suit your needs and take into account the screen DPI
final image = await picture.toImage(width.toInt(), height.toInt());
ByteData bytes = await image.toByteData(format: ImageByteFormat.png);
return bytes.buffer.asUint8List();
}
Solution 2:[2]
@pierre-hubert answer is nice. But I had to do some changes to get it working.
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:xml/xml.dart';
Future<Uint8List> svgToPng(BuildContext context, String svgString,
{int? svgWidth, int? svgHeight}) async {
DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, "key");
// Parse the SVG file as XML
XmlDocument document = XmlDocument.parse(svgString);
// Getting size of SVG
final svgElement = document.findElements("svg").first;
final svgWidth = double.parse(svgElement.getAttribute("width")!);
final svgHeight = double.parse(svgElement.getAttribute("height")!);
// toPicture() and toImage() don't seem to be pixel ratio aware, so we calculate the actual sizes here
double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
double width = svgHeight * devicePixelRatio;
double height = svgWidth * devicePixelRatio;
// Convert to ui.Picture
final picture = svgDrawableRoot.toPicture(size: Size(width, height));
// Convert to ui.Image. toImage() takes width and height as parameters
// you need to find the best size to suit your needs and take into account the screen DPI
final image = await picture.toImage(width.toInt(), height.toInt());
ByteData? bytes = await image.toByteData(format: ImageByteFormat.png);
return bytes!.buffer.asUint8List();
}
You can then use Image.memory()
widget to render the result
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Pierre HUBERT |
Solution 2 | Aadarsh Patel |