Pass an image to REST with POST API Call in flutter - image

I am trying to pass an image that is taken from either camera or picked from the gallery and pass it to the backend using a POST API call.
I am using image_picker plugin for flutter to access the image from camera and and gallery.
following is what I tried.
get the image file (from file path) in file format.
decrease the size of the image into a smaller value (uses flutter_image_compress library for this).
convert the result into a base64 string value or as form data and set it to the field in request body.
I will provide what I tried from the flutter code end for the above approach. please can anyone guide me am I doing this right or is there a better way to achieve this?
Pick image from camera
Future _getImageFromCamera() async {
PickedFile petImage = await picker.getImage(source: ImageSource.camera,maxHeight: 1000);
var _imageURITemp = File(petImage.path);
final filePath = _imageURITemp.absolute.path;
final lastIndex = filePath.lastIndexOf(new RegExp(r'.jp'));
final splitted = filePath.substring(0, (lastIndex));
final outPath = "${splitted}${filePath.substring(lastIndex)}";
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath,
outPath,
minWidth: 1000,
minHeight: 1000,
quality: 50);
//
setState(() {
var str = compressedImage.path.split('/');
_imageURI = str[str.length - 1] as IO.File;
}
Uploading with the POST method*
String base64Image;
if(_imageURI != null) {
List<int> imageBytes = _imageURI.readAsBytesSync();
base64Image = base64.encode(imageBytes);
//
var data = {
'user_email': userEmail,
'user_token': userToken,
'pet': {
"age": petAgeController.text,
"birth_date": bdate,
'eatbone': ,
'ideal_weight': petIdealWeightController.text,
'image': base64Image,
'name': petNameController.text,
"sex": _petSex,
'weight': petWeightController.text,
'guideline_id': '1',
'activity_level_id': '2',
'breed_id': '12',
'user_id': userID,
}
};
// final PET.PetCreate
final pet = await CallApi().createThePet(data, 'pets/create')
}

Related

How to encode and download png on Flutter web

I am trying to take a screenshot of a widget and save it as a png.
Its working fine for macos and ios but not for desktop(chrome).
The file downloaded from browser seems to be not encoded correct, I have tried a lot of different encodings but cant get it working.
Would be nice if someone knows how to encode the image so its downloaded correct in web too.
final boundary = _boundaryKey.currentContext.findRenderObject() as RenderRepaintBoundary;
final image = await boundary.toImage(pixelRatio: 2);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData.buffer.asUint8List();
if (kIsWeb) {
final blob = html.Blob(<dynamic>[base64Encode(pngBytes)], 'image/png');
final anchorElement = html.AnchorElement(
href: html.Url.createObjectUrlFromBlob(blob),
)
..setAttribute('download', 'details.png')
..click();
} else {
await File('details_${widget.order.id}'.trim().replaceAll(' ', '_')).writeAsBytes(pngBytes);
}
The trick is to set 'application/octet-stream' when creating the Blob
final fileName = 'details_${widget.order.id.trim().replaceAll(' ', '_')}';
final boundary = _boundaryKey.currentContext.findRenderObject() as RenderRepaintBoundary;
final image = await boundary.toImage(pixelRatio: 2);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData.buffer.asUint8List();
final blob = html.Blob(<dynamic>[pngBytes], 'application/octet-stream');
html.AnchorElement(href: html.Url.createObjectUrlFromBlob(blob))
..setAttribute('download', fileName)
..click();

Flutter - How to convert an NetworkImage into an ui.Image?

I need to convert a NetworkImage to an ui.Image.
I tried to use the given solution from this question with some adjusts but it isn't working.
Someone can help me?
Uint8List yourVar;
ui.Image image;
final DecoderCallback callback =
(Uint8List bytes, {int cacheWidth, int cacheHeight}) async {
yourVar = bytes.buffer.asUint8List();
var codec = await instantiateImageCodec(bytes,
targetWidth: cacheWidth, targetHeight: cacheHeight);
var frame = await codec.getNextFrame();
image = frame.image;
return image;
};
ImageProvider provider = NetworkImage(yourImageUrl);
provider.obtainKey(createLocalImageConfiguration(context)).then((key) {
provider.load(key, callback);
});
first create a field in your class:
var cache = MapCache<String, ui.Image>();
then to get ui.Image you can simply call:
var myUri = 'http:// ...';
var img = await cache.get(myUri, ifAbsent: (uri) {
print('getting not cached image from $uri');
return http.get(uri).then((resp) => decodeImageFromList(resp.bodyBytes));
});
print('image: $img');
of course you should add some http response error handling but this is the base idea...

Cognitive face detection is not working when I try to upload the image with a face mask

Any suggestions on how to get info of the image with a mask in cognitive face recognition?
When I upload image with headwear or eyeglasses then cognitive service returns the image information but when picking an image with mask, Cognitive service doesn't return any information. That means my implementation of cognitive service is not able to recognize the image with the mask. If anybody has faced this issue and resolved it please suggest me a solution.
public string subscriptionKey = "88c**************************f7";
public string uriBase = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect";
//Method to pick an image from the gallery
async void btnPick_Clicked(object sender, System.EventArgs e)
{
try
{
if (!CrossMedia.Current.IsPickPhotoSupported)
{
return;
}
var file = await CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions
{
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium
});
if (file == null) return;
imgSelected.Source = ImageSource.FromStream(() => {
var stream = file.GetStream();
return stream;
});
MakeAnalysisRequest(file.Path);
}
catch (Exception ex)
{
string test = ex.Message;
}
}
> //convert Convert image to byte array
public byte[] GetImageAsByteArray(string imageFilePath)
{
using (FileStream fileStream =
new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
BinaryReader binaryReader = new BinaryReader(fileStream);
return binaryReader.ReadBytes((int)fileStream.Length);
}
}
> //Method to get image information from the detection Url
public async void MakeAnalysisRequest(string imageFilePath)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
string requestParameters = "returnFaceId=true&returnFaceLandmarks=false" +
"&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses," +
"emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";
string uri = uriBase + "?" + requestParameters;
HttpResponseMessage response;
byte[] byteData = GetImageAsByteArray(imageFilePath);
using (ByteArrayContent content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uri, content);
string contentString = await response.Content.ReadAsStringAsync();
//***************************************************
//Here it return null in case of mask else its working fine
//***************************************************
List<ResponseModel> faceDetails = JsonConvert.DeserializeObject<List<ResponseModel>>(contentString);
if (faceDetails.Count != 0)
{
lblTotalFace.Text = "Total Faces : " + faceDetails.Count;
lblGender.Text = "Gender : " + faceDetails[0].faceAttributes.gender;
lblAge.Text = "Total Age : " + faceDetails[0].faceAttributes.age;
Console.WriteLine(faceDetails[0].faceAttributes.accessories.FirstOrDefault(x => x.type == "mask").confidence);
}
}
}
There a 2 different things that you must have in mind:
Some faces might not be seen by the services, see doc:
Some faces might not be detected because of technical challenges.
Extreme face angles (head pose) or face occlusion (objects such as
sunglasses or hands that block part of the face) can affect detection.
Frontal and near-frontal faces give the best results.
There are currently 2 detection models in Face API: "detection_01" and "detection_02". This latest model (existing since May 2019 if I remember well) has better performances (especially for rotated or partially hidden faces) but is not providing all the information in output that model 1 is giving.
Difference in detection models
I made a quick demo using a the "Cognitive Workbench" demo portal (available here) with the following image:
With detection_01: no face found
With detection_02: the face is found, as you can see in this capture:
But if you need to use specific attributes from the face, this might not solve your problem. See API documentation extract:

