I want to take a screenshot of any widget and then share it to WhatsApp or any other app. But from the screenshot widget, I get uint8List type of image but I want to convert it into image type and then Share it with Flutter_Share plugin, so I have to convert it into Image. How to do that?
controller
.capture(delay: Duration(milliseconds: 10))
.then((capturedImage) async {
final imagePath = await File('/image.png').create();
await imagePath.writeAsBytes(capturedImage!);
await Share.shareFiles([imagePath.path]);
}).catchError((onError) {
print(onError);
});
Here I am trying to convert it to imagePath but I got "FormatException: Unexpected extension byte (at offset 0)" this type of error, Also I have tried,
File img = File.fromRawPath(imageFile!);
but still, I got an error.
You can use Image.memory
Image.memory(listHere);
https://api.flutter.dev/flutter/widgets/Image/Image.memory.html
Related
I'm using dart:io to convert file to bytes. with image and short video it's work. but with large file (more than 1GB) i got error
E/flutter (16030): [ERROR:flutter/shell/common/shell.cc(93)] Dart Error: NewExternalTypedData expects argument 'length' to be in the range [0..1073741823].
my code
Uint8List bytes;
try {
bytes = imageFile.readAsBytesSync();
print('bytes $bytes');
lengthInBytes = bytes.buffer.asByteData().lengthInBytes;
} catch (e) {
print('e $e');
}
it's look like limit of memory. any way to solve this?
Try uploading in chunks of the file size is bigger. You can try some package like
https://pub.dev/packages/chunked_uploader
ChunkedUploader chunkedUploader = ChunkedUploader(Dio(BaseOptions(
baseUrl: 'https://example.com/api',
headers: {'Authorization': 'Bearer'})));
try {
Response? response = await chunkedUploader.upload(
filePath: '/path/to/file',
maxChunkSize: 500000,
path: '/file',
onUploadProgress: (progress) => print(progress));
print(response);
} on DioError catch (e) {
print(e);
}
It will automatically convert into chunks and upload
i found a solution to get file size
imageFile.lengthSync()
it's solve my problem. readAsBytesSync make full memory
I have been struggling for a few days with taking a photo with the phone camera, using Ionic and Android device, and sending it to the server in a post request. Optionally, I want to display the image to the screen.
I read a lot of previous posts with similar problems, but none of the solutions worked for me. I want to mention that I am quite new to the ionic world, so I am still learning. Maybe it is a stupid problem that I cannot see.
Before adding the code that I tried, I want to list the things that I have tried so far:
Used FILE_URL and DATA_URL for the destinationType option
Manually convert the image to base 64
Used domSanitizer.bypassSecurityTrustUrl(b64img) in the .html file
Please, see below the code that I tried:
This is the code for taking the photo:
const options: CameraOptions = { // photo options
quality: 50,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
} // take picture
this.camera.getPicture(options).then((imageData) => {
this.imageData = imageData;
this.image = ( < any > window).Ionic.WebView.convertFileSrc(imageData);
//extra http://localhost/file.. and I slice it to remove extra chars
this.image = this.image.slice(27);
},
(err) => {
this.helperService.showAlert(JSON.stringify(err));
});
This is the code for uploading the photo to the server:
upload() { // upload method
let url = 'url/to/post';
const date = new Date().valueOf();
const imageName = date + '.jpeg';
console.log(this.imageData);
-- - > undefined
//slice it to remove extra chars
this.imageData = this.imageData.slice(27);
const imageBlob = this.dataURItoBlob(this.imageData);
const imageFile = new File([imageBlob], imageName, {
type: 'image/jpeg'
});
let postData = new FormData();
postData.append('file', imageFile);
let data: Observable < any > = this.httpClient.post(url, postData);
data.subscribe((result) => {
this.helperService.showSuccess(result);
});
}
And this is the blob function:
dataURItoBlob(dataURI) {
const byteString = window.atob(dataURI);
const arrayBuffer = new ArrayBuffer(byteString.length);
const int8Array = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
int8Array[i] = byteString.charCodeAt(i);
}
const blob = new Blob([int8Array], {
type: 'image/jpeg'
});
return blob;
}
This is my HTML file:
<ion-content>
<ion-grid>
<img [src]="DomSanitizer.bypassSecurityTrustUrl(image)">
</ion-grid>
<ion-button (click)="upload()" color="success">
<ion-icon slot="icon-only" name="checkmark"></ion-icon>
</ion-button>
</ion-content>
Problems:
The photo is not displayed on the screen and my image is Undefined - I tried both with and without DomSanitizer
this.imageData is undefined inside the upload() method
This is the reference post that I followed, but I cannot manage to see the problems:
Capture and upload image to server using Ionic 4
Looking at this reference post, I sliced even the extra characters displayed in front of the image, but I did not manage to solve the problems.
Let me know if I should add any other information. Thank you for your help!
I manage to display the image on the screen by using:
let b64 = 'data:image/jpeg;base64,' + imageData;
this.image = b64;
instead of
this.image = (<any>window).Ionic.WebView.convertFileSrc(imageData);
Unfortunately, this.imageData is still undefined, and I cannot figure out why.
Update: Looks like the photo is sent to bakend now, but its size is 0 and backend (which is Nodejs) cannot use it. What should I do? Should I parse it in some way?
Thank you!
I am trying to pass an image as Uint8List to native code Android/iOS from Flutter, but getting an error in iOS side. I am modifying a plugin and i never developed in iOS before.
Here is the Flutter code to capture an image from widget and send the Uint8List to native code.
Future<void> _capturePng() async {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 1.50);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
printer.printImage(pngBytes);
}
In Android, i am using Kotlin:
private fun printImage(call: MethodCall, result: Result) {
val image = call.arguments as ByteArray
val res = mPrinterPlugin.printImage(image)
result.success(res)
}
In iOS, the plugin is written in Objective-C. i added this check for my image
else if([#"imagePrint" isEqualToString:call.method]){
NSData *imgBytes = call.arguments;
UIImage *label = [UIImage imageWithData:imgBytes];
}
I saw that Uint8List is FlutterStandardTypedData typedDataWithBytes in iOS, but when i set the imgBytes type to it i get an error.
You should take first argument as a typed data, probably:
NSArray *args = call.arguments;
FlutterStandardTypedData *list = args[0];
kotlin:
val args: List<Any> = call.arguments as List<Any>
val list = args[0] as ByteArray
and you invoke it like this:
Uint8List uint8List;
_channel.invokeMethod("your_function_name", [uint8List]);
I just dealt with this. Letting Xcode do its magical conversion was burning me. For instance, in your iOS plugin implementation, the line:
NSData *imgBytes = call.arguments;
When i was doing this, in Xcode the debugger would see the data type would come through as a FlutterStandardTypedData (as i passed in a list of ints) but every time i would try to access an element/object it would give me memory errors. It was like Xcode was honoring my parameter list (NSArray) in reality, but showing me the data type as a FlutterStandardTypedData while debugging. Seemed like a bug in the IDE to be honest.
Just as the upvoted answer shows, i resolved by using the flutter data type:
FlutterStandardTypedData *bytesList = call.arguments[#"listOfBytes"];
I am trying to get image from video url when my list scroll but when I use of video thumbnail library and call it in my app list freezes and my app crashed this is my code
Future _loadMore(context) async {
final directory=Provider.of<DirectoryPath>(context,listen: false);
Provider.of<LoadState>(context).setLoadState(true);
final index= Provider.of<IndexLazyloading>(context);
if(moves.length!=index.oldmove){
resetlist(context);
}
// Add in an artificial delay
for (var i = index.currentindex; i <= index.currentindex + increment && i<moves.length; i++) {
File f=new File( "${directory.directory}/${moves[i].videourl.split("/").last.replaceAll("mp4", "png")}");
if(!f.existsSync())
await getimage("${strings.baseurl}/videos/${moves[i].videourl}",context);
index.setdata(i);
}
await new Future.delayed(const Duration(seconds: 2));
Provider.of<LoadState>(context).setLoadState(false);
index.setcurrentIndex(index.data.length) ;
index.setoldMove(moves.length);
}
and this is my plugin that used
Future<Null> getimage(videourl,context)async{
final uint8list = await VideoThumbnail.thumbnailFile(
video: videourl,
thumbnailPath: Provider.of<DirectoryPath>(context).directory,
imageFormat: ImageFormat.WEBP,
maxHeightOrWidth: 0, // the original resolution of the video
quality: 75,
);
}
i try with png but dont work
this is my list that call this function what is problem in this code please help me
LazyLoadScrollView(
isLoading: loadstate.isload,
onEndOfPage: () => _loadMore(context),
child: ListView.builder(
itemCount: indexlayze.data.length,
itemBuilder: (context, position) {
return _buildProductItem(context,position);
},
));
my list get 10 image thumbnail when reach to end of list but is very slow how to handle it
How about dedicate this job to a NGINX/NodeJS service running on the cloud? Let the App just downloads the thumbnails from it. This is what I did before.
If you really need to generate the thumbnails by App, try couple things:
Use JPG/PNG instead of WebP because it costs a lot CPU on iOS
Create a list or stream to queue the requests, display a placeholder thumbnail before it done.
Priority the queue once ListView stops scrolling.
Signal the image component once the thumbnail finished, also take next item to call thumbnail
I understand that Android automatically creates a thumbnail, for every picture taken by the camera. I need to be able to display that thumbnail.
I'm using nativescript-imagepicker plugin to select images. The plugin returns only the size and src of the selected image(s), for instance:
'/storage/emulated/0/DCIM/DSCF2060.jpg'
How could i use this src, to retrieve the corresponding thumbnail(is it even possible?).
The Android API is very confusing for me(not to mention the Java), so any help will be greatly appreciated.
Use ThumbnailUtils
export function onGetImageButtonTap(args) {
let context = imagepicker.create({
mode: "single"
});
context
.authorize()
.then(function () {
return context.present();
})
.then(function (selection) {
selection.forEach(function (selected) {
const size = layout.toDevicePixels(96);
const bitmap = android.media.ThumbnailUtils.extractThumbnail(android.graphics.BitmapFactory.decodeFile(selected.android),
size, size);
args.object.page.getViewById("thumbnailImg").src = fromNativeSource(bitmap);
});
}).catch(function (e) {
console.log(e)
});
}
Playground Sample