I am looking for a way to embed image to Rich text box. My rtf file is portable which contains both image and text. i.e. It can be moved from one computer to another. So the user should be able to see the content of rtf file (text+image) even if its in another machine.
Now I am using the following code to insert image.
public static void ApplyImage(RichTextBox RichTextBoxControl)
{
try
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".png";
dlg.Filter = "PNG Files (.png)|*.png|JPG Files (.jpg)|*.jpg|GIF Files (.gif)|*.gif";
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
string fileName = dlg.FileName;
if (File.Exists(fileName))
{
BitmapImage bi = new BitmapImage(new Uri(fileName));
Image image = new Image();
image.Source = bi;
InlineUIContainer container = new InlineUIContainer(image);
Paragraph paragraph = new Paragraph(container);
RichTextBoxControl.Document.Blocks.Add(paragraph);
}
}
}
catch
{
throw;
}
}
But this code is not suitable for my purpose. Because the embedded image may not be in the other machine. So it won't work. Either I need to embed image or store image as binary in rtf file. I searched everywhere and no luck.
Can anyone help me please?
I got a solution for the problem. I am not sure its the right way, but still this solution is working for me. Hope it may help others.
The solution is to iterate through all image tags in flow document and copy the images to a repository folder which is portable. Then load the images from that repository folder next time to show the images back in to richtextbox.
foreach (Block block in rtb.Blocks)
{
if (block is Paragraph)
{
Paragraph paragraph = (Paragraph)block;
foreach (Inline inline in paragraph.Inlines)
{
if (inline is InlineUIContainer)
{
InlineUIContainer uiContainer = (InlineUIContainer)inline;
if (uiContainer.Child is Image)
{
Image image = (Image)uiContainer.Child;
//Copy Image source to another repository folder and save the path.
}
}
}
}
Related
I'm creating a FixedDocument by adding FixedPages to PageContents, then adding them to the FixedDocument somehow like this
FixedDocument fd = new FixedDocument();
// add FixedPages in PageContent to fd
Printing them with a PrintDialog, like this
pdialog.PrintDocument(fd.DocumentPaginator, "Test");
results in the correct number of pages. However, every page printed - e.g. to a PDF - is the content of the first page.
I tried testing the ImageSources I add to the FixedPages, those seem correct. I also tested the final FixedDocument with a DocumentViewer like so
Window wnd = new Window();
DocumentViewer viewer = new DocumentViewer();
viewer.Document = fd;
wnd.Content = viewer;
try
{
wnd.Show();
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
This strangely shows the correct output I would expect. What's even stranger is that I get an IOException after wnd.Show(); (which is why I surrounded it with a try/catch). Even with the try catch I can only view it maybe 1-2 seconds before the same IOException thrown by my MainWindow. Something like "Wrong username or password" - which doesn't make sense, since the images I'm trying to print are local ones.
Putting the DocumentViewer aside, my problem with the Print() method only printing the first page n times (n being the number of actual pages it should be) still persists, just thought that the exception in the DocumentViewer may give someone an idea of an underlying problem.
This might be a possible duplicate of FixedDocument always print first page - however he doesn't mention problems with DocumentViewer and the question remains unanswered.
Thanks in advance for any help!
I have had a similar issue, printing labels in a FixedDocument from a List of Data, that contains a List Of Image Sources (User Photo), and also dynamically creates a QRCode image from an integer for the users id.
The format for the image is created from a custom UserControl that I used to position The Text fields and images for each label. When I viewed the created document in the DocumentViewer control, it displayed perfectly. Correct photo image, correct QRCode image for each label. However, when I printed the document (or saved to PDF file or XPS File), Ever Label had only the first image in both the Photo and QRCode image positions on the label.
When I came across this post, I though that I would try saving then reloading the images as suggested, and this worked!! However the IO overhead for 30 labels per page, and many pages of labels meant that this wasn't a very useful workaround! I
Then found that simply converting the ImageSource to a ByteArray, and then back again, before adding to the FixedDocument worked also, but without the added IO overhead. Not massively elegant, but has been a real headache for me for a week now!!
Here is a snippet of code from the main body of the method that builds the labels:
var qr = GetQRCodeImage(playerId); // Gets ImageSource
var ph = LoadImage(data[dataIndex].Photo); // Gets ImageSource
var qrCode = FixDocumentCacheImageBugFix(qr); // Gets ImageSource
if (ph != null) {
var photo = FixDocumentCacheImageBugFix(ph);
label = new AveryBarcodeLabel(line1, line2, line3, qrCode, photo); // Calls constructor to instantiate new Label with new ImageSources
}
else {
label = new AveryBarcodeLabel(line1, line2, line3, qrCode); // Calls constructor to instantiate new Label with new ImageSources (where photo is null)
}
and here are the methods I used to "Fix" the Images
public static ImageSource FixDocumentCacheImageBugFix(ImageSource image) {
var bytes = ImageSourceToBytes(image);
return ByteToImage(bytes);
}
public static ImageSource ByteToImage(byte[] imageData) {
var biImg = new BitmapImage();
var ms = new MemoryStream(imageData);
biImg.BeginInit();
biImg.StreamSource = ms;
biImg.EndInit();
ImageSource imgSrc = biImg;
return imgSrc;
}
public static byte[] ImageSourceToBytes(ImageSource imageSource) {
byte[] bytes = null;
var bitmapSource = imageSource as BitmapSource;
if (bitmapSource != null) {
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream()) {
encoder.Save(stream);
bytes = stream.ToArray();
}
}
return bytes;
}
So, this isn't really the answer to why it happened, but I found at least the culprit: my image.
I'm loading a multipage LZW-compressed TIFF like so:
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
foreach (ImageSource frame in encoder.Frames)
{
frame.Freeze();
Images.Add(frame);
}
where Images is a collection of ImageSource. They display fine in the application, I can also save them again using a TiffBitmapEncoder, but printing them using WPF ends up with the in the question mentioned problem as well as - when using a DocumentViewer - an exception telling me about 'wrong username or password', which doesn't make sense.
The way I found out the image to be the problem was temporarily saving the individual ImageSources of the TIFF using a PngBitmapEncoder and immediately reloading the pages from the separate files with the same encoder into the same slot in my Images collection.
Since this works without any issues (no username/password exception in my DocumentViewer and my printing working correctly) I have to assume that he doesn't like something about the TIFF format.
This doesn't answer my underlying question of why it didn't work, but since this is at least a workaround that works, I'll just put that here and don't check the 'answered' mark just yet.
Maybe someone knows why my TIFF ImageSource produced those strange results?
I am trying to make a file display. When the user selects a file, it displays the icon of the file in the window. When I select the Google Chrome icon and click on 'OK' in the openfiledialog, the intended result happens. (see pictures below)
However, when I select another icon (e.g Word), it gives me the error 'Path does not exist'.
(see pictures below)
If I select another file (e.g File Explorer) it gives me 'Catastrophic Error' (see pictures below)
For some reason, this problem only happens with shortcut files. For other files like .txt files or .exe files, this problem does not occur.
Here is my code (Add_Item is the name of the button)
private void AddItem_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
foreach (String myfile in openFileDialog.FileNames)
{
// here myfile represent your selected file name
//get filename
string filename = System.IO.Path.GetFileName(myfile);
//TODO: Create settings
Icon icon1 = System.Drawing.Icon.ExtractAssociatedIcon(myfile);
Bitmap icon = icon1.ToBitmap();
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Source = BitmapToImageSource(icon);
Tiles.Children.Add(image);
}
}
}
Can anyone help me?
Thanks
Alright, {DeferenceLinks = false} fixed my problem.
I have a pictureBox that loads an image directly from the internet. The image can change dynamically and is specified by the user in a textBox that has a TextChanged event that changes the image in pictureBox to the URL in the textBox. When user clicks the submit button, the image URL is saved in the database. But before saving I want to validate the image, that whether the image displayed successfully or the error image is displayed in place of it. So how can I validate this?
You can use the LoadComplete event to see when it has changed, and if the eventArg's error is null (successful) or not null (fail).
void pictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
MessageBox.Show(e.Error.ToString());
}
this.pictureBox1.Validated += new EventHandler(pictureBox1_Validated);
this.pictureBox1.ImageLocation = this.textBox1.Text;
-
Edit: Just saw Dips' comment, did not use that link but is same means to answer this.
Place the code below in the function where you are retrieving the path of image from textBox ,be sure to place it before you do anything else on that path;
string path = "Path to image";
Bitmap bmp;//To validate the Image.
try
{
bmp = new Bitmap(path);//Create a Bitmap object from the given path.
if (bmp != null)
{
pictureBox1.Load(path);//Display the image to the user.
//Now it's safe to store the image path in the database,
//because we have validated it.
bmp.Dispose();//Dispose the Bitmap object to free occupied resources.
//Place you database related code here which uses the path we just validated.
}
}
catch (ArgumentException)
{
MessageBox.Show("The specified image file is invalid.");
//Show error image in PictureBox.
//(pictureBox1.Image="Path to error image").
//Don't store image path,its invalid.
}
catch (FileNotFoundException)
{
MessageBox.Show("The path to image is invalid.");
//Show error image in PictureBox.
//(pictureBox1.Image="Path to error image").
//Don't store image path,its invalid.
}
When you've done this you can place your code where I've shown the comment //Place your database....This ensures that the file path and image is validated before anything else uses them.`This method also checks if the image file is actually an image and not a .txt or .exe with its extension changed to .jpg or any other image format,as you've mentioned in your comments you need to check if the path actually points to an image file.
You can the extend the exception handling mechanism if you need something more than displaying a MessageBox with error information.One more thing that is worth to be mentioned is that,before you display any image or do anything you will have to check if the url is valid one,to simplify this step you can try to download the file(it can be anything - an image,an executable,a text file or at least a web page,when it has been downloaded pass the path to that file(relative to filesystem) to this function.
Hope it works for you.
Suppose Pic1 is name of your control. To validate then you can use simply,
if(pic1.ImageLocation.Trim().Length>4) // > 4 since a shortest valid image
file will be a.png or something
similar; length= 5
{
if(validExtensions(pic1.ImageLocation)
{
//then put the path to database
}
}
Updated
//Mehod to valid image extensions
private bool validExtensions(string url)
{
var imgs = new []{".jpg",".gif",".png",".bmp",".jpeg"};
var ext = System.IO.Path.GetFileExtention(url); // see the correct method
in intellisense
if(imgs.Contains(ext)
return false;
}
Update 2
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) | *.jpg; *.jpeg; *.jpe; *.jfif; *.png";
dialog.InitialDirectory = #"C:\";
dialog.Title = "Please select an image file to encrypt.";
if (dialog.ShowDialog() == DialogResult.OK)
{
//Encrypt the selected file. I'll do this later. :)
}
I have an Image Control (WPF) called image1 that load an Image when I click on a commandbutton (here is the code about that event). Now what I have to do if I want to copy that image file on the current directory (so the project dir) ?
private void commandButton1_Click(object sender, System.Windows.RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = "*.jpg";
dlg.Filter = "Image Files|*.jpg";
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
image1.Source = new BitmapImage(new Uri(dlg.FileName));
}
// to do
}
}
Use the File.Copy method. You may get the file name without path from Path.GetFileName:
// get file name from full source path (for example)
string targetFileName = Path.GetFileName(dlg.FileName);
// copy to relative path, i.e. current directory
File.Copy(dlg.FileName, targetFileName);
In case your question is about how to save a BitmapSource, you may look at BitmapEncoder.
I am trying to select an image and split it into 9 pieces and place randomly in a canvas. I am at the point where I have selected an image, but I am unsure of how to split the image.
I have looked at similar questions but no luck. I'm not looking for someone else to do the work, but advice on how best to do it.
private void uploadImage_Click(object sender, RoutedEventArgs e)
{
//creates (but not yet displays) a OpenFile dialog box
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
//specifies the look of the open file dialog box
dlg.DefaultExt = ".jpg";
dlg.Filter = "Image Files|*.jpg;";
dlg.InitialDirectory = Environment.CurrentDirectory;
//shows the open file dialog box to user and awaits OK or Cancel
bool? result = dlg.ShowDialog();
//result is true if user selects an image file
if (result == true)
{
filename = dlg.FileName;
var uri = new Uri(filename);
var bitmap = new BitmapImage(uri);
Image bg = new Image();
bg.Source = new BitmapImage(uri);
}
else
return;
}
I have already answered similiar question. Either use my solution, or resort to CroppedBitmap.
How to crop image and save into ImageSource in WPF?