I'm trying to share a local image loacted in my Resources/Drawables folder in Android.
I'm using Xamarin and the Xamarin.Essentials plugin.
So there is this function:
await Share.RequestAsync(new ShareFileRequest
{
Title = Title,
File = new ShareFile(file)
});
So for the File I need the Path to the File from the Drawable Folder.
I have tried so much variations.
For example:
var file = Android.Net.Uri.Parse("android.resource://" + Android.App.Application.Context.PackageName + "/" + Resource.Drawable.image).Path;
But I always get an error, that the file is not found.
What I'm doing wrong?
Thanks in advance
Because Resources don't have file paths, as #Jason said I saved the image in another accesible file.
So I don't know if this is the best solution, but it works for me:
Drawable drawable = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.image, null);
Bitmap bitmap = ((BitmapDrawable)drawable).Bitmap;
byte[] imgByteArray;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
imgByteArray = stream.ToArray();
}
var file = System.IO.Path.Combine(FileSystem.CacheDirectory, "share.png");
File.WriteAllBytes(file, imgByteArray);
await Share.RequestAsync(new ShareFileRequest
{
Title = "Share",
File = new ShareFile(file)
});
Related
I'm trying to get image picker to work, and it does, but for some reason it won't populate as an image.
var openPicker = new FileOpenPicker
{
ViewMode = PickerViewMode.Thumbnail,
SuggestedStartLocation = PickerLocationId.PicturesLibrary
};
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
//Image img = new Image();
userImage.Source = new BitmapImage(new Uri(file.Path));
//await ProcessFile(file);
}
and the image is just simply:
<image name="userImage" height="500px" width="500px"/>
This isn't work because the UWP applications have permissions only for some users folders and even you need to browse their files, you need to specify it in the package.manifest of your application which folders you want to access. For simplification, you could create a copy of the file inside the application data folder and get the path from there or set the image source from the stream of the file, but be careful, the second option maybe lead some high memory usage and leaks. You can find how to avoid this here.
You can set stream as source instead of path.
var result = new BitmapImage();
using (var randomAccessStream = await file.OpenAsync(FileAccessMode.Read))
{
await result.SetSourceAsync(randomAccessStream);
}
I'm writing a telegram bot that takes jpg from it's users and sends it back as stickers.
I did this correctly by downloading jpg, change the extension of file to png and upload and send it back as a sticker message to the user. as shown below:
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var filename = file.FileId + "." + file.FilePath.Split('.').Last();
var pngFileName = filename.Split('.')[0] + ".png";
using (var saveImageStream = System.IO.File.Open(pngFileName, FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
using (var stream = System.IO.File.Open(pngFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
but the these stickers don't load in telegram on IOS devices and this code just works for telegram users on android. I tried to just changing the extension of jpg file to webp but it didn't work.
after that I downloaded the standard telegram stickers and found that the standard format of stickers in telegram is webp files.
now I want to know how can I convert received jpg file to webp file.
I searched alot and just find this , found here .
using (Image image = Image.FromFile("image.jpg"))
{
Bitmap bitmap = new Bitmap(image);
WebPFormat.SaveToFile("image.webp", bitmap);
}
I added it's files to my project and I added "using LibwebpSharp;" at the top of my code, but when I add it's sample code, the VS cannot find "WebpFormat" class.
please help me and answer my question:
"How can I convert jpg to webp in C# telegram bot?"
thank you
I solved this problem in this way:
I installed Imazen.WebP nuget.
I downloaded the 32bit dll from here and added it to release folder.
I added "using Imazen.WebP;in top of my code
I used this code to convert jpg to webp.
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var jpgFileName = file.FileId + ".jpg";
using (var saveImageStream = System.IO.File.Open(jpgFileName,FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
var webpFileName = file.FileId + ".webp";
using (Bitmap bitmap = new Bitmap(jpgFileName))
{
using (var saveImageStream = System.IO.File.Open(webpFileName, FileMode.Create))
{
var encoder = new SimpleEncoder();
encoder.Encode(bitmap, saveImageStream, 20);
}
}
using (var stream = System.IO.File.Open(webpFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
System.IO.File.Delete(jpgFileName);
System.IO.File.Delete(webpFileName);
Install the following packages first using Visual Studio's NuGet package manager:
Install-Package System.Drawing.Common
Install-Package ImageProcessor
Install-Package ImageProcessor.Plugins.WebP
Then use this code for conversion:
using (var webPFileStream = new FileStream(WebpFilePath, FileMode.Create))
{
using (ImageFactory imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(File.OpenRead(OriginalImagePath))
.Format(new WebPFormat())
.Quality(100)
.Save(webPFileStream);
}
}
Imageprocessor looks like a good library to convert the image. There is a Webp plugin.
Here is an article that may help.
Code example:
using ImageProcessor;
using ImageProcessor.Plugins.WebP.Imaging.Formats;
using (var normalFileStream = new FileStream(normalImagePath, FileMode.Create))
using (var webPFileStream = new FileStream(webPImagePath, FileMode.Create))
using (var imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(image.OpenReadStream())
.Format(new WebPFormat())
.Quality(50)
.Save(webPFileStream);
}
I made an application to save photos on the phone.
public void DownloadImage(string linkbitmap, string title)
{
Bitmap bitmap = GetImageBitmapFromUrl(linkbitmap).Result;
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures + "/Tsundere");
var complete = path.AbsolutePath;
var filepatch = System.IO.Path.Combine(complete, title + ".jpg");
var filestream = new FileStream(filepatch, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Png, 100, filestream);
filestream.Close();
}
The pictures are displayed in the file manager, but in the example the discord application does not have them. I have to restart the phone to be visible. How to make photos immediately visible in other applications, such as photos from the camera or photos downloaded from facebook?
I solve this problem. Just add MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] {path}, null, null);in the code
description this class https://developer.xamarin.com/api/type/Android.Media.MediaScannerConnection/
Construct an Intent action (Intent.ActionMediaScannerScanFile) with a uri that includes the file path:
using (var file = new Java.IO.File(path))
using (var uri = Android.Net.Uri.FromFile(file))
{
var scanFileIntent = new Intent(Intent.ActionMediaScannerScanFile, uri);
SendBroadcast(scanFileIntent);
}
FYI: You can create/register a BroadcastReceiver that listens for Intent.ActionMediaScannerFinished to determine when the media scanner is done processing your request.
I hope anyone can help me, I'am new in C, I am working on making web APIs that sends files from server based on an input , When I enter an ID , I get all files related to that ID (Indesign files, jpegs, pngs, illustator files ...)
I use Postman to get the resulat and it looks like the attached fileenter image description here :
I have to copy each link and paste it to address bar to download the file.
What I want is to have only one file (Zip) that contains all files.
Is that even doable ? Thanks
I found solution and it's returning a zipfile with the correct files, the issue now that these files have 0Kb size , Help please ?
Here's my code
``
MemoryStream archiveStream = new MemoryStream();
using (ZipArchive archiveFile = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (var item in assetsNotDuplicated)
{
// create file streams
// add the stream to zip file
var entry = archiveFile.CreateEntry(item.Name);
using (StreamWriter sw = new StreamWriter(entry.Open()))
{
sw.Write(item.Url);
}
}
}
HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);
responseMsg.Content = new ByteArrayContent(archiveStream.ToArray());
//archiveStream.Dispose();
responseMsg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "allfiles.zip" };
responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return responseMsg;
}
I want to get Thumbnail of files stored in Videos folder and save them as image in my local folder .
here is my code to get files .
var v = await KnownFolders.VideosLibrary.GetFilesAsync();
foreach (var file in v)
{
var thumb = await file.GetScaledImageAsThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem);
BitmapImage Img = new BitmapImage();
Img.SetSource(thumb);
await ApplicationData.Current.LocalFolder.CreateFolderAsync("VideoThumb");
var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"VideoThumb\\" + file.Name, CreationCollisionOption.FailIfExists);
var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite);
//I don't know how to save thumbnail on this file !
}
my project is a Windows Phone 8.1 Runtime C# app .
There are couple of things you need to handle:
you don't need BitmapImage, as thumbnail provides a stream which you can write directly to file,
you are not handling the case when create file method fails (file exists),
create folder method will throw exception as the folder is created (or already exists) with the first file in foreach. Rather than that, create/open folder outside foreach,
also creating image with file.Name is not a good idea, hence those are videos and their extension will likely be mp4/mpg/other not jpg/png/other,
remember to add capabilities in packageappx.manifest file.
I think the below code should do the job:
private async Task SaveViedoThumbnails()
{
IBuffer buf;
StorageFolder videoFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("VideoThumb", CreationCollisionOption.OpenIfExists);
Windows.Storage.Streams.Buffer inputBuffer = new Windows.Storage.Streams.Buffer(1024);
var v = await KnownFolders.VideosLibrary.GetFilesAsync();
foreach (var file in v)
{
var thumb = await file.GetScaledImageAsThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.SingleItem);
var imageFile = await videoFolder.CreateFileAsync(file.DisplayName + ".jpg", CreationCollisionOption.ReplaceExisting);
using (var destFileStream = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
while ((buf = (await thumb.ReadAsync(inputBuffer, inputBuffer.Capacity, Windows.Storage.Streams.InputStreamOptions.None))).Length > 0)
await destFileStream.WriteAsync(buf);
}
}