Add Bitmap to HTML - c#

I have an ASP.NET web form. This web form has an event handler that generates some HTML. This HTML is based on the time-of-day, that is why it is created in the event handler. Based on the time of day, an image is created programmatically via the following method:
private Bitmap GetImageForTime(DateTime time)
{
Bitmap bitmap = new Bitmap();
// Dynamically build the bitmap...
return bitmap;
}
I want to call this method when the HTML is being generated. However, I do NOT want to write the image on the server. Instead, I would like to figure out a way to write it out along with the HTML. In a sense, I'm trying to accomplish the following:
protected void myLiteral_Load(object sender, EventArgs e)
{
string html = "<table><tr><td>";
html += GetImageForTime(DateTime.Now); // This is the problem because it's binary.
html += "</td><td>";
html += GetWeatherHtmlText();
html += "</td></tr></table>";
myLiteral.Text = html;
}
Is this possible? If so, how?

I would suggest implementing an IHttpHandler that generates your image and returns it as a byte stream. Then in the tag on the page, set the src attribute to the address of the HTTP Handler.
<html><body><img src="TimeImageHandler.ashx"/></body></html>
Example: http://www.c-sharpcorner.com/uploadfile/desaijm/httphandlersforimages11152005062705am/httphandlersforimages.aspx
Generic HTTP Handlers are pretty simple to create once you're aware of them:
public class TimeImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
Bitmap bitmap = GetImageForTime(DateTime.Now);
context.Response.ContentType = "image/jpeg";
bitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
public bool IsReusable { get { return false; } }
}

The way I have done this is to create an image tag in the HTML and point the image source (<img src="xxx" />) to a page that dynamically creates the image and returns that (and only that) on the response stream, with the correct mime type.

Potentially you could use the data URI scheme in an <img> tag or in some CSS but personally, I wouldn't.
Some more explanation.

Images in HTML are displayed as a result of an <img> element in the HTML. I don't believe there is any other way to display an image in an HTML page.
You will need to write a handler which can be invoked via the URL in the src attribute of the <img> element. That handler will generate and return the image.

Create another aspx page called TimeImage.aspx then in the Page_Load of the code-behind for the page put this code:
void Page_Load(object sender, EventArgs args) {
string mime = "image/jpeg";
Response.ContentType = mime;
Bitmap b = GetImageForTime(DateTime.Now);
var codec = ImageCodecInfo.GetImageEncoders().Where(i => i.MimeType == mime).SingleOrDefault();
if(codec != null)
b.Save(Response.OutputStream, codec, null);
}
Then make your html generation look like this:
protected void myLiteral_Load(object sender, EventArgs e)
{
string html = "<table><tr><td>";
html += "<img src='TimeImage.aspx'>"
html += "</td><td>";
html += GetWeatherHtmlText();
html += "</td></tr></table>";
myLiteral.Text = html;
}
This will create an img tag that calls the TimeImage.aspx page, that page changes the response mime-type to image/jpeg, converts your bitmap to a JPG, and then saves it to the response output stream so that the image tag can display it as a JPG.
If you prefer a different format just change the mime type at the top (e.g. "image/gif" for GIF, or "image/png" for PNG).

Beyond the already given solutions of using the data URI scheme or sending the image dynamically created (so, without storing it), there's another odd solution you can try: a table with each cell 1-pixel tall and wide and proper background per cell, and no borders of course... GIMP e.g. is able to export images this way as html, and if you force the size of cells and table, you can see the image as if it were embedded... of course, it is rather "heavy" if the image is big, but it could work ok for relatively small images.
EDITED (italics part added)

Related

Bind a PictureBox with a string of a url for LoadAsync

Is there a way to bind a PictureBox to a string so that when the string will change, it will call LoadAsync() with the url in the string and load an image?
Currently this is what I have in the auto generated code.
this.itemImagePictureBox.DataBindings.Add(new System.Windows.Forms.Binding("Image", this.MySource, "ItemImage", true));
What I want instead is:
this.itemImagePictureBox.DataBindings.Add(new System.Windows.Forms.Binding("String", this.MySource, "ImageUrl", true));
MySource has a property for url string, and I also tried to make it have a field of an Image, but a Bitmap for example doesn't have a load async feature so I still can't use the url string.
Make sure the WaitOnLoad property is false (default), thus enabling asynchronous image load, and then bind to ImageLocation property:
this.itemImagePictureBox.WaitOnLoad = false;
this.itemImagePictureBox.DataBindings.Add(new System.Windows.Forms.Binding(
"ImageLocation", this.MySource, "ImageUrl", true));
Does it have to be databinding? Why not:
MyImage = new Bitmap(fileToDisplay);
itemImagePictureBox.Image = (Image) MyImage ;
await itemImagePictureBox.LoadAsync();
itemImagePictureBox.Refresh();
Or, if the image is a URL:
Load an image from a url into a PictureBox

