ImageTests.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using FluentAssertions;
  5. using NUnit.Framework;
  6. using QuestPDF.Drawing;
  7. using QuestPDF.Drawing.Exceptions;
  8. using QuestPDF.Elements;
  9. using QuestPDF.Fluent;
  10. using QuestPDF.Helpers;
  11. using QuestPDF.Infrastructure;
  12. using QuestPDF.UnitTests.TestEngine;
  13. using ImageElement = QuestPDF.Elements.Image;
  14. using DocumentImage = QuestPDF.Infrastructure.Image;
  15. namespace QuestPDF.UnitTests
  16. {
  17. [TestFixture]
  18. public class ImageTests
  19. {
  20. [Test]
  21. public void Measure_TakesMinimalSpaceRegardlessOfSize()
  22. {
  23. TestPlan
  24. .For(x => new ImageElement
  25. {
  26. DocumentImage = GenerateDocumentImage(400, 300)
  27. })
  28. .MeasureElement(new Size(300, 200))
  29. .CheckMeasureResult(SpacePlan.FullRender(0, 0));
  30. }
  31. [Test]
  32. public void Draw_TakesAvailableSpaceRegardlessOfSize()
  33. {
  34. TestPlan
  35. .For(x => new ImageElement
  36. {
  37. CompressionQuality = ImageCompressionQuality.High,
  38. TargetDpi = DocumentSettings.DefaultRasterDpi,
  39. DocumentImage = GenerateDocumentImage(400, 300)
  40. })
  41. .DrawElement(new Size(300, 200))
  42. .ExpectCanvasDrawImage(new Position(0, 0), new Size(300, 200))
  43. .CheckDrawResult();
  44. }
  45. [Test]
  46. public void Fluent_RecognizesImageProportions()
  47. {
  48. var image = GenerateDocumentImage(600, 200);
  49. TestPlan
  50. .For(x =>
  51. {
  52. var container = new Container();
  53. container.Image(image);
  54. return container;
  55. })
  56. .MeasureElement(new Size(300, 200))
  57. .CheckMeasureResult(SpacePlan.FullRender(300, 100));;
  58. }
  59. [Test]
  60. public void ImageObject_ThrowsEncodingException_WhenImageDataIsIncorrect()
  61. {
  62. Func<Infrastructure.Image> action = () => Infrastructure.Image.FromBinaryData(new byte[] { 1, 2, 3 });
  63. action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot decode the provided image.");
  64. }
  65. [Test]
  66. public void ImageObject_ThrowsEncodingException_WhenStreamIsIncorrect()
  67. {
  68. Func<Infrastructure.Image> action = () =>
  69. {
  70. using var stream = new MemoryStream(new byte[] { 1, 2, 3 });
  71. return Infrastructure.Image.FromStream(stream);
  72. };
  73. action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot decode the provided image.");
  74. }
  75. [Test]
  76. public void ImageObject_ThrowsFileNotFoundException_FileIsNotFound()
  77. {
  78. Func<Infrastructure.Image> action = () => Infrastructure.Image.FromFile("non-existing-file.jpg");
  79. action.Should().ThrowExactly<DocumentComposeException>().WithMessage("Cannot load provided image, file not found: *");
  80. }
  81. [Test]
  82. public void UsingSharedImageShouldNotDrasticallyIncreaseDocumentSize()
  83. {
  84. var photo = File.ReadAllBytes("Resources/photo.jpg");
  85. var documentWithSingleImageSize = GetDocumentSize(container =>
  86. {
  87. container.Image(photo);
  88. });
  89. var documentWithMultipleImagesSize = GetDocumentSize(container =>
  90. {
  91. container.Column(column =>
  92. {
  93. foreach (var i in Enumerable.Range(0, 10))
  94. column.Item().Image(photo);
  95. });
  96. });
  97. var documentWithSingleImageUsedMultipleTimesSize = GetDocumentSize(container =>
  98. {
  99. container.Column(column =>
  100. {
  101. var sharedImage = DocumentImage.FromBinaryData(photo);
  102. foreach (var i in Enumerable.Range(0, 10))
  103. column.Item().Image(sharedImage);
  104. });
  105. });
  106. (documentWithMultipleImagesSize / (float)documentWithSingleImageSize).Should().BeInRange(9.9f, 10);
  107. (documentWithSingleImageUsedMultipleTimesSize / (float)documentWithSingleImageSize).Should().BeInRange(1f, 1.05f);
  108. }
  109. [Test]
  110. public void ImageCompressionHasImpactOnDocumentSize()
  111. {
  112. var photo = File.ReadAllBytes("Resources/photo.jpg");
  113. var veryLowCompressionSize = GetDocumentSize(container => container.Image(photo).WithCompressionQuality(ImageCompressionQuality.VeryLow));
  114. var bestCompressionSize = GetDocumentSize(container => container.Image(photo).WithCompressionQuality(ImageCompressionQuality.Best));
  115. (bestCompressionSize / (float)veryLowCompressionSize).Should().BeGreaterThan(10);
  116. }
  117. [Test]
  118. public void TargetDpiHasImpactOnDocumentSize()
  119. {
  120. var photo = File.ReadAllBytes("Resources/photo.jpg");
  121. var lowDpiSize = GetDocumentSize(container => container.Image(photo).WithRasterDpi(12));
  122. var highDpiSize = GetDocumentSize(container => container.Image(photo).WithRasterDpi(144));
  123. (highDpiSize / (float)lowDpiSize).Should().BeGreaterThan(40);
  124. }
  125. private static int GetDocumentSize(Action<IContainer> container)
  126. {
  127. return Document
  128. .Create(document =>
  129. {
  130. document.Page(page =>
  131. {
  132. page.Content().Element(container);
  133. });
  134. })
  135. .GeneratePdf()
  136. .Length;
  137. }
  138. static DocumentImage GenerateDocumentImage(int width, int height)
  139. {
  140. var image = Placeholders.Image(width, height);
  141. return DocumentImage.FromBinaryData(image);
  142. }
  143. }
  144. }