Resize IFormFile before Upload to Blob Storage - c#

I'm currently uploading a list of images to azure blob storage via the below function (path is then stored in DB).
This is all working fine however if the images are larger than a certain resolution, I want to resize to hopefully cut down the image file size (this would obviously be.
I've found examples of cropping an 'Image' however as this is a list of IFormFile (from an input type=upload) it doesn't seem to work the same. I've tried converting the IFormFile to an image and then resizing the image, however I'm then unable to convert back to IFormFile.
Any help or pointers would be great. Thanks.
public async Task UploadImagesAsync(IFormFileCollection files, int VehicleID)
{
var connectionString = _configuration.GetConnectionString("AzureStorageAccount");
var container = _uploadService.GetBlobContainer(connectionString);
foreach (var file in files)
{
// Resize file here
// parse the content disposition header
var contentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
// grab file name
var fileName = "Vehicles/" + VehicleID + "/" + contentDisposition.FileName.Trim('"');
// get reference
var blockBlob = container.GetBlockBlobReference(fileName);
// upload
await blockBlob.UploadFromStreamAsync(file.OpenReadStream());

According to my research, we can use SixLabors to resize the image in the application.
For example
public async Task UploadImagesAsync(IFormFileCollection files, int VehicleID)
{
foreach (var file in files)
{
var extension = Path.GetExtension(file.FileName);
var encoder = GetEncoder(extension);
if (encoder != null)
{
using (var output = new MemoryStream())
using (Image<Rgba32> image = Image.Load(input))
{
var divisor = image.Width / thumbnailWidth;
var height = Convert.ToInt32(Math.Round((decimal)(image.Height / divisor)));
image.Mutate(x => x.Resize(thumbnailWidth, height));
image.Save(output, encoder);
output.Position = 0;
await blockBlob.UploadFromStreamAsync(output);
}
}
}
}
private static IImageEncoder GetEncoder(string extension)
{
IImageEncoder encoder = null;
extension = extension.Replace(".", "");
var isSupported = Regex.IsMatch(extension, "gif|png|jpe?g", RegexOptions.IgnoreCase);
if (isSupported)
{
switch (extension)
{
case "png":
encoder = new PngEncoder();
break;
case "jpg":
encoder = new JpegEncoder();
break;
case "jpeg":
encoder = new JpegEncoder();
break;
case "gif":
encoder = new GifEncoder();
break;
default:
break;
}
}

Related

C# Image Resize from Stream

I'm trying to resize an image from stream. Getting the error
Value cannot be null.Parameter name: encoder
on the line
System.Drawing.Bitmap fullSizeBitmap = new
System.Drawing.Bitmap(fullsizeImage, new System.Drawing.Size(width,
image_height));
How do I add an encoder here? and I need it to be from the original image
public static FileProperty UploadImage(IFormFile file, string folderPath, string fileName, FileNote note, int image_height)
{
FileProperty property = new FileProperty();
if (file.Length > 0)
{
MemoryStream ms = new MemoryStream();
file.CopyTo(ms);
var fileBytes = ms.ToArray();
MemoryStream inputMemoryStream = new MemoryStream(fileBytes);
System.Drawing.Image fullsizeImage = System.Drawing.Image.FromStream(inputMemoryStream);
int width = (image_height / fullsizeImage.Height) * fullsizeImage.Width;
System.Drawing.Bitmap fullSizeBitmap = new System.Drawing.Bitmap(fullsizeImage, new System.Drawing.Size(width, image_height));
using (var stream = new MemoryStream())
{
fullSizeBitmap.Save(stream, fullSizeBitmap.RawFormat);
using (MemoryStream memoryStream = new MemoryStream(stream.ToArray()))
{
UploadFromStreamAsync(memoryStream);
}
}
property.FileName = fileName;
property.FileExtention = Path.GetExtension(fileName);
property.FileSize = file.Length;
property.FileType = file.ContentType;
property.FileNote = note.ToString();
}
return property;
}
Just use file.OpenReadStream() to read and resize the file, then save the resized bitmap to the MemoryStream and upload.
And instead of using bitmap.RawFormat you can get the uploaded image format using a method as below:
if (file.Length > 0)
{
using(var stream = file.OpenReadStream())
{
var image = Image.FromStream(stream);
int width = (image_height / fullsizeImage.Height) * fullsizeImage.Width;
Bitmap fullSizeBitmap = new Bitmap(fullsizeImage, new Size(width, image_height));
var imgFormat = GetImageFormat(file.FileName);
using(var ms = new MemoryStream())
{
fullSizeBitmap.Save(ms, imgFormat);
UploadFromStreamAsync(ms);
}
}
}
The method to get the image format by file extension:
public ImageFormat GetImageFormat(string fileName)
{
var dotIndex = fileName.LastIndexOf('.');
var ext = fileName.Substring(dotIndex, fileName.Length - dotIndex).ToLower();
switch (ext)
{
case ".bmp": return ImageFormat.Bmp;
case ".emf": return ImageFormat.Emf;
case ".exif": return ImageFormat.Exif;
case ".gif": return ImageFormat.Gif;
case ".icon": return ImageFormat.Icon;
case ".Jpg": return ImageFormat.Jpeg;
case ".Jpeg": return ImageFormat.Jpeg;
case ".png": return ImageFormat.Png;
case ".tiff": return ImageFormat.Tiff;
case ".Wmf": return ImageFormat.Wmf;
default: throw new InvalidDataException("Format not supported");
}
}
If you still need to get the uploaded image encoder info use the below method:
// ext: image extension
using System.Drawing.Imaging;
public static ImageCodecInfo GetEncoderInfo(string ext)
{
return ImageCodecInfo.GetImageEncoders().SingleOrDefault(x => x.FilenameExtension.ToLower().Contains(ext));
}

How to save photos from gallery to shared folder on a windows server in xamarin

I am trying to save an image from the Android gallery to a shared folder on a windows server. With the NuGet SharpCifs.Std package installed, I try to use the CopyTo method to save the image but it gives an error when the path is correct to my knowledge.
This is the error
Piece of code ...
using SharpCifs.Smb;
...
...
var windowsAuth = new NtlmPasswordAuthentication("mydomain.local", "user", "password");
var source = new SmbFile(photoFile);
var dest = new SmbFile(photosPath, windowsAuth);
source.CopyTo(dest);
In debug mode, the value of variables are:
source = file:///storage/emulated/0/Android/data/com.salicru/files/Pictures/temp/IMG_20190828_101004_88.jpg
dest = file://srvdoc/compartit/fotos equips/M3/6A0BW000001/
What am I doing wrong?
I had to create a method that I called ConvertMediaFileToByteArray for the conversion of the photo stream to a byte[].
private byte[] ConvertMediaFileToByteArray(MediaFile file)
{
using (var memoryStream = new MemoryStream())
{
file.GetStream().CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
Converting call.
file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
{
PhotoSize = PhotoSize.Small
});
if (file != null)
{
imageSource = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
//Convert ImatgeStream to BYTE[]
var imageToByte = ConvertMediaFileToByteArray(file);
}
Then, instead of using CopyTo method i used CreateNewFile method.
var windowsAuth = new NtlmPasswordAuthentication("domain", "admin", "password");
var dest = new SmbFile(photosPath + imageName, windowsAuth);
dest.CreateNewFile();
var writeStream = dest.GetOutputStream();
writeStream.Write(imageToByte);
writeStream.Dispose();

Create Zip file for multiple images c#

In my requirement I am converting docx to images its working fine but I need to store that converted multiple images into Zip file. Zip file was created successfully but Images are not opening it show corrupted/damage. Please try to help me to solve this solution. please refer my below total code. I used using Ionic.Zip; for creating a zip file.
//Opens the word document and fetch each page and converts to image
foreach (Microsoft.Office.Interop.Word.Window window in doc1.Windows)
{
foreach (Microsoft.Office.Interop.Word.Pane pane in window.Panes)
{
using (var zip = new ZipFile())
{
var pngTarget = "";
for (var i = 1; i <= pane.Pages.Count; i++)
{
var page = pane.Pages[i];
var bits = page.EnhMetaFileBits;
var target = Path.Combine(startupPath.Split('.')[0], string.Format("{1}_page_{0}", i, startupPath.Split('.')[0]));
try
{
using (var ms = new MemoryStream((byte[])(bits)))
{
var image = System.Drawing.Image.FromStream(ms);
pngTarget = Path.ChangeExtension(target, "png");
image.Save(pngTarget, ImageFormat.Png);
zip.AddEntry(pngTarget, "Img");
}
}
catch (System.Exception ex)
{ }
}
// CREATE A FILE USING A STRING.
// THE FILE WILL BE STORED INSIDE THE ZIP FILE.
// ZIP THE FOLDER WITH THE FILES IN IT.
//zip.AddFiles(Directory.GetFiles(#"c:\\users\\chaitanya_t\\Downloads\\"), "Images");
zip.Save(#"c:\\users\\chaitanya_t\\Downloads\\encoded.zip"); // SAVE THE ZIP FILE.
}
}
}
Try setting the stream position at the begin of the stream before processing:
using (var ms = new MemoryStream((byte[])(bits))){
ms.Position = 0; // Set stream position at the begin of the stream
var image = System.Drawing.Image.FromStream(ms);
pngTarget = Path.ChangeExtension(target, "png");
image.Save(pngTarget, ImageFormat.Png);
zip.AddEntry(pngTarget, ms.ToArray());
}

Get Thumbnail from mp3 file in c# xaml for windows phone 8.1

I need to get Thumbnail from mp3 files. I Implemented this but it never catch thumbnails. I checked the existence of the images opening them with windows media player and from xbox music (on the phone) but i can't retrieve them in my app. Please Help
async private void ThumbnailFetcher(StorageFile file)
{
if (file != null)
{
const ThumbnailMode thumbnailMode = ThumbnailMode.MusicView;
const uint size = 100;
using (StorageItemThumbnail thumbnail = await file.GetThumbnailAsync(thumbnailMode, size))
{
if (thumbnail != null && thumbnail.Type == ThumbnailType.Image)
{
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
BitmapImage thumbnailImage = new BitmapImage();//image used for display
thumbnailImage.SetSource(thumbnail);
CurrentAlbumArt.Source = thumbnailImage;
Debug.WriteLine("true");
});
}
else
{
Debug.WriteLine("False");
}
}
}
}
P.s It gives always false.
It seems there is a bug on windows phone 8.1, I searched all the night and the only method I could implemented is this
var fileStream = await file.OpenStreamForReadAsync();
var TagFile = File.Create(new StreamFileAbstraction(file.Name, fileStream, fileStream));
// Load you image data in MemoryStream
var tags = TagFile.GetTag(TagTypes.Id3v2);
IPicture pic = TagFile.Tag.Pictures[0];
MemoryStream ms = new MemoryStream(pic.Data.Data);
ms.Seek(0, SeekOrigin.Begin);
bitmap.SetSource(ms.AsRandomAccessStream());
AlbumArt.Source = bitmap;
but it doesn't work too..
var filestream = await receivedFile.OpenStreamForReadAsync();
var tagFile = File.Create(new StreamFileAbstraction(receivedFile.Name, filestream, filestream));
var tags = tagFile.GetTag(TagLib.TagTypes.Id3v2);
var bin = (byte[])(tags.Pictures[0].Data.Data);
MemoryStream ms = new MemoryStream(bin);
await bitmapImage.SetSourceAsync(ms.AsRandomAccessStream());
AlbumArt.Source=bitmapImage;
use this and taglib portable. (Sorry for take so much time)

Windows 8 - Save Image in XAML as local file ( inside Application folder )

In my Windows store application, i am displaying a picture using Image control in XAML. Source of the Image control is set, code wise using WriteableBitmap. I am trying to send this image as attachment in email. Is there any easy way for that? I am trying to save that image locally( within application ) and attach that saved image to email. But not able to save locally. Any help is appreciated.
Here is the code.
bitmap = await WriteableBitmapRenderExtensions.Render(dataCanvas);
image.Source = bitmap;
dataCanvas is a Canvas control consists of two images, one place above another. Actually i have to place a sunglass top of users face and display it as another image in xaml. Also email that image.
Check out the WriteableBitmapSaveExtensions class in WinRT XAML Toolkit for all the SaveToFile() extension methods you can use to save your WriteableBitmap.
The core one is this:
public static async Task SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFile outputFile,
Guid encoderId)
{
Stream stream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)writeableBitmap.PixelWidth,
(uint)writeableBitmap.PixelHeight,
96,
96,
pixels);
await encoder.FlushAsync();
using (var outputStream = writeStream.GetOutputStreamAt(0))
{
await outputStream.FlushAsync();
}
}
}
You can get the encoder ID using an overload of the method:
public static async Task<StorageFile> SaveToFile(
this WriteableBitmap writeableBitmap,
StorageFolder storageFolder,
string fileName,
CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
{
StorageFile outputFile =
await storageFolder.CreateFileAsync(
fileName,
options);
Guid encoderId;
var ext = Path.GetExtension(fileName);
if (new[] { ".bmp", ".dib" }.Contains(ext))
{
encoderId = BitmapEncoder.BmpEncoderId;
}
else if (new[] { ".tiff", ".tif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".gif" }.Contains(ext))
{
encoderId = BitmapEncoder.GifEncoderId;
}
else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegEncoderId;
}
else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegXREncoderId;
}
else //if (new [] {".png"}.Contains(ext))
{
encoderId = BitmapEncoder.PngEncoderId;
}
await writeableBitmap.SaveToFile(outputFile, encoderId);
return outputFile;
}
Any subclass of BitmapSource (including WritableBitmap) can be passed to a BitmapEncoder. A BitmapEncoder takes a Stream to which the encoded JPEG, PNG or other image is written.
You can then use a mailer library to reference the stream used by the encoder, or use the Share contract, and pass the stream directly.
Example:
var bitmap = new WritableBitmap();
// ... draw your bitmap
var tempPath = // path to where you want to save (probably in your appx temp);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(bitmap);
using (var fs = new FileStream(tempPath))
{
encoder.Save(fs);
}
// use the image saved to tempPath
// http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh871370.aspx

Categories

Resources