MarkdownViewerPlusPlus icon indicating copy to clipboard operation
MarkdownViewerPlusPlus copied to clipboard

Local images are not shown

Open prtomasi opened this issue 4 years ago • 26 comments

Hi,

Local images are not being shown inside the plugin

In the .md file I'm reading, two images are present in the code:

![01](01.png)
![02](02.png)

Both images are in the same directory of readme.md file, no need to absolute path or subdirectories Both images are PNG with 1192 x 836 resolution

When the .md is exported to html, the images appear correctly

<img src="01.png" alt="01" />
<img src="02.png" alt="02" />

prtomasi avatar Dec 18 '20 15:12 prtomasi

use ![01](file:///01.png)

See the issues #30 and #23

cstichlberger avatar Jan 10 '21 18:01 cstichlberger

The file:/// trick isn't a good idea unless you wanna restrict yourself and your md files to MarkdownViewer++. Forget about "Export to HTML".

Tontyna avatar Nov 04 '21 15:11 Tontyna

I started using Visual Studio Code + markdownlint extension, because of this limitation.

iisti avatar Mar 09 '22 21:03 iisti

I think that the issue is because of..

InvalidOperationException This instance represents a relative URI, and this property is valid only for absolute URIs.

https://docs.microsoft.com/en-us/dotnet/api/system.uri.scheme?view=net-6.0

.. and..

InvalidOperationException This instance represents a relative URI, and this property is valid only for absolute URIs.

https://docs.microsoft.com/en-us/dotnet/api/system.uri.localpath?view=net-6.0#system-uri-localpath

I haven't tested the following diff, but it seems that it should address all issues I think..

In MarkdownViewerRenderer.cs..

//Get some file information
string src = imageLoadEvent.Src;
Uri uri = new Uri(src);
string extension = Path.GetExtension(src);

+ if(uri.IsAbsoluteUri)
+ {
-    //Check if local file or web resource
+    //Check if local file from absolute path or web resource
    switch (uri.Scheme.ToLowerInvariant())
    {
        case "file":
            //In case of a local file -> Try to load it directly
            imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
            ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(src, imageLoadEvent));
            break;
        case "http":
        case "https":
            //For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
            if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
                || uri.ToString().Contains("svg="))
            {
                //In case of a web resource file -> Load async
                using (WebClient webClient = new WebClient())
                {
                    imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
                    webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
                    webClient.DownloadDataAsync(uri);
                }
            }
            break;
    }
+}
+else
+{
+    //Local file from relative path -> Try to load it directly
+    imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
+    ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(@"file:///" + this.FileInfo.FileDirectory + "/" + src, imageLoadEvent));
+}

.. and..

/// <summary>
/// 
/// </summary>
/// <param name="src"></param>
/// <param name="imageLoadEvent"></param>
protected void LoadImageFromFile(string src, HtmlImageLoadEventArgs imageLoadEvent)
{
    try
    {
        Uri uri = new Uri(src);
        //Try to load the file as Image from file
        //Remove the scheme first
        string srcWithoutScheme = src;
        int i = srcWithoutScheme.IndexOf(':');
        if (i > 0) srcWithoutScheme = srcWithoutScheme.Substring(i + 1).TrimStart('/');
-        //If not absolute, add the current file path
-        if (!Path.IsPathRooted(srcWithoutScheme))
-        {
-            uri = new Uri(@"file:///" + this.FileInfo.FileDirectory + "/" + srcWithoutScheme);
-        }

        //For SVG images: Convert to Bitmap
        string extension = Path.GetExtension(src);
        if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
        {
            ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
        }
        else
        {
            //Load uri, 8, 1
            imageLoadEvent.Callback((Bitmap)Image.FromFile(uri.LocalPath, true));
        }
    }
    catch { } //Not able to handle, refer back to orginal process
}

Wallby avatar Mar 26 '22 19:03 Wallby

In my opinion NppMarkdownPanel is much better then MarkdownViewer++ (even javascript can be used). My comment on Github: (A Notepad++ Plugin to view a Markdown) - goto NppMarkdownPanel -> https://github.com/andrzejQ/NppMarkdownPanel

andrzejQ avatar Mar 30 '22 05:03 andrzejQ

@andrzejQ for viewing markdown, there doesn't seem to be any major difference between MarkdownViewerPlusPlus and https://github.com/mohzy83/NppMarkdownPanel. Though NppMarkdownPanel doesn't have the issue that images don't load.

Wallby avatar Mar 30 '22 13:03 Wallby

Hi, I can confirm that if I use a local image with relative path, such as:

![](image/aaa.png)

I see that the NppMarkdownPanel plugin shows the image correctly, but MarkdownViewerPlusPlus failed to show the image.

Any idea to fix this issue in this plugin? Thanks.

asmwarrior avatar Feb 22 '24 02:02 asmwarrior