I'm not quite sure what's happening, so I apologize if the title isn't specific. I've provided the code and xaml below which demonstrates my problem. I have the static methods that I call to convert bitmap to byte [] and vice versa. These methods work fine when used to bind source to image control. However, when I use them to assign a source to images which are children of BlockUIContainer as the code demostrates... I get the same image as the previous on my second call to ByteArrayToBitmapSource.
I'm clueless. What is obvious to me, however, is that the second image has the properties of the image that I expect it display, but is apparently the wrong image.
C# MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing;
using System.Windows.Xps.Packaging;
using System.Windows.Xps;
namespace FlowDocumentTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IDisposable
{
private XpsDocument xpsDocument;
private String randomFileName;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
FlowDocument doc = new FlowDocument();
doc.Blocks.Add(new Paragraph(new Run("Test")));
Section section1 = new Section();
BlockUIContainer blockUIContainer1 = new BlockUIContainer();
blockUIContainer1.Child = new System.Windows.Controls.Image { Source = Source1 };
Section section2 = new Section();
BlockUIContainer blockUIContainer2 = new BlockUIContainer();
blockUIContainer2.Child = new System.Windows.Controls.Image { Source = Source2 };
doc.Blocks.Add(blockUIContainer1);
doc.Blocks.Add(blockUIContainer2);
randomFileName = System.IO.Path.GetRandomFileName();
this.xpsDocument = new XpsDocument(randomFileName, System.IO.FileAccess.ReadWrite);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(((IDocumentPaginatorSource)doc).DocumentPaginator);
this.Viewer.Document = xpsDocument.GetFixedDocumentSequence();
}
public BitmapSource Source1
{
get
{
byte[] tmp = BitmapSourceToByteArray(GetBitmapImage(new Bitmap(#"source1.jpg")));
return ByteArrayToBitmapSource(tmp);
}
}
public BitmapSource Source2
{
get
{
byte[] tmp = BitmapSourceToByteArray(GetBitmapImage(new Bitmap(#"source2.bmp")));
return ByteArrayToBitmapSource(tmp);
}
}
public static BitmapImage GetBitmapImage(Bitmap bitmap)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
return bitmapImage;
}
public static byte[] BitmapSourceToByteArray(BitmapSource bitmapSource)
{
byte[] data;
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
return data;
}
public static BitmapSource ByteArrayToBitmapSource(byte[] data)
{
BitmapSource result;
using (MemoryStream ms = new MemoryStream(data))
{
PngBitmapDecoder decoder = new PngBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
result = decoder.Frames[0];
}
return result;
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
this.Dispose();
}
public void Dispose()
{
this.xpsDocument.Close();
if (System.IO.File.Exists(randomFileName))
System.IO.File.Delete(randomFileName);
}
}
}
XAML MainWindow.xaml
<Window x:Class="FlowDocumentTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DocumentViewer Name="Viewer" />
</Grid>
</Window>
I guess it has to do with returning a BitmapSource as oppose to a discreet BitmapImage. Created this method and called this method instead, and it works as I expect.
Still don't know whether this is FlowDocument or XPSDocument related issue.
public static BitmapSource GetBitmapImage(Bitmap bitmap)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
return bitmapImage;
}
Related
I am attempting to save an embedded shape as an image using C#.
If the object is embedded as an actual image (WMF/JPEG) I can retrieve the image without issue but when the object is an embedded shape or an OLE Object that displays as an image in Word I cannot seem to extract or retrieve said object to then either copy to the clipboard or save said image.
Here is my current code sample; either the object is empty or I get the following error:
System.Runtime.InteropServices.ExternalException: 'A generic error occurred in GDI+.'
Any help is appreciated. Thank you
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ImageMagickSandboxWinForms
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
public static BitmapSource ConvertBitmap(Bitmap source)
{
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
source.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
public static Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
Bitmap bitmap;
using (var outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new Bitmap(outStream);
}
return bitmap;
}
private void button1_Click(object sender, EventArgs e)
{
string physicsDocLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
physicsDocLocation += #"\[Doc path Here].docx";
var wordApp = new Microsoft.Office.Interop.Word.Application();
var wordDoc = wordApp.Documents.Open(physicsDocLocation);
int iCount = wordDoc.InlineShapes.Count;
for (int i = 1; i < (wordDoc.InlineShapes.Count + 1); i++)
{
var currentInlineShape = wordDoc.InlineShapes[i];
currentInlineShape.Range.Select();
wordDoc.ActiveWindow.Selection.Range.Copy();
BitmapSource clipBoardImage = System.Windows.Clipboard.GetImage();
Bitmap bmpClipImage = BitmapFromSource(clipBoardImage);
string finalPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), #"TestConversions");
finalPath += #"\" + Guid.NewGuid().ToString() + ".jpg";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(finalPath, FileMode.Create, FileAccess.ReadWrite))
{
bmpClipImage.Save(memory, ImageFormat.Jpeg); <<<---- Error happens here.
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
}
wordDoc.Close();
wordApp.Quit();
}
}
}
i have these code in my library, dunno where i have found that but hope you do the job for you: i am using Clippboard to trap the different images, jus t dont forget, Thread is needed to access Clipboard
for (var i = 1; i <= wordApplication.ActiveDocument.InlineShapes.Count; i++)
{
var inlineShapeId = i;
var thread = new Thread(() => SaveInlineShapeToFile(inlineShapeId, wordApplication));
// STA is needed in order to access the clipboard
// https://stackoverflow.com/a/518724/700926
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
// General idea is based on: https://stackoverflow.com/a/7937590/700926
protected static void SaveInlineShapeToFile(int inlineShapeId, Application wordApplication)
{
// Get the shape, select, and copy it to the clipboard
var inlineShape = wordApplication.ActiveDocument.InlineShapes[inlineShapeId];
inlineShape.Select();
wordApplication.Selection.Copy();
// Check data is in the clipboard
if (Clipboard.GetDataObject() != null)
{
var data = Clipboard.GetDataObject();
// Check if the data conforms to a bitmap format
if (data != null && data.GetDataPresent(DataFormats.Bitmap))
{
// Fetch the image and convert it to a Bitmap
var image = (Image) data.GetData(DataFormats.Bitmap, true);
var currentBitmap = new Bitmap(image);
// Save the bitmap to a file
currentBitmap.Save(#"C:\Users\Username\Documents\" + String.Format("img_{0}.png", inlineShapeId));
}
}
}
following if you are using Winform or WPF the clipboard acts differently for an image:
if (Clipboard.ContainsImage())
{
// ImageUIElement.Source = Clipboard.GetImage(); // does not work
System.Windows.Forms.IDataObject clipboardData = System.Windows.Forms.Clipboard.GetDataObject();
if (clipboardData != null)
{
if (clipboardData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap))
{
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)clipboardData.GetData(System.Windows.Forms.DataFormats.Bitmap);
ImageUIElement.Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());
Console.WriteLine("Clipboard copied to UIElement");
}
}
}
after if its not functionam due to a bug in translation of format, there is this solution . So its infrecnh but its easily to understand the logic of the using of "DeviceIndependentBitmap"
I have a button and an image named as image1 in my wpf app. I want add image source of the image1 from a file icon of a location or file path. Here is my code:
using System.Windows;
using System.Windows.Media.Imaging;
using System.IO;
using System.Drawing;
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Icon ico = System.Drawing.Icon.ExtractAssociatedIcon(#"C:\WINDOWS\system32\notepad.exe");
image1.Source = ico.ToBitmap();
}
}
}
And the error is saying
Cannot implicitly convert type 'System.Drawing.Bitmap' to
'System.Windows.Media.ImageSource'
How to solve this problem?
The solution suggested by Farhan Anam will work, but it's not ideal: the icon is loaded from a file, converted to a bitmap, saved to a stream and reloaded from the stream. That's quite inefficient.
Another approach is to use the System.Windows.Interop.Imaging class and its CreateBitmapSourceFromHIcon method:
private ImageSource IconToImageSource(System.Drawing.Icon icon)
{
return Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
new Int32Rect(0, 0, icon.Width, icon.Height),
BitmapSizeOptions.FromEmptyOptions());
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
using (var ico = System.Drawing.Icon.ExtractAssociatedIcon(#"C:\WINDOWS\system32\notepad.exe"))
{
image1.Source = IconToImageSource(ico);
}
}
Note the using block to dispose the original icon after you converted it. Not doing this will cause handle leaks.
The error you get is because you try to assign a bitmap as the source of an image. To rectify that, use this function:
BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
like this:
image1.Source = BitmapToImageSource(ico.ToBitmap());
Need a little help here. I have a app that I am creating that mergies two pictures together. The issue is when i am trying to convert the bitmap into a bitmpaimage to display the result on the screen. from what i can tell, the image is not being save to the memory stream at "NwImg.Save(memory,ImageFormat.Jpeg);" Any ideas??
//The Code
//bitmap to bitmapimage conversion
using (MemoryStream memory = new MemoryStream())
{//NwImg is type Bitmap, and at this point i checked properties and values did copy over from the merging
NwImg.Save(memory, ImageFormat.Jpeg);//here image NwImg.save is suppose to transfer to memory
memory.Position = 0;
Nwbi.StreamSource = memory;//memory stream is showing null
Nwbi.CacheOption = BitmapCacheOption.OnLoad;
}
I don't know if this matter but NwImg represents a bitmap that was created by merging a png image on top of a jpeg. I didn't read anything that said it matter but i figured i would through that in there.
/// here is all the code as requested david
//Main c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
namespace PicMerger2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Pic currentPic = new Pic();
BitmapImage bi = new BitmapImage(new Uri("\\original photo.jpg"));
BitmapImage Nwbi = new BitmapImage();
public MainWindow()
{
InitializeComponent();
OriginalPhoto.Source = bi;
ResultPhoto.Source = Nwbi;
}
private void apply_Click(object sender, RoutedEventArgs e)
{
Bitmap NwImg;
//bitmapimage to bitmap conversion
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bi));
enc.Save(outStream);
System.Drawing.Bitmap MarkThisPic = new System.Drawing.Bitmap(outStream);
// return bitmap; <-- leads to problems, stream is closed/closing ...
NwImg = new Bitmap(MarkThisPic);
}
NwImg = currentPic.MergerTheseTwo(NwImg);
//bitmap to bitmapimage conversion
using (MemoryStream memory = new MemoryStream())
{
NwImg.Save(memory, ImageFormat.Jpeg);
memory.Position = 0;
Nwbi.StreamSource = memory;
Nwbi.CacheOption = BitmapCacheOption.OnLoad;
}
ResultPhoto.Source = Nwbi;
}
}
}
//Main xaml
<Window x:Class="PicMerger2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Image x:Name="OriginalPhoto" Height="200" Stretch="UniformToFill" Source="{Binding}"></Image>
<Label>Original Images</Label>
</StackPanel>
<Button x:Name="apply" Click="apply_Click" Height="25" >Apply Watermark</Button>
<StackPanel>
<Image x:Name="ResultPhoto" Height="200" Stretch="UniformToFill" Source="{Binding}"></Image>
<Label>Watermarked Image</Label>
</StackPanel>
</StackPanel>
</Grid>
</Window>
// pic class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace PicMerger2
{
class Pic
{
Bitmap Watermark = new Bitmap(PicMerger2.Properties.Resources._Watermark);
public Bitmap MergerTheseTwo(Bitmap BottomImage)
{
try
{
using (var canvas = Graphics.FromImage(BottomImage))
{
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
// canvas.DrawImage(BottomImage, new Rectangle(0, 0, BottomImage.Width, BottomImage.Height), new Rectangle(0, 0, BottomImage.Width, BottomImage.Height), GraphicsUnit.Pixel);
canvas.DrawImage(Watermark, 0, 0);
canvas.Save();
//Save to current picture
Bitmap NewImage = new Bitmap(BottomImage.Width, BottomImage.Height, canvas);
return NewImage;
}
}
catch (Exception)
{
throw;
}
}
}
}
You will need to change a couple of things so that your code can work.
Use the following code for the Bitmap to BitmapImage conversion.
using (MemoryStream memory = new MemoryStream())
{
NwImg.Save(memory, ImageFormat.Jpeg);
memory.Position = 0;
Nwbi = new BitmapImage();
Nwbi.BeginInit();
Nwbi.StreamSource = memory;
Nwbi.CacheOption = BitmapCacheOption.OnLoad;
Nwbi.EndInit();
}
Inside your Pic class, replace these lines
//Save to current picture
Bitmap NewImage = new Bitmap(BottomImage.Width, BottomImage.Height, canvas);
return NewImage;
to this
return BottomImage;
since the overload of the Bitmap class that you are using, doesn't create a new bitmap based on the Graphics object but just its resolution (this results to an empty image). So, since you draw onto the BottomImage bitmap, you just need to return that image.
The variable "memory" cannot possibly be null on the line where you commented "memory stream is showing null" when that line executes because it is definitely assigned in the "using" block 4 lines above it. I'm guessing you put a debugger breakpoint too early in the method. Try putting your breakpoint on the line where you assign Nwbi.CacheOption and see if the debugger tells you what you expected.
I am creating application in Silverlight. There is only a DataGrid right now. I am using WCF RIA Service for getting datas from database. Everything works fine expect Images. I am getting images as byte array and trying to convert them to BitmapImage using Converter. I want to show images in RowDetailsTemplate of DataGrid.
Here it is:
<sdk:DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<StackPanel>
<Image x:Name="thumbNail" Width="60" Height="60" VerticalAlignment="Center" ImageFailed="thumbNail_ImageFailed"
Source="{Binding gameImage,Converter={StaticResource byteToImageConverter}}">
</Image>
</StackPanel>
</StackPanel>
</DataTemplate>
</sdk:DataGrid.RowDetailsTemplate>
And converter:
public class ByteToImageConverter : IValueConverter
{
public BitmapImage ConvertByteArrayToBitMapImage(byte[] imageByteArray)
{
BitmapImage img = new BitmapImage();
using (MemoryStream memStream = new MemoryStream(imageByteArray))
{
img.SetSource(memStream);
}
return img;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapImage img = new BitmapImage();
if (value != null)
{
img = this.ConvertByteArrayToBitMapImage(value as byte[]);
}
return img;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
But images are not displaying.
The method in my wcf service is like that:
public List<Games> GamesList()
{
string gmConn = ConfigurationManager.ConnectionStrings["GamesConnectionString"].ConnectionString;
var gamesList = new List<Games>();
using (SqlConnection conn = new SqlConnection(gmConn))
{
string sql = #"Select Name, Developer,Longevity,Distributor,Year,State,Type,graphics, gameplay,sound,general,photo From Games join scores on Games.G_ID=Scores.G_ID";
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
SqlDataReader dr = cmd.ExecuteReader();
if (dr != null)
while (dr.Read())
{
Games game = new Games
{
Name = dr.GetString(0),
developer = dr.GetString(1),
Longevity = dr.GetInt32(2),
Distributor = dr.GetString(3),
Year = dr.GetString(4),
State = dr.GetString(5),
Type = dr.GetString(6),
Graphics = dr.GetDouble(7),
Gameplay = dr.GetDouble(8),
Sound = dr.GetDouble(9),
General = dr.GetDouble(10)
};
if (!dr.IsDBNull(11))
{
byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 0, blob.Length - 0);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
game.gameImage = msJpg.GetBuffer();
}
}
}
gamesList.Add(game);
}
return gamesList;
}
}
}
And in mainPage.xaml.cs I am setting ItemsSource of my datagrid.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
SampleServiceClient client = new SampleServiceClient();
client.GamesListCompleted += new EventHandler<GamesListCompletedEventArgs>(client_GamesListCompleted);
client.GamesListAsync();
}
void client_GamesListCompleted(object sender, GamesListCompletedEventArgs e)
{
CustomerGrid.ItemsSource = e.Result;
}
}
Thanks in advance.
I have created a simple test project with your code and I could not recreate your problem. It might be the case that the byte array is corrupted? (Just a guess..)
Any way, you can find and download the test project here: https://skydrive.live.com/redir?resid=DEB5DDFF6A505390!278 I have made a simple project with an embedded image. I opened that image and converted it into a byte array. Then I used binding to display the image.
MainPage.xaml.cs
using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Resources;
namespace SilverlightTest
{
public partial class MainPage : UserControl, INotifyPropertyChanged
{
public MainPage()
{
InitializeComponent();
using (var ms = new MemoryStream())
{
StreamResourceInfo sr = Application.GetResourceStream(new Uri("SilverlightTest;component/Koala.jpg", UriKind.Relative));
sr.Stream.CopyTo(ms);
_photo = ms.ToArray();
}
this.DataContext = this;
}
private byte[] _photo;
public byte[] Photo
{
get
{
return _photo;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
}
Mainpage.xaml
<UserControl x:Class="SilverlightTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SilverlightTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<local:ByteToImageConverter x:Name="byteToImageConverter" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Image Width="320" Height="240" VerticalAlignment="Center" Source="{Binding Path=Photo, Converter={StaticResource byteToImageConverter}}" />
</Grid>
</UserControl>
And the image was included in the project as a resource.
UPDATE
I saw you used the following code in your project:
byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 0, blob.Length - 0);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
game.gameImage = msJpg.GetBuffer();
}
}
This code won't work. You use GetBuffer() this code returns (according to msdn):
The byte array from which this stream was created, or the underlying
array if a byte array was not provided to the MemoryStream constructor
during construction of the current instance.
To get to right array use the ToArray() function of the MemoryStream class:
byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 0, blob.Length - 0);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
game.gameImage = msJpg.ToArray();
}
}
And with a little refactoring:
byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
using (MemoryStream ms = new MemoryStream(blob))
{
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
game.gameImage = msJpg.ToArray();
}
}
UPDATE 2
I wrote a little program to test the file you gave me (renamed the file btw):
SilverlightTestV2.zip
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace ByteTransformer
{
class Program
{
static void Main(string[] args)
{
using (var fs = File.OpenRead("byteArray.dat"))
{
var bm = Image.FromStream(fs);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
using (var ts = File.Create("out.jpg"))
{
var img = msJpg.ToArray();
ts.Write(img, 0, img.Length);
}
}
}
}
}
}
This program throws an ArgumentException on the line: var bm = Image.FromStream(fs);
Hence I think that or the file you gave me doesn't contain the actual byte array from the sql (aka you saved it wrong) or the byte array in the sql is corrupt. But since you can actual see the image I think you saved it wrong.
Update:
It should be enough to assign the blob directly to your gameImage-Property in your method GamesList. The other code should be useless.
byte[] blob = new byte[(dr.GetBytes(11, 0, null, 0, int.MaxValue))];
dr.GetBytes(11, 0, blob, 0, blob.Length);
game.gameImage = blob;
Also when you call GetBuffer on the MemoryStream you will get the array that is passed in the ctor of the MemoryStream. In your case you will get an empty array or null. I´m not sure.
Initial:
Change the ConvertByteArrayToBitMapImage method to the following
public BitmapImage ConvertByteArrayToBitMapImage(byte[] imageByteArray) {
BitmapImage img = new BitmapImage();
MemoryStream memStream = new MemoryStream(imageByteArray);
img.SetSource(memStream);
return img;
}
When you dispose the MemoryStream using the using-Statement, the stream gets set to closed. So can´t the BitmapImage read from the stream that is set by using SetSource.
I want to bind an image that save in varbinary type in database in XAML.How I can do that?
for example Picture field in northwind DataBase.
thanks
EDIT 1:)
I write this codes for convert Image field (Picture field in Categories table in Northwind DataBase) but every time I get Exception:
class ImageConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null) { return null; }
var image = (System.Drawing.Image)value;
var bitmap = new System.Windows.Media.Imaging.BitmapImage();
bitmap.BeginInit();
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Bmp);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
return bitmap;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
And :
class ImageConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is byte[])
{
byte[] bytes = value as byte[];
MemoryStream stream = new MemoryStream(bytes);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = stream;
image.EndInit();
return image;
}
return null;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
and the exception:
Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.
If you are getting byte array from database then no need to convert that to image or bitmap image...
You can bind Source property of image to byte array.. wpf internally handle the byte array and it converts byte array to image...
Edit:
If you still want to convert byte array to Bitmap image here is the method which was tested
public BitmapImage ImageFromBytearray(byte[] imageData)
{
if (imageData == null)
return null;
MemoryStream strm = new MemoryStream();
strm.Write(imageData, 0, imageData.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
MemoryStream memoryStream = new MemoryStream();
img.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);
memoryStream.Seek(0, SeekOrigin.Begin);
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
return bitmapImage;
}
I have crated a sample using above method...
Xaml code:
<Window x:Class="WpfApplication1.ImageFromByteArray"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ImageFromByteArray" Height="300" Width="300" Name="Root">
<Grid>
<Image Source="{Binding ImageSource,ElementName=Root}" Height="300" Width="300" RenderOptions.BitmapScalingMode="HighQuality"/>
</Grid>
</Window>
Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for ImageFromByteArray.xaml
/// </summary>
public partial class ImageFromByteArray : Window
{
public byte[] ByteArray
{
get
{
return (byte[])GetValue(ByteArrayProperty);
}
set
{
SetValue(ByteArrayProperty, value);
}
}
// Using a DependencyProperty as the backing store for ByteArray. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ByteArrayProperty =
DependencyProperty.Register("ByteArray", typeof(byte[]), typeof(ImageFromByteArray));
public BitmapImage ImageSource
{
get { return (BitmapImage)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ImageSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(BitmapImage), typeof(ImageFromByteArray), new UIPropertyMetadata(null));
public ImageFromByteArray()
{
InitializeComponent();
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
if (dlg.ShowDialog().GetValueOrDefault())
{
FileStream fs = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read);
ByteArray = new byte[fs.Length];
fs.Read(ByteArray, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
ImageSource = ImageFromBytearray(ByteArray);
}
}
public BitmapImage ImageFromBytearray(byte[] imageData)
{
if (imageData == null)
return null;
MemoryStream strm = new MemoryStream();
strm.Write(imageData, 0, imageData.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
MemoryStream memoryStream = new MemoryStream();
img.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);
memoryStream.Seek(0, SeekOrigin.Begin);
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
return bitmapImage;
}
}
}
Hope this will help you...
This can be achieved only using a custom converter. Look at this for details on how to implement the "image" part and here for details about creating a converter.