diff --git a/Aspose.Slides.WebExtensions.Tests/SLIDESNET_43224.cs b/Aspose.Slides.WebExtensions.Tests/SLIDESNET_43224.cs new file mode 100644 index 0000000..855a762 --- /dev/null +++ b/Aspose.Slides.WebExtensions.Tests/SLIDESNET_43224.cs @@ -0,0 +1,130 @@ +using Aspose.Slides.Export.Web; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Aspose.Slides.Export; +using System.Drawing; + +namespace Aspose.Slides.WebExtensions.Tests +{ + [TestClass] + public class SLIDESNET_43224 + { + [TestMethod] + public void Test_43224() + { + var RootDirectory = Path.GetFullPath("../../../"); + var PresentationFilePath = Path.Combine(RootDirectory, "TestData", "SLIDESNET_43224", "SLIDESNET-43224.pptx"); + var EthalonPath = Path.Combine(RootDirectory, "TestData", "SLIDESNET_43224", "html"); + var TemplatePath = Path.Combine(RootDirectory, "TestData", "Out", "templates"); + var OutputPath = Path.Combine(RootDirectory, "TestData", "Out", "SLIDESNET_43224"); + + var sourcePath1 = Path.GetFullPath(Path.Combine(RootDirectory, "..", "Aspose.Slides.WebExtensions", "templates", "single-page")); + var sourcePath2 = Path.GetFullPath(Path.Combine(RootDirectory, "..", "Aspose.Slides.WebExtensions", "templates", "common")); + + Directory.CreateDirectory(OutputPath); + Directory.CreateDirectory(TemplatePath); + + foreach (string dirPath in Directory.GetDirectories(sourcePath1, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(dirPath.Replace(sourcePath1, TemplatePath)); + foreach (string newPath in Directory.GetFiles(sourcePath1, "*.*", SearchOption.AllDirectories)) File.Copy(newPath, newPath.Replace(sourcePath1, TemplatePath), true); + + foreach (string dirPath in Directory.GetDirectories(sourcePath2, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(dirPath.Replace(sourcePath2, TemplatePath)); + foreach (string newPath in Directory.GetFiles(sourcePath2, "*.*", SearchOption.AllDirectories)) File.Copy(newPath, newPath.Replace(sourcePath2, TemplatePath), true); + + string testImagePath = Path.Combine(OutputPath, "images/image0red1.png"); + + using (Presentation pres = new Presentation(PresentationFilePath)) + { + WebDocument document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi72); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(608, testImage.Width); + Assert.AreEqual(342, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi96); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(811, testImage.Width); + Assert.AreEqual(456, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi96); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(811, testImage.Width); + Assert.AreEqual(456, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi150); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(1268, testImage.Width); + Assert.AreEqual(713, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi220); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(1400, testImage.Width); + Assert.AreEqual(788, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.Dpi330); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(1400, testImage.Width); + Assert.AreEqual(788, testImage.Height); + } + + document = pres.ToSinglePageWebDocument( + new WebDocumentOptions { EmbedImages = false }, + TemplatePath, + OutputPath); + document.Global.Put("picturesCompression", PicturesCompression.DocumentResolution); + document.Save(); + + using (Bitmap testImage = new Bitmap(testImagePath)) + { + Assert.AreEqual(1400, testImage.Width); + Assert.AreEqual(788, testImage.Height); + } + } + } + } +} \ No newline at end of file diff --git a/Aspose.Slides.WebExtensions.Tests/TestData/SLIDESNET_43224/SLIDESNET-43224.pptx b/Aspose.Slides.WebExtensions.Tests/TestData/SLIDESNET_43224/SLIDESNET-43224.pptx new file mode 100644 index 0000000..26c14ff Binary files /dev/null and b/Aspose.Slides.WebExtensions.Tests/TestData/SLIDESNET_43224/SLIDESNET-43224.pptx differ diff --git a/Aspose.Slides.WebExtensions/Helpers/ImageHelper.cs b/Aspose.Slides.WebExtensions/Helpers/ImageHelper.cs index a3c2078..8d6c0e1 100644 --- a/Aspose.Slides.WebExtensions/Helpers/ImageHelper.cs +++ b/Aspose.Slides.WebExtensions/Helpers/ImageHelper.cs @@ -8,11 +8,14 @@ using System.IO; using Aspose.Slides.Util; using System.Collections.Generic; +using Aspose.Slides.Export; namespace Aspose.Slides.WebExtensions.Helpers { public static class ImageHelper { + public const int DefaultDpi = 72; + public static string GetImageURL(IPPImage image, TemplateContext model) { string result = ""; @@ -275,5 +278,114 @@ public static string CreateSvgFilter(PictureFrame pictureFrame, string id) } return svgFilter; } + public static string ApplyDPI(string imgSrc, TemplateContext model, PicturesCompression dpi) + { + const string b64prefix = "data:image/png;base64, "; + int resolution = 72; + switch (dpi) + { + case PicturesCompression.Dpi330: resolution = 330; break; + case PicturesCompression.Dpi220: resolution = 220; break; + case PicturesCompression.Dpi150: resolution = 150; break; + case PicturesCompression.Dpi96: resolution = 96; break; + case PicturesCompression.Dpi72: resolution = 72; break; + default: return imgSrc; + } + return imgSrc.StartsWith(b64prefix) + ? ApplyDPIEmbed(imgSrc, model, resolution) + : ApplyDPIFile(imgSrc, model, resolution); + } + + private static string ApplyDPIFile(string imgSrc, TemplateContext model, int resolution) + { + using (Image bmpCompressed = GetImageCompressed(model, resolution)) + { + var slidesPath = model.Global.Get("slidesPath"); + string convertedFileName = GetImageURL(model.Object.PictureFormat.Picture.Image, model).Replace(".png", string.Format("red{0}.png", model.Object.UniqueId)); + string convertedFilePath = Path.Combine(slidesPath, convertedFileName); + string imagesPath = Path.GetDirectoryName(convertedFilePath); + if (!Directory.Exists(imagesPath)) Directory.CreateDirectory(imagesPath); + + bmpCompressed.Save(convertedFilePath, System.Drawing.Imaging.ImageFormat.Png); + return convertedFileName; + } + } + + private static string ApplyDPIEmbed(string imgSrc, TemplateContext model, int resolution) + { + using (Image bmpCompressed = GetImageCompressed(model, resolution)) + { + using (MemoryStream buffer = new MemoryStream()) + { + bmpCompressed.Save(buffer, System.Drawing.Imaging.ImageFormat.Png); + buffer.Position = 0; + return "data:image/png;base64, " + Convert.ToBase64String(buffer.ToArray()); + } + } + } + + private static Image GetImageCompressed(TemplateContext model, int resolution) + { + PictureFrame pictureFrame = model.Object; + RectangleF boundRect = pictureFrame.Frame.Rectangle; + Image originImage = Image.FromStream(new MemoryStream(model.Object.PictureFormat.Picture.Image.BinaryData)); + var newSize = GetCompressedSize(originImage.Size, resolution, boundRect.Size, boundRect); + return CompressImage(originImage, newSize, originImage.PixelFormat, new RectangleF(0, 0, originImage.Width, originImage.Height)); + } + + + public static SizeF GetCompressedSize(SizeF sourceImageSize, int dpi, SizeF bounds, RectangleF rect) + { + SizeF compressedSize; + + if (dpi == DefaultDpi) + { + compressedSize = new SizeF(rect.Width, rect.Height); + } + else if (dpi == 0) + { + compressedSize = sourceImageSize; + } + else + { + compressedSize = CompressSize(dpi, bounds); + } + + if (sourceImageSize.Width <= compressedSize.Width && sourceImageSize.Height <= compressedSize.Height) + { + compressedSize = sourceImageSize; // there're no sense to increase image according to DPI if source image DPI less than a target. + } + + return compressedSize; + } + + private static SizeF CompressSize(int dpi, SizeF size) + { + if (dpi < 0) + { + throw new ArgumentException("dpi"); + } + + if (dpi == 0 || dpi == DefaultDpi) + { + return size; + } + + float coeff = (float)dpi / 72f; + + return new SizeF(size.Width * coeff, size.Height * coeff); + } + + public static Image CompressImage(Image sourceImage, SizeF compressedSize, PixelFormat pixelFormat, RectangleF originalSourceRect) + { + Image tempImage = new Bitmap((int)compressedSize.Width, (int)compressedSize.Height, pixelFormat); + using (Graphics g = Graphics.FromImage(tempImage)) + { + RectangleF destRect = new RectangleF(0, 0, (int)compressedSize.Width, (int)compressedSize.Height); + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.DrawImage(sourceImage, destRect, originalSourceRect, GraphicsUnit.Pixel); + } + return tempImage; + } } } \ No newline at end of file diff --git a/Aspose.Slides.WebExtensions/RazorEngineService.cs b/Aspose.Slides.WebExtensions/RazorEngineService.cs index ce32fbf..a9b9f61 100644 --- a/Aspose.Slides.WebExtensions/RazorEngineService.cs +++ b/Aspose.Slides.WebExtensions/RazorEngineService.cs @@ -35,6 +35,7 @@ IRazorEngineCompiledTemplate GetCompiledOrCashed(string content) builder.AddUsing("System.Collections"); builder.AddUsing("System.Collections.Generic"); builder.AddUsing("Aspose.Slides"); + builder.AddUsing("Aspose.Slides.Export"); builder.AddUsing("Aspose.Slides.Export.Web"); builder.AddUsing("Aspose.Slides.WebExtensions.Helpers"); diff --git a/Aspose.Slides.WebExtensions/Templates/common/pictureFrame.html b/Aspose.Slides.WebExtensions/Templates/common/pictureFrame.html index 4a72867..d01e07c 100644 --- a/Aspose.Slides.WebExtensions/Templates/common/pictureFrame.html +++ b/Aspose.Slides.WebExtensions/Templates/common/pictureFrame.html @@ -4,6 +4,9 @@ PictureFrame contextObject = Model.Object; var origin = Model.Local.Get("origin"); + var picturesCompression = Model.Global.ContainsKey("picturesCompression") + ? Model.Global.Get("picturesCompression") + : PicturesCompression.DocumentResolution; string imgSrc = ImageHelper.GetImageURL(contextObject.PictureFormat.Picture.Image, Model); @@ -41,6 +44,7 @@ string svgFilter = ImageHelper.CreateSvgFilter(contextObject, id + "-effect"); string filterStyle = string.IsNullOrEmpty(svgFilter) ? "" : "filter: url(#" + id + "-effect)"; string shadowStyle = ImageHelper.GetImageShadowStyle(contextObject); + imgSrc = ImageHelper.ApplyDPI(imgSrc, Model as TemplateContext, picturesCompression); } @functions {