Getting the original Picture back out of a Visio shape

Started by Visisthebest, August 23, 2023, 05:31:33 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Visisthebest

I often use PNG's that I Page.Import in to a Visio Page.

Now however for rebuilding a diagram, I need to read the PNG's from the shapes. It does not matter if they have been reduced in quality, I know this can happen in Visio.

I can only find a function for getting pictures out of a shape as an EMF:
https://learn.microsoft.com/en-us/office/vba/api/visio.shape.picture

Is there a straightforward way to get a PNG back out of a Shape (as a .BMP is fine as well).

I could maybe Shape.Copy from the source document the Shape with the picture and then Page.Paste the shape with the picture in to the destination document but I would rather recreate the shape if that is possible. (also I worry that if I copy-paste tens of shapes across the clipboard a user action on the clipboard might cause issues.

(If I do Shape.Export I get a lot more than just the picture from the shape)
Visio 2021 Professional

Nikolay

The Chat GPT is getting proficient in Visio, nothing to add from my side  :D
All three methods should work fine, IMHO.

Quote
If you have inserted a picture into a Microsoft Visio shape and you wish to extract or save that picture as an individual file, there's no direct "export picture" function. However, there are workarounds to achieve this. Here are a few methods:

1. Using Screen Capture:
This method is quick but may compromise the image quality.

Zoom In: To maximize quality, zoom in on the Visio diagram so the picture is as large as possible on your screen without losing any part of it.
Screen Capture:
Windows: Use the Snipping Tool or Snip & Sketch. You can also use the shortcut Windows + Shift + S to capture a part of the screen directly.
Mac: Use Cmd + Shift + 4 to capture a portion of the screen.
Save: After capturing, save the screenshot as an image file.

2. Using a Graphic Editor:
This method requires a graphic editing program, like Adobe Photoshop, GIMP, or similar.

Copy the Picture:
Select the shape in Visio.
Right-click and choose 'Copy'.
Paste in Graphic Editor: Open your graphic editor and paste the clipboard contents.
Edit and Save: Crop if necessary and save as your desired file format.

3. Extract from VSDX:
If your Visio file is in the newer .vsdx format, it's essentially a zipped collection of files, and images can be extracted directly.

Rename File: Change the extension of your .vsdx file to .zip.
Extract: Unzip the file (you can use software like WinRAR, 7-Zip, etc.).
Search for Images: Navigate through the extracted folders. Typically, images are stored under a folder named media. You'll find your image there.
Remember to rename the file back to .vsdx if you want to continue editing it in Visio.

Unfortunately, I don't know a way to do it programmatically.

Yacine

If you select one or many shapes and export the drawing, Visio will export only the selected shapes.

Here's what the macro recorder says:

Sub Macro1()

  'Enable diagram services
  Dim DiagramServices As Integer
  DiagramServices = ActiveDocument.DiagramServicesEnabled
  ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150

  Application.Settings.SetRasterExportResolution visRasterUseScreenResolution, 96#, 96#, visRasterPixelsPerInch
  Application.Settings.SetRasterExportSize visRasterFitToSourceSize, 11.354167, 11.34375, visRasterInch
  Application.Settings.RasterExportDataFormat = visRasterInterlace
  Application.Settings.RasterExportColorFormat = visRaster24Bit
  Application.Settings.RasterExportRotation = visRasterNoRotation
  Application.Settings.RasterExportFlip = visRasterNoFlip
  Application.Settings.RasterExportBackgroundColor = 16777215
  Application.Settings.RasterExportTransparencyColor = 16777215
  Application.Settings.RasterExportUseTransparencyColor = False
  ActiveWindow.DeselectAll
ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(12816), visSelect
  Application.ActiveWindow.Selection.Export "C:\temp\test.png"

  'Restore diagram services
  ActiveDocument.DiagramServicesEnabled = DiagramServices

End Sub

The adjustments to do:
- Adjust the size arguments to the actual size of your shape.
- Find out a naming rule (Inputbox or based on shape's name, or timed, ...)

Rgds,
Y.
Yacine

Visisthebest

Thank you Nikolay and Yacine, unfortunately there is no really straightforward way to just get the picture out of Visio again (I don't mind it has been compressed, but the quality should not degrade further).

Another option is when the picture is put in to the diagram, is to keep a copy of the original picture in a subfolder next to a Visio file. Not a very elegant solution, but fortunately there a several options to get the pictures out.
Visio 2021 Professional

Yacine

Would reformulate your last post. I did not get your point.
Yacine

Visisthebest

Yes sorry could be read in more ways than one.

What  I mean is that before the PNG picture is put in to a shape the first time, I also copy the original PNG file in to a subdirectory next to the Visio file, and I keep a reference to this file in the shape in a User cell.

Then if I need to get the original PNG again, I just retrieve the original file. Not an elegant solution but it is an option.

Your solution works well Yacine I used this option earlier but I see that there is another change to the quality of the BMP/PNG after the export (on top of what Visio may have done in terms of compression).

It certainly is a good option, but if users copy a picture like this several times the quality keeps degrading (from what I see when doing this).
Visio 2021 Professional

Nikolay

Maybe you could use the #3 suggested by GPT. It does make sense IMHO.
Theoretically, you can grab the images programmatically directly from the ".vsdx" file. They are all there in their "original" form in the "media" folder inside of the ".vsdx" file.
Here is some C# to extract them (again, thanks to GPT). Using the standard OpenXml package, DocumentFormat.OpenXml

using System;
using System.IO;
using System.IO.Packaging;

        public static byte[] ReadAllBytesFromStream(Stream stream)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                stream.CopyTo(ms);
                return ms.ToArray();
            }
        }

        public static void ExtractMediaFromVisio(string vsdxFilePath, string destinationFolder)
        {
            using (Package visioPackage = Package.Open(vsdxFilePath, FileMode.Open, FileAccess.Read))
            {
                foreach (PackagePart part in visioPackage.GetParts())
                {
                    if (part.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
                    {
                        var uri = part.Uri;
                        var fileName = Path.GetFileName(uri.ToString());
                        var fileBytes = ReadAllBytesFromStream(part.GetStream());

                        // Save the image to the destination directory
                        File.WriteAllBytes(Path.Combine(destinationFolder, fileName), fileBytes);
                    }
                }
            }
        }

Visisthebest

Yes I overlooked that option Nikolay thank you for the sample code will try this.

Is it possible to read the XML from the source file while the file is open in Visio or do I need to close it then read the XML with the destination file open? (where I import the PNG file in to)
Visio 2021 Professional

Nikolay

It should be possible to read file that is already opened by Visio. But you would need to change the code above like this:

            // open file that is already opened by Visio
            var stream = File.Open(vsdxFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            using (Package visioPackage = Package.Open(stream))

Visisthebest

Super Nikolay that is much more convenient for the end user!
Visio 2021 Professional

Nikolay

That should be doable with VBA as well, but that would be at a totally different level  ;D

wapperdude

#11
Quote from: Visisthebest on August 23, 2023, 05:31:33 PM
I often use PNG's that I Page.Import in to a Visio Page.
Now however for rebuilding a diagram, I need to read the PNG's from the shapes.

I know this is late in the game, but I'm confused.  Are the pictures inserted onto the page, or are they embedded into a shape?  If the latter, other than grouping, how does a pic become intrinsically embedded within a shape?   If the former, is the issue that it is the entire page that gets exported which may include additional shapes and not just the picture itself?

At risk of repeating what may have been said:  from a page, with or without other shapes present, it is possible to export just the picture via the Visio Export menu.  From that menu it is possible to change and select from a variety of picture formats.  The method simply requires selecting the picture prior to exporting process.

If the pix is part of a grouped shape, the Export process still works provided the pic is selected.
Visio 2019 Pro

wapperdude

Quote from: Visisthebest on August 24, 2023, 09:07:09 AM
Thank you Nikolay and Yacine, unfortunately there is no really straightforward way to just get the picture out of Visio again (I don't mind it has been compressed, but the quality should not degrade further).

Not to flog a dead horse, to add to my immediate post above, which was sans programming, then I'm not understanding why Yacine's method isn't considered direct???  That's about as direct as it gets.  I'm sure the code might be embellished to allow the user to (1) choose the file format, and (2) set the directory.  Certainly the latter could quite simply be the Visio working directory.

I feel like maybe I'm missing something.  I even tried the macro recorder and merely replicated Yacine's results with changes to resolution and sizing.
Visio 2019 Pro

Nikolay

#13
The Yacine's method just does not get the initial picture (the one that has been inserted).
Image, you repeat the procedure - you insert an image, export it, then insert the exported again, then export it again, etc.
You may end up with a broken image eventually, since even small differences will be piling up.

wapperdude

Quote from: Nikolay on August 24, 2023, 07:37:51 PM
The Yacine's method just does not get the initial picture (the one that has been inserted).

Agreed.  The XML method you presented would grab the original.  The complaint would be it's not direct/straight forward.  The Yacine process is digital, not screen capture, so would not expect much progressive degradation.  What it lacks is the interactive Export menu features wrt size, resolution.  I imagine the XML method has similar shortcomings, as would the use of an original picture repository.



Visio 2019 Pro