I am using the barcode_widget to generate both barcode and 2d QR code. But I also need to print and save the codes.
My Current code for generating bar code and qr code is as below:
Center(
child: BarcodeWidget(
data: widget.product.productId!,
barcode: Barcode.code128(),
width: 200,
height: 200,
drawText: false,
),
),
and
BarcodeWidget(
data: widget.product.productId!,
barcode: Barcode.qrCode(),
),
Both are inside a Column and I have two buttons called save and print. So how can I save and print the generated codes?
You can use RepaintBoundary
Follow these steps:
1. Create a key.
GlobalKey _screenShotKey = GlobalKey();
2. Wrap the barcode in a repaint boundary and attach the key
RepaintBoundary(
key: _screenShotKey,
child: Center(
child: BarcodeWidget(
data: widget.product.productId!,
barcode: Barcode.code128(),
width: 200,
height: 200,
drawText: false,
),
)
)
3. Import dart:ui as ui
import 'dart:ui' as ui;
4. Create a method to take a screenshot of the widget and save it.
Future<File> takeScreenshot() async {
RenderRepaintBoundary boundary =
_screenShotKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final tempPath = (await getTemporaryDirectory()).path;
final path = tempPath + "qr.png";
File imgFile = File(path);
return imgFile.writeAsBytes(pngBytes);
}
5. To save in gallery/photos app; Use GallerySaver package
void save() async {
takeScreenshot().then((value) async {
bool saved = await GallerySaver.saveImage(value.path);
print(saved);
}).catchError((onError) {});
}
Related
I am downloading an image from Internet to the device and then updating a SQLITE table to store the image path:
Future<void> _download(String archivo, String docId, OfertaDB doc) async {
final docUrl = Constantes.docsProyecto+archivo;
final response = await http.get(Uri.parse(docUrl));
// Get the image name
final imageName = path.basename(docUrl);
// Get the document directory path
final appDir = await getApplicationDocumentsDirectory();
// This is the saved image path
// You can use it to display the saved image later
final localPath = path.join(appDir.path, imageName);
// Downloading
final imageFile = File(localPath);
await imageFile.writeAsBytes(response.bodyBytes);
print("path de ofertas ${appDir.path}/${imageName}");
var documentoDescargado = OfertaDB(
id: doc.id,
header: doc.header,
estado: doc.estado,
titulo: doc.titulo,
titulofr: doc.titulofr,
texto: doc.texto,
textofr: doc.textofr,
fechas: doc.fechas,
imagen: doc.imagen,
path: "${appDir.path}/${imageName}"
);
await dbHelper.updateOferta(documentoDescargado);
}
Then on another screen I need to display the image from SQLITE table:
var pathAr = news_promos.path;
print("path es ${pathAr}");//output /data/user/0/red.faro.labelconciergeflutter/app_flutter/Ezg7a9joalimaldivesvilla.jpeg
File image = File(pathAr);
Then to display the image:
Container(
alignment: Alignment.center,
width: 100,
height: 100,
child: image != null
? Image.file(image!, fit: BoxFit.cover)
: const Text('Please select an image'),
),
But the image is not displayed, it is shown an Exception: invalid image data error
What is wrong in the code used?
I want to have a feature in my Flutter App like Snapcodes on Snapchat. Basically custom “QR” Codes (they aren’t scannable to anything besides Snapchat so not really QR codes) with the app icon in them that launch a users profile when scanned in the app. I can make a simple version of this with plain QR codes using a pub package and Firebase Deeplinking but that isn’t what I want. What I think needs to be done is to create my own “qr” code generator that makes code holding a uid and then a way to decode them when scanned but I have no idea how to do that. Any ideas or pub packages that can do this?
Added for comment:
So I was looking through my old project and I got this ( The Idea of the source code below is that your taking a screenshot programmatically):
import 'dart:ui' as ui; //
final _renderObjectKey = new GlobalKey();
int randomDigit;
Timer _timer;
String userID;
void startTimer() {
//Generate random numbers attached to userID to make qrcode change periodically: improve on this!!!
var range = new Random();
_timer = new Timer.periodic(Duration(seconds: 10), (timer) {
setState(() {
randomDigit = range.nextInt(800) + 100;
});
});
}
#override
void initState() {
super.initState();
userID = auth.currentUser.uid; //if you are using firebaseauth
startTimer();
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
......
// The widget below is placed inside the body of scaffold
RepaintBoundary(
key: _renderObjectKey,
child:Stack(
alignment: Alignment.center,
children:[
BarcodeWidget(
color: Color(0xFFF9F9F9),
barcode: Barcode.qrCode(
errorCorrectLevel:BarcodeQRCorrectionLevel.high,),
data: '$userID$randomDigit', // this could be uuid
width: height * 0.32, // you can adjust to your liking
height: height * 0.32,
) // BarcodeWidget,
Container( height: 50,width: 50,child:AssetImage('assets/icon.png') // you can do whatever here
])//Stack
)//Repaint boundary
This is where the sauce is:
For android:
void _takePhoto(String _dataString) async {
int randomDigit;
var range = new Random();
randomDigit = range.nextInt(1000000) + 1;
RenderRepaintBoundary boundary =
_renderObjectKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file =
await new File('${tempDir.path}/image$randomDigit.png').create();
await file.writeAsBytes(pngBytes).then((value) {
GallerySaver.saveImage(value.path, albumName: 'Android Photo album')
.then((bool success) {});
});
}
For Ios:
Future<Uint8List> _getWidgetImage(String _dataString) async {
try {
RenderRepaintBoundary boundary =
_renderObjectKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
ByteData byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.png').create();
await file.writeAsBytes(pngBytes);
await Share.file(_dataString, '$_dataString.png', pngBytes, 'image/png');
var bs64 = base64Encode(pngBytes);
debugPrint(bs64.length.toString());
return pngBytes;
} catch (exception) {
print(exception);
}
}
Calling the functions:
_takePhoto('$userID$randomDigit');//Android in a textbutton your choice
_getWidgetImage('$userID$randomDigit');//IOS in a textbtuton
keep in mind that I have not been tracking the flutter dependencies I used in this project but I will include them from my pubspec.yaml file:
qr_flutter: ^3.2.0
qrcode: ^1.0.4
barcode: ^1.17.1
share: ^0.6.5+4
gallery_saver: ^2.0.1
path_provider: ^1.6.24
path: ^1.7.0
esys_flutter_share: ^1.0.2
Note: Copy and paste will not work. This will need adjustments.
There are lot of references of uploading a dart:io 'File' but I want to upload a material.dart Image to firebase.
My Image comes from a processed Thumbnail of a video and not just picked by a Image picker.
This is how I generate a thumbnail,
Future<ThumbnailResult> genThumbnail(url) async {
//WidgetsFlutterBinding.ensureInitialized();
Uint8List bytes;
final Completer<ThumbnailResult> completer = Completer();
bytes = await VideoThumbnail.thumbnailData(
video: url,
imageFormat: ImageFormat.JPEG,
maxHeight: 250,
maxWidth: 300,
timeMs: 0,
quality: 0);
int _imageDataSize = bytes.length;
print("image size: $_imageDataSize");
final _image = Image.memory(bytes);
//final _file =File.fromRawPath(bytes);
_image.image
.resolve(ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(ThumbnailResult(
image: _image,
dataSize: _imageDataSize,
height: info.image.height,
width: info.image.width,
));
}));
return completer.future;
}
and this is how File is uploaded to firebase
String Thumbfileurl = await uploadFile(thumbResult.image, fileName, fileType);
And inside uploadFile()
final StorageUploadTask uploadTask = storageReference.putFile(file);
So as you see , A File is needed , but i have an Image , is there a way to Convert Image to File or is there any workaround to achieve this .
I am trying to generate an image using RenderRepaintBoundary and want to save the image in my local directory.
I am able to save the image but I get a black image instead of a QR image.
Code block where I am writing the image to the directory:
try {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
var image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final file =
await new File('/<localpath>/image.png').create();
await file.writeAsBytes(pngBytes);
} catch (e) {
print(e);
}
Code block where QR code is being generated:
RepaintBoundary( key: globalKey,child: QrImage(data: _dataString,size: 0.3 * bodyHeight,), );
This is caused by having transparent background;
Simple solution is to wrap your QrImage with Container that has white backround:
Container(
color: Colors.white,
child: QrImage(....
)
There is the way to save the widget into transparent png and save it into gallery?
Thanks in advance.
Flutter draws every single pixel, so you can easily convert your widget to an image.
You need to follow these steps:
Edit -- first import path_provider link to pupspec.yaml and then follow this steps
Create a GlobalKey
final _globalKey = GlobalKey();
Create Uint8List
Uint8List pngBytes;
Wrap your widget with RepaintBoundary widget & pass in the key
RepaintBoundary(
key: _globalKey,
child: YourWidget(),
),
Create a method to convert your widget to image:
Future<void> _capturePng() async {
try {
final RenderRepaintBoundary boundary =
_globalKey.currentContext.findRenderObject();
final image = await boundary.toImage(pixelRatio: 2.0); // image quality
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
pngBytes = byteData.buffer.asUint8List();
} catch (e) {
print(e);
}
}
Convert your image to a file so that you can save it in your app
Future<File> convertImageToFile(Uint8List image) async {
final file = File(
'${(await
getTemporaryDirectory()).path}/${DateTime.now().millisecondsSinceEpoch}.png');
await file.writeAsBytes(image);
return file;
}