Files
PdfPig/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/GenerateLetterBoundingBoxImages.cs
BobLd 255e70f0a7
Some checks failed
Build, test and publish draft / build (push) Has been cancelled
Build and test [MacOS] / build (push) Has been cancelled
Run Common Crawl Tests / build (0000-0001) (push) Has been cancelled
Run Common Crawl Tests / build (0002-0003) (push) Has been cancelled
Run Common Crawl Tests / build (0004-0005) (push) Has been cancelled
Run Common Crawl Tests / build (0006-0007) (push) Has been cancelled
Run Integration Tests / build (push) Has been cancelled
Nightly Release / Check if this commit has already been published (push) Has been cancelled
Nightly Release / tests (push) Has been cancelled
Nightly Release / build_and_publish_nightly (push) Has been cancelled
Set Type 3 font ascent to Top instead of Height, see #1164
2025-10-14 12:18:52 +01:00

264 lines
8.5 KiB
C#

namespace UglyToad.PdfPig.Tests.Integration.VisualVerification
{
using PdfPig.Core;
using SkiaSharp;
public class GenerateLetterBoundingBoxImages
{
private const string ByzantineGenerals = "byz";
private const string NonLatinAcrobatDistiller = "Single Page Non Latin - from acrobat distiller";
private const string SingleGoogleDrivePage = "Single Page Simple - from google drive";
private const string SinglePageFormattedType0Content = "Type0 Font";
private const string SinglePageType1Content = "ICML03-081";
private const string SingleInkscapePage = "Single Page Simple - from inkscape";
private const string MotorInsuranceClaim = "Motor Insurance claim form";
private const string PigProduction = "Pig Production Handbook";
private const string SinglePage90ClockwiseRotation = "SinglePage90ClockwiseRotation - from PdfPig";
private const string SinglePage180ClockwiseRotation = "SinglePage180ClockwiseRotation - from PdfPig";
private const string SinglePage270ClockwiseRotation = "SinglePage270ClockwiseRotation - from PdfPig";
private const string SPARCv9ArchitectureManual = "SPARC - v9 Architecture Manual";
private const string CroppedAndRotatedFile = "cropped-and-rotated";
private const string MOZILLA_10372_2File = "MOZILLA-10372-2";
private const string Type3FontZeroHeight = "type3-font-zero-height";
private const string OutputPath = "Images";
private static readonly SKPaint violetPen = new SKPaint() { Color = SKColors.BlueViolet, StrokeWidth = 1 };
private static readonly SKPaint redPen = new SKPaint() { Color = SKColors.Crimson, StrokeWidth = 1 };
private static readonly SKPaint bluePen = new SKPaint() { Color = SKColors.GreenYellow, StrokeWidth = 1 };
private static string GetFilename(string name)
{
var documentFolder = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "Integration", "Documents"));
if (!name.EndsWith(".pdf"))
{
name += ".pdf";
}
return Path.Combine(documentFolder, name);
}
[Fact]
public void SinglePageWithType1Content()
{
Run(SinglePageType1Content);
}
[Fact]
public void SinglePageSimpleFromInkscape()
{
Run(SingleInkscapePage, 841);
}
[Fact]
public void SinglePageNonLatinFromAcrobatDistiller()
{
Run(NonLatinAcrobatDistiller);
}
[Fact]
public void SinglePageSimpleFromGoogleDrive()
{
Run(SingleGoogleDrivePage);
}
[Fact]
public void SinglePageType0Font()
{
Run(SinglePageFormattedType0Content);
}
[Fact]
public void RotatedTextLibreOffice()
{
Run("Rotated Text Libre Office", 841);
}
[Fact]
public void PigProductionCompactFontFormat()
{
Run(PigProduction, 680);
}
[Fact]
public void PopBugzilla37292()
{
Run("pop-bugzilla37292");
}
[Fact]
public void MultiPageMortalityStatistics()
{
Run("Multiple Page - from Mortality Statistics");
}
[Fact]
public void MotorInsuranceClaimForm()
{
Run(MotorInsuranceClaim, 841);
}
[Fact]
public void ByzantineGeneralsTrueTypeStandard14()
{
Run(ByzantineGenerals, 702);
}
[Fact]
public void SinglePage90ClockwiseRotationFromPdfPig()
{
Run(SinglePage90ClockwiseRotation, 595);
}
[Fact]
public void SinglePage180ClockwiseRotationFromPdfPig()
{
Run(SinglePage180ClockwiseRotation, 842);
}
[Fact]
public void SinglePage270ClockwiseRotationFromPdfPig()
{
Run(SinglePage270ClockwiseRotation, 595);
}
[Fact]
public void SPARCv9ArchitectureManualTest()
{
Run(SPARCv9ArchitectureManual);
}
[Fact]
public void CroppedAndRotatedTest()
{
Run(CroppedAndRotatedFile, 205);
}
[Fact]
public void MOZILLA_10372_2Test()
{
Run(MOZILLA_10372_2File, 1584, 7);
}
[Fact]
public void Type3FontZeroHeightTest()
{
Run(Type3FontZeroHeight, 1255);
}
[Fact]
public void test_a()
{
// Rendered glyphs are not correct, but we use the grid to assess
Run("test_a", 1584, 1);
}
private static void Run(string file, int imageHeight = 792, int pageNo = 1)
{
var pdfFileName = GetFilename(file);
using (var document = PdfDocument.Open(pdfFileName))
using (var image = GetCorrespondingImage(pdfFileName))
{
var page = document.GetPage(pageNo);
double scale = imageHeight / page.Height;
using (var bitmap = SKBitmap.FromImage(image))
using (var graphics = new SKCanvas(bitmap))
{
foreach (var word in page.GetWords())
{
DrawRectangle(word.BoundingBox, graphics, redPen, imageHeight, scale);
}
foreach (var letter in page.Letters)
{
DrawRectangle(letter.GlyphRectangle, graphics, violetPen, imageHeight, scale);
}
foreach (var annotation in page.GetAnnotations())
{
DrawRectangle(annotation.Rectangle, graphics, bluePen, imageHeight, scale);
}
graphics.Flush();
var imageName = $"{file}.jpg";
if (!Directory.Exists(OutputPath))
{
Directory.CreateDirectory(OutputPath);
}
var savePath = Path.Combine(OutputPath, imageName);
using (var fs = new FileStream(savePath, FileMode.Create))
using (SKData d = bitmap.Encode(SKEncodedImageFormat.Jpeg, 100))
{
d.SaveTo(fs);
}
}
using (var bitmap = SKBitmap.FromImage(image))
using (var graphics = new SKCanvas(bitmap))
{
foreach (var letter in page.Letters)
{
DrawRectangle(letter.GlyphRectangleLoose, graphics, violetPen, imageHeight, scale);
}
graphics.Flush();
var imageName = $"{file}_loose.jpg";
if (!Directory.Exists(OutputPath))
{
Directory.CreateDirectory(OutputPath);
}
var savePath = Path.Combine(OutputPath, imageName);
using (var fs = new FileStream(savePath, FileMode.Create))
using (SKData d = bitmap.Encode(SKEncodedImageFormat.Jpeg, 100))
{
d.SaveTo(fs);
}
}
}
}
private static void DrawRectangle(PdfRectangle rectangle, SKCanvas graphics, SKPaint pen, int imageHeight, double scale)
{
int GetY(PdfPoint p)
{
return imageHeight - (int)(p.Y * scale);
}
SKPoint GetPoint(PdfPoint p)
{
return new SKPoint((int)(p.X * scale), GetY(p));
}
graphics.DrawLine(GetPoint(rectangle.BottomLeft), GetPoint(rectangle.BottomRight), pen);
graphics.DrawLine(GetPoint(rectangle.BottomRight), GetPoint(rectangle.TopRight), pen);
graphics.DrawLine(GetPoint(rectangle.TopRight), GetPoint(rectangle.TopLeft), pen);
graphics.DrawLine(GetPoint(rectangle.TopLeft), GetPoint(rectangle.BottomLeft), pen);
}
private static SKImage GetCorrespondingImage(string filename)
{
var pdf = GetFilename(filename);
pdf = pdf.Replace(".pdf", ".jpg");
if (File.Exists(pdf))
{
return SKImage.FromEncodedData(pdf);
}
return SKImage.FromEncodedData(pdf.Replace(".jpg", ".png"));
}
}
}