I created an app with image picker and I want to embed a text or image to that selected picture and saved it to gallery.
👇 My App
👇 I tried to create this
This is the code I used for image picker
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Watermark',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
File _pickedImage;
Future pickAnImage() async {
final pickedFile =
await ImagePicker().getImage(source: ImageSource.gallery);
setState(() {
_pickedImage = File(pickedFile.path);
});
}
_saveImage() {
//TODO: Save image to gallery
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text("Flutter Watermark"),
),
body: SingleChildScrollView(
child: Center(
child: Column(
children: <Widget>[
_pickedImage == null
? TextButton(
child: Text("Pick an Image"),
onPressed: pickAnImage,
)
: Column(
children: [
Image.file(_pickedImage),
SizedBox(
height: 50.0,
),
TextButton(
onPressed: _saveImage, child: Text("Save Image"))
],
),
],
),
),
),
),
);
}
}
I followed the below tutorial but it is freeze the app and I couldn't implement it.
Tutorial
https://medium.com/flutter-community/add-watermark-over-image-in-flutter-e7353e3cf603
Can anyone help me please?
You can try using this dependency:
As suggested by the author, this example is similar to your query
import 'dart:io';
import 'package:image/image.dart';
void main() {
// Create an image
Image image = Image(320, 240);
// Draw some text using 24pt arial font
drawString(image, arial_24, 0, 0, 'Hello World');
// Save the image to disk as a PNG
File('test.png').writeAsBytesSync(encodePng(image));
}
Image downloaded from this link.
Related
I try to create a widget test. But I can't understand how to identify widgets can find the key in the main code and do a test?
Main. dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Reversi',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var _controller;
var _reversed;
#override
void initState() {
super.initState();
_controller = TextEditingController();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Reversi'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Enter string to reverse"),
),
const SizedBox(height: 10.0),
if (_reversed != null) ...[
Text(
_reversed,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0,
),
),
const SizedBox(height: 10.0),
],
RaisedButton(
child: Text("Reverse"),
onPressed: () {
if (_controller.text.isEmpty) return;
setState(() {
_reversed = reverseString(_controller.text);
});
},
),
],
),
),
);
}
}
String reverseString(String initial) {
return initial.split('').reversed.join();
}
This is the widget test code I created. Is this code correct to find the key in the main code and do the test?
main_widget_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_testing/main.dart';
import 'package:flutter_test/flutter_test.dart';
void main(){
testWidgets('Reverse string widget test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
var textField = find.byType(TextField);
expect(textField, findsOneWidget);
await tester.enterText(textField, 'Hello');
expect(find.text('Hello'), findsOneWidget);
var button = find.text("Reverse");
expect(button,findsOneWidget);
await tester.tap(button);
await tester.pump();
expect(find.text("olleH"),findsOneWidget);
});
}
How can we identify whether the widget can find the key in the main code and do a test? Can someone explain to me if this code is correct?
I am using https://pub.dev/packages/gallery_saver for saving compressed images in a folder named Image Resizer now I want to open that saved images folder
You can use the image_picker plugin in Flutter for opening the images from the device. It will provide an option to open the gallery through which you can open the folder of saved images.
You can get the image_picker plugin here.
below is the solution i did it
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
//import 'package:ext_storage/ext_storage.dart';
import 'ext_storage.dart';
class SavedFiles extends StatefulWidget {
#override
_SavedFilesState createState() => _SavedFilesState();
}
class _SavedFilesState extends State<SavedFiles> {
List<dynamic> listImagePath = List<dynamic>();
Future<String> _getPath() {
return ExtStorage.getExternalStoragePublicDirectory(ExtStorage.PICTURES);
}
_fetchFiles(Directory dir) {
List<dynamic> listImage = List<dynamic>();
dir.list().forEach((element) {
RegExp regExp =
new RegExp("\.(gif|jpe?g|tiff?|png|webp|bmp)", caseSensitive: false);
// Only add in List if path is an image
if (regExp.hasMatch('$element')) listImage.add(element);
setState(() {
listImagePath = listImage;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Saved Images'),backgroundColor: Colors.orange,),
body: Column(
children: [
Expanded(
child: FutureBuilder(
future: _getPath(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
// print('data');
var dir = Directory(snapshot.data);
_fetchFiles(dir);
// return Text(snapshot.data);
return Container();
} else {
return Text("Loading");
}
},
),
),
// Expanded(child: Text('sss')),
Expanded(
flex: 19,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(5),
crossAxisSpacing: 2,
mainAxisSpacing: 2,
crossAxisCount: 3,
children: _getListImg(listImagePath),
),
)
],
)
);
}
List<Widget> _getListImg(List<dynamic> listImagePath) {
List<Widget> listImages = List<Widget>();
for (var imagePath in listImagePath) {
listImages.add(
Container(
padding: const EdgeInsets.all(8),
child: Image.file(imagePath, fit: BoxFit.cover),
),
);
}
return listImages;
}
}
I take a picture with phone's camera, then resize it and convert it to base64 string. However, after those manipulations, base64 string that I get doesn't seem to be valid.
I try to convert it back to image on this website https://codebeautify.org/base64-to-image-converter . After I click generate image, nothing happens, however sample on their website works. Tried on the other websites and still no luck.
My code:
import 'package:image/image.dart' as img;
import 'package:image_picker/image_picker.dart';
File _photo;
String photoBase64;
Future getImage(ImageSource source) async {
var photo = await ImagePicker.pickImage(source: source);
img.Image image = img.decodeImage(photo.readAsBytesSync());
img.Image imageResized = img.copyResize(image, width: 120);
setState(() {
_photo = photo;
List<int> imageBytes = imageResized.getBytes();
photoBase64 = base64Encode(imageBytes);
});
}
I tried base64UrlEncode() too, however the issue still remains. String I am trying to convert back to image is photoBase64. My goal is to send it in a body of a POST request later. What exactly am I doing wrong here?
Thank you
You can copy paste run full code below
You can use package https://pub.dev/packages/flutter_native_image to get resized image
imageResized = await FlutterNativeImage.compressImage(photo.path,
quality: 100, targetWidth: 120, targetHeight: 120);
...
List<int> imageBytes = imageResized.readAsBytesSync();
working demo
full code
import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'dart:convert';
import 'package:flutter_native_image/flutter_native_image.dart';
void main() => runApp(MyApp());
File _photo;
String photoBase64;
class MyApp extends StatelessWidget {
#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> {
int _counter = 0;
File imageResized;
Future getImage(ImageSource source) async {
var photo = await ImagePicker.pickImage(source: source);
imageResized = await FlutterNativeImage.compressImage(photo.path,
quality: 100, targetWidth: 120, targetHeight: 120);
setState(() {
_photo = photo;
List<int> imageBytes = imageResized.readAsBytesSync();
photoBase64 = base64Encode(imageBytes);
print(photoBase64);
});
}
void _incrementCounter() {
getImage(ImageSource.camera);
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
imageResized == null ? Container() : Image.file(imageResized),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
my solution
Future getImage() async {
pickedFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
if (pickedFile != null) {
file = File(pickedFile!.path);
final bytes =
file!.readAsBytesSync();
img64 = base64Encode(bytes);
} else {
print('No image selected.');
}
});
}
Is it possible to edit image like to rotate and to add text over image. Is there any plugin for that? I need an editor for image to add texts with various fonts and colors. Thank you
you should use RepaintBoundary to capture it as a widget and to overlap widget use stack.
Look at this code how to capture widget as a image.
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _globalKey = new GlobalKey();
bool inside = false;
Uint8List imageInMemory;
Future<Uint8List> _capturePng() async {
try {
print('inside');
inside = true;
RenderRepaintBoundary boundary =
_globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
ByteData byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
// String bs64 = base64Encode(pngBytes);
// print(pngBytes);
// print(bs64);
print('png done');
setState(() {
imageInMemory = pngBytes;
inside = false;
});
return pngBytes;
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return RepaintBoundary(
key: _globalKey,
child: new Scaffold(
appBar: new AppBar(
title: new Text('Widget To Image demo'),
),
body: SingleChildScrollView(
child: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'click the button below to capture image',
),
new RaisedButton(
child: Text('capture Image'),
onPressed: _capturePng,
),
inside ? CircularProgressIndicator()
:
imageInMemory != null
? Container(
child: Image.memory(imageInMemory),
margin: EdgeInsets.all(10))
: Container(),
],
),
),
)),
);
}
}
I am trying to display all the phone gallery images myself by reading the external files directory and possibly every image that ends with jpg or png. I achieved that, but could not display all of them in a grid as due to their sizes or the no. of images, the app crashes. Code looks bit like this..
new GridView.count(
shrinkWrap: true,
physics: new ClampingScrollPhysics(),
crossAxisCount: 2,
// children: new List<Widget>.generate(_images.length, (index) {
// children: new List<Widget>.generate(allImages.length, (index) {
children: new List<Widget>.generate(_PhoneImages.length, (index) {
File imgFile = _phoneImageFiles[index];
thumbBytes = _phoneThumbBytes[index]; // assuming it got created!!!
// print('thumbbytes $thumbBytes');
print('phone image index: $index');
return new GridTile(
child: new GestureDetector(
child: new Stack(
children: [
new Card(
// color: Colors.blue.shade200,
color: Colors.white70,
child: new Center(
// child: new Text('tile $index'),
// child: new Image.asset(_images[index]),
/*
child: new CachedNetworkImage(
imageUrl: allImages[index].path,
// placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
)
*/
child: new Image.file(imgFile,
// child: new Image.memory(thumbBytes,
So I tried the imageresize library which tells me to do a heavy operation of resizing, that takes almost 20 minutes before I can show the thumbnails.
All I need is to read thumbnails from gallery like how the phone gallery displays. I don't need categorization. I need all and a link to their full version so that I can do something with them later on.
I think this might help multi_image_picker
e.g
import 'package:flutter/material.dart';
import 'package:multi_image_picker/asset.dart';
class AssetView extends StatefulWidget {
final int _index;
final Asset _asset;
AssetView(this._index, this._asset);
#override
State<StatefulWidget> createState() => AssetState(this._index, this._asset);
}
class AssetState extends State<AssetView> {
int _index = 0;
Asset _asset;
AssetState(this._index, this._asset);
#override
void initState() {
super.initState();
_loadImage();
}
void _loadImage() async {
await this._asset.requestThumbnail(300, 300); // here requesting thumbnail
setState(() {});
}
#override
Widget build(BuildContext context) {
if (null != this._asset.thumbData) {
return Image.memory(
this._asset.thumbData.buffer.asUint8List(),
fit: BoxFit.cover,
);
}
return Text(
'${this._index}',
style: Theme.of(context).textTheme.headline,
);
}
}
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:multi_image_picker/asset.dart';
import 'package:multi_image_picker/multi_image_picker.dart';
import 'asset_view.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Asset> images = List<Asset>();
String _error;
#override
void initState() {
super.initState();
}
Widget buildGridView() {
return GridView.count(
crossAxisCount: 3,
children: List.generate(images.length, (index) {
return AssetView(index, images[index]);
}),
);
}
Future<void> loadAssets() async {
setState(() {
images = List<Asset>();
});
List resultList;
String error;
try {
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
);
} on PlatformException catch (e) {
error = e.message;
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
images = resultList;
if (error == null) _error = 'No Error Dectected';
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
Center(child: Text('Error: $_error')),
RaisedButton(
child: Text("Pick images"),
onPressed: loadAssets,
),
Expanded(
child: buildGridView(),
)
],
),
),
);
}
}