Resize uploaded image in MVC 6 - image

What is the best way to resize an uploaded image in MVC 6? I'd like to store multiple variants of an image (such as small, large, etc.) to be able to choose which to display later.
Here's my code for the action.
[HttpPost]
public async Task<IActionResult> UploadPhoto()
{
if (Request.Form.Files.Count != 1)
return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
IFormFile file = Request.Form.Files[0];
// calculate hash
var sha = System.Security.Cryptography.SHA256.Create();
byte[] hash = sha.ComputeHash(file.OpenReadStream());
// calculate name and patch where to store the file
string extention = ExtentionFromContentType(file.ContentType);
if (String.IsNullOrEmpty(extention))
return HttpBadRequest("File type not supported");
string name = WebEncoders.Base64UrlEncode(hash) + extention;
string path = "uploads/photo/" + name;
// save the file
await file.SaveAsAsync(this.HostingEnvironment.MapPath(path));
}

I would suggest using Image Processor library.
http://imageprocessor.org/imageprocessor/
Then you can just do something along the lines of:
using (var imageFactory = new ImageFactory())
using (var fileStream = new FileStream(path))
{
file.Value.Seek(0, SeekOrigin.Begin);
imageFactory.FixGamma = false;
imageFactory.Load(file.Value)
.Resize(new ResizeLayer(new Size(264, 176)))
.Format(new JpegFormat
{
Quality = 100
})
.Quality(100)
.Save(fileStream);
}
Where file.Value is your file that was uploaded (the stream) (I don't know what it is in MVC, this is code I use in a Nancy project)

Related

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:

ImageProcessorCore: Attempt to resample image results in zero-length response

I am trying to resample a JPG image from 300dpi to 150dpi and am getting back a zero-length file.
Controller's ActionResult:
public ActionResult ViewImage(string file, int dpi = 300, bool log = true)
{
FileExtensions fileExtensions = new FileExtensions();
ImageExtensions imageExtensions = new ImageExtensions();
FileModel fileModel = fileExtensions.GetFileModel(file);
string contentType = fileModel.FileType;
byte[] fileData = fileModel.FileData;
string fileName = Path.GetFileNameWithoutExtension(fileModel.FileName) + "_" + dpi + "DPI" + Path.GetExtension(fileModel.FileName);
FileStreamResult resampledImage = imageExtensions.ResampleImage(fileData, contentType, dpi);
resampledImage.FileDownloadName = fileName;
return resampledImage;
}
ResampleImage method:
public FileStreamResult ResampleImage(byte[] fileData, string contentType, int targetDPI)
{
MemoryStream outputStream = new MemoryStream();
using (Stream sourceStream = new MemoryStream(fileData))
{
Image image = new Image(sourceStream);
image.HorizontalResolution = targetDPI;
image.VerticalResolution = targetDPI;
JpegEncoder jpegEncoder = new JpegEncoder();
jpegEncoder.Quality = 100;
image.Save(outputStream, jpegEncoder);
}
FileStreamResult file = new FileStreamResult(outputStream, contentType);
return file;
}
I thought I best answer here since we've already dealt with it on the issue tracker.
ImageProcessorCore at present (2016-08-03) is alpha software and as such is unfinished. When you were having the issue, horizontal and vertical resolution was not settable in jpeg images. This is now solved.
Incidentally there are overloads that allow saving as jpeg without having to create your own JpegEncoder instance.
image.SaveAsJpeg(outputStream);

How to download files from Wikimedia Commons by API?

How can I download a lot of audio (.ogg) files from Wikimedia Commons? Is it possible using the Mediawiki API?
You can use MediaWiki API to get the url download links not only for .ogg but also to any other image or media file uploaded on Wikimedia Commons. From the response you can easy download each one file. Here is an example in C#:
private static void GetFiles(List<string> fileNames)
{
//Get HTML request with all file names
var url = "https://commons.wikimedia.org/w/api.php?action=query&format=xml" +
"&prop=imageinfo&iiprop=url&titles=File:" + string.Join("|File:", fileNames);
using (var webResponse = (HttpWebResponse)WebRequest.Create(url).GetResponse())
{
using (var reader = new StreamReader(webResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
//Get all file url links by parsing the XML response
var links = XElement.Parse(response).Descendants("ii")
.Select(x => x.Attribute("url").Value);
foreach (var link in links)
{
//Save the current file on the disk
using (var client = new WebClient())
{
var fileName = link.Substring(link.LastIndexOf("/") + 1);
client.DownloadFile(link, fileName);
}
}
}
}
}
Usage:
//list of files to download
var fileNames = new List<string>() {
"Flag of France.svg", "Black scorpion.jpg", "Stop.png", //image
"Jingle Bells.ogg", "Bach Astier 15.flac", //audio
"Cable Car.webm", "Lion.ogv", //video
"Animalibrí.gif", //animation
};
GetFiles(fileNames);
Note: The API has limit for the files:
Maximum number of values is 50 (500 for bots).
So, if you need to download more files, you will have to split the list in parts and to create another requests.

Want an efficient ASP.NET Web API controller that can reliably return 30 to 50 ~3MB JPEGs

I'd like to change the following code into an efficient Web API controller method that can return 30 to 50 JPEGs (for <20 simultaneous users) of average 3MB size.
public async Task<HttpResponseMessage> Get(int imageid) {
return await Task.Run(() => {
var dzImage = _dataContext.DeepZoomImages.SingleOrDefault(_ => _.ImageID == imageid);
if (dzImage == default(DeepZoomImage)) {
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
var response = new HttpResponseMessage(HttpStatusCode.OK);
var bitmap = GetFullSizeBitmap(dzImage);
var memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Jpeg);
response.Content = new ByteArrayContent(memoryStream.ToArray());
var fileName = string.Format("{0}.jpg", dzImage.ImageName);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = fileName };
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
memoryStream.Flush();
return response;
});
}
The foregoing method handles one image. How can I best pluralize it to handle multiple images efficiently for this usage/load scenario? Is it possible to return Task<HttpResponseMessage>[] or Task<HttpResponseMessage[]>?
Or would it be better generate all images and return them in one go?
Thanks for your help...
Based on our discussion the best approach here would be to create a ZIP file on the server and then download that one file to the user. As an alternative you could try this multi-file download approach.

How to upload images on Facebook wall by using MVC3, C#?

I'm trying to upload photos into Facebook by using MVC3 C#. The code is running successfully but the photos are not uploaded into Facebook. I'm having add ID and App Secret. I tried many ways and for many days I worked hard, but the result is zero. Here is the code of my controller
[HttpPost][HttpGet]
public ActionResult Profile(HttpPostedFileBase file, FacebookOAuthResult facebookOAuthResult) {
dynamic args = new ExpandoObject();
args = new Dictionary<string, object>();
args["message"] = "hi";
args["picture"] = "http://apps.facebook.com/Uploads/photos";
string accesstoken=FacebookWebContext.Current.AccessToken;
FacebookClient fbApp = new FacebookClient(accesstoken);
try {
fbApp.Post("MYAPPID" + "/Photos", args);
} catch (FacebookOAuthException ex) {
//
}
// Verify that the user selected a file
if (file != null && file.ContentLength > 0) {
var path1 = Path.Combine(Server.MapPath("~/Content/uppoads"), file.FileName);
//file.SaveAs(path1);
fbApp.Post("MYAPPID" + "/photos", path1);
}
// redirect back to the index action to show the form once again
return RedirectToAction("Profile");
}
Could anyone help me to find the solution? Thanks in advance.
You are Post the local path of the photo to Facebook, FB doesn't know what it is.
You should post the photo as binary in the Post body.
var media = new Facebook.FacebookMediaObject();
var filebytes = System.IO.File.ReadAllBytes(path1);
media.SetValue(filebytes);
fbApp.Post("248050331932489" + "/photos", media);

Resources