I am developing an app that allows a user to fill metadata to an image from UI like:
Name
Location
Maker Notes
....
Is there any way to do it in Flutter?
You can check by http://metapicz.com/#landing with any image URL
If you only need mobile support, there's a new package that can do this for you.
You add it as a dependency and then...
final exif = await Exif.fromPath(file.path);
final attributes = await exif!.getAttributes();
attributes['UserComment'] = "This file was edited by FlutterApp!";
final result = await exif.writeAttributes(attributes);
Related
I'm trying to update a placeholder image with a new image that has an updated URL. The URL in fact is a valid Google Static Map URL that I'm using in other contexts successfully. I'm using the Google Document API to manipulate the document. Following the code I've been using:
var element = body.findElement(DocumentApp.ElementType.INLINE_IMAGE).getElement();
var imageMap = element.asInlineImage();
// if there was an image found in document
if (imageMap != null) {
// get current parent and index inside parent
var parent = imageMap.getParent();
var childIndex = parent.getChildIndex(imageMap);
// remove image from paragraph
imageMap = imageMap.removeFromParent();
// get static image url for territory
var url = getStaticMapURLForTerritory(id);
Logger.log(url);
imageMap.setLinkUrl(url);
// create a new image
parent.insertInlineImage(childIndex, imageMap)
}
This seems to work fine in that it does update the image url correctly. However, the image itself (the result of the url) is not updated. When I click on the link URL it does return the correct image.
Is there a way to force a refetch of the image blob associated with the URL? I've also attempted to use UrlFetchApp but that complains about a missing size parameter (google static api) which is certainly included in the url string and within the max 640x640 bounds.
I've exhausted all my options unless....
TIA, --Paul
setLinkUrl only does that: sets the link. To actually add a new image you'll have to get its blob:
function replaceImage() {
// [...]
// get static image url for territory
const url = getStaticMapURLForTerritory(id)
const response = UrlFetchApp.fetch(url)
// create a new image
parent.insertInlineImage(childIndex, response.getBlob())
.setAltDescription(img.getAltDescription())
.setAltTitle(img.getAltTitle())
.setWidth(img.getWidth())
.setHeight(img.getHeight())
.setLinkUrl(url)
}
References
Class InlineImage (Google Apps Script reference)
I am trying to save the image from assets to internal storage. But, I could not load the image from assets to file. Here is what I have done:
onTap: () async {
final String documentPath = (await getApplicationDocumentsDirectory()).path;
String imgPath = (galleryItems[currentIndex].assetName).substring(7);
File image = await getImageFileFromAssets(imgPath);
print(image.path);
}
I used substring(7) to eliminate assets/ as, my assetName comes as assets/images/foo.jpg.
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final file =
await File('${(await getApplicationDocumentsDirectory()).path}/$path')
.create(recursive: true);
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
After I get image, I don't know how to proceed forward to create a directory with my name in internal storage. And, copy file there.
*Note:- I have editted the post, as some basic mistakes were pointed out.
Update
Here is what I came up with. And it saves image in the /storage/emulated/0/Android/data/com.example.my_project/files/Pics/foo.jpg path.
File image = await getImageFileFromAssets(imgPath);
final extDir = await getExternalStorageDirectory();
// Path of file
final myImagePath = '${extDir.path}/Pics';
// Create directory inside where file will be saved
await new Directory(myImagePath).create();
// File copied to ext directory.
File newImage =
await image.copy("$myImagePath/${basename(imgPath)}");
print(newImage.path);
Here are some links that really helped me:
Flutter How to save Image file to new folder in gallery?
How to Save Image File in Flutter ? File selected using Image_picker plugin
How to convert asset image to File?
Special thanks to #David for the help. Please see comments to understand full scene if you are here to solve your similar problem.
So, I am accepting the answer from #David.
You are trying to create a file object in a path that doesn't exist. You're using your asset path, the path relative to the root of your Flutter project. However, this path doesn't exist in the device's documents folder, so the file can't be created there. The file also doesn't exist in the assets folder because you're prepending the documents path.
To fix your issue, you should pass assetName to rootBundle.load(), without the documents path and open the File() somewhere like $documentPath/foo.jpg
Edit:
To create the file you still have to call File.create, so you need to run:
final file = await File('$documentPath/images/foo.jpg').create(recursive: true);
For future reference, this is just to update the solution of #Biplove which really helped me a lot as a newbie...
Future<File> getImageFileFromAssets(String unique, String filename) async {
ByteData byteData = await rootBundle.load(assets/filename));
// this creates the file image
File file = await File('$imagesAppDirectory/$filename').create(recursive: true);
// copies data byte by byte
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
Thanks.
I am using VS 2017 to create a cross platform (UWP, Android, iOS) Xamarin app. I am trying to show all images from a folder on device as thumbnails (similar to gallery app, sample screenshot attached).
I have looked into WrapLayout sample code provided on Xamarin website (Link), but it's loading all images from internet using JSON
protected override async void OnAppearing()
{
base.OnAppearing();
var images = await GetImageListAsync();
foreach (var photo in images.Photos)
{
var image = new Image
{
Source = ImageSource.FromUri(new Uri(photo + string.Format("?width={0}&height={0}&mode=max", Device.OnPlatform(240, 240, 120))))
};
wrapLayout.Children.Add(image);
}
}
async Task<ImageList> GetImageListAsync()
{
var requestUri = "https://docs.xamarin.com/demo/stock.json";
using (var client = new HttpClient())
{
var result = await client.GetStringAsync(requestUri);
return JsonConvert.DeserializeObject<ImageList>(result);
}
}
I have also looked into Xamarin Media Plugin (Link), but it shows only one image at a time. Sample code -
await CrossMedia.Current.Initialize();
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
MainImage.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
But I am unable to find a way to implement these two (or any other methods) in such a way that I can create my own gallery section in my app.
You need to create an Activity in your specific platform. This activity will be launched as an intent throught your PCL project using, for instance, Dependency Services.
In this custom Activity you should have a GridView which fills its source from the current directory if the file fits your restrictions, such a specific extension, size, etc.
Finally, to get the selected image you just send the image path or whatever you need to the PCL project with DependencyService.
I'm trying to copy a user profile picture from an external service onto my firebase server. So far I have:
final File file = await new File.fromUri(Uri.parse(auth.currentUser.photoUrl)).create();
final StorageReference ref = FirebaseStorage.instance.ref().child("profile_image_${auth.currentUser.uid}.jpg");
final StorageUploadTask uploadTask = ref.put(file);
final Uri downloadUrl = (await uploadTask.future).downloadUrl;
// add user profile picture url to user object
final userReference = FirebaseDatabase.instance
.reference()
.child('users/' + auth.currentUser.uid);
userReference.set({'photoUrl': downloadUrl});
The very top line gives me the error: Unsupported operation: Cannot extract a file path from a https URI
What is the correct way to do this? Should this even be done client-side? (Should I just be passing this url to firebase and use a function to download it server-side?)
File only supports files on a file system.
To load content using HTTP use the http package.
See also https://flutter.io/networking/
var httpClient = createHttpClient();
var response = await httpClient.get(url);
and then get the data from response.body,
or
var response = await httpClient.readBytes(url);
to get it as binary (Uint8List)
See also https://www.dartdocs.org/documentation/http/0.11.3+14/http/Client-class.html
I'm caching images using Universal Image Loader, but I need save images with the name I want and I dont Know how can I do it.
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisc(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(options)
.memoryCacheSize(41943040)
.discCacheSize(104857600)
.threadPoolSize(10)
.build();
ImageLoader.getInstance().init(config);
and I display Image:
imageLoader.displayImage(fileObject.getUrl(), imgPromo);
This save image in sdcard/android/mypackage/cache/uil-images with a name by default(I think), but I need that the image's name is "myimage" for example.
thanks!!