Flutter display gif from Uint8List - flutter

I need to display gif in my Flutter application. From the backend I get the gif as an Uint8List list from the response. Can you help me please how can I display this in the screen?
My code is here:
widget.session
.get('/api/caff/getCaff/' + widget.gifId.toString())
.then((response) async {
if (response.statusCode == 200) {
Uint8List bytes = response.bodyBytes;
_gifFile = File.fromRawPath(bytes); // tried this but didn't work
} else {
CaffToast.showError(
'Something went wrong! Please check your network connection!');
}
});
And I tried to display it as a file image but it didnt work:
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
_gifFile == null ? Container() : Container(
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(_gifFile!))),
),
],
),
);
}
Do you have any suggestions how can I solve this problem?

There's no need to write your data to a file. The image data is already in memory so just display it. Just use a MemoryImage image provider instead
I'm not sure how you're getting the data from your network call to your build method so I'm using placeholders, but just do it the same was that you did when you were using a file.
_bytes = response.bodyBytes;
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
_gifFile == null ? Container() : Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(_bytes!))),
),
],
),
);
}

Related

I have problem with using condition to display an image

I am using image picker to get image from user then displayed in "CreateCard" UI.
The issue occur when i try using condition in my UI file, i need the condition so i can check if the file image is null before i can display it.
I am working with flutter GetX..
"CreateCard "UI Code:
GetBuilder<CreateCardContollerImp>(builder: (controller) =>UploadImage(
ontap: () {
showModalBottomSheet(
context: context,
builder: (context) {
return CreateCardBottomSheet(
uploadImageGallery: () {
controller.uploadImageGallery();
});
});
},
image: controller.image == null // Error occur here !
? AssetImage(AppImageAsset.profileimage)
: FileImage(controller.image),
),),
"UploadImage" Deifiniton:
class UploadImage extends StatelessWidget {
final void Function() ontap;
final ImageProvider<Object> image;
const UploadImage({super.key, required this.ontap, required this.image});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: ontap,
child: Stack(children: [
Container(
width: 170,
height: 170,
decoration: BoxDecoration(
boxShadow: const [
BoxShadow(
offset: Offset(0, 0),
color: AppColor.primaryColor,
blurRadius: 0,
),
],
borderRadius: BorderRadius.circular(100),
),
padding: const EdgeInsets.symmetric(vertical: 5),
child: CircleAvatar(
backgroundImage: image,
radius: MediaQuery.of(context).size.width - 310,
),
),
]),
);
}
}
"CreateCard" Controller:
class CreateCardContollerImp extends CreateCardContoller {
GlobalKey<FormState> formstate = GlobalKey<FormState>();
final imagepicker = ImagePicker();
late String imagePath;
late File image;
#override
uploadImageGallery() async {
final pickedimage = await imagepicker.getImage(source: ImageSource.gallery);
if (pickedimage != null) {
image = File(pickedimage.path);
imagePath = pickedimage.path;
update();
} else {
printError(info: "No image selected");
}
}
I was expecting this method will work fine.
you're logic looks fine, try casting the as ImageProvider:
controller.image == null
? AssetImage(AppImageAsset.profileimage) as ImageProvider
: FileImage(controller.image) as ImageProvider,
Another alternative is to try just using ImageProvider directly without unnecessary casting.
controller.image == null
? AssetImage(AppImageAsset.profileimage)
: NetworkImage(controller.image),
TheAssetImage is used in getting the avatar profile image from the app's asset.
The NetworkImage is used in getting the avatar profile image from the online DB or API.

Storing base 64 locally and use it offline

I have a 64 base image that am getting from my database , which I want to store locally and reuse offline. am using local storage package , the image works perfectly fine when I call it online but fades away offline . here is where am storing it :
String baseUrl = await GetSharedPrefs.getBaseURl();
_imageLogoPath =
(await SettingsServices().fetchLogoImage(baseUrl: baseUrl, id: 1));
storage.setItem('logoImage', _imageLogoPath);
notifyListeners();
and this is where am calling it :
class _LogoViewState extends State<Logo> {
void initState() {
Provider.of<SettingsViewModel>(context, listen: false).fetchLogoPath();
super.initState();
}
#override
Widget build(BuildContext context) {
final LocalStorage storage = new LocalStorage('deepnrise');
var settings = Provider.of<SettingsViewModel>(context);
String? image = settings.imagepath;
int i = 1;
String im = storage.getItem('logoImage');
if (im!.isNotEmpty) {
i +=1;
print("soy image $im");
final UriData? data = Uri.parse(im).data;
print(image);
Uint8List? myImage = data?.contentAsBytes();
return Padding(
padding: EdgeInsets.all(10.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.memory(
myImage!,
fit: BoxFit.contain,
width: 50,
)),
);
} else if (im.isEmpty || im == null) {
return Padding(
padding: EdgeInsets.all(16.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.asset(
"assets/images/deepn.png",
fit: BoxFit.contain,
width: 35,
)),
);
}
return Padding(
padding: EdgeInsets.all(16.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.asset(
"assets/images/deepn.png",
fit: BoxFit.contain,
width: 35,
)),
);
}
}
every time I get a null exception (null is not subtype of type string) , so I tried to call my provider in another widget , which resulted in the image fading away when offline . I want to be able to call the image from local storage , when off/ online . I have tried shared preferences package and the same thing happens if anyone please know how to help don't hesitate thanks in advance.

Flutter Exception: Invalid image data

I am working on a Flutter application that uploads to and gets data from PostgreSQL Database.
I am using postgres: ^2.3.2 in pubspec.yaml file.
First, I am converting the image to base64.
And then, I am uploading the image to the database as BYTEA.
And when I query the image data from the database, it provides me with an integer list.
I searched the web, and found that I had to convert that list to Uint8List.
After converting it to Uint8List, I have to use the Image.memory method to convert the Uint8List to an image widget.
But when I do so, I get this error on the Debug Console:
═══════ Exception caught by image resource service ════════════════════════════
The following _Exception was thrown resolving an image codec:
Exception: Invalid image data
When the exception was thrown, this was the stack
#0 _futurize (dart:ui/painting.dart:5326:5)
#1 ImageDescriptor.encoded (dart:ui/painting.dart:5194:12)
#2 instantiateImageCodec (dart:ui/painting.dart:2048:60)
<asynchronous suspension>
════════════════════════════════════════════════════════════════════════════════
And this image on the device:
Device screenshot
The code is below:
import 'dart:typed_data';
import 'package:flutter/material.dart';
class ShowImage extends StatefulWidget {
const ShowImage({Key? key}) : super(key: key);
#override
_ShowImageState createState() => _ShowImageState();
}
class _ShowImageState extends State<ShowImage> {
dynamic _image;
Map data = {};
void setImage() async {
GetImage getImgObj = GetImage(connection: data['connection']);
dynamic imgBytes = await getImgObj.getImage();
print(imgBytes.runtimeType);
setState(() {
_image = Image.memory(imgBytes);
});
}
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context)!.settings.arguments as Map;
// setImage();
return Scaffold(
appBar: AppBar(
title: Text("Show Image"),
centerTitle: true,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(
onPressed: () {
setImage();
},
child: Text("Get Image"),
),
SizedBox(height: 10.0),
Container(
width: 100,
height: 350,
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: _image == null
? Align(
alignment: Alignment.center,
child: Text(
"Image not selected",
textAlign: TextAlign.center,
),
)
: Align(
alignment: Alignment.center,
child: _image,
),
),
],
),
),
),
);
}
}
class GetImage {
var connection;
GetImage({this.connection});
Future<dynamic> getImage() async {
int itemId = 1;
String query = "SELECT img FROM lawbreach WHERE lid = $itemId;";
List<dynamic> results = await this.connection.query(query);
final bytes = Uint8List.fromList(results[0][0]);
return bytes;
}
}
I tried searching every corner of the web, but couldn't find any solution.
Hope, someone here has an answer to my question :)
The reason why the Image widget throws an "Invalid image data" Exception is because the base64 that you're trying to load is invalid. You need to check if the encoded base64 image that you've downloaded is being encoded to base64 again. Decode the downloaded base64 encoded image before loading it to the widget.
Uint8List _imageBytesDecoded = base64.decode(encodedImage);
...
Image.memory(_imageBytesDecoded)
How I solved my own, I extracted the image because it was in zip folder and go to pubspect.yaml assets: - images/image_22.jpg then in my widget I then added child: Image.asset('images/image_22.jpg')

