How to convert an SVG file from the Flutter Assets to a Bitmap?
You need flutter_svg library, that you probably already use if you are playing with SVG.
You need also bitmap library.
import 'package:bitmap/bitmap.dart';
import 'package:flutter_svg/flutter_svg.dart';
String svgString = await DefaultAssetBundle.of(context).loadString(svg_path);
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 = int.parse(temp.substring(0, temp.indexOf('p')));
temp = svgString.substring(svgString.indexOf('width="')+7);
int originalWidth = 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
ui.Picture 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
ui.Image image = await picture.toImage(width.toInt(), height.toInt());
ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png);
// finally to Bitmap
Bitmap bitmap = await Bitmap.fromHeadless(width.toInt(), height.toInt(),
bytes.buffer.asUint8List()
);
// if you need to save it:
File file = File('temporary_file_path/unique_name.bmp');
file.writeAsBytesSync(bitmap.content);
Some credit to this StackOverflow answer
Related
I'm working on a screen recording app in Flutter. In order to keep the quality of the captured screen image, I have to scale the image as shown below. However, it makes the image data very large. How can I reduce the data size (scale back to the original size) before saving it to a file? For performance reasons, I want to work with raw RGBA instead of encoding it PNG.
double dpr = ui.window.devicePixelRatio;
final boundary =
key.currentContext!.findRenderObject() as RenderRepaintBoundary;
return getBufferSync(key);
}
ui.Image image = boundary.toImageSync(pixelRatio: dpr);
var rawBytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
Uint8List uData = rawBytes!.buffer.asUint8List();
I am trying to create custom dynamic markers (changes on tap) for my google maps project. Each marker shows a shop with some promotion going on. A single shop can have 3 promotions displayed at the same time and it is supposed to be highlighted if tapped on
I have tried to convert the SVGs for the markers in Canvas code using online tools, but it's bulky and I don't understand it well.
Here's the screenshot for an example screen
Here's the code written for converting theses SVGs to image byte data for use as marker icons
static Future<ByteData?> marker({double? width}) async {
width ??= 88;
double height = width * 1.2247191011235956;
final recorder = ui.PictureRecorder();
final canvas = Canvas(recorder,
Rect.fromPoints(const Offset(0.0, 0.0), const Offset(200.0, 200.0)));
Size size = Size(width, (width * 1.2247191011235956).toDouble());
_paintMarker(size: size, canvas: canvas);
final picture = recorder.endRecording();
final img = await picture.toImage((width).toInt(), height.toInt());
return await img.toByteData(format: ui.ImageByteFormat.png);
}
I have the following method var res = await _createChartImage(); which returns an image un byte data that I later I send to firebase await widget.firebaseRepository.saveChart(wiijiiChart, res);
I would like to resize the image using dart and not the Flutter image package I would then need to convert it back to byte data
try this for resizing image, bitmap:
You can create from a headed Uint8List:
import 'package:bitmap/bitmap.dart';
Bitmap bitmap = Bitmap.fromHeadful(imageWidth, imageHeight, theListOfInts); // Not async
Or a headless:
Bitmap bitmap = Bitmap.fromHeadless(imageWidth, imageHeight, theListOfInts); // Not async
This is useful when you are dealing with the Uint8List that ByteData generates.
import 'package:bitmap/bitmap.dart';
Bitmap bitmap = await Bitmap.fromProvider(NetworkImage("http://pudim.com.br/pudim.jpg"));
Bitmap resizedBitmap = bitmap.apply(BitmapResize.to(width: 50, height: 50));;
Uint8List headedBitmap = resizedBitmap.buildHeaded();
I have the following code and I need a way to resize the image height and width that it in ByteData here is my code
Future<ByteData?> _createChartImage() async {
var data = await _chartKey.currentState?.toImage(pixelRatio: 3.0);
var byteData = await data!.toByteData(format: ImageByteFormat.png);
return byteData;
}
You can't resize byte data, especially not byte data encoded in PNG format. So you have to first parse the byte data from PNG format back into a bitmap. And then resize the bitmap and then encode it back to PNG.
I would suggest taking a look at the image package.
Something like the following should work:
final image = decodePng(byteData!.buffer.asUint8List());
final resized = copyResize(image, width: 120);
final resizedByteData = encodePng(image);
return ByteData.sublistView(resizedByteData);
I want to OCR text from a base64 encoded image.
I know the image works because I can display it using
Image.memory(base64Decode(captchaEncodedImgFetched))
Now, the problem is I need to pass this image to Firebase ML Vision for processing.
The library firebase_ml_vision has an example for using a image from file
final File imageFile = getImageFile();
final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(imageFile);`
However I have a base64 encoded image.
I tried the following
final FirebaseVisionImage visionImage = FirebaseVisionImage.fromBytes(
base64Decode(captchaEncodedImgFetched));
But it seems to need FirebaseVisionImageMetadata() as a argument, but I know nothing about byte images.
This class needs a lot more arguments which I don't understand.
For example, it needs a size : Size(width, height) argument. Isn't the image supposed to have a size already? Why do I need to specify it again?
For now I set it to Size(200, 50). Then there are the other arugments and I don't know what to pass to them. For exmaple the planeData and rawFormat.
Here are the docs for these:
https://pub.dev/documentation/firebase_ml_vision/latest/firebase_ml_vision/FirebaseVisionImageMetadata-class.html
https://pub.dev/documentation/firebase_ml_vision/latest/firebase_ml_vision/FirebaseVisionImagePlaneMetadata-class.html
https://pub.dev/documentation/firebase_ml_vision/latest/
FirebaseVisionImage.fromBytes needs FirebaseVisionImageMetadata which intern needs FirebaseVisionImagePlaneMetadata. Example below :
// Below example uses metadata values based on an RGBA-encoded 1080x1080 image
final planeMetadata = FirebaseVisionImagePlaneMetadata(
width: 1080,
height: 1080,
bytesPerRow: 1080 * 4,
);
final imageMetadata = FirebaseVisionImageMetadata(
size: Size(1080, 1080),
planeData: planeMetadata,
rawFormat: 'RGBA',
);
final visionImage = FirebaseVisionImage.fromBytes(decoded, metadata);
The simpler workaround though at a cost of performance is to write the bytes to the disk and read the image from there, as :
File imgFile = File('myimage.png');
imageFile.writeAsBytesSync(decoded.ToList());
final visionImage = FirebaseVisionImage.fromFile(imageFile);