dart 如何在flutter中将SVG转换为PNG

u0njafvf  于 2023-03-27  发布在  Flutter
关注(0)|答案(3)|浏览(315)

我期待将SVG从资产转换为PNG,并将其写入文件。
我已经设法将SVG写入文件,但我想将图像作为PNG写入文件
将SVG写入文件的代码:

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;
}
zte4gxcn

zte4gxcn1#

我在another answer上找到了解决问题的方法。
您需要添加flutter_svg作为项目的依赖项。
这几乎是引用答案中给出的代码的副本:

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();
}
laawzig2

laawzig22#

@pierre-hubert的回答很好。但是我必须做一些改变才能让它工作。

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();
}

然后可以使用Image.memory()小部件呈现结果

gojuced7

gojuced73#

DrawableRoot在新版本的flutter_svg中不可用。新的方法是使用VectorGraphicUtilities:

final pictureInfo = await vg.loadPicture(SvgStringLoader(...));
final image = await pictureInfo.picture.toImage(...);

结果是一个位图图像,可以转换成任何其他支持的格式,例如png:

final byteData = await image.toByteData(format: ImageByteFormat.png);
final pngBytes = byteData!.buffer.asUint8List();

然后可以在设备上保存为Img:

final file = await File('test.png').create();
await file.writeAsBytes(pngBytes);

所以所有的东西放在一起:

import 'package:flutter_svg/flutter_svg.dart';
Future<Uint8List> svgToPng(String svgString, BuildContext context) async {
  final pictureInfo = await vg.loadPicture(SvgStringLoader(svgString), context);

  final image = await pictureInfo.picture.toImage(100, 100);
  final byteData = await image.toByteData(format: ImageByteFormat.png);

  if (byteData == null) {
    throw Exception('Unable to convert SVG to PNG');
  }

  final pngBytes = byteData.buffer.asUint8List();
  return pngBytes;

}

相关问题