page curl effect using pdf file

I have a PDF file and I would like to reproduce a page curl effect like in this package page:
https://pub.flutter-io.cn/packages/page_turn
I tried using this page_turn plugin and it takes list of widgets that will display in order. I tried using native_pdf_renderer plugin to render the pdf and display on each page, but when I do this, the pages are blank. but if I remove from the PageTurn widget, it works.
import 'package:flutter/material.dart';
import 'package:native_pdf_renderer/native_pdf_renderer.dart';
import 'package:page_turn/page_turn.dart';
class TestScreen extends StatelessWidget {
final _controller = GlobalKey<PageTurnState>();
Future<PdfPageImage> getPageImage() async {
final document = await PdfDocument.openAsset('assets/pdfs/222.pdf');
final page = await document.getPage(6);
final pageImage = await page.render(
width: page.width,
height: page.height,
format: PdfPageFormat.JPEG,
);
await page.close();
return pageImage;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder<PdfPageImage>(
future: getPageImage(),
builder: (context, snapshot) {
print(snapshot.data);
if (snapshot.data == null) return CircularProgressIndicator();
// This works:
// return Image(
// image: MemoryImage(snapshot.data.bytes),
// );
//This makes all my pages blank
return PageTurn(
key: _controller,
backgroundColor: Colors.white,
children: <Widget>[
Image(
image: MemoryImage(snapshot.data.bytes),
),
Image(
image: MemoryImage(snapshot.data.bytes),
),
Image(
image: MemoryImage(snapshot.data.bytes),
),
],
);
},
)),
);
}
}
after reading the lib code i see there is widget to show image pre-renderd
you should use PageTurnImage instead Image like this
PageTurn(
key: _controller,
backgroundColor: Colors.white,
children: <Widget>[
PageTurnImage(
image: MemoryImage(snapshot.data.bytes),
),
PageTurnImage(
image: MemoryImage(snapshot.data.bytes),
),
PageTurnImage(
image: MemoryImage(snapshot.data.bytes),
),
],
);
try it and give me a feedback and up vote if it work

