Upload image to a server from PictureBox - c#

I have one pictureBox and a button on form1 one. When the button is clicked, it should upload the file to the server. For now I am using the below method. First save the image locally and then upload to the server:
Bitmap bmp = new Bitmap(this.form1.pictureBox1.Width, this.form1.pictureBox1.Height);
Graphics g = Graphics.FromImage(bmp);
Rectangle rect = this.form1.pictureBox1.RectangleToScreen(this.form1.pictureBox1.ClientRectangle);
g.CopyFromScreen(rect.Location, Point.Empty, this.form1.pictureBox1.Size);
g.Dispose();
bmp.Save("filename", ImageFormat.Jpeg);
And then uploading that file:
using (var f = System.IO.File.OpenRead(#"F:\filename.jpg"))
{
HttpClient client = new HttpClient();
var content = new StreamContent(f);
var mpcontent = new MultipartFormDataContent();
content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
mpcontent.Add(content);
client.PostAsync("http://domain.com/upload.php", mpcontent);
}
I can't use the Bitmap type in StreamContent. How can I stream the image from pictureBox directly instead saving it as file first?
I came up with the below code using MemoryStream, but the uploaded file size is 0 using this method. Why?
byte[] data;
using (MemoryStream m = new MemoryStream())
{
bmp.Save(m, ImageFormat.Png);
m.ToArray();
data = new byte[m.Length];
m.Write(data, 0, data.Length);
HttpClient client = new HttpClient();
var content = new StreamContent(m);
var mpcontent = new MultipartFormDataContent();
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
mpcontent.Add(content, "file", filename + ".png");
HttpResponseMessage response = await client.PostAsync("http://domain.com/upload.php", mpcontent);
//response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
MessageBox.Show(body);
}

I am not sure if it is the correct way to do it, but I have solved it by creating a new stream and then copying the older one to it:
using (MemoryStream m = new MemoryStream())
{
m.Position = 0;
bmp.Save(m, ImageFormat.Png);
bmp.Dispose();
data = m.ToArray();
MemoryStream ms = new MemoryStream(data);
// Upload ms
}

Image returnImage = Image.FromStream(....);

Related

REST response trying to IMG or other filetype

Ive got a question I am having a case of rest response that is always string, it suppose to download content of the file, but there can be many different files, for example PNG, now if I'm getting a string in response is it possible to convert it back to PNG at the end, I tried something like:
byte[] array = Encoding.ASCII.GetBytes(result.data); //response content
MemoryStream ms = new MemoryStream(array);
Image i = Image.FromStream(ms);
I dont think im getting base64 string from rest looks like (part of it, and if i remmebr base64 ends with 3 === and don't have any non printable chars):
�PNG\r\n\n\0\0\0\rIHDR\0\0�\0\0\0�\b\0\0\0���\0\0\0sRGB\0���\0\0\0gAMA\0\0��\v�a\0\0\0\tpHYs\0\0t\0\0t�fx\0\0\f\aIDATx^��!x�L���Jde%�yY�D�H$�d%2��S��Hd%y�<�ӹ�B�ٝ�O�mﺔ��d����\r\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0���\a�(H|\0�\"D�WU��v������r��o#\f!��y�����K�\0�'D�O�SM�\f�����\0��Dǯ�z4�R��C�7\0��+�\0�\0Q��\0�\0Q��UU���ļO ?�������!�#J�>���|D��$>\f�|D��$>\f��7X,�?�_\v]�V�^/�=��#4$�����$:��P9
Assuming you are returning base 64 string from the API response, you can do something like this
byte[] bytes = Convert.FromBase64String(result.data);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
Or you can save it directly to the file
string filePath = "Image.png";
File.WriteAllBytes(filePath, Convert.FromBase64String(result.data));
EDIT 1:
How are you returning data from your web API? You could do something like this to return byte array and then use this array directly to write to stream.
var result = new HttpResponseMessage(HttpStatusCode.OK);
String filePath = HostingEnvironment.MapPath("~/imagename.png");
FileStream fileStream = new FileStream(filePath, FileMode.Open);
Image image = Image.FromStream(fileStream);
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Jpeg);
result.Content = new ByteArrayContent(memoryStream.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return result;
and on the client side you can do something like
var data = response.Content.ReadAsByteArrayAsync().Result;
Image image;
using (MemoryStream ms = new MemoryStream(data))
{
image = Image.FromStream(ms);
}
return image;

Changing image size from stream

I've searched here for help with this, but nothing quite matches what I need. I have an image that gets uploaded, and I'd like to change the size before it gets saved to azure.
So currently my code is:
public ActionResult UserDetails(HttpPostedFileBase photo)
{ var inputFile = new Photo()
{
FileName = photo.FileName,
Data = () => photo.InputStream
};
//then I save to Azure
How would I change the photo.InputStream to 100x 100 px for example?
Here is how I do it:
byte[] imageBytes;
//Of course image bytes is set to the bytearray of your image
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
using (Image img = Image.FromStream(ms))
{
int h = 100;
int w = 100;
using (Bitmap b = new Bitmap(img, new Size(w,h)))
{
using (MemoryStream ms2 = new MemoryStream())
{
b.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);
imageBytes = ms2.ToArray();
}
}
}
}
From there, I use a MemoryStream to upload. I use blob storage and use the UploadFromStreamAsync to load to blob.
This is a basic view of it.

Upload Image to server with EXIF data

I'm not trying to read the EXIF data on either the device or server, but the data needs to be present on the server.
I am currently sending the image to the server via converting it to a byte[] and then to base64 Convert.ToBase64(byte[]) and sending it using JSON - see code below.
But when I get the file at the other end, it doesn't have any EXIF data. If I get the image off the emulator with the fake SD card, the EXIF data exists.
Does anyone know how to upload the image and then reconstruct it at the other end so that the EXIF data stays intact?
Image to bytes to base64 to JSON
BitmapImage image = new BitmapImage();
image.SetSource(e.ChosenPhoto);
image = ResizeImage(image);
byte[] imageBytes;
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(image);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, image.PixelWidth, Image.PixelHeight, 0, 100);
image = null;
imageBytes = ms.ToArray();
}
Base64Image imagestring = new Base64Image();
imagestring.imagestring = Convert.ToBase64String(imageBytes);
string json = JsonConvert.SerializeObject(imagestring);
JSON To base64 to byte[] to image
using (StreamReader sr = new StreamReader(inputStream))
{
postData = sr.ReadToEnd();
}
JavaScriptSerializer deserializer = new JavaScriptSerializer();
Dictionary<string, object> jsonObjects = (Dictionary<string, object>)deserializer.DeserializeObject(postData);
string base64image = jsonObjects["imagestring"].ToString();
byte[] imagebytes = Convert.FromBase64String(base64image);
BitmapImage bitmapImage = new BitmapImage();
MemoryStream ms = new MemoryStream(imagebytes);
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnDemand;
bitmapImage.CreateOptions = BitmapCreateOptions.None;
bitmapImage.Rotation = Rotation.Rotate0;
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
bitmapImage.CreateOptions = BitmapCreateOptions.None;
WriteableBitmap wBmp = new WriteableBitmap(bitmapImage);
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wBmp));
I had to change my code completely to cut out any connection to Bitmaps or other formats, and just used byte[] through it. See code:
On the app:
ImageData imagedata = new ImageData();
byte[] imagebytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(imagebytes, 0, int.Parse(e.ChosenPhoto.Length.ToString()));
imagedata.imagestring = Convert.ToBase64String(imagebytes);
string json = JsonConvert.SerializeObject(imagedata);
At the server:
JavaScriptSerializer deserializer = new JavaScriptSerializer();
deserializer.MaxJsonLength = 50000000;
Dictionary<string, object> jsonObjects = (Dictionary<string, object>)deserializer.DeserializeObject(postData);
string base64image = jsonObjects["imagestring"].ToString();
byte[] imagebytes = Convert.FromBase64String(base64image);
Guid imagename = Guid.NewGuid();
if (!Directory.Exists(EM.ImagePath))
Directory.CreateDirectory(EM.ImagePath);
using (FileStream sw = new FileStream(EM.ImagePath + imagename + ".jpg", FileMode.CreateNew))
{
sw.Write(imagebytes, 0, imagebytes.Length);
}

