I am trying to upload an image to Amazon S3 but before that I am resizing the image. For resizing I have to pass the stream objects and at one point (line commented as //Error) I am getting 'Stream does not support writing.' Exception. Please help.
public ActionResult AddPost(AddPost post)
{
Guid guid = new Guid();
AccountController ac=new AccountController();
string randomId = guid.ToString();
PutAttributesRequest putAttributesAction = new PutAttributesRequest().WithDomainName("ThisIsMyEXDomainPosts").WithItemName(randomId);
List<ReplaceableAttribute> attrib = putAttributesAction.Attribute;
System.IO.Stream stream;
System.IO.StreamReader sr = new System.IO.StreamReader(post.imageFileAddress.ToString());
sr.ReadToEnd();
stream = sr.BaseStream;
Amazon.S3.Model.PutObjectRequest putObjectRequest = new Amazon.S3.Model.PutObjectRequest();
System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
System.Drawing.Image imgResized = ResizeImage(img, 640, 800);
System.IO.MemoryStream mstream = new System.IO.MemoryStream();
imgResized.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
mstream.WriteTo(stream);//Error
putObjectRequest.WithBucketName("TIMEXImages");
putObjectRequest.CannedACL = Amazon.S3.Model.S3CannedACL.PublicRead;
putObjectRequest.Key = randomId + "_0.jpg";
putObjectRequest.InputStream = stream;
Amazon.S3.Model.S3Response s3Response = as3c.PutObject(putObjectRequest);
s3Response.Dispose();
//Uploadig the Thumb
System.Drawing.Image imgThumb = ResizeImage(img, 80, 100);
imgThumb.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
mstream.WriteTo(stream);
putObjectRequest.WithBucketName("MyProjectImages");
putObjectRequest.CannedACL = Amazon.S3.Model.S3CannedACL.PublicRead;
putObjectRequest.Key = randomId + ".jpg";
putObjectRequest.InputStream = stream;
Amazon.S3.Model.S3Response s3Response2 = as3c.PutObject(putObjectRequest);
s3Response2.Dispose();
//Closing all opened streams
sr.Close();
stream.Close();
mstream.Close();
//Adding to SimpleDB
attrib.Add(new ReplaceableAttribute().WithName("category").WithValue(post.category));
attrib.Add(new ReplaceableAttribute().WithName("description").WithValue(post.description));
attrib.Add(new ReplaceableAttribute().WithName("favoriteCount").WithValue("0"));
attrib.Add(new ReplaceableAttribute().WithName("imageThug").WithValue(randomId));
attrib.Add(new ReplaceableAttribute().WithName("title").WithValue(post.title));
attrib.Add(new ReplaceableAttribute().WithName("userId").WithValue(ac.GetLoggedInUserId()));
sdb.PutAttributes(putAttributesAction);
return View();
}
It seems like the BaseStream of a StreamReader is read only - which makes sense. Why do you need to re-use this stream in the first place though? Just use the memory stream directly:
mstream.Position = 0;
putObjectRequest.InputStream = mstream;
Input stream doesnt support writing and vice versa is with Output stream. See if you have interchanged its meaning.
Related
I try to load a picture (PNG), save-it in Base64 in a text file and reload it, but I only see gliberish pictures (black and white, very ugly, far from original!) after I load the picture from the text file.
Where's my problem?
BTW all examples (load the picture from image file, save to base64, load from base64) are all taken from SO questions.
First it's how a load the pictures from the PNG file:
try
{
var openFileDialog = new OpenFileDialog
{
CheckFileExists = true,
Multiselect = false,
DefaultExt = "png",
InitialDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
};
if (openFileDialog.ShowDialog() == true)
{
Bitmap img;
using (var stream = File.Open(openFileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
img = new Bitmap(stream);
}
Logo.Source = BitmapToImageSource(img);
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
Save it to base64:
try
{
Bitmap img = BitmapSourceToBitmap2((BitmapSource) Logo.Source);
string base64String;
using (var stream = new MemoryStream())
{
img.Save(stream, ImageFormat.Png);
byte[] imageBytes = stream.ToArray();
base64String = Convert.ToBase64String(imageBytes);
}
string fileName = string.Format(CultureInfo.InvariantCulture, "image{0:yyyyMMddHHmmss}.txt",
DateTime.Now);
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
using (var stream = File.Open(path, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
using (var writer = new StreamWriter(stream, System.Text.Encoding.UTF8))
{
writer.Write(base64String);
writer.Flush();
}
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
BitmapSourceToBitmap2:
int width = srs.PixelWidth;
int height = srs.PixelHeight;
int stride = width*((srs.Format.BitsPerPixel + 7)/8);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(height*stride);
srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height*stride, stride);
using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))
{
// Clone the bitmap so that we can dispose it and
// release the unmanaged memory at ptr
return new Bitmap(btm);
}
}
finally
{
if (ptr != IntPtr.Zero)
Marshal.FreeHGlobal(ptr);
}
And load it back from the file:
try
{
var openFileDialog = new OpenFileDialog
{
CheckFileExists = true,
Multiselect = false,
DefaultExt = "txt",
InitialDirectory =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (openFileDialog.ShowDialog() == true)
{
string base64String;
using (FileStream stream = File.Open(openFileDialog.FileName, FileMode.Open))
{
using (var reader = new StreamReader(stream))
{
base64String = reader.ReadToEnd();
}
}
byte[] binaryData = Convert.FromBase64String(base64String);
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new MemoryStream(binaryData);
bi.EndInit();
Logo.Source = bi;
}
}
catch (Exception exception)
{
MessageBox.Show(exception.ToString(), "An error occured", MessageBoxButton.OK, MessageBoxImage.Warning);
}
Here is a short code sequence that reads a JPG file into a byte array, creates a BitmapSource from it, then encodes it into a base64 string and writes that to file.
In a second step, the base64 string is read back from the file, decoded and a second BitmapSource is created.
The sample assumes that there is some XAML with two Image elements named image1 and image2.
Step 1:
var imageFile = #"C:\Users\Clemens\Pictures\DSC06449.JPG";
var buffer = File.ReadAllBytes(imageFile);
using (var stream = new MemoryStream(buffer))
{
image1.Source = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
var base64File = #"C:\Users\Clemens\Pictures\DSC06449.b64";
var base64String = System.Convert.ToBase64String(buffer);
File.WriteAllText(base64File, base64String);
Step 2:
base64String = File.ReadAllText(base64File);
buffer = System.Convert.FromBase64String(base64String);
using (var stream = new MemoryStream(buffer))
{
image2.Source = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
In case you need to encode an already existing BitmapSource into a byte array, use code like this:
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
buffer = stream.ToArray();
}
I have this code, it works very well in android studio but not in xamarin
bitmap.Compress() has different arguments in xamarin and i am confused how to convert image into base64 or binary in xamarin.android?
I am receving an error in the 3rd line:
( bitmap.Compress() has some invalid arguments).
Bitmap bitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.ace1);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100,bao);
byte[] ba = bao.ToByteArray();
string bal = Base64.EncodeToString(ba, Base64.Default);
If you look at the documentation for Bitmap.Compress in Xamarin, you'll see that the last parameter is a Stream.
The equivalent of ByteArrayOutputStream in .NET is MemoryStream, so your code would be:
Bitmap bitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.ace1);
MemoryStream stream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
byte[] ba = stream.ToArray();
string bal = Base64.EncodeToString(ba, Base64Flags.Default);
(You could use Convert.ToBase64String instead of Base64.EncodeToString if you wanted, too.)
This is how I'm getting a Byte[] for my Bitmap object:
Byte[] imageArray = null;
Bitmap selectedProfilePic = this.GetProfilePicBitmap ();
if (selectedProfilePic != null) {
using (var ms = new System.IO.MemoryStream ()) {
selectedProfilePic.Compress (Bitmap.CompressFormat.Png, 0, ms);
imageArray = ms.ToArray ();
}
}
Hope this helps.
Since two days I try to manage my images in a WPF application but I have errors and errors errors, ...
The image is show in a System.Windows.Control.Image.
For this reason I try to work with variable BitMapImage.
Now I have the error : "Impossible to access close stream" and I can not find a solution.
I have created two function for convert :
public static BitmapImage ConvertToBitMapImage(byte[] bytes)
{
if (bytes == null || bytes.Length == 0) return null;
var image = new BitmapImage();
using (var mem = new MemoryStream(bytes))
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
//image.Freeze();
return image;
}
public static byte[] ImageToByte(BitmapImage imageSource)
{
Stream stream = imageSource.StreamSource;
Byte[] buffer = null;
if (stream != null && stream.Length > 0)
{
using (BinaryReader br = new BinaryReader(stream))
{
buffer = br.ReadBytes((Int32)stream.Length);
}
}
return buffer;
}
In my object I have a property :
public BitmapImage MiniatureApp
{
get
{
if (IMAGES != null)
_MiniatureApp = Tools.BinaryImageConverter.ConvertToBitMapImage(IMAGES.IMAGE);
return _MiniatureApp;
}
set
{
if (this.IMAGES != null)
this.IMAGES.IMAGE = Tools.BinaryImageConverter.ImageToByte((BitmapImage)value);
else
{
IMAGES img = new IMAGES();
img.NOM = "";
img.IMAGE = Tools.BinaryImageConverter.ImageToByte((BitmapImage)value);
this.IMAGES = img;
}
NotifyPropertyChanged();
}
}
And in my main I do this :
FileStream fs = new FileStream(pathImage, FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
VMAppareil.VMApp.CurrentAppareil.MiniatureApp = Tools.BinaryImageConverter.ConvertToBitMapImage(data);
Exist a solution for my problem or exist a best way to do this ?
Gobelet.
You can fix your solution replacing the ImageToByte method with the following (borrowed from https://stackoverflow.com/a/6597746/5574010)
public static byte[] ImageToByte(BitmapImage imageSource)
{
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageSource));
using (var ms = new MemoryStream())
{
encoder.Save(ms);
return ms.ToArray();
}
}
Your previous solution did not work because the ConvertToBitMapImage method close the stream that you assign to image.StreamSource as soon as your code exit the unit statement. When you call the ImageToByte method as part of the MiniatureApp setter the StreamSource will be close and you get an error.
I'm not really sure what you're doing with the getter-setter.
For getting a byte array from a file, I would have this:
public static byte[] FileToByteArray(string fileName)
{
byte[] fileData = null;
using (FileStream fs = new File.OpenRead(fileName))
{
var binaryReader = new BinaryReader(fs);
fileData = binaryReader.ReadBytes((int)fs.Length);
}
return fileData;
}
And once you have the bytes from that function, you can use ConvertToBitMapImage() and assign that to the Image.Source, like this:
byte[] bytes = FileToByteArray(fileName);
YourImage.Source = ConvertToBitMapImage(bytes);
I'm not sure why you would need to convert a BitmapImage into bytes, but you should be able to call your function directly for that:
BitmapImage bImg = new BitmapImage();
bImg.Source = ConvertToBitMapImage(bytes);
byte[] bytes = ImageToByte(bImg); // these should be the same bytes as went in
Set it up like this and step through the code to see where it snags. It's possible the bytes might need encoding when you grab it in ImageToByte().
But also, you don't just then set the byte[] directly to the IMAGES or this.IMAGES.IMAGE, because that isn't an Image object, it's a byte[]. Without knowing what your IMAGES model construct looks like with its property types, it's a little vague to know what is being set to what and why, but this seems like a bad idea to over-complicate what you should just do with function calls as it is needed, without a getter-setter and an IMAGES model in the way.
I'm displaying an image from a base 64 string that came from an API. The problem is, the image is not being displayed.
Here's the code:
profilePictureImg.Source = GetUserImage(user.MobileNumber);
private BitmapImage GetUserImage(string phoneNumber)
{
BitmapImage bitmapImage = new BitmapImage();
var baseAddress = "http://192.168.0.103/vchatapi/api/Images/" + phoneNumber;
var http = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(new System.Uri(baseAddress));
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "GET";
var response = http.GetResponse();
var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();
var y ="";
var x = y.FromJson(content);
byte[] binaryData = Convert.FromBase64String(x);
using (MemoryStream ms = new MemoryStream(binaryData, 0, binaryData.Length))
{
ms.Write(binaryData, 0, binaryData.Length);
bitmapImage.StreamSource = ms;
}
return bitmapImage;
}
Any Ideas?? Thanks!
EDIT:
Got the fix. For some reason, it requires to call BeginInit and EndInit.
The image may be decoded as shown in this answer:
var binaryData = Convert.FromBase64String(x);
var bitmapImage = new BitmapImage();
using (var stream = new MemoryStream(binaryData))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
}
The reason why you have to use BeginInit and EndInit is explained in the Remarks section of the BitmapImage MSDN documentation:
BitmapImage implements the ISupportInitialize interface to optimize
initialization on multiple properties. Property changes can only occur
during object initialization. Call BeginInit to signal that
initialization has begun and EndInit to signal that initialization has
completed. After initialization, property changes are ignored.
This may be one of those cases where it pays not to dispose the stream too eagerly; also, the Write here is unnecessary: you already added the data via the constructor. So just:
bitmapImage.StreamSource = new MemoryStream(binaryData);
return bitmapImage;
does that work?
You can try the following
byte[] binaryData = Convert.FromBase64String(x);
using (MemoryStream ms = new MemoryStream(binaryData))
{
bitmapImage = (Bitmap)Image.FromStream(ms);
}
I'm working on file manager project. I need to generate thumbnail if file is of image type. i'm able to get by using IHttpHandler with method
Sytem.Drawing.Image.GetThumbnailImage(),
Here is some code
Hashtable ht;
ht = new Hashtable();
using (FileStream fInfo = new FileStream(context.Server.MapPath(url), FileMode.Open))
{
byte[] bFile;
bFile = GenerateThumbnail(fInfo, XLen, YLen);
ht.Add(id, bFile);
fInfo.Close();
Byte[] arrImg = (byte[])ht[id];
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(arrImg);
context.Response.End();
}
private byte[] GenerateThumbnail(Stream fStream, string xLen, string yLen)
{
using (Image img = Image.FromStream(fStream))
{
Image thumbnailImage = img.GetThumbnailImage(int.Parse(xLen), int.Parse(yLen), new Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
using (MemoryStream imageStream = new MemoryStream())
{
thumbnailImage.Save(imageStream,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imageContent = new Byte[imageStream.Length];
imageStream.Position = 0;
imageStream.Read(imageContent, 0, (int)imageStream.Length);
return imageContent;
}
}
}
Problem
Newly uploaded file on genrating thumb throwing expection : being used by another process, after sometime its shows the thumbnail. Q. where im missing to close the stream ?