Android post image to Facebook comment

This is a followup to my previous question: Xamarin.Forms App return data to calling App
That works perfectly and I can share images to anywhere, except to Facebook comments. When I click the camera on the content box the app can be selected, I can select the image, Set result and Finish are called, and the app closes and it sends data to Facebook, and then however I then get the error : The image could not be uploaded, try again?
I can't find any fundamental differences between posting to a status or a comment, so I'm guessing it's subtle. Any thoughts on how I can change my intent to post properly?
Adding for completeness:
Bitmap b = null;
string url;
if (!string.IsNullOrEmpty(this.saleItems[i].ImageUrl))
{
url = this.saleItems[i].ImageUrl;
}
else
{
url = await FileHelper.GetLocalFilePathAsync(this.saleItems[i].Id);
}
//download
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
b = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
//set local path
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose();
var imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent();
sharingIntent.SetAction(Intent.ActionSend);
sharingIntent.SetType("image/*");
sharingIntent.PutExtra(Intent.ExtraText, "some txt content");
sharingIntent.PutExtra(Intent.ExtraStream, imageUri);
sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
//await SaleItemDataService.Instance.BuySaleItemAsync(this.saleItem);
SetResult(Result.Ok, sharingIntent);
Finish();
Use below:
Intent sharingIntent = new Intent();
string imageUri = "file://" + requestedUri;
sharingIntent.SetData(Android.Net.Uri.Parse(imageUri));