Convert bitmap to ImageSource give NullReference exception

I've got WCF service to send image as a stream to client app.
My client app gets the stream :
Stream imageStream = client.GetImage();
When I use this code:
imageStream.CopyTo(stream);
int size = (int)stream.Length;
stream.Seek(0, SeekOrigin.Begin);
BitmapFrame bf = BitmapFrame.Create(stream,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
cam_img.Source = bf;
It work's fine but I need apply some filters to image before assign to source.
So I need bitmap. First, I convert Stream imageStream to byte array and then I use some code I find on forums:
byte[] tab_img;
using (var memoryStream = new MemoryStream())
{
imageStream.CopyTo(memoryStream);
tab_img= memoryStream.ToArray();
}
Bitmap bm;
using (MemoryStream mStream = new MemoryStream())
{
mStream.Write (tab_img, 0, tab_img.Length);
mStream.Seek(0, SeekOrigin.Begin);
bm = new Bitmap(mStream);
Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
Bitmap bm_post = filter.Apply(bm);
ImageSourceConverter c = new ImageSourceConverter();
object source = new ImageSourceConverter().ConvertFrom(bm_post);
ImageSource is1 = (ImageSource)source;
cam_img.Source = is1;
}
but I still get NullReferenceException in line
object source = new ImageSourceConverter().ConvertFrom(bm_post);

Image from URL to stream

I'm getting images from a url:
BitmapImage image = new BitmapImage(new Uri(article.ImageURL));
NLBI.Thumbnail.Source = image;
This works perfect, now i need to put it in a stream, to make it into byte array. I'm doing this:
WriteableBitmap wb = new WriteableBitmap(image);
MemoryStream ms = new MemoryStream();
wb.SaveJpeg(ms, image.PixelWidth, image.PixelHeight, 0, 100);
byte[] imageBytes = ms.ToArray();
And code fails with NullReference, how to fix it?
var webClient = new WebClient();
byte[] imageBytes = webClient.DownloadData(article.ImageURL);
You get a NullReference exception because the image is still not loaded when you use it. You can wait to the ImageOpened event, and then work with it:
var image = new BitmapImage(new Uri(article.ImageURL));
image.ImageOpened += (s, e) =>
{
image.CreateOptions = BitmapCreateOptions.None;
WriteableBitmap wb = new WriteableBitmap(image);
MemoryStream ms = new MemoryStream();
wb.SaveJpeg(ms, image.PixelWidth, image.PixelHeight, 0, 100);
byte[] imageBytes = ms.ToArray();
};
NLBI.Thumbnail.Source = image;
Other option is to get the stream of the image file directly using WebClient:
WebClient client = new WebClient();
client.OpenReadCompleted += (s, e) =>
{
byte[] imageBytes = new byte[e.Result.Length];
e.Result.Read(imageBytes, 0, imageBytes.Length);
// Now you can use the returned stream to set the image source too
var image = new BitmapImage();
image.SetSource(e.Result);
NLBI.Thumbnail.Source = image;
};
client.OpenReadAsync(new Uri(article.ImageURL));
you can use this:
private async Task<byte[]> GetImageAsByteArray(string urlImage, string urlBase)
{
var client = new HttpClient();
client.BaseAddress = new Uri(urlBase);
var response = await client.GetAsync(urlImage);
return await response.Content.ReadAsByteArrayAsync();
}

Categories

Resources