How to replace some text with picture in RichTextBox without clipboard? [duplicate]

Most of the examples I see say to put it on the clipboard and use paste, but that doesn't seem to be very good because it overwrites the clipboard.
I did see one method that manually put the image into the RTF using a pinvoke to convert the image to a wmf. Is this the best way? Is there any more straightforward thing I can do?
The most straightforward way would be to modify the RTF code to insert the picture yourself.
In RTF, a picture is defined like this:
'{' \pict (brdr? & shading? & picttype & pictsize & metafileinfo?) data '}'
A question mark indicates the control word is optional.
"data" is simply the content of the file in hex format. If you want to use binary, use the \bin control word.
For instance:
{\pict\pngblip\picw10449\pich3280\picwgoal5924\pichgoal1860 hex data}
{\pict\pngblip\picw10449\pich3280\picwgoal5924\pichgoal1860\bin binary data}
\pict = starts a picture group,
\pngblip = png picture
\picwX = width of the picture (X is the pixel value)
\pichX = height of the picture
\picwgoalX = desired width of the picture in twips
So, to insert a picture, you just need to open your picture, convert the data to hex, load these data into a string and add the RTF codes around it to define a RTF picture. Now, you have a self contained string with picture data which you can insert in the RTF code of a document. Don't forget the closing "}"
Next, you get the RTF code from your RichTextBox (rtbBox.Rtf), insert the picture at the proper location, and set the code of rtbBox.Rtf
One issue you may run into is that .NET RTB does not have a very good support of the RTF standard.
I have just made a small application* which allows you to quickly test some RTF code inside a RTB and see how it handles it. You can download it here:
RTB tester (http://your-translations.com/toys).
You can paste some RTF content (from Word, for instance) into the left RTF box and click on the "Show RTF codes" to display the RTF codes in the right RTF box, or you can paste RTF code in the right RTB and click on "Apply RTF codes" to see the results on the left hand side.
You can of course edit the codes as you like, which makes it quite convenient for testing whether or not the RichTextBox supports the commands you need, or learn how to use the RTF control words.
You can download a full specification for RTF online.
NB It's just a little thing I slapped together in 5 minutes, so I didn't implement file open or save, drag and drop, or other civilized stuff.
I use the following code to first get the data from clipboard, save it in memory, set the image in clipboard, paste it in Rich Text Box and finally restore the data in Clipboard.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
OpenFileDialog1.Filter = "All files |*.*"
OpenFileDialog1.Multiselect = True
Dim orgdata = Clipboard.GetDataObject
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each fname As String In OpenFileDialog1.FileNames
Dim img As Image = Image.FromFile(fname)
Clipboard.SetImage(img)
RichTextBox1.Paste()
Next
End If
Clipboard.SetDataObject(orgdata)
End Sub
The OpenFileDailog1, RichTextBox1 and Button1 are Open File Dialog, Rich Text Box and button controls respectively.
private void toolStripButton1_Click(object sender, EventArgs e)
{
FileDialog fDialog = new OpenFileDialog();
fDialog.CheckFileExists = true;
fDialog.CheckPathExists = true;
fDialog.RestoreDirectory = true;
fDialog.Title = "Choose file to import";
if (fDialog.ShowDialog() == DialogResult.OK)
{
string lstrFile = fDialog.FileName;
Bitmap myBitmap = new Bitmap(lstrFile);
// Copy the bitmap to the clipboard.
Clipboard.SetDataObject(myBitmap);
DataFormats.Format format = DataFormats.GetFormat(DataFormats.Bitmap);
// After verifying that the data can be pasted, paste
if(top==true && this.rtTop.CanPaste(format))
{
rtTop.Paste(format);
}
if (btmLeft == true && this.rtBottomLeft.CanPaste(format))
{
rtBottomLeft.Paste(format);
}
if (btmCenter == true && this.rtBottomCenter.CanPaste(format))
{
rtBottomCenter.Paste(format);
}
if (btmRight == true && this.rtBottomRight.CanPaste(format))
{
rtBottomRight.Paste(format);
}
}
}
Here is what I do to hack the rich text control:
Insert the required image in wordpad or MS-WORD. Save the file as 'rtf'. Open the rtf file in notepad to see the raw rtf code. Copy the required tags & stuff to the 'rtf' property of your Rich Text Box (append to existing text).
There is some trial and error involved but works.
With C#, I use place holder StringBuilder objects with the necessary rtf code. Then I just append the image path.
This is a workaround for not having to learn the RTF syntax.
My own version that I posted in a new thread, apparently I should have searched and posted it here. Anyway, using the clipboard again, very easy.
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "Images |*.bmp;*.jpg;*.png;*.gif;*.ico";
openFileDialog1.Multiselect = false;
openFileDialog1.FileName = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
Image img = Image.FromFile(openFileDialog1.FileName);
Clipboard.SetImage(img);
richTextBox1.Paste();
richTextBox1.Focus();
}
else
{
richTextBox1.Focus();
}
}
}
If you were in C++, the way to do it is thru OLE. More specifically, if you search Google for ImageDataObject it will show C++ code how to insert a HBITMAP into the RTF Control. One link is here.
Now, how this translates into .Net code, I don't know. I currently don't have the time to work thru the details.
I was also looking for something for this same task and found this ->
http://sourceforge.net/projects/netrtfwriter/
You can generate any type of RTF text that you would want and then use it however you wish. Very well structured example which will auto sense the image type being used (jpg/jpeg/png etc) and worked for the image files I have been using. If you are in a hurry then this is a great RTF generator!
All I did was make a small pictureBox control in c# and made sure it was hidden behind another object big enough to hide it. Then I made a button to insert a picture, and it loaded the pictureBox with the image then it puts it in the richTextBox then it clears the pictureBox control.
Here is the code.
private void InsertPicture_Click(object sender, EventArgs e)
{
{
if (openFileDialog4.ShowDialog() == DialogResult.OK)
{
// Show the Open File dialog. If the user clicks OK, load the
// picture that the user chose.
pictureBox2.Load(openFileDialog4.FileName);
Clipboard.SetImage(pictureBox2.Image);
pictureBox2.Image = null;
this.richTextBox1.Paste();
}
}
}
After inserting the code to do it with the clipboard, type in Clipboard.Clear();. It works well and it doesn't clear everything, only the item last added to the clipboard.
Full Code:
private void addPictureToRTB()
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Pictures|*.png" })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
ClipBoard.SetImage(Image.FromFile(ofd.FileName));
richTextBox.Paste();
Clipboard.Clear();
}
}
}
Then reference this function where you need to.
Several hours surfing for solution to insert image without loosing quality and fixed the gray background with transparent image/png
// assuming the image is in your Resources
var img = Resources.ImageWithTransparentBckgrnd;
var g = Graphics.FromImage(img);
using (var ms = new MemoryStream())
{
img.Save(ms, ImageFormat.Png);
IntPtr ipHdc = g.GetHdc();
Metafile mf = new Metafile(ms, ipHdc);
g = Graphics.FromImage(mf);
g.FillEllipse(Brushes.White, 0, 0, 16, 16); // size you want to fill in
g.Dispose();
mf.Save(ms, ImageFormat.Png);
IDataObject dataObject = new DataObject();
dataObject.SetData("PNG", false, ms);
Clipboard.SetDataObject(dataObject, false);
richTextBox1.Paste();
SendKeys.Send("{RIGHT}");
richTextBox1.Focus();
}

