I am working on a Self Hosted WPF Application (using Owin) that returns bitmap images to the browser.
My controller code looks like this:
public ImageSource GetmbTiles(string FILE, string Z, string X, string Y)
{
string mbtiles = string.Format(("C:\\{0}.mbtiles"), FILE);
string connString = string.Format("Data Source={0}", mbtiles);
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
System.Text.StringBuilder Query = new System.Text.StringBuilder();
Query.Append("SELECT tile_data ");
Query.Append("FROM tiles ");
Query.Append(string.Format("where zoom_level={0} and tile_column={1} and tile_row={2} ", Z, X, Y));
using (SQLiteCommand cmd = new SQLiteCommand(Query.ToString(), conn))
{
conn.Open();
using (SQLiteDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
buffer = GetBytes(dr);
}
}
}
}
//return new System.IO.MemoryStream(buffer);
return byteArrayToImage(buffer);
}
private static BitmapImage byteArrayToImage(byte[] imageData)
{
if (imageData == null || imageData.Length == 0) return null;
var image = new BitmapImage();
using (var mem = new MemoryStream(imageData))
{
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;
}
private static byte[] GetBytes(SQLiteDataReader reader)
{
const int CHUNK_SIZE = 2 * 1024;
byte[] buffer = new byte[CHUNK_SIZE];
long bytesRead = 0;
long fieldOffset = 0;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length);
while (bytesRead == buffer.Length)
{
stream.Write(buffer, 0, Convert.ToInt32(bytesRead));
fieldOffset += bytesRead;
bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length);
}
stream.Write(buffer, 0, Convert.ToInt32(bytesRead));
return stream.ToArray();
}
}
When I call this controller from my browser I only get a json file and not the image.
The exception Message is
<ExceptionMessage>Type 'System.IO.MemoryStream' with data contract name 'MemoryStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.</ExceptionMessage>
I am web developer very new to the world of WPF so pardon this noob question. But whatever I try to return the image so far isnt helping. I can see that the byte array is being populated. But the Byte Array wont display in a browser, is there some conversion that I am missing ? Any hint or help will be highly appreciated.
I am posting this solution for anyone else who may be in the same scenario, OWIN Self Hosted App that serves images or other files.
I resolved this by adding this to the controller method
Image img = byteArrayToImage(buffer);
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(ms.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return result;
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
Related
I need to convert a BitmapImage in a byte[] but I don't find how to do it in C# web.
I found examples but none of them work (JpegBitmapEncoder doesn't exist, BitmapImageObject.StreamSource doesn't exist, there isn't WriteableBitmap constructor with BitmapImage as parameter, Extensions.SaveJpeg(parameters) doesn't exist ...).
Examples I found:
Constructor new WriteableBitmap(bitmapImage) doesn't exist.
public static byte[] ConvertToBytes(this BitmapImage bitmapImage)
{
byte[] data;
// Get an Image Stream
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(bitmapImage);
// write an image into the stream
Extensions.SaveJpeg(btmMap, ms,
bitmapImage.PixelWidth, bitmapImage.PixelHeight, 0, 100);
// reset the stream pointer to the beginning
ms.Seek(0, 0);
//read the stream into a byte array
data = new byte[ms.Length];
ms.Read(data, 0, data.Length);
}
//data now holds the bytes of the image
return data;
}
new WriteableBitmap(img), System.Windows.Media.Imaging.Extensions.SaveJpeg don't exist.
public static byte[] ImageToBytes(BitmapImage img)
{
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(img);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, img.PixelWidth, img.PixelHeight, 0, 100);
img = null;
return ms.ToArray();
}
}
imageSource.StreamSource doesn't exist.
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;
}
JpegBitmapEncoder doesn't exist.
byte[] data;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
using(MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
Try with the using statement to a namespace in the beginning of your code.
Otherwise there should be some Nuget packages which you could install to achieve your goal.
using System.Drawing;
In Main method
Image img = Image.FromFile("path to the file");
var byteArray = ImageToByte(img);
public static byte[] ImageToByte(Image img)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
Try this
I think this will help...
public byte[] ConvertBitMapToByteArray(Bitmap bitmap)
{
byte[] result = null;
if (bitmap != null)
{
MemoryStream stream = new MemoryStream();
bitmap.Save(stream, bitmap.RawFormat);
result = stream.ToArray();
}
return result;
}
byte[] foo = System.IO.File.ReadAllBytes("bitmap path");
Or
byte[] foo;
Object obj = YourBitmap;
BinaryFormatter bf = new BinaryFormatter();
using (var ms = new MemoryStream())
{
bf.Serialize(ms, obj);
foo = ms.ToArray();
}
Or
ImageConverter foocon = new ImageConverter();
byte[] foo = (byte[])foocon.ConvertTo(YourBitmap, typeof(byte[]));
Or
MemoryStream ms = new MemoryStream();
Bitmap.Save(ms, YourBitmap.RawFormat);
byte[] foo = ms.ToArray();
Finally, it seems that, obviously, it missed some libraries but we are limited with our application, so we decided to recover our pictures by another way. Anyway, thank you all.
I'm writing Windows 10 UWP that takes a picture of a user and then places that picture in another one. (It'll be more useful once I have the specific pictures). Basically, the program seems to be unable to access pictures in my computer no matter where they are stored. The following line:
input2 = new FileStream(file2.Path, FileMode.Open, FileAccess.Read);
also throws an exception, sometimes saying file2 is in use other times saying that I should place it in a task.run box.
Suggestions? I'm totally new to C#. Thank you!
private async void processing()
{
CameraCaptureUI dialog = new CameraCaptureUI();
Size aspectRatio = new Size(1, 1);
dialog.PhotoSettings.CroppedAspectRatio = aspectRatio;
StorageFile file = await dialog.CaptureFileAsync(CameraCaptureUIMode.Photo);
StorageFile file2;
Image playbutton = new Image();
try
{
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
playbutton.Source = bmp;
stream = null;
}
catch (Exception ex)
{
return;
}
Image frame = new Image();
try
{
FileOpenPicker picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".png");
file2 = await picker.PickSingleFileAsync();
file2 = await StorageFile.GetFileFromPathAsync("C:\\Users\\Kyle\\Downloads\\BingWallpaper-2016-02-07");
IRandomAccessStream stream = await file2.OpenAsync(FileAccessMode.ReadWrite);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
playbutton.Source = bmp;
frame.Source = bmp;
stream = null;
}
catch (Exception ex)
{
return;
}
FileStream input2;
var t = Task.Run(() => {
input2 = new FileStream(file2.Path, FileMode.Open, FileAccess.Read);
byte[] arrayForImage2;
byte[] buffer2 = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input2.Read(buffer2, 0, buffer2.Length)) > 0)
{
ms.Write(buffer2, 0, read);
}
arrayForImage2 = ms.ToArray();
}
byte[] arrayForImage1;
FileStream input = new FileStream(file.Path, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
arrayForImage1 = ms.ToArray();
}
if (arrayForImage1.Length > arrayForImage2.Length)
{
for (int x = 0; x < arrayForImage2.Length; x++)
{
arrayForImage1[x] = arrayForImage2[x];
}
FileStream fSO = new FileStream("C:/Users/Kyle/Pictures/imageCompiled.png", FileMode.Create, FileAccess.Write);
fSO.Write(arrayForImage1, 0, arrayForImage1.Length);
}
else if (arrayForImage1.Length < arrayForImage2.Length)
{
for (int x = 0; x < arrayForImage1.Length; x++)
{
arrayForImage2[x] = arrayForImage1[x];
}
FileStream fSO = new FileStream("C:/Users/Kyle/Pictures/imageCompiled.png", FileMode.Create, FileAccess.Write);
fSO.Write(arrayForImage2, 0, arrayForImage2.Length);
}
});
t.Wait();
}
}
}
also throws an exception, sometimes saying file2 is in use
I see you are not closing the streams by calling close() or dispose() methods.
FileStream fSO = new FileStream("C:/Users/Kyle/Pictures/imageCompiled.png", FileMode.Create, FileAccess.Write);
fSO.Write(arrayForImage2, 0, arrayForImage2.Length);
Here, fSO.close(); should be called after work is done.
Also, input, input2 and other streams that you are using should be checked if they are closed properly.
I am getting an error while instantiating ExifReader in Windows Phone 8 C#. Please find the code snippet below. Kindly do the needful
Error : "ExifLib requires a seekable stream"
byte[] imageBytes = (byte[])PhoneApplicationService.Current.State["ViewImage"];
MemoryStream ms = new MemoryStream(imageBytes,0,imageBytes.Length);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
try
{
ExifReader xif = new ExifReader(toStream(bitmapImage)); // Getting Error here
double gpsLat, gpsLng;
xif.GetTagValue<double>(ExifTags.GPSLatitude, out gpsLat);
xif.GetTagValue<double>(ExifTags.GPSLongitude, out gpsLng);
map.Center = new System.Device.Location.GeoCoordinate(gpsLat, gpsLng);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
Stream toStream(BitmapImage img)
{
WriteableBitmap bmp = new WriteableBitmap((BitmapSource)img);
using (MemoryStream stream = new MemoryStream())
{
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
stream.Position = 0;
return stream;
}
}
Your MemoryStream is returning false when CanSeek is called. This is because you've wrapped your MemoryStream in a using statement, which means that you're returning a disposed object.
Your toStream method should actually look like this:
Stream ToStream(BitmapImage img)
{
MemoryStream stream = new MemoryStream();
using (WriteableBitmap bmp = new WriteableBitmap((BitmapSource)img))
{
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
}
stream.Position = 0;
return stream;
}
I am copying all images from my device to directory. While copying the images I am getting this error Operation not permitted on IsolatedStorageFileStream.
Here is my code to copy the files.
MediaLibrary m = new MediaLibrary();
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.DirectoryExists("ImagesZipFolder"))
{
deleteFileFolder("ImagesZipFolder");
}
if (!store.DirectoryExists("ImagesZipFolder"))
{
store.CreateDirectory("ImagesZipFolder");
foreach (var picture in m.Pictures)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder/" + picture.Name, FileMode.CreateNew, store))
{
BitmapImage image = new BitmapImage();
image.SetSource(picture.GetImage());
byte[] bytes = ConvertToBytes(image);
stream.Write(bytes, 0, bytes.Length);
}
}
}
}
Here is my ConvertToBytes method.
public byte[] ConvertToBytes(BitmapImage bitmapImage)
{
byte[] data = null;
WriteableBitmap wBitmap = null;
using (MemoryStream stream = new MemoryStream())
{
wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
//data = stream.GetBuffer();
data = stream.ToArray();
DisposeImage(bitmapImage);
return data;
}
}
Basically what I am trying is to create a zip file of all images. I have total 222 images in my device. So how can I solve this issue ? How can I create a zip of this images?
Most probably this is due to the concurrent access to the file
you can refer to the link:
Operation not permitted on IsolatedStorageFileStream. error
I checked your code and it seems to be working (providing there's no error in DisposeImage() method) There is no OperationNotPermittedException occuring. However, if there is error in your code, then it can only be because of deleteFileFolder("ImagesZipFolder") line. Can you give me the snippet so that I can study it further. I m posting the working code... I have replaced that method with simple predefined one--
MediaLibrary m = new MediaLibrary();
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.DirectoryExists("ImagesZipFolder"))
{
store.DeleteDirectory("ImagesZipFolder");
}
if (!store.DirectoryExists("ImagesZipFolder"))
{
store.CreateDirectory("ImagesZipFolder");
foreach (var picture in m.Pictures)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder/" + picture.Name, FileMode.CreateNew, store))
{
BitmapImage image = new BitmapImage();
image.SetSource(picture.GetImage());
byte[] bytes = ConvertToBytes(image);
stream.Write(bytes, 0, bytes.Length);
}
}
}
}
I have a following problem:
I am using c# and .aspx pages. On .aspx page i have a GridView. I set a GridView datasource to be:
GridView1.DataSource = PictureInfo.PictureInfoList;
My "PictureInfo" class looks like this:
public class PictureInfo
{
public static List<PictureInfo> PictureInfoList = new List<PictureInfo>();
public string PictureDescription { get; set; }
public byte[] Picture { get; set; }
}
Is it possible and how to show a picture which is in "byte[] Picture" in a GridView? Or which way it is possible? I'm saving data in this way before i send it to a database. And i would like to show it in a GridView before i send it to a database. As you can see I'm a beginner but i would be very happy if i could make this work. My head hearts already from reading some solutions online, none helped until now.
thank you very much
I suggest you a solution for: Converting byte[] to Bitmap (may it will be useful for you):
public BitmapSource ByteArrayToBitmap(byte[] byteArray) {
BitmapSource res;
try {
using (var stream = new MemoryStream(byteArray)) {
using (var bmp = new Bitmap(stream)) {
res = ToBitmap(bmp);
}
}
} catch {
res = null;
}
return res;
}
public BitmapSource ToBitmap(Bitmap bitmap) {
using (var stream = new MemoryStream()) {
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
var result = new BitmapImage();
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
Next, you should adapt, and include the Bitmap in your GridView.
on your handler.ashx
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
string ImageID=request["ID"];
//byte[] ImageByte=pictureInfo.Picture;//local imageByte
byte[] ImageByte=getImage(ImageId);//image byte from any other sour,e.g database
Stream strm = new MemoryStream(ImageByte));
long length = strm.Length;
byte[] buffer = new byte[length];
int byteSeq = strm.Read(buffer, 0, 2048);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 2048);
}
}
now set image url for your asp:image inside your gridview as follows
Image1.ImageUrl = "somthing.ashx?ID="+userImageID;
i hope you have unique id for your image to be visible. I hope you have all set now. Comments and query are well comed.
retrieve image byte from database
public byte[] GetImage(string ImageId)
{ byte[] img = null;
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SlikaHendler";
cmd.Parameters.AddWithValue("#Id", ImageId);
cmd.Connection = yourConnection();
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (dr.Read())
{
img = (byte[])dr[0];
}
dr.Close();
return img;//returns array of byte
}
I know pictures are recorded as binaries to databases. In this aspect, your problem turns to a "converting binary to byte".
If you can reach your picture info as binary data, you can convert it as taking 3 digits for 1 byte, and convert & show as bytes.
http://en.wikipedia.org/wiki/ASCII