I have created a sample app that saves a container as an image using flutter. This works totally fine with the android device and the saved image is of good quality. However, when I check this in the iPhone (emulator and physical device) the saved image is not in good quality.
Below is the code that I have used to save the container as an image and I just pass the global key of my container that needs to save.
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:ui' as ui;
import 'dart:io' as Io;
import 'package:path_provider/path_provider.dart';
import 'package:gallery_saver/gallery_saver.dart';
class ImageExport {
save(GlobalKey globalKey) async {
Random random = new Random();
int randomNumber = random.nextInt(1000);
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 5.0);
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
Io.File imgFile = new Io.File('$directory/test$randomNumber.jpg');
imgFile.writeAsBytes(pngBytes);
imgFile.writeAsBytesSync(pngBytes);
GallerySaver.saveImage(imgFile.path, albumName: "test");
}
}
Could some please help me resolve this issue?
Related
I am trying to build an application on Windows, which i pick (.pdf) files that contain a barcode on them.
I want to find and extract the barcode info and put it on a list.
I need a package that it can make it happen. A package except https://pub.dev/packages/flutter_barcode_sdk because it has an annually cost for its licence.
I spent some time writing this for you and I made it using two different packages.
This one is able to read barcodes from camera and files
scan: 1.6.0
But I could not make it read PDFs, so I installed another package to render images from PDF files.
native_pdf_renderer: 3.1.0
This package is also required:
path_provider: ^2.0.11
This is the code that worked fine for me:
import 'dart:async';
import 'dart:io';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
import 'package:path_provider/path_provider.dart';
import 'package:scan/scan.dart';
Future<void> readBarcodeFromPDF(String assetPath) async {
PdfDocument pdf = await PdfDocument.openAsset(assetPath);
for (var pageIndex = 0; pageIndex < pdf.pagesCount; pageIndex++) {
final page = await pdf.getPage(pageIndex);
final image = await page.render(width: 2048, height: 2048);
if (image != null) {
final byteData = image.bytes;
final file = File('${(await getTemporaryDirectory()).path}/barcodes');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
String? barcode = await Scan.parse(file.path);
if (barcode == null) {
print("barcode not found in page $pageIndex");
} else {
print("Barcode Found: $barcode in page $pageIndex");
}
}
}
}
To get images from phone gallery,, Using MultiImagePicker2 package https://pub.dev/packages/multi_image_picker2
you get The Images in Object of type Asset,, then you usually transform the ByteData into a File to use it around ,, using the below method,, you get File from Asset.
import 'dart:io';
import 'package:bldrs/controllers/drafters/text_manipulators.dart';
import 'package:flutter/services.dart';
import 'package:multi_image_picker2/multi_image_picker2.dart';
import 'package:path_provider/path_provider.dart';
Future<File> getFileFromAsset(Asset asset) async {
ByteData _byteData = await asset.getThumbByteData(asset.originalWidth, asset.originalHeight, quality: 100);
String _name = TextMod.trimTextAfterLastSpecialCharacter(asset.name, '.');
print('asset name is : ${asset.runtimeType}');
final _tempFile = File('${(await getTemporaryDirectory()).path}/${_name}');
await _tempFile.writeAsBytes(_byteData.buffer.asUint8List(_byteData.offsetInBytes, _byteData.lengthInBytes));
await _tempFile.create(recursive: true);
File _file = _tempFile;
return _file;
}
so my question is..
Can you reverse this method,, to get Asset from File instead ?
In my App, I need to create Images from the Widgets shown on Screen.
I used the below code to create the Image using RepaintBoundary.
But the image I get is of 72 PPI.
Is there any way I can get An Image of Higher Resolution?
Future<void> takePicture() async {
RenderRepaintBoundary boundary = genKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
File imgFile = new File('$directory/photo.png');
imgFile.writeAsBytes(pngBytes);
}
use this line will improve the "boundary.toImage(pixelRatio: 10.0)"
pixelRatio use as double to improve the quality as u want.
In Flame documentation, Image class just load from asset folder.
bgSprite = Sprite('avatar/avatar-sample.png');
How can I load network images in Flame.
You could do something like this in versions after 1.0.0:
import dart:ui; // This is the package you want the Image class from, there are several
Future<Image> getImage(String path) async {
Completer<ImageInfo> completer = Completer();
var img = new NetworkImage(path);
img.resolve(ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info,bool _){
completer.complete(info);
}));
ImageInfo imageInfo = await completer.future;
return imageInfo.image;
}
and then in your onLoad method, just initiate bgSprite:
#override
Future<void> onLoad() async {
final image = await getImage("your-url.com/sample.png");
bgSprite = Sprite(image);
}
In 0.28.0, which it looks like you are running, you'll just replace the last line with (but I really recommend upgrading to a version after 1.0.0):
bgSprite = Sprite.fromImage(image);
I'm trying to convert a network image into a file and the first part of that is to convert it into a Uint8List. Here is how I'm doing this with 1 of my asset images...
final ByteData bytes = await rootBundle.load('assests/logo');
final Uint8List list = bytes.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.jpg').create();
file.writeAsBytesSync(list);
How can I do this with Image.network(imageUrl.com/image)
The simplest way seeems to get the http response using the image url and response.bodyBytes would contain the data in Uint8List.
http.Response response = await http.get(
'https://flutter.io/images/flutter-mark-square-100.png',
);
response.bodyBytes //Uint8List
Now you can do things like converting to base64 encoded string base64.encode(response.bodyBytes);
Update: With newer version of http, you need to add Uri.parse()
Eg.
http.Response response = await http.get(
Uri.parse('https://flutter.io/images/flutter-mark-square-100.png'),
);
I figured out a different solution. Hope it helps someone.
import 'dart:typed_data';
import 'package:flutter/services.dart';
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imageUrl))
.load(imageUrl))
.buffer
.asUint8List();
void initState() {
super.initState();
var sunImage = new NetworkImage(
"https://resources.ninghao.org/images/childhood-in-a-picture.jpg");
sunImage.obtainKey(new ImageConfiguration()).then((val) {
var load = sunImage.load(val);
load.addListener((listener, err) async {
setState(() => image = listener);
});
});
}
See also https://github.com/flutter/flutter/issues/23761#issuecomment-434606683
Then you can use image.toByteData().buffer.asUInt8List()
See also https://docs.flutter.io/flutter/dart-ui/Image/toByteData.html
The answers here are relevant and help explain how dart and flutter image compression/conversion works. If you would like a shortcut, there is this package https://pub.dev/packages/network_image_to_byte that makes it really easy.
After trying for hours this is what helped me
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
Future<File> getFileFromNetworkImage(String imageUrl) async {
var response = await http.get(imageUrl);
final documentDirectory = await getApplicationDocumentsDirectory();
String fileName = DateTime.now().millisecondsSinceEpoch.toString();
File file = File(path.join(documentDirectory.path, '$fileName.png'));
file.writeAsBytes(response.bodyBytes);
return file;
}
final file = await getFileFromNetworkImage("<your network image Url here>");
Note: this also converts mp4 videos to a File.
originally answered here
As http needs Uri this would be helpful:
you should remove the begining serverAddress from your ImageAddress first :
something like this in my case that I have 3001 in my url:
String serverAddress = 'myAddress.com:3001';
int indexOf3001 = imageAddress.indexOf('3001');
String trimmedImageAddress= imageAddress.substring(indexOf3001 + 4);
then :
var imageUrl = Uri.https(serverAddress, trimmedImageAddress);
final http.Response responseData = await http.get(imageUrl);
Uint8List imageBytes = responseData.bodyBytes;
this works on device and web too, hope it can help.