Windows Phone - update live tile from background agent with custom image

I am trying to add cloud image to album cover if the cover is loaded from internet. I am trying to do this in Background Audio agent and I think I almost got it. The problem is that I have black image in tile. Few times when testing I got cover image with my cloud image in it but mostly I get black image (and sometimes black image with cloud in it).
Can anyone help me find the problem? Thanks
private void UpdateAppTile()
{
var apptile = ShellTile.ActiveTiles.First();
if (apptile != null && _playList != null && _playList.Any())
{
var track = _playList[currentTrackNumber];
var size = 360;
Uri coverUrl;
if (track.AlbumArt.OriginalString.StartsWith("http"))
{
BitmapImage img = null;
using (AutoResetEvent are = new AutoResetEvent(false))
{
string filename = Path.GetFileNameWithoutExtension(track.AlbumArt.OriginalString);
var urlToNewCover = String.Format("http://.../{0}/{1}", filename, size);
coverUrl = new Uri(urlToNewCover, UriKind.Absolute);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
img = new BitmapImage(coverUrl);
are.Set();
});
are.WaitOne();
var wbmp = CreateTileImageWithCloud(img);
SaveTileImage(wbmp, "/shared/shellcontent/test.jpg");
coverUrl = new Uri("isostore:/shared/shellcontent/test.jpg", UriKind.RelativeOrAbsolute);
}
}
else
{
var coverId = track.Tag.Split(',')[1];
var urlToNewCover = String.Format("http://.../{0}/{1}", coverId, size);
coverUrl = new Uri(urlToNewCover, UriKind.Absolute);
}
var appTileData = new FlipTileData
{
BackgroundImage = coverUrl,
WideBackgroundImage = coverUrl,
...
}
apptile.Update(appTileData);
}
}
public static BitmapImage LoadBitmap(string iFilename)
{
Uri imgUri = new Uri(iFilename, UriKind.Relative);
StreamResourceInfo imageResource = Application.GetResourceStream(imgUri);
BitmapImage image = new BitmapImage();
image.SetSource(imageResource.Stream);
return image;
}
private void SaveTileImage(WriteableBitmap wbmp, string filename)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(filename))
store.DeleteFile(filename);
var stream = store.OpenFile(filename, FileMode.OpenOrCreate);
wbmp.SaveJpeg(stream, wbmp.PixelWidth, wbmp.PixelHeight, 100, 100);
stream.Close();
}
}
private WriteableBitmap CreateTileImageWithCloud(BitmapImage img)
{
Image image = null;
WriteableBitmap wbmp = null;
using (AutoResetEvent are = new AutoResetEvent(false))
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
image = new Image { Source = img };
Canvas.SetLeft(image, 0);
Canvas.SetTop(image, 0);
var cloud = new BitmapImage(new Uri("Assets/Images/Other/Cloud_no.png", UriKind.Relative));
var cloudImg = new Image { Source = cloud };
Canvas.SetLeft(cloudImg, 125);
Canvas.SetTop(cloudImg, 10);
var canvas = new Canvas
{
Height = 176,
Width = 176
};
canvas.Children.Add(image);
canvas.Children.Add(cloudImg);
wbmp = new WriteableBitmap(176, 176);
wbmp.Render(canvas, null);
wbmp.Invalidate();
are.Set();
});
are.WaitOne();
}
return wbmp;
}
Edit
I found little pattern in which this is working and in which not. When application is running and I called this twice (in TrackReady and SkipNext) then I very often get cover image with cloud. When I am running just background agent (without running app) I get always black image. And often first UpdateAppTile call is just black image and second it's black image with cloud. That black color is default canvas background so I guess I have problems with delay when loading cover image from url. But I am not sure how in my case use ImageOpened event and if it help.
I think that you should call Measure and Arrange after adding elements to canvas and before rendering canvas (as with other UIElements):
canvas.Measure( new Size( Width, Height ) );
canvas.Arrange( new Rect( 0, 0, Width, Height ) );

Resources