How to show Image from byte array in Microsoft report - c#

I am using a Report file and a ReportViewer control to show a report which loads data dynamically from objects during run-time.
I need to show an image which is stored as a byte array in the object.
The PictureBox's value is currently set to:
=First(Fields!ImageData.Value, "dtstItemImage")
And I set the DataSource using:
ImageBindingSource.DataSource = this.item.Image.ImageData;
The code compiles and runs but the image is not displayed in the report.
Is this because the PictureBox needs to be bound to an Image object (and not to a byte array)? Or are there perhaps some properties of the PictureBox which I need to set?
UPDATE 1
I've added a border to the PictureBox just to make sure that's its visible and it does show up in the report. It just doesn't contain the image.
UPDATE 2
I've fixed a mistake in my code. I've changed:
ImageBindingSource.DataSource = this.item.Image.ImageData;
to:
ImageBindingSource.DataSource = this.item.Image;
as the PictureBox is bound to the ImageData field BUT the DataSource is the Image object.
Now I get a small cross icon instead of nothing which (at least for me) indicates some progress but I don't know where the byte[]-bitmap conversion code needs to be.

I managed to solve this by setting the report's Image box Source property to Database (it was previously set to External).
More info about the different available Source values can be found at (MSDN) HowTo: Add an Image (Reporting Services).

You need to create an image object from the byte array and use that as the source.
To do this, you can use a helper function like the following
public static Image LoadImage(byte[] imageBytes)
{
Image image = null;
using (var ms = new MemoryStream(imageBytes))
image = Image.FromStream(ms);
return image;
}
Edit
For WPF, you need to use BitmapSource (MSDN) instead of Image (MSDN)
public static BitmapSource LoadImage(Byte[] imageBytes)
{
var image = new BitmapImage();
using (var ms = new MemoryStream(binaryData))
{
image.BeginInit();
image.StreamSource = ms;
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
}
if (image.CanFreeze)
image.Freeze();
return image;
}
NB: You can could also do this using a IValueConverter, see this blog post for the source code.
and then modify your data binding
ImageBindingSource.DataSource = LoadImage(item.Image.ImageData);
...
Make sure that the image (and MemoryStream) is disposed properly when you finished with it, as otherwise you will leak memory.
Also, depending on the format of your byte array you may need to do some work. See one of my question/answers for some helpful information.

Related

Set background of a div from a generated image

I am programmatically creating an image via C#, and I'm wondering how can I use this created image as a background of a div.
To explain it better, here's an example:
public string BackImage()
{
System.Drawing.Image img = //generated image goes here
var ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
return Convert.ToBase64String(ms.ToArray());
//should I return it in a different way?
}
This gives me the image that I can use, now how would I set this image to be a background of a div?
<div id="main">
</div>
I have tried using background-image:url(data:image/jpeg;base64,#Html.Action("BackImage"))" but the browser starts freezing because of the image.
Is there some simpler way of doing it?
Thanks.
Two ways:
Simple:
Save your image in a temp folder and in your css class or style definition use
background-image: url('whatevertheurlis')
A bit more complex:
Create an IHttpHandler implementation to deliver the generated image. The css/style background-image setting is different only in the Url part.
I've done both before and the choice was based on the requirements of the number of different images to create and lifetime.

How can I change an image/bitmap that is already in use?

I have a directory with .png images which I display in a third party combobox of my c# program. So the user is able to choose one of this images using the combo box. Basic code used:
Bitmap thump = new Bitmap(<path>);
ComboItem item = new ComboItem();
item.Image = thump;
MyComboBox.Items.Add(item);
Now I would like to update one of this images at runtime. Unfortunately I can't delete the old image because it is still opened in my program, so somehow I either need to close it or open it in a way that does not keep the image in use by my program. The changes to the bitmap are not done in my program, I just pass the path of the dirctory to another program which saves the bitmap there (but fails at the moment because it can't delete the old bitmap).
I guess this is a simple problem but I could not find a solution here or on the internet.
First read the file to memory, then create the Bitmap using that data.
var m = new MemoryStream(File.ReadAllBytes(filename));
Bitmap thump = (Bitmap)Bitmap.FromStream(m);

Extracting a image from a WebBrowser Control

My aim is to extract an image from a loaded webbrowser control.
// get the image link from the image element ID.
string imageLink = wbVideos.Document.GetElementById("sbvdcapimg").GetAttribute("src").ToString();
//Download the image into a bitmap
Bitmap image = new Bitmap(new System.IO.MemoryStream(new System.Net.WebClient().DownloadData(imageLink)));
so the code works for most pictures, but i receive me a format error when i use it with the link below.
The error is thrown when i parse this link into my code: "http://www.swagbucks.com/?cmd=cp-get-captcha-image&ctype=1&tai=478817685&sid=0.4015013770493371"
(Please Note to view the image you need to login!)
Notice how the image does not end in a extension, this is most likely causing the error.
Example of the extracted link:
so, my question, how can i make my code accept this link as a valid image file?

WPF cannot implicitly convert system.drawing.bitmap to media.brush

I want to change the background of a button manually in my WPF app.
I have an image imported into my resources and I want to do:
MyButton.Background = MyProject.Properties.Resources.myImage;
But I get the error:
cannot implicitly convert system.drawing.bitmap to media.brush
How can I do this??
You should read about brushes first here.
And then use ImageBrush, something like this:
MyButton.Background = new ImageBrush(...);
(or, maybe, put the brush into resources...)
UPDATE
You can find how to create imageSource from bitmap easilly. for example, here. Like:
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
MyButton.Background = new ImageBrush(bitmapSource);
In a WPF application, you do usually not add image resources as you did in WinForms.
Instead you add the image file directly to your Visual Studio project, just like any other file. If there are multiple images, it may make sense to put them in a subfolder of the project (e.g. called "images"). The Build Action of that file has to be set to Resource (which is the default for image files).
Now you can create a BitmapImage from a Pack URI to that file.
Finally you create an ImageBrush from the BitmapImage to set the Background property.
var uri = new Uri("pack://application:,,,/images/myImage.jpg");
var image = new BitmapImage(uri);
MyButton.Background = new ImageBrush(image);

Image.Source (with binding) is blocking image file after binding is removed

In a GridView, I've templated the items so an Image control inside that template receives an Uri using a binding (also tried with BitmapImage) to show a picture file. It works, but I cannot delete those files because those files are blocked. Even if I clear the collection feeding the GridView.ItemsSource, and even if I call GC.Collect(), they are still blocked.
Thanks to Philip for his working suggestion... as I used a Converter to feed a BitmapImage to every Image control, found some particular things had to do to make it work, and here it is for future reference:
InMemoryRandomAccessStream Ras = new InMemoryRandomAccessStream();
var archivo = CartoonsDownloader.FolderImagenes.GetFileAsync(TheFileName);
var fileStream = CartoonsDownloader.FolderImagenes.OpenStreamForReadAsync(TheFileName);
fileStream.Result.CopyTo(Ras.AsStreamForWrite());
BitmapImage MapaDeBits = new BitmapImage();
// Even it's RANDOM, I have to manually "Seek" it at 0.
Ras.Seek(0);
MapaDeBits.SetSource(Ras);
MapaDeBits.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
return MapaDeBits;
This could be a bug in the XAML stack (so you could report it on MSDN forums), or just a side effect of its nature of caching images. As an alternative - you can open the file yourself and set the image using the SetSource method. Then you should have better control over the file access.

Categories