/// <summary> /// Discover the metadata of the image. /// </summary> public static bool Provision(HtmlImageInfo imageInfo, Uri imageUrl) { if (imageInfo?.RawData == null) { return(false); } if (!imageInfo.Type.HasValue) { imageInfo.Type = GetImagePartTypeForImageUrl(imageUrl); } if (!imageInfo.Type.HasValue) { return(false); } if (imageInfo.Size.Width == 0 || imageInfo.Size.Height == 0) { using (Stream outputStream = new MemoryStream(imageInfo.RawData)) imageInfo.Size = GetImageSize(outputStream); } return(true); }
/// <summary> /// Download the image and try to find its format type. /// </summary> private HtmlImageInfo DownloadRemoteImage(string src) { Uri imageUri = new Uri(src, UriKind.RelativeOrAbsolute); Resource response; try { response = resourceLoader.FetchAsync(imageUri, CancellationToken.None).Result; if (response?.Content == null) { return(null); } } catch (Exception exc) { if (Logging.On) { Logging.PrintError(String.Format("Error fetching image from url: {0}", src), exc); } return(null); } HtmlImageInfo info = new HtmlImageInfo() { Source = src }; ImagePartType type; using (response) { // For requested url with no filename, we need to read the media mime type if provided response.Headers.TryGetValue("Content-Type", out string mime); if (!TryInspectMimeType(mime, out type) && !TryGuessTypeFromUri(imageUri, out type) && !TryGuessTypeFromStream(response.Content, out type)) { return(null); } var ipart = mainPart.AddImagePart(type); using (var outputStream = ipart.GetStream(FileMode.Create)) { response.Content.CopyTo(outputStream); outputStream.Seek(0L, SeekOrigin.Begin); info.Size = GetImageSize(outputStream); } info.ImagePartId = mainPart.GetIdOfPart(ipart); return(info); } }
private Drawing AddImagePart(Uri imageUrl, String imageSource, String alt, Size preferredSize) { if (imageObjId == UInt32.MinValue) { // In order to add images in the document, we need to asisgn an unique id // to each Drawing object. So we'll loop through all of the existing <wp:docPr> elements // to find the largest Id, then increment it for each new image. drawingObjId = 1; // 1 is the minimum ID set by MS Office. imageObjId = 1; foreach (var d in mainPart.Document.Body.Descendants <Drawing>()) { if (d.Inline == null) { continue; // fix some rare issue where Inline is null (reported by scwebgroup) } if (d.Inline.DocProperties.Id > drawingObjId) { drawingObjId = d.Inline.DocProperties.Id; } var nvPr = d.Inline.Graphic.GraphicData.GetFirstChild <pic.NonVisualPictureProperties>(); if (nvPr != null && nvPr.NonVisualDrawingProperties.Id > imageObjId) { imageObjId = nvPr.NonVisualDrawingProperties.Id; } } if (drawingObjId > 1) { drawingObjId++; } if (imageObjId > 1) { imageObjId++; } } // Cache all the ImagePart processed to avoid downloading the same image. CachedImagePart imagePart = null; // if imageUrl is null, we may consider imageSource is a DataUri. // thus, no need to download and cache anything if (imageUrl == null || !knownImageParts.TryGetValue(imageUrl, out imagePart)) { HtmlImageInfo iinfo = null; ImageProvisioningProvider provider = new ImageProvisioningProvider(this.WebProxy, preferredSize); if (imageUrl == null) { iinfo = provider.DownloadData(DataUri.Parse(imageSource)); } else if (this.ImageProcessing == ImageProcessing.ManualProvisioning) { // as HtmlImageInfo is a class, the EventArgs will act as a proxy iinfo = new HtmlImageInfo() { Size = preferredSize }; ProvisionImageEventArgs args = new ProvisionImageEventArgs(imageUrl, iinfo); OnProvisionImage(args); // did the user want to ignore this image? if (args.Cancel) { return(null); } } // Automatic Processing or the user did not supply himself the image and did not cancel the provisioning. // We download ourself the image. if (iinfo == null || (iinfo.RawData == null && imageUrl.IsAbsoluteUri)) { iinfo = provider.DownloadData(imageUrl); } if (!ImageProvisioningProvider.Provision(iinfo, imageUrl)) { return(null); } ImagePart ipart = mainPart.AddImagePart(iinfo.Type.Value); imagePart = new CachedImagePart() { Part = ipart }; imagePart.Width = iinfo.Size.Width; imagePart.Height = iinfo.Size.Height; using (Stream outputStream = ipart.GetStream(FileMode.Create)) { outputStream.Write(iinfo.RawData, 0, iinfo.RawData.Length); outputStream.Seek(0L, SeekOrigin.Begin); } if (imageUrl != null) // don't need to cache inlined-image { knownImageParts.Add(imageUrl, imagePart); } } if (preferredSize.IsEmpty) { preferredSize.Width = imagePart.Width; preferredSize.Height = imagePart.Height; } else if (preferredSize.Width <= 0 || preferredSize.Height <= 0) { Size actualSize = new Size(imagePart.Width, imagePart.Height); preferredSize = ImageHeader.KeepAspectRatio(actualSize, preferredSize); } String imagePartId = mainPart.GetIdOfPart(imagePart.Part); long widthInEmus = new Unit(UnitMetric.Pixel, preferredSize.Width).ValueInEmus; long heightInEmus = new Unit(UnitMetric.Pixel, preferredSize.Height).ValueInEmus; ++drawingObjId; ++imageObjId; var img = new Drawing( new wp.Inline( new wp.Extent() { Cx = widthInEmus, Cy = heightInEmus }, new wp.EffectExtent() { LeftEdge = 19050L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new wp.DocProperties() { Id = drawingObjId, Name = imageSource, Description = String.Empty }, new wp.NonVisualGraphicFrameDrawingProperties { GraphicFrameLocks = new a.GraphicFrameLocks() { NoChangeAspect = true } }, new a.Graphic( new a.GraphicData( new pic.Picture( new pic.NonVisualPictureProperties { NonVisualDrawingProperties = new pic.NonVisualDrawingProperties() { Id = imageObjId, Name = imageSource, Description = alt }, NonVisualPictureDrawingProperties = new pic.NonVisualPictureDrawingProperties( new a.PictureLocks() { NoChangeAspect = true, NoChangeArrowheads = true }) }, new pic.BlipFill( new a.Blip() { Embed = imagePartId }, new a.SourceRectangle(), new a.Stretch( new a.FillRectangle())), new pic.ShapeProperties( new a.Transform2D( new a.Offset() { X = 0L, Y = 0L }, new a.Extents() { Cx = widthInEmus, Cy = heightInEmus }), new a.PresetGeometry( new a.AdjustValueList() ) { Preset = a.ShapeTypeValues.Rectangle } ) { BlackWhiteMode = a.BlackWhiteModeValues.Auto }) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) ) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U } ); return(img); }
internal ProvisionImageEventArgs(Uri uri, HtmlImageInfo info) { this.ImageUrl = uri; this.info = info; }