type 'FutureBuilder<File>' is not a subtype of type 'ImageProvider<dynamic>' - Image Picker problem

I need to add an image in a Container. The image is coming from IMAGE PICKER.
Im getting the error:
type 'FutureBuilder<File>' is not a subtype of type 'ImageProvider<dynamic>'
Here's the original code:
Container( //<-- HEADER CONTAINER
height: kHeaderHeight,
width: kHeaderWidth,
decoration:
BoxDecoration(
image: DecorationImage(
image:
_imageFileForHeader.path != null?
FutureBuilder(
future: _getLocalFile(_imageFileForHeader.path),
builder: (BuildContext context, AsyncSnapshot<io.File> snapshot)
{
return Image.file(snapshot.data);
}
):
NetworkImage(urlImage + _kHeaderImage), fit: BoxFit.cover,
),
),
I really could do with any help here.
If the user does not select an image from the gallery - then use the image in the URL (urlImage).
I think I'm doing a very standard routine, and I cannot see why its not working.
Thanks
-- I just want to add that I tried also :
return FileImage(snapshot.data)
and this did not work either.
I think I exhausted every permutation possible here.
By the way, here's the _getLocalFile...
Future<io.File> _getLocalFile(String filename) async
{
io.File f = new io.File(filename);
return f;
}
You don't need any future in _getLocalFile as there is no async operations inside. You can just do
return Container( //<-- HEADER CONTAINER
height: kHeaderHeight,
width: kHeaderWidth,
decoration:
BoxDecoration(
image: DecorationImage(
image: _imageFileForHeader?.path != null
? Image.file(File(_imageFileForHeader.path))
: Image.network(urlImage + _kHeaderImage);
),
),
Or Assuming _imageFileForHeader is already a file we could simplify this even more
return Container( //<-- HEADER CONTAINER
height: kHeaderHeight,
width: kHeaderWidth,
decoration:
BoxDecoration(
image: DecorationImage(
image: _imageFileForHeader != null
? Image.file(_imageFileForHeader)
: Image.network(urlImage + _kHeaderImage);
),
),
I think your _getLocalFile function returns the wrong datatype. Maybe if you try the following:
Future<File> _getLocalFile() async{
final ImagePicker _picker = ImagePicker();
PickedFile pickedFile= await _picker.getImage(source: ImageSource.gallery);
File file = File(pickedFile.path);
return file;
}
Futhermore, I don´t belive that you can use a FutureBuilder for the Containers image variable. To display a image inside a Container you can use:
File file;
Container(
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.cover,
image: new FileImage(file),
),
),
),
So I think you have to check the file variable for null and if it is null, maybe show a button. If the user presses the button, you can call the async _getLocalFile function and than maybe update with setState to show the image.
Maybe you could also wrap the image around a FutureBuilder:
FutureBuilder<File>(
future: _getLocalFile(),
builder: (BuildContext context, AsyncSnapshot<File> snapshot)
{
if(!snapshot.hasData){
return CircularProgressIndicator();
}else{
return Container(
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.cover,
image: new FileImage(snapshot.data),
),
),
);
}
}
);