Custom control Image not showing

I have a custom control. It has an image. I have exposed the ImageURL attribute in the custom control code by creating a new attribute called ButtonIconImgSrc as follows:
[Category("Appearance")]
[Description("Gets or sets the logo image path")]
public String ButtonIconImgSrc
{
get
{
EnsureChildControls();
return iconImg.ImageUrl;
}
set
{
if (value != null)
{
iconImg.ImageUrl = value.ToString();
}
}
}
I compile the customeControl code to create a dll and then add the dll to my web site solution so i can drag and drop it onto my designer view or dynamically create it. Everything seems to work great in designer, i drop it on, set my custom atributes and looks good.
..... but the img does not show when i compile and run the site in a browser. nothing gets set correctly, its all lost by the time it gets back to the calling code - labels and textboxes and widths and heights etc. I want to create this customcontrol dynamically, not use the designer but same issue.
Below is the code that calls the above 'set' method, except after it comes back from th eset method its still blank.
protected void Page_Load(object sender, EventArgs e)
{
myCustomButton tb = new myCustomButton();
tb.ButtonIconImgSrc = "~/imgs/target_logo.png";
pnlButtons.Controls.Add(tb);
}
I see the code above being hit and the string "~/imgs/ibc_foh.png" being set in the myCustomButton code and that code exits and everything looks good. When the debugger gets back to the calling class (my websites Page_Load) the attribute tb.ButtonIconImgSrc is still blank, "". And so the image does not appear.
Updated: problem solved. I misunderstood the lifecycle of the control, the image was being overwritten in the createChildControls method
Create/Add a Generic HttpHandler page to your project.
in the function 'ProcessRequest'. there will be a HttpContext object (called context).
do as followed:
public class YouHandlerPage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// REVIEW AND PROCESS THE REQUEST (i.e. ...
// context.Request.QueryString
// context.Request.RequestContext.RouteData.Values;
// context.Request.Form
string fDirectory = #"C:\Users\john\Desktop\";
string fileName = "ibc";
string fileExt = "png";
context.Response.StatusCode = 200;
context.Response.ContentType = "Image/" + fileExt;
//let context.Response.ContentLength be specified by the following WriteFile method
context.Response.WriteFile(Format.String("{0}{1}.{2}", fDirectory, fileName, fileExt));
}
public bool IsReusable { get { return false;} }
}
now, run your web application.. and goto localhost:<portassigned>/<handlerpagefilename>.ashx
Where locahost:<portassigned> is your domain (or IIS Express assigned), and <handlerpagefilename> is whatever your named you added GenericHandlerPage (which should end with .ashx).
When you visit this page, you should get your image..
Further Review
review Registering Routes to map to your HandlerPage.
review HttpModules as an alternative to httphandler pages
problem solved. I misunderstood the lifecycle of the control, the image was being overwritten in the createChildControls method

how to save image url into session

I want to save a image url into session and this url I get into another page load then load into image button. Is it possible or not? I use the following code to save image url;
Image = Image1.ImageUrl.ToString();
Session["logo"] = Convert.FromBase64String(Image);
But I get the following error, like so;
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.
Another page I get this image url,
protected void Page_Load(object sender, EventArgs e)
{
Image img =(Image)Session["logo"];
ImageButton1.Controls.Add(img);
}
The above code also gets an error. So please help me.
Do you want the URL or the binary data of the image? You are storing the URL (e.g. http://www.mycompany.com/logo.png) in the Image variable, but then trying to "decode" it from Base64. It looks like you're trying to get the binary data of the image and store that in session. Why not just store the URL as-is rather than trying to decode it?
string image = Image1.ImageUrl.ToString();
Session["logo"] = image;
protected void Page_Load(object sender, EventArgs e)
{
string imgURL = Session["logo"];
ImageButton1.Controls.Add(new Image() { ImageURL = imgURL });
}
Otherwise you're going to have to create an HttpRequest to capture the binary data of the image, then embed that in the form (which is not as simple as adding an image control since there's nowhere to but the binary data in the web control)

How do I get the Source of an Image on GestureCompleted

I want to find the URI of an Image on the phone screen when the image is dragged.
I have many images on the screen and I need to know which one has been dragged, I can easily find that from the filename of the image as they are named A.png, B.png and so on.
private void OnGestureCompleted(object sender, Microsoft.Phone.Controls.GestureEventArgs e){
Image image = sender as Image;
TranslateTransform transform = image.RenderTransform as TranslateTransform;
//storing the final values after the gesture is complete
xFin = (e.GetPosition(null).X);
yFin = (e.GetPosition(null).Y);
//failed attempts to convert adress to string
MessageBox.Show(image.Source.ToString());
}
This returns System.Windows.Controls.Image.
and this on the other hand throws an exception stating that ConvertToString hasn't been implemented.
ImageSourceConverter convertor = new ImageSourceConverter();
string location = convertor.ConvertToString(image);
MessageBox.Show(location);
Is there some way this can be done?
If you know that the Source property is BitmapImage (which it probably is if you are passing in a URI to the Image in the Source property in XAML) then you can use UriSource:
MessageBox.Show(((BitmapImage)image.Source).UriSource.ToString());
I suggest you use the Tag property of the Image control to store the info you need though. More scalable robust in the long run.

Categories

Resources