Is there a way to resize an image without having it previously written to storage?
I am using a pdf library that for the images needs the bytes of it.
What I do is get image with an http.get and I get the bytes to put it in the pdf.
The problem is that I need to resize the image BEFORE putting it in the pdf.
The only thing I have is the url of the image or the uint8list
Response response = await http.get(imageUrl);
Uint8List imgBytes = response.bodyBytes;
Later:
Image(
PdfImage.file(pdf.document,
bytes: imageBytes)
),
Pdf lib I use: https://pub.dev/packages/pdf
You can copy paste run full code below
You can use ui.instantiateImageCodec and specify targetHeight and targetWidth
You can see output image size become smaller after resize
code snippet
String imageUrl = 'https://picsum.photos/250?image=9';
http.Response response = await http.get(imageUrl);
originalUnit8List = response.bodyBytes;
ui.Image originalUiImage = await decodeImageFromList(originalUnit8List);
ByteData originalByteData = await originalUiImage.toByteData();
print('original image ByteData size is ${originalByteData.lengthInBytes}');
var codec = await ui.instantiateImageCodec(originalUnit8List,
targetHeight: 50, targetWidth: 50);
var frameInfo = await codec.getNextFrame();
ui.Image targetUiImage = frameInfo.image;
ByteData targetByteData =
await targetUiImage.toByteData(format: ui.ImageByteFormat.png);
print('target image ByteData size is ${targetByteData.lengthInBytes}');
targetlUinit8List = targetByteData.buffer.asUint8List();
output of working demo
I/flutter (17023): original image ByteData size is 250000
I/flutter (17023): target image ByteData size is 4060
working demo
full code
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Uint8List targetlUinit8List;
Uint8List originalUnit8List;
void _resizeImage() async {
String imageUrl = 'https://picsum.photos/250?image=9';
http.Response response = await http.get(imageUrl);
originalUnit8List = response.bodyBytes;
ui.Image originalUiImage = await decodeImageFromList(originalUnit8List);
ByteData originalByteData = await originalUiImage.toByteData();
print('original image ByteData size is ${originalByteData.lengthInBytes}');
var codec = await ui.instantiateImageCodec(originalUnit8List,
targetHeight: 50, targetWidth: 50);
var frameInfo = await codec.getNextFrame();
ui.Image targetUiImage = frameInfo.image;
ByteData targetByteData =
await targetUiImage.toByteData(format: ui.ImageByteFormat.png);
print('target image ByteData size is ${targetByteData.lengthInBytes}');
targetlUinit8List = targetByteData.buffer.asUint8List();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
originalUnit8List == null
? Container()
: Image.memory(originalUnit8List),
targetlUinit8List == null
? Container()
: Image.memory(targetlUinit8List),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _resizeImage,
tooltip: 'Resize',
child: Icon(Icons.add),
),
);
}
}
Related
PLease help me , i want to put watermark on the image and text when the user want share it ,I tried a lot but could not get a correct result. Found this example only
my share image code is ::
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
void sharePhoto(String uurl) async {
final urlImage = uurl;
final url = Uri.parse(urlImage);
final response = await http.get(url);
final bytes = response.bodyBytes;
final temp = await getTemporaryDirectory();
final path = '${temp.path}/image.jpg';
File(path).writeAsBytesSync(bytes);
await Share.shareFiles([path], text: "dfgdfgdf gdf gdf g");
}
Below is an example of how you can overlay two images before you share it. If you are still looking for how to do it, you can use this as a starting point. Obviously, there has to be more sanity checking and all, treat this solely as a POC. Also take it a grain of salt, as I am a week and a half into dart/flutter myself, and will happily take advises/comments/suggestions re this code.
Here is a quick 8s video of the result.
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';
import 'package:http/http.dart' as http;
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var imageBytes;
Future<Uint8List> _getImage() async {
final response = await http.get(Uri.parse(
'https://upload.wikimedia.org/wikipedia/commons/d/dd/Stack_Overflow_Home.png'));
imageBytes = response.bodyBytes;
return response.bodyBytes;
}
void _share(Uint8List originallImage) async {
final image = img.decodePng(originallImage)!;
// get second image
final responseWaterMark = await http
.get(Uri.parse('http://www.dspsl.com/images/700_confidential.png'));
final waterMark = img.decodeImage(responseWaterMark.bodyBytes)!;
// resize watermark if needed (like in my case)
final resizedWaterMark =
img.copyResize(waterMark, height: image.height, width: image.width);
// you may want to calculate the size of the resulting image
// based on other parameters
final mergedImage = img.Image(image.width, image.height);
// copy image and watermark into the resulting image
img.copyInto(mergedImage, image);
img.copyInto(mergedImage, resizedWaterMark);
// prep data in the temp folder
final mergedImageBytes = img.encodePng(mergedImage);
final directory = await getTemporaryDirectory();
final path = directory.path;
final imagePath = File('$path/image.png');
imagePath.writeAsBytesSync(mergedImageBytes);
// share image
await Share.shareFiles([imagePath.path]);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder(
future: _getImage(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
Image.memory(snapshot.data as Uint8List),
TextButton(
onPressed: () {
_share(imageBytes);
},
child: const Text(
'Share Image',
style: TextStyle(fontSize: 40),
),
)
],
);
} else {
return const Center(child: CircularProgressIndicator());
}
}),
],
))));
}
}
I want to share an image that I took from the CameraController.
I location of the file is as example /data/user/0/com.user.test/cache/2019-09-10 16:32:52.281842.png
How it is possible to share this local image?
I added these two line for read/write to local storage:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
I use the share component from https://pub.dev/packages/esys_flutter_share which works great.
void _sharePicture() async {
print('Share picture');
print(this.imagePath);
final ByteData bytes = await rootBundle.load(this.imagePath);
await Share.file('esys image', 'esys.png', bytes.buffer.asUint8List(), 'image/png', text: 'My optional text.');
}
this.imagePath is the local location of the file: :/data/user/0/com.user.test/cache/2019-09-10 16:32:52.281842.png
Do you first have to save the image? And the use it for sharing? How is it possible to share this local image?
The idea is share Uint8List
This demo use camera_camera package's example. https://github.com/gabuldev/camera_camera/tree/master/example
camera_camera package https://pub.dev/packages/camera_camera is an greate package have well made features and use camera plugin inside
code snippet
after click take picture, the system return a file (val in this example), read bytes and transfer to Uint8List
print("path ${val}");
List<int> bytes = await val.readAsBytes();
Uint8List ubytes = Uint8List.fromList(bytes);
await Share.file('ESYS AMLOG', 'amlog.jpg', ubytes, 'image/jpg');
full code
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera_camera/camera_camera.dart';
import 'dart:typed_data';
import 'package:esys_flutter_share/esys_flutter_share.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
File val;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Rully")),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.camera_alt),
onPressed: () async {
val = await showDialog(
context: context,
builder: (context) => Camera(
mode: CameraMode.fullscreen,
orientationEnablePhoto: CameraOrientation.landscape,
/*
imageMask: CameraFocus.square(
color: Colors.black.withOpacity(0.5),
),
*/
));
print("path ${val}");
List<int> bytes = await val.readAsBytes();
Uint8List ubytes = Uint8List.fromList(bytes);
await Share.file('ESYS AMLOG', 'amlog.jpg', ubytes, 'image/jpg');
setState(() {});
}),
body: Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.7,
width: MediaQuery.of(context).size.width * 0.8,
child: val != null
? Image.file(
val,
fit: BoxFit.contain,
)
: Text("Tire a foto"))));
}
}
demo screen
In camera_camera example take picture button will show in landscape mdoe
file path display in bottom
For camera plugin official example, I only change the following
code snippet
void onTakePictureButtonPressed() {
takePicture().then((String filePath) async{
if (mounted) {
setState(() {
imagePath = filePath;
videoController?.dispose();
videoController = null;
});
if (filePath != null) {
showInSnackBar('Picture saved to $filePath');
File val = File(filePath);
List<int> bytes = await val.readAsBytes();
Uint8List ubytes = Uint8List.fromList(bytes);
await Share.file('ESYS AMLOG', 'amlog.jpg', ubytes, 'image/jpg');
}
}
});
}
I have been trying to add text on top of an image and then allow the user to share the image. I'm having two issues that I can't seem to figure out.
The text is overflowing off the screen and not wrapping in the TextPainter when adding to Canvas.
I have been trying to share the image using a FloatingActionButton. The issue I am having is sharing an actual image and not image string. I have been using the esys_flutter_share package to try and achieve it but I get an error. I really just want to share the Image that I wrote the text on top of.
Unhandled Exception: type 'Image' is not a subtype of type 'String'
.
Any help is greatly appreciated.
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _imageUrl = 'https://imageurl.png';
var _img;
var nimg;
#override
void initState() {
_showImg();
super.initState();
}
#override
Widget build(BuildContext context) {
var widget =
_img != null ? Image.memory(_img) : Text('pleace click button');
return Scaffold(
appBar: AppBar(),
body: Center(child: widget),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final ByteData bytes = await rootBundle.load(nimg);
await Share.file('esys image', '$nimg', bytes.buffer.asUint8List(), 'image/png');
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
_showImg() async{
var uri = Uri.parse(_imageUrl);
var httpClient = HttpClient();
var request = await httpClient.getUrl(uri);
var response = await request.close();
var imageData = <int>[];
await response.forEach((data) async {
imageData.addAll(data);
});
ui.Image image =
await decodeImageFromList(Uint8List.fromList(imageData));
var pictureRecorder = ui.PictureRecorder();
var canvas = Canvas(pictureRecorder);
var paint = Paint();
paint.isAntiAlias = true;
var src = Rect.fromLTWH(
0.0, 0.0, image.width.toDouble(), image.height.toDouble());
var dst = Rect.fromLTWH(
0.0, 0.0, image.width.toDouble(), image.height.toDouble());
canvas.drawRect(Rect.fromLTWH(0.0, 0.0, 200.0, 200.0), paint);
canvas.drawImageRect(image, src, dst, paint);
//Add text on image
TextSpan span = new TextSpan(
style: new TextStyle(color: Colors.white, fontSize: 150.0,
fontFamily: 'Roboto'), text: "Here is some great text to put on top");
TextPainter tp = new TextPainter(
text: span, textDirection: TextDirection.ltr, textAlign: TextAlign.center);
tp.layout();
tp.paint(canvas, new Offset(image.width/2 - image.width/2 /2, image.height/2 - image.height/2 /3));
var pic = pictureRecorder.endRecording();
ui.Image img = await pic.toImage(image.width, image.height);
var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
var buffer = byteData.buffer.asUint8List();
//Assign image to be shared
nimg = img;
//Set the image as the child in the body
setState(() {
_img = buffer;
});
}
}
The easiest way to share image with text:
Create a Stack and put Image in it, positioned the Text widget anywhere you want on the image.
Wrap Stack with RepaintBoundary
Screenshot with
RenderRepaintBoundary boundary = _globalKey.currentContext.findRenderObject();
Image image = await boundary.toImage();
Share with esys_flutter_share
PS. Of course you can also use image packages to add text to image.
esys_flutter_share is not having capability of sharing both data type at a same time. I have faced this issue and fixed by taking this package in my code and editing it's methods that allows us to share both data type. Here is the edited package files.
How to take packages in local code?
Checkout this answer
The updated code url is this, download it and follow above answer.
I'm trying to use firebase_ml_vision with image_picker.
Here's the code:
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
void main() => runApp(MyHomePage());
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
FirebaseVisionImage visionImage;
final BarcodeDetector barcodeDetector = FirebaseVision.instance.barcodeDetector();
final TextRecognizer textRecognizer = FirebaseVision.instance.textRecognizer();
final ImageLabeler labeler = FirebaseVision.instance.imageLabeler(
ImageLabelerOptions(confidenceThreshold: 0.75),
);
final FaceDetector faceDetector = FirebaseVision.instance.faceDetector();
void detections() async {
final VisionText visionText = await textRecognizer.processImage(visionImage);
}
File _image;
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
var something = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
this.visionImage = FirebaseVisionImage.fromFile(something);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Picker Example'),
),
body: Center(
child: _image == null
? Text('No image selected.')
: Image.file(_image),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
tooltip: 'Pick Image',
child: Icon(Icons.add_a_photo),
),
);
}
}
But I am unable to use the File datatype and this is the error I get:
Error
Here's what I get when I run flutter doctor:
Doctor
And here's what I get when I run flutter --version:
Version
I'm very new to Flutter so please let me know if you need anything else.
Thank you!
File type is in dart:io, which you are missing. Add import 'dart:io'; to the top of the file.
I am trying to create a new Image from two existing images using Canvas
one Img from asset ("asset image")
one Img from network
To achieve that first problem is to draw "asset image" on Canvas using drawImage.. this is where I am facing the problem.
drawCircle is working fine, But for using drawImage as per following code, it is outputting blank image.
I am new to using Canvas and experimenting, any help appreciated..
Complete code..
import 'package:flutter/material.dart';
//import 'package:path_provider/path_provider.dart';
import 'dart:ui' as ui;
import 'dart:typed_data';
import 'dart:async';
//import 'dart:io';
import 'package:flutter/services.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Image _image;
ui.Image imagetoDraw;
#override
void initState() {
super.initState();
_image = new Image.network(
'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png',
);
getImageFromAsset();
}
getImageFromAsset() async {
imagetoDraw = await load('images/loading.png');
print('...getImageFromAsset done');
}
Future<ui.Image> load(String asset) async {
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return fi.image;
}
_generateImage() {
_generate().then((val) => setState(() {
_image = val;
}));
}
Future<Image> _generate() async {
ui.PictureRecorder recorder = new ui.PictureRecorder();
Canvas c = new Canvas(recorder);
var rect = new Rect.fromLTWH(0.0, 0.0, 100.0, 100.0);
c.clipRect(rect);
final paint = new Paint();
paint.strokeWidth = 2.0;
paint.color = const Color(0xFF333333);
paint.style = PaintingStyle.fill;
final offset = new Offset(50.0, 50.0);
// c.drawCircle(offset, 40.0, paint);
c.drawImage(imagetoDraw, offset, paint);
var picture = recorder.endRecording();
final pngBytes = await picture
.toImage(100, 100)
.toByteData(format: ui.ImageByteFormat.png);
var image = Image.memory(pngBytes.buffer.asUint8List());
return image;
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_image,
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _generateImage,
tooltip: 'Generate',
child: new Icon(Icons.add),
),
);
}
}
The image asset path seems to be the problem. I can not say that for sure, as There is no pubspec.yaml asset declarations here.
Let's assume that you have added assets in pubspec.yaml as below:
assets:
- assets/images/image_01.png
- assets/images/image_02.jpg
In that case, you need to specify the path of asset 'assets/images/image_01.png'.
Means the exact path that is defined inside the pubspec.yaml file.
i.e. In your case, imagetoDraw = await load('assets/images/image_01.png');
Tip: You can directly use Image.asset('assets/images/image_01.png'); to get the image from assets.
The source I have referred to: Load Image from assets in flutter
I hope this helps.