public static SvgDataUri Parse(string href)
href
The href value as a string.
Object that contains the parsed values.
The Parse method takes an href value as a raw string and tries to parse the data URI uniform resource identifier (URI) members out of it. Refer to SvgDataUri for more information. Parsing is useful for extracting, setting, and converting the pixel data of an image element in an SVG document.
For example, if the image element contains an embedded pixel data as follows:
<image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA ... etc" />then Parse will return an SvgDataUri object set up as follows:
| Member | Value |
|---|---|
| IsDataUri |
true since the parsing was successful and the href contains valid data URI. |
| Href |
Same value as the source |
| MediaOffset |
5. This is the offset into the href where the media type part starts. In this particular case it is 5, since this is the start of |
| MediaLength |
9. This is the length of |
| CharSetOffset |
-1 since the source href does not contain an explicit charset value. If it did, then this will contain the index into the href where the value starts. |
| CharSetLength |
0 since the source href does not contain an explicit charset value. Otherwise, it will contain the number of characters of the value. |
| IsBase64 |
true since the source href states the encoding. |
| ValueOffset |
22. This is the offset into the href where the pixel data of the image starts. In this case 22, since this is the start of the pixel data |
| ValueLength |
The length of the pixel data in the href from ValueOffset to the end of the string. |
| ImageFormat |
RasterImageFormat.Png since the media type is |
| Extension |
|
The reason for using offsets/length pairs instead of getting the values and putting them into properties in the class is because the href can be a very lengthy string containing the pixel data of a large image and making a copy can use unnecessary memory if the user is not interested in the particular value.
To get the values to a separate string, simply use String.Substring passing SvgDataUri.Href and the offset and the length of the desired value. For example, this gets the Media type:
string mediaType = svgDataUri.Href.Substring(svgDataUri.MediaOffset, svgDataUri.MediaLength);And to get the image data, use:
string base64ImageData = svgDataUri.Href.Substring(svgDataUri.ValueOffset, svgDataUri.ValueLength);In both cases, checking if the offset is not -1 beforehand in case the object does not contain the value.
The image data is base64 encoded. To convert it to a byte array, use any standard base-64 conversion function such as Convert.FromBase64String or Convert.ToBase64String to encode the data in a byte into a base 64 encoded string.
If the SVG element does not contain a valid data URI but instead has a link to an external resource, for example <image xlink:href="image.png" /> or <image xlink:href="http://server/image.png" /> then calling Parse will succeed, but the value of IsDataUri will be false and the rest of the values of the class should not be used (will be set to their default values.
After successfully parsing (or constructing manually) an SvgDataUri object, you can save the resulting image to a disk file or stream using DecodeToStream or DecodeToFile. For example, with the previous SVG image element with the data URI, calling DecodeToFile will result in a PNG file saved to disk. The Extension property is useful for automatically setting the extension of the file as follows:
var href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA ... etc";// Parse it. If successful, save it to diskvar svgDataUri = SvgDataUri.Parse(href);if(svgDataUri.IsDataUri)svgDataUri.DecodeToFile("filename." + svgDataUri.Extension);
The EncodeFromFile and EncodeFromStream methods can create data URI values from image files. For example:
// filename.png is from the previous examplevar href = SvgDataUri.EncodeFromFile("filename.png");// Results in href = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA ... etc"// Same as the original value.
These methods can accept any image file encoded as PNG, GIF, or JPEG. These are the standard file formats used by the web (and by extension, SVG). Any other image format will fail.
using Leadtools;using Leadtools.Codecs;using Leadtools.Drawing;using Leadtools.Forms.DocumentWriters;using Leadtools.Svg;using Leadtools.Document.Writer;private static void SvgDocumentEnumerateElementsExample(){// The source PDF filevar sourceFile = $@"{LEAD_VARS.ImagesDir}\Leadtools.pdf";var beforeSvgFile = $@"{LEAD_VARS.ImagesDir}\Leadtools_before.svg";var afterSvgFile = $@"{LEAD_VARS.ImagesDir}\Leadtools_after.svg";// Assume this is our Virtual Directoryvar virtualDirectory = "http://localhost/leadtools_images/svg/resources";// Assume this phrysical directory maps to the Virtual Directoryvar physicalDirectory = $@"{LEAD_VARS.ImagesDir}\svg\resources";if (!Directory.Exists(physicalDirectory))Directory.CreateDirectory(physicalDirectory);// Our SVG element enumartion callbackSvgEnumerateElementsCallback callback = (SvgDocument document, SvgNodeHandle node, object userData) =>{if (node.ElementType == SvgElementType.Image){// Get the hrefvar href = node.GetAttributeValue("xlink:href");if (!string.IsNullOrEmpty(href)){// Parse it as data URIvar dataUri = SvgDataUri.Parse(href);// Check if it is a data URIif (dataUri.IsDataUri){// Yes, create a new file in a virtual directory// Show the dataURI propertiesConsole.WriteLine("Replacing data URI");Console.WriteLine("Format:" + dataUri.ImageFormat);if (dataUri.MediaLength > 0)Console.WriteLine("Media:" + dataUri.Href.Substring(dataUri.MediaOffset, dataUri.MediaLength));if (dataUri.CharSetOffset > 0)Console.WriteLine("CharSet:" + dataUri.Href.Substring(dataUri.CharSetOffset, dataUri.CharSetLength));elseConsole.WriteLine("CharSet: not set");Console.WriteLine("IsBase64:" + dataUri.IsBase64);Console.WriteLine("ImageFormat:" + dataUri.ImageFormat);var extension = dataUri.Extension;Console.WriteLine("Extension:" + dataUri.Extension);// Get a file namevar name = Guid.NewGuid().ToString().Replace("-", "") + "." + dataUri.Extension;// Save it// Full physical pathvar filePath = Path.Combine(physicalDirectory, name);dataUri.DecodeToFile(filePath);/* Alternatively you can save the data yourself using this codevar data = dataUri.Href.Substring(dataUri.ValueOffset, dataUri.ValueLength);// Save the datavar base64String = dataUri.Href.Substring(dataUri.ValueOffset, dataUri.ValueLength);byte[] rawData = Convert.FromBase64String(base64String);// Save it to diskFile.WriteAllBytes(filePath, rawData);*/// Finally replace the attribute in the image element with the URIvar virtualPath = virtualDirectory + "/" + name;node.SetAttributeValue("xlink:href", virtualPath);}else{Console.WriteLine("Does not contain a valid data URI.");}}}return true;};using (var rasterCodecs = new RasterCodecs()){// Use 300 DPI when loading document imagesrasterCodecs.Options.RasterizeDocument.Load.Resolution = 300;// Load the first page as SVGusing (var svg = rasterCodecs.LoadSvg(sourceFile, 1, null) as SvgDocument){if (!svg.IsFlat)svg.Flat(null);if (!svg.Bounds.IsValid)svg.CalculateBounds(false);// Save this SVG to disk, report the sizesvg.SaveToFile(beforeSvgFile, null);Console.WriteLine("Before unembedding the image, size is " + new FileInfo(beforeSvgFile).Length);// Now enumerate the elements to replace each embedded image with a URL// Since we are going to modify the SVG, call BeginUpdate/EndUpdate to speed up the processsvg.BeginUpdate();svg.EnumerateElements(new SvgEnumerateOptions { EnumerateDirection = SvgEnumerateDirection.TopToBottom }, callback, null);svg.EndUpdate();// Save this SVG to disk again, report the size, should be alot smaller since the image are unembedded and stored as external resourcessvg.SaveToFile(afterSvgFile, null);Console.WriteLine("Before unembedding the image, size is " + new FileInfo(afterSvgFile).Length);}}}static class LEAD_VARS{public const string ImagesDir = @"C:\LEADTOOLS23\Resources\Images";}