How to set image from code behind? - c#

I have the following aspx code
<asp:Image ID="pbScannedImage" runat="server" />
And my code behind c# code is
System.Drawing.Image image;
image = System.Drawing.Image.FromStream(new MemoryStream(dDSImageViewerDTO.ROI));
pbScannedImage.Visible = true;
pbScannedImage.ImageUrl = "";
// This is available but I don't want to write file to the disk and
// assign directly to the image box something like
pbScannedImage.Image = image;
//i know this is not possible so any other work around would be great help
So basically I want to assign the image to the image control without writing it to the anywhere else. Is it possible and if not then are there any workarounds for this available?

You can seperate your database image logic into a Generic Handler (ASHX) and then use the handler as your image's src e.g.
img.src=GetImage.ashx?id=1;
You'd need to create GetImage.ashx and handle your id's (or whatever your using) appropriately. Then you can do a simple write back to the page.

Working off guymid's answer, you can also assign the img.Src from code behind like so...
pbScannedImage.Src = "data:image/png;base64," + ImageToBase64String(Image);

pbScannedImage.Src = "ImageHandler.ashx";
And the handler code must be like:
name
System.Drawing.Image dbImage =
System.Drawing.Image.FromFile("file path");
System.Drawing.Image thumbnailImage =
dbImage.GetThumbnailImage(80, 80, null, new System.IntPtr());
thumbnailImage.Save(mstream, dbImage.RawFormat);
Byte[] thumbnailByteArray = new Byte[mstream.Length];
mstream.Position = 0;
mstream.Read(thumbnailByteArray, 0, Convert.ToInt32(mstream.Length));
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(thumbnailByteArray);

One way to do this, especially if you want to ensure images are never cached (which is common with dynamically loaded images) is to add the image data as CSS background-image data to an element such as a div with:
"background-image:url(data:image/gif;base64," + ImageToBase64String(Image) + ")"
public string ImageToBase64String(Image image)
{
using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Png);
return Convert.ToBase64String(stream.ToArray());
}
}

How said #Sain Pradeep, you can create service(ashx or contoller method if you use mvc) for return image stream and use that with html tag <img>(asp:Image is wrapper over<img>).
See samples from Display Image using ashx Handler

Related

C# .svg file to System.Drawing.Image

I need to convert the selected .svg file to System.Drawing.Image object, so I can resize it and save it as .png. Can anyone help me with this?
Here is what I have so far:
Svg.SvgDocument svgDocument = SVGParser.GetSvgDocument(mPath);
image = svgDocument.Draw();
But it gives me out of memory error.
You can use the SVG Rendering Engine Lib:
Install-Package Svg
It's quite easy to draw images using it:
var svgDoc = SvgDocument.Open(imagePath);
using(var Image = new Bitmap(svgDoc.Draw()))
{
Image.Save(context.Response.OutputStream, ImageFormat.Png);
context.Response.ContentType = "image/png";
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddMonths(1));
}
In this example i'm using a handler to display the image on the browser but you can easily save it on some folder just by changing the first parameter of the Save method.
The resource Miljan Vulovic used is svg (https://archive.codeplex.com/?p=svg).
Link is only valid until July 2021, it might be available on GitHub by then, but I'm not sure.
Anyways his solution works for me.
So,
SVGParser.MaximumSize = new System.Drawing.Size(4000, 4000);
svgDocument = SVGParser.GetSvgDocument(mPath);
var bitmap = svgDocument.Draw();
image = bitmap;

Resize Image with PHP for using in .NET

i have images on a webserver and I convert they in Base64 to receive it on a .Net application. I use this code:
$imagedata = file_get_contents($local_uri);
$d = base64_encode($imagedata);
It works perfekt.
Now i had the idea to resize the images to save time for transmission.
So I resize the images with a simple PHP-Framework from http://deruwe.de/vorschaubilder-einfach-mit-php-realisieren-teil-2.html
On behind it use ImageJPEG to "return" or create the edited image.
On an other post here i read that if you want to use ImageJPEG and translate it on Base64 you have to use this code:
ob_start();
$thumbnail->output(false, false);
$p = ob_get_contents();
ob_end_clean();
$d = base64_encode($p);
The "new" Base64 code seems legit, because if I try to illustrate it with http://www.freeformatter.com/base64-encoder.html, I got a legit image.
BUT due an unknown reason my .Net application will throw an System.NotSupportedException (No imaging component suitable to complete this operation was found.) and don't like the "new" one.
This is my .Net function to convert Base64 String in BitmapImage:
public static BitmapImage getImage(String s)
{
byte[] binaryData = Convert.FromBase64String(s);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new MemoryStream(binaryData);
bi.EndInit();
return bi;
}
Any idea whats gone wrong or how to fix it?

Displaying a byte[] in an image control

So I collect a varbinary(MAX) value from a database where an image is stored.
It gets converted to byte[], then the aim is to display this in an image control.
This is where I read from the database
public TemplateData(SqlDataReader dr)
{
initialiseData();
if (dr.HasRows)
{
Logo = (byte[])dr["Logo"];
//Logo = dr["Logo"].ToString();
TemplateId = dr["TemplateId"].ToString();
Comment = dr["Comment"].ToString();
SchemeCode = dr["SchemeCode"].ToString();
Version = dr["Version"].ToString();
}
}
This is where the values are displayed into the corresponding controls
protected void ddSchemeCode_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddSchemeCode.SelectedIndex > 0)
{
// Existing Data to load from database
TemplateData temp = DataClass.ReturnData(ddSchemeCode.SelectedItem.Text);
if (temp != null)
{
txtVersion.Text = temp.Version;
txtComment.Text = temp.Comment;
txtSchemeCode.Text = temp.SchemeCode;
txtTemplateId.Text = temp.TemplateId;
img.Src = temp.Logo;
}
So at the moment I am passing a byte[] into the source of an image control, where it would instead like a string. I've tried converting it to a string with Convert.ToBase64String(Logo) and ToString(Logo) but these do not work.
Any help is greatly appreciated. Cheers guys and gals.
Try converting the byte array to image and assign it to picturebox as below,
try
{
using (MemoryStream mStream = new MemoryStream())
{
// where pData is your byte array
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Image originalImage = Image.FromStream(mStream);
picBox.Image = originalImage;
}
}
catch (Exception ex)
{
}
Hope it helps.
As you may have noticed, you cannot "print" an image in a webpage. You need to get a little bit creative now.
What you want to look into is Response.BinaryWrite. More information about that, here: https://msdn.microsoft.com/en-us/library/system.web.httpresponse.binarywrite%28v=vs.110%29.aspx
You will probably also need a generic ashx handler. Here is an example of how to show a picture using a handler: http://www.dotnetperls.com/ashx
My suggestion would be to store the logo as a byte[] into the http session. Put the source of the image to theHttpHandlerYourGonnaCreate.ashx. You can then binary write the byte[] you've stored into the session there.
Hope this helps!
As Michael shows here, you can convert the byte array to a Bitmap object with something like this:
Bitmap bitmap = null;
using (MemoryStream imageStream = new MemoryStream(imageData))
{
bitmap = new Bitmap(imageStream);
}
It isn't entirely clear what you're using for a control to show the image, but any control that can display an image should be able to take a Bitmap or Image object.

Error Loading and Deleting Images using HTML Input File Control

I desperately need help with an issue I am having while trying load an image or unload an image using ASP/C#. The problem I am having is the first time I run the code and Load the image into the thumbnail, I have no problem but the minute I try to remove the picture or load a second or third image, it takes very very long to hit the event and I get an Out of Memory error. I think something is getting locked and takes a while to get unlocked but I am not sure.
Here is the code I am using:
protected void btnUploadImgPicture1_ServerClick(object sender, EventArgs e)
{
using (filePicture1)
{
if (filePicture1.PostedFile.FileName != "")
{
imageUtil = new ImageUtility();
string realPhysicalPath = Path.Combine(Server.MapPath("~/upload/"), filePicture1.PostedFile.FileName);
filePicture1.PostedFile.SaveAs(realPhysicalPath);
//imgVehiclePicture1.Src = realPhysicalPath;
using (imgVehiclePicture1)
{
imgVehiclePicture1.Attributes["src"] = imageUtil.getBase64String(realPhysicalPath);
Session.Add("Image1", realPhysicalPath);
imageUtil = null;
}
}
}
}
public string getBase64String(string path)
{
Image img = Image.FromFile(path);
byte[] imageBytes = imageToByteArray(img);
string base64String = Convert.ToBase64String(imageBytes, 0, imageBytes.Length);
return "data:image/png;base64," + base64String;
}
I am using this code on 3 times for 3 different events and then I am using similar code to remove the selected image from the upload.
What is ImageUtility? If it implements IDisposable then you might want to try explicitly disposing it instead of setting the variable to null. Even better if you can wrap it inside of a using block.

Could this use of System.Drawing.Image.FromStream be pointing the same memory?

I'm having to fix a bug in some very old code that converts a Base64 string to a image using Memory Stream. Basically it loops through a list of images stored as base64 strings and converts them to images then draws them using ActiveReports.
The bug is that once it loads one image all following images will be a copy of the first image.
I found the code that is doing the conversion of string to image and immediately noticed it isn't disposing of the memory stream. If I wrap the memory stream in a using block I get a GDI exception. I'm guessing this is because the image isn't really read from memory yet or something, but I'd like to hear if anyone has a guess. Thanks in advance!
byte[] oGraphic = null;
try
{
oGraphic = Convert.FromBase64String(psGraphic);
DataDynamics.ActiveReports.Picture oImg = new Picture();
oImg.Top = this.Legend.Top + this.fTopFirst;
oImg.Visible = true;
oImg.Name = sLabelName;
oImg.PictureAlignment = PictureAlignment.Center;
oImg.Image = null;
if (oGraphic != null)
{
var oStream = new MemoryStream(oGraphic);
oImg.Image = System.Drawing.Image.FromStream(oStream);
oImg.Height = Convert.ToSingle(oImg.Image.Height)/(oImg.Image.VerticalResolution);
oImg.Width = Convert.ToSingle(oImg.Image.Width)/(oImg.Image.HorizontalResolution);
oImg.SizeMode = SizeModes.Zoom;
this.fGraphicHeight = oImg.Height;
this.fGraphicWidth = oImg.Width;
if (this.fConstantGraphic > this.fGraphicWidth)
oImg.Left = this.Legend.Left + this.fLeftFirst +
((this.fConstantGraphic - this.fGraphicWidth)/2);
else
oImg.Left = this.Legend.Left + this.fLeftFirst;
}
else
{
this.fGraphicHeight = 0f;
this.fGraphicWidth = 0f;
}
this.GHMap.Controls.Add(oImg);
}
catch (Exception oE)
{
.....
}
The only thing I can imagine is if there is a line of code missing from what you have here:
if (oGraphic == null) // missing line
oGraphic = Convert.FromBase64String(psGraphic);
There is no reason for this byte[] to be declared outside of the try { } block. That array gets wrapped into a MemoryStream which is then wrapped into an Image. That image is attached to a brand new Picture which is added to a Picture collection.
What is it we don't see?
Here's another guess (I'll leave the first guess alone for posterity):
I'm not familiar with Active Reports, but it looks like you're setting the Top and PictureAlignment properties of the Picture object to the same value and adding more than one Picture. Is it possible they are all there, but one on top of each other? So the result is a single picture?
Guess #3 (one of these is going to get a checkmark, I just know it!)
Everything looks OK in the code provided, therefore the problem is somewhere else (though it's still entirely possible I'm wrong about it being OK).
Are you certain that psGraphic is different each time this code is executed?
The cause of the problem is that the Picture control is a single control instance on a single section. So you're just overwriting the image on this single control over and over.
If the only thing you want to see in this report is the images, then the best thing to do is use ActiveReports' Unbound mode and treat each image as another "record". See this walkthrough for an example of using unbound mode (see the DataInitialize and FetchData events for the meat of the matter).
Using unbound mode, ActiveReports will render the image one after the other in sections treating each image like a new record. The code would be something like the following (sorry I don't have ActiveReports handy at the moment so I can't check this code, but this should be pretty close. Let me know if you run into any problems and I'll clean it up in the morning):
In ActiveReports' ReportStart Event:
DataDynamics.ActiveReports.Picture oImg = new Picture();
oImg.Top = 0;
oImg.Visible = true;
oImg.Name = sLabelName;
oImg.PictureAlignment = PictureAlignment.Center;
// setting DataField "binds" the Picture control to get it's data from the MyImageField field which we'll initialize and bind in the events below
oImg.DataField = "MyImageField";
this.Sections["Detail"].Controls.Add(oImg);
In ActiveReports' DataInitialize Event:
this.Fields.Add("MyImageField");
In ActiveReports FetchData Event:
var imageBytes = Convert.FromBase64String(_imageStrings.Current); // I'm not sure where the base64 image strings come from, some I'm assuming you can put them in an enumerator field in the report like "_imageStrings"
var imageStream = new MemoryStream(imageBytes);
var image = Image.FromStream(imageStream);
Fields["MyImageField"].Value = image;
// This tells ActiveReports if there are more records, and if it should raise the FetchData event again (allowing you to add another image).
eArgs.EOF = !_imageStrings.MoveNext();
If you need to resize the image control for each image, use the section's Format event for that. You could use something like the following:
In Detail_Format Event:
var pictureControl = this.Sections["Detail"].Controls["MyImageControl"] as DataDynamics.ActiveReports.Picture;
pictureControl.Width = Convert.ToSingle(pictureControl.Image.Width)/(pictureControl.Image.VerticalResolution);
pictureControl.Width = Convert.ToSingle(pictureControl.Image.Width)/(pictureControl.Image.HorizontalResolution);
Finally, ActiveReports will also just automatically bind to a set of POCO objects in an IEnumerable (or IList, I forget). So you could simply have a "MyImage" class with a property like "MyImage" and ActiveReports will read it and bind with it (you wouldn't have to write any code in DataInitialize and FetchData). I think you might also just be able to put the MemoryStream in there as the binding too and ActiveReports will read it, but I'm not positive on that.
BTW: The reason that GDI exception occurs when disposing the MemoryStream is because GDI attempts to just seek within that single MemoryStream for the image data rather than making a copy of it. So you'll need to supply each System.Drawing.Image instance with a new stream (don't worry MemoryStream will clean itself up when everything is released).
It turned out to be a problem with the way we were creating the image. Adding the code below fixed the problem.
oImg.Image = System.Drawing.Image.FromStream(oStream);
TO THIS
oImg.Image = ImageFromBase64String(psGraphic);
private Image ImageFromBase64String(string sBase64String)
{
using (var sStream = new MemoryStream(Convert.FromBase64String(sBase64String)))
using (var iSourceImage = Image.FromStream(sStream))
{
return new Bitmap(iSourceImage);
}
}

Categories