Resize Image When Upload in Asp Core - c#

I need to change the size of the photo and save it to a new size when the user selects a photo for the upload, before saving the photo.
i using this code but it not save with new size . whats the problem ?
public async Task<IActionResult> UploadNewsPic()
{
var file = Request.Form.Files[0];
try
{
if (file.Length > 0)
{
string fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
string fullPath = Path.Combine(_applicationRoot.UploadNewPath(), file.Name);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
if (file.IsImage())
{
await file.ResizeImage(3, 3);
file.CopyTo(stream);
}
}
}
return Ok();
}
catch (Exception e)
{
return BadRequest();
}
}
and this is Resize Extention :
public async static Task<Image> ResizeImage(this IFormFile file, int width, int height)
{
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
using (var img = Image.FromStream(memoryStream))
{
return img.Resize(width, height);
}
}
}
public static Image Resize(this Image image, int width, int height)
{
var res = new Bitmap(width, height);
using (var graphic = Graphics.FromImage(res))
{
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.DrawImage(image, 0, 0, width, height);
}
return res;
}

You need to save the result from ResizeImage to the stream. Right now you are just copying the original file.
var img = await file.ResizeImage(3, 3);
img.Save(stream, SomeFormat);

Your ResizeImage() function return a resized image, it doesn't edit the image itself, so you must set it to a variable.
if (file.IsImage())
{
Image imageResized = await file.ResizeImage(3, 3);
// ...
}

Related

GDI+ System.Runtime.InteropServices.ExternalException On Image resize and conversion

The ImageHandler class is responsible for converting the image to jpg and 60x60 size, then it converts it to Base64. The first Image is fine but when I try to proccess another image in the same run it crashes.
class ImageHandler
{
public static void convertToFormat(string filename)
{
var image = Image.FromFile(#filename);
var bitmap = ResizeImage(image, Globals.ImageSize, Globals.ImageSize);
bitmap.Save(Globals.PRED_PATH, ImageFormat.Jpeg);
}
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
public static string ConvertImageToBase64String()
{
Image image = Image.FromFile(Globals.PRED_PATH);
var imageStream = new MemoryStream();
image.Save(imageStream, ImageFormat.Jpeg);
imageStream.Position = 0;
var imageBytes = imageStream.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
Function Call:
ImageHandler.convertToFormat(FilePath);
string encodedImage = ImageHandler.ConvertImageToBase64String();
As a quick fix you can add image.Dispose(); after image.Save(imageStream, ImageFormat.Jpeg); in the method ConvertImageToBase64String to make it work.
However I would recommend that you add using statements to convertToFormat and ConvertImageToBase64String to properly free the resources after use.
public static void convertToFormat(string filename)
{
using (var image = Image.FromFile(#filename))
{
using (var bitmap = ResizeImage(image, Globals.ImageSize, Globals.ImageSize))
{
bitmap.Save(Globals.PRED_PATH, ImageFormat.Jpeg);
}
}
}
public static string ConvertImageToBase64String()
{
using (var image = Image.FromFile(Globals.PRED_PATH))
{
using (var imageStream = new MemoryStream())
{
image.Save(imageStream, ImageFormat.Jpeg);
imageStream.Position = 0;
var imageBytes = imageStream.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
}

Resize an image after upload and before saving it into the db

I have a simple web application (ASP.NET MVC 5 C#) which allows users to upload several files (images actually).
Currently it works well, the images are stored into the data base and I can read them later.
But I want to resize the images before saving them into the db, since the user can upload extremely big images.
Here is my controller:
public ActionResult Create(Annonce annonce, IEnumerable<HttpPostedFileBase> photos)
{
if (ModelState.IsValid)
{
// Read each uploaded files and add if into the collection
foreach (HttpPostedFileBase fichier in photos)
{
if (fichier != null && fichier.ContentLength > 0)
{
// Making a new object
var photo = new Photo
{
FileName = System.IO.Path.GetFileName(fichier.FileName),
ContentType = fichier.ContentType
};
using (var reader = new System.IO.BinaryReader(fichier.InputStream))
{
photo.Content = reader.ReadBytes(fichier.ContentLength);
}
// Add the current image to the collection
annonce.Photos.Add(photo);
}
}
db.Annonces.Add(annonce);
db.SaveChanges();
return RedirectToAction("Details", new { id = annonce.ID });
}
return View(annonce);
}
How can I resize my images and still be able to save them into the db?
Is-it even possible?
Thanks!
This code will perform a high quality resizing.(means you wont lose very much)
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width,image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Call ResizeImage() and assign it to a bitmap which you'll insert into your database.goodluck
you can convert it to byte array and than store it in your db as byte type
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
you can do the same but inverted to get it out and display it as image from the DB:
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
You also approach to ImageResizer as link below:
http://www.c-sharpcorner.com/article/image-resize-in-asp-net-mvc-using-image-resizer/

Set Secondary Tile BackgroundImage from Image in Isolated Storage

This is how I get the stream from an image url:
using (var httpClient = new HttpClient())
{
response = await httpClient.GetStreamAsync(new Uri(IMAGEURL_HERE, UriKind.Absolute));
}
SaveImage(response);
And this is how I save it to IsoloatedStorage:
private void SaveImage(Stream result)
{
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(result);
var wb = new WriteableBitmap(bitmap);
using (IsolatedStorageFileStream fileStream = file.CreateFile("FILENAME.jpg"))
{
int width = wb.PixelWidth;
int height = wb.PixelHeight;
if (wb.PixelWidth > 336)
{
width = 336;
}
if (wb.PixelHeight > 336)
{
height = 336;
}
Extensions.SaveJpeg(wb, fileStream, width, height, 0, 100);
}
}
}
So let's say the file is FILENAME.jpg, I thought I could set it as BackgroundImage to a Secondary Tile like this:
var tileData = new FlipTileData()
{
...
BackgroundImage = new Uri("isostore:/Shared/ShellContent/FILENAME.jpg", UriKind.Absolute),
...
It won't work. It throws no exception, only the image won't be displayed. What do I miss? Of course if I put the Image Url as Uri to BackgroundImage it works, but this is not what I want.
Edit: And I have seen similar questions here but it did not help me with my code.
Try this. May be its help.
string imageFolder = #"\Shared\ShellContent";
string shareJPEG = "FILENAME.jpg";
private void SaveImage(Stream result)
{
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
if(!myIsolatedStorage.DirectoryExists(imageFolder))
{
myIsolatedStorage.CreateDirectory(imageFolder);
}
if (myIsolatedStorage.FileExists(shareJPEG))
{
myIsolatedStorage.DeleteFile(shareJPEG);
}
string filePath = System.IO.Path.Combine(imageFolder, shareJPEG);
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(filePath);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(result);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
int width = wb.PixelWidth;
int height = wb.PixelHeight;
if (wb.PixelWidth > 336)
{
width = 336;
}
if (wb.PixelHeight > 336)
{
height = 336;
}
Extensions.SaveJpeg(wb, fileStream, width, height, 0, 100);
fileStream.Close();
}
}
private void CreateTile()
{
var tileData = new FlipTileData()
{
....
string filePath = System.IO.Path.Combine(imageFolder, shareJPEG);
BackgroundImage = new Uri(#"isostore:" + filePath, UriKind.Absolute);
....
}
}

mvc c# upload image after resize

So I have an action which processes the uploading of a file. What I do is I check if the file size is 100kb, if not I resize it to a certain width and height (altho im not sure that's the right way to go to the desired size, thoughts?)
And then I'm planning to save it to a subdomain of my website.
this is how the action looks like
public ActionResult New(string account, int id, HttpPostedFileBase file)
{
if (file == null)
{
ModelState.AddModelError("", "File not found.");
return View();
}
if (!ImageUpload.FileTypeValid(file.ContentType))
{
ModelState.AddModelError("", "File type is invalid. Please choose a different file.");
return View();
}
if (file.ContentLength > 100)
{
Image image = ImageUpload.ResizeFile(file, 100, 100);
}
try
{
icdb.SaveChanges();
ModelState.AddModelError("", "Sucesfully saved Image.");
return RedirectToAction("Details", "OfAController", new { account = account, id= id});
}
catch (Exception ex)
{
ModelState.AddModelError("", ex.Message);
}
return View();
}
this is the resize method
static public Image ResizeFile(HttpPostedFileBase file, int targeWidth, int targetHeight)
{
Image originalImage = Image.FromStream(file.InputStream, true, true);
var newImage = new MemoryStream();
Rectangle origRect = new Rectangle(0, 0, originalImage.Width, originalImage.Height);
// if targets are null, require scale. for specified sized images eg. Event Image, or Profile photos.
int newWidth = targeWidth;
int newHeight = targetHeight;
var bitmap = new Bitmap(newWidth, newHeight);
try
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(originalImage, new Rectangle(0, 0, newWidth, newHeight), origRect, GraphicsUnit.Pixel);
bitmap.Save(newImage, originalImage.RawFormat);
}
return (Image)bitmap;
}
catch
{ // error before IDisposable ownership transfer
if (bitmap != null)
bitmap.Dispose();
throw new Exception("Error resizing file.");
}
}
so my problem is, im trying to find ways on how to save this resized file to my directory. And then I keep finding that I have to upload the image first before resizing? Is that right? Or is there a way where I can resize this before I save to my directory?
Thoughts?
Thanks!

Image Resizing from SQL Database on the fly with MVC2

I have a simple MVC2 app that uploads a file from the browser to an MS SQL database as an Image blob.
Then I can return the results with something like:
public FileContentResult ShowPhoto(int id)
{
TemporaryImageUpload tempImageUpload = new TemporaryImageUpload();
tempImageUpload = _service.GetImageData(id) ?? null;
if (tempImageUpload != null)
{
byte[] byteArray = tempImageUpload.TempImageData;
return new FileContentResult (temp, "image/jpeg");
}
return null;
}
But I want to return these images resized as both thumbnails and as a gallery-sized view. Is this possible to do within this Result? I've been playing around with the great imageresizer.net but it seems to want to store the images on my server which I want to avoid. Is it possible to do this on the fly..?
I need to keep the original file and don't, if possible, want to store the images as files on the server.
Thanks for any pointers!
ImageResizer.NET allows you to pass a stream to it for resizing, see Managed API usage
The method you'd use is:
ImageResizer.ImageBuilder.Current.Build(object source, object dest, ResizeSettings settings)
I modified your method to go about it this way, but it is untested. Hope it helps.
public FileContentResult ShowPhoto(int id)
{
TemporaryImageUpload tempImageUpload = new TemporaryImageUpload();
tempImageUpload = _service.GetImageData(id) ?? null;
if (tempImageUpload != null)
{
byte[] byteArray = tempImageUpload.TempImageData;
using(var outStream = new MemoryStream()){
using(var inStream = new MemoryStream(byteArray)){
var settings = new ResizeSettings("maxwidth=200&maxheight=200");
ImageResizer.ImageBuilder.Current.Build(inStream, outStream, settings);
var outBytes = outStream.ToArray();
return new FileContentResult (outBytes, "image/jpeg");
}
}
}
return null;
}
There was a recent Hanselminutes podcast on Image Resizing with Nathanael Jones discussing some of the pitfalls of image resizing.
Even if you do not have 30 odd minutes to listen to the full podcast, the show notes point to some interesting resizing pitfalls, as well as an image resizing library also written by Nathanael Jones.
You could resize the image on the fly:
public void ResizeImage(Stream input, Stream output, int newWidth, int maxHeight)
{
using (var srcImage = Image.FromStream(input))
{
int newHeight = srcImage.Height * newWidth / srcImage.Width;
if (newHeight > maxHeight)
{
newWidth = srcImage.Width * maxHeight / srcImage.Height;
newHeight = maxHeight;
}
using (var newImage = new Bitmap(newWidth, newHeight))
using (var gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
newImage.Save(output, ImageFormat.Jpeg);
}
}
}
and then you could have 2 controller actions (one that displays the full image size and one that displays a thumbnail):
public ActionResult Thumbnail(int id)
{
var tempImageUpload = new TemporaryImageUpload();
tempImageUpload = _service.GetImageData(id) ?? null;
if (tempImageUpload == null)
{
return HttpNotFound();
}
using (var input = new MemoryStream(tempImageUpload.TempImageData))
using (var output = new MemoryStream())
{
ResizeImage(input, output, 640, 1000);
return File(output.ToArray(), "image/jpeg");
}
}

Categories