Reputation: 577
Below is a snippet of code from a function that uploads a generated QR code (using the qr_flutter package) to firebase storage; then gets the firebase storage url to save in a custom model that is uploaded to firebase firestore (not shown).
This works fine, however I want to upload a file that consists of the QR code bounded by title text above and address text below. (Essentially a Column with children [title, qrFile, address]).
My question is: How do I combine Text and my qrFile into a single image file that I can upload to firebase storage?
String qrString = 'qr_data_here';
final qrValidationResult = QrValidator.validate(
data: qrString,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.L,
);
if (qrValidationResult.status == QrValidationStatus.valid) {
final qrCode = qrValidationResult.qrCode;
const String title = 'title_name_here';
final String address = 'address_here';
final painter = QrPainter.withQr(
qr: qrCode!,
color: const Color(0xFF000000),
gapless: true,
embeddedImageStyle: null,
embeddedImage: null,
);
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
final ts = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$tempPath/$ts.png';
// ui is from import 'dart:ui' as ui;
final picData =
await painter.toImageData(2048, format: ui.ImageByteFormat.png);
// writeToFile is seen in code snippet below
await writeToFile(
picData!,
path,
);
} else {
genericErrorDialog(context);
}
// qrStorage is a reference to a folder in firebase storage
await qrStorage.child('name_here').putFile(qrFile);
var url =
await qrStorage.child('name_here').getDownloadURL();
late File qrFile;
Future<void> writeToFile(ByteData data, String path) async {
final buffer = data.buffer;
qrFile = await File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
Upvotes: 1
Views: 1184
Reputation: 577
One solution is to use the screenshot package (https://pub.dev/packages/screenshot). This package has a function to save a widget as an image (without displaying it on screen) as shown below.
ScreenshotController screenshotController = ScreenshotController();
await screenshotController
.captureFromWidget(CustomWidget())
.then((capturedImage) async {
await do_something_with_capturedImage_here();
});
As it relates to my question specifically; Below is the code to generate a qr code, place it in a widget (needs some more formatting) with text, and then save the widget as an image file and upload to firebase.
String qrString = 'qr_data_here';
final qrValidationResult = QrValidator.validate(
data: qrString,
version: QrVersions.auto,
errorCorrectionLevel: QrErrorCorrectLevel.L,
);
if (qrValidationResult.status == QrValidationStatus.valid) {
final qrCode = qrValidationResult.qrCode;
const String title = 'title_name_here';
final String address = 'address_here';
final painter = QrPainter.withQr(
qr: qrCode!,
color: const Color(0xFF000000),
gapless: true,
embeddedImageStyle: null,
embeddedImage: null,
);
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
final ts = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$tempPath/$ts.png';
// ui is from import 'dart:ui' as ui;
final picData =
await painter.toImageData(2048, format: ui.ImageByteFormat.png);
// writeToFile is seen in code snippet below
await writeToFile(
picData!,
path,
);
await screenshotController
.captureFromWidget(Column(
children: [
Text(title),
Image.file(qrFile),
Text(address),
],
))
.then((capturedImage) async {
await widgetToImageFile(capturedImage);
});
} else {
genericErrorDialog(context);
}
// qrStorage is a reference to a folder in firebase storage
await qrStorage.child('name_here').putFile(fullQrFile);
var url =
await qrStorage.child('name_here').getDownloadURL();
ScreenshotController screenshotController = ScreenshotController();
late File qrFile;
late File fullQrFile;
Future<void> writeToFile(ByteData data, String path) async {
final buffer = data.buffer;
qrFile = await File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
Future<void> widgetToImageFile(
Uint8List capturedImage,
) async {
Directory newTempDir = await getTemporaryDirectory();
String newTempPath = newTempDir.path;
final newTs = DateTime.now().millisecondsSinceEpoch.toString();
String path = '$newTempPath/$newTs.png';
fullQrFile = await File(path).writeAsBytes(capturedImage);
}
Upvotes: 1