Move page rendering code to PdfPageRenderer.
This commit is contained in:
@@ -98,7 +98,7 @@ namespace VAR.PdfTools.Workbench
|
|||||||
{
|
{
|
||||||
var fontNames = textElement.Childs.Select(c => c.Font == null ? "#NULL#" : c.Font.Name);
|
var fontNames = textElement.Childs.Select(c => c.Font == null ? "#NULL#" : c.Font.Name);
|
||||||
StringBuilder sbFontName = new StringBuilder();
|
StringBuilder sbFontName = new StringBuilder();
|
||||||
foreach(string fontNameAux in fontNames)
|
foreach (string fontNameAux in fontNames)
|
||||||
{
|
{
|
||||||
if (sbFontName.Length > 0) { sbFontName.Append(";"); }
|
if (sbFontName.Length > 0) { sbFontName.Append(";"); }
|
||||||
sbFontName.Append(fontNameAux);
|
sbFontName.Append(fontNameAux);
|
||||||
@@ -248,7 +248,7 @@ namespace VAR.PdfTools.Workbench
|
|||||||
}
|
}
|
||||||
txtOutput.Lines = columnData.ToArray();
|
txtOutput.Lines = columnData.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnRender_Click(object sender, EventArgs e)
|
private void btnRender_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (File.Exists(txtPdfPath.Text) == false)
|
if (File.Exists(txtPdfPath.Text) == false)
|
||||||
@@ -257,8 +257,6 @@ namespace VAR.PdfTools.Workbench
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MaxSize = 10000;
|
|
||||||
|
|
||||||
PdfDocument doc = PdfDocument.Load(txtPdfPath.Text);
|
PdfDocument doc = PdfDocument.Load(txtPdfPath.Text);
|
||||||
string baseDocumentPath = Path.GetDirectoryName(txtPdfPath.Text);
|
string baseDocumentPath = Path.GetDirectoryName(txtPdfPath.Text);
|
||||||
string baseDocumentFilename = Path.GetFileNameWithoutExtension(txtPdfPath.Text);
|
string baseDocumentFilename = Path.GetFileNameWithoutExtension(txtPdfPath.Text);
|
||||||
@@ -270,136 +268,18 @@ namespace VAR.PdfTools.Workbench
|
|||||||
int pageNumber = 1;
|
int pageNumber = 1;
|
||||||
foreach (PdfDocumentPage page in doc.Pages)
|
foreach (PdfDocumentPage page in doc.Pages)
|
||||||
{
|
{
|
||||||
double pageXMin = double.MaxValue;
|
PdfPageRenderer pdfPageRenderer = new PdfPageRenderer(page);
|
||||||
double pageYMin = double.MaxValue;
|
Bitmap bmp = pdfPageRenderer.Render();
|
||||||
double pageXMax = double.MinValue;
|
|
||||||
double pageYMax = double.MinValue;
|
|
||||||
|
|
||||||
// Preprocess page to get max size
|
lines.Add(string.Format("Page {0:0000} TextElements : {1}", pageNumber, pdfPageRenderer.Extractor.Elements.Count));
|
||||||
PdfTextExtractor extractor = new PdfTextExtractor(page);
|
|
||||||
foreach (PdfTextElement textElement in extractor.Elements)
|
|
||||||
{
|
|
||||||
double textElementXMin = textElement.GetX();
|
|
||||||
double textElementYMax = textElement.GetY();
|
|
||||||
double textElementXMax = textElementXMin + textElement.VisibleWidth;
|
|
||||||
double textElementYMin = textElementYMax - textElement.VisibleHeight;
|
|
||||||
|
|
||||||
if (textElementXMax > pageXMax) { pageXMax = textElementXMax; }
|
// Save image to disk
|
||||||
if (textElementYMax > pageYMax) { pageYMax = textElementYMax; }
|
string fileName = Path.Combine(baseDocumentPath, string.Format("{0}_{1:0000}.png", baseDocumentFilename, pageNumber));
|
||||||
if (textElementXMin < pageXMin) { pageXMin = textElementXMin; }
|
bmp.Save(fileName, ImageFormat.Png);
|
||||||
if (textElementYMin < pageYMin) { pageYMin = textElementYMin; }
|
|
||||||
}
|
|
||||||
lines.Add(string.Format("Page {0:0000} TextElements : {1}", pageNumber, extractor.Elements.Count));
|
|
||||||
|
|
||||||
// Prepare page image
|
|
||||||
int pageWidth = (int)Math.Ceiling(pageXMax - pageXMin);
|
|
||||||
int pageHeight = (int)Math.Ceiling(pageYMax - pageYMin);
|
|
||||||
int Scale = 10;
|
|
||||||
while ((pageWidth * Scale) > MaxSize) { Scale--; }
|
|
||||||
while ((pageHeight * Scale) > MaxSize) { Scale--; }
|
|
||||||
if (Scale <= 0) { Scale = 1; }
|
|
||||||
using (Bitmap bmp = new Bitmap(pageWidth * Scale, pageHeight * Scale, PixelFormat.Format32bppArgb))
|
|
||||||
using (Graphics gc = Graphics.FromImage(bmp))
|
|
||||||
using (Pen penTextElem = new Pen(Color.Blue))
|
|
||||||
{
|
|
||||||
gc.Clear(Color.White);
|
|
||||||
|
|
||||||
// Draw text elements
|
|
||||||
foreach (PdfTextElement textElement in extractor.Elements)
|
|
||||||
{
|
|
||||||
DrawTextElement(textElement, gc, penTextElem, Scale, pageHeight, pageXMin, pageYMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save image to disk
|
|
||||||
string fileName = Path.Combine(baseDocumentPath, string.Format("{0}_{1:0000}.png", baseDocumentFilename, pageNumber));
|
|
||||||
bmp.Save(fileName, ImageFormat.Png);
|
|
||||||
}
|
|
||||||
pageNumber++;
|
pageNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
txtOutput.Lines = lines.ToArray();
|
txtOutput.Lines = lines.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawTextElement(PdfTextElement textElement, Graphics gc, Pen penTextElem, int Scale, int pageHeight, double pageXMin, double pageYMin)
|
|
||||||
{
|
|
||||||
double textElementX = textElement.GetX() - pageXMin;
|
|
||||||
double textElementY = textElement.GetY() - pageYMin;
|
|
||||||
double textElementWidth = textElement.VisibleWidth;
|
|
||||||
double textElementHeight = textElement.VisibleHeight;
|
|
||||||
string textElementText = textElement.VisibleText;
|
|
||||||
string textElementFontName = (textElement.Font == null ? string.Empty : textElement.Font.Name);
|
|
||||||
|
|
||||||
if (textElementHeight < 0.0001) { return; }
|
|
||||||
|
|
||||||
double textElementPageX = textElementX;
|
|
||||||
double textElementPageY = pageHeight - textElementY;
|
|
||||||
|
|
||||||
DrawRoundedRectangle(gc, penTextElem,
|
|
||||||
(int)(textElementPageX * Scale),
|
|
||||||
(int)(textElementPageY * Scale),
|
|
||||||
(int)(textElementWidth * Scale),
|
|
||||||
(int)(textElementHeight * Scale),
|
|
||||||
5);
|
|
||||||
|
|
||||||
using (Font font = new Font("Arial", (int)(textElementHeight * Scale), GraphicsUnit.Pixel))
|
|
||||||
{
|
|
||||||
foreach (PdfCharElement c in textElement.Characters)
|
|
||||||
{
|
|
||||||
gc.DrawString(c.Char,
|
|
||||||
font,
|
|
||||||
Brushes.Black,
|
|
||||||
(int)((textElementPageX + c.Displacement) * Scale),
|
|
||||||
(int)(textElementPageY * Scale));
|
|
||||||
gc.FillRectangle(Brushes.Red,
|
|
||||||
(int)((textElementPageX + c.Displacement) * Scale),
|
|
||||||
(int)(textElementPageY * Scale),
|
|
||||||
2, 2);
|
|
||||||
gc.FillRectangle(Brushes.Green,
|
|
||||||
(int)((textElementPageX + c.Displacement + c.Width) * Scale),
|
|
||||||
(int)(textElementPageY * Scale),
|
|
||||||
2, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GraphicsPath RoundedRect(int x, int y, int width, int height, int radius)
|
|
||||||
{
|
|
||||||
int diameter = radius * 2;
|
|
||||||
Size size = new Size(diameter, diameter);
|
|
||||||
Rectangle arc = new Rectangle(x, y, diameter, diameter);
|
|
||||||
GraphicsPath path = new GraphicsPath();
|
|
||||||
|
|
||||||
// top left arc
|
|
||||||
path.AddArc(arc, 180, 90);
|
|
||||||
|
|
||||||
// top right arc
|
|
||||||
arc.X = (x + width) - diameter;
|
|
||||||
path.AddArc(arc, 270, 90);
|
|
||||||
|
|
||||||
// bottom right arc
|
|
||||||
arc.Y = (y + height) - diameter;
|
|
||||||
path.AddArc(arc, 0, 90);
|
|
||||||
|
|
||||||
// bottom left arc
|
|
||||||
arc.X = x;
|
|
||||||
path.AddArc(arc, 90, 90);
|
|
||||||
|
|
||||||
path.CloseFigure();
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, int x, int y, int width, int height, int cornerRadius)
|
|
||||||
{
|
|
||||||
if (graphics == null)
|
|
||||||
throw new ArgumentNullException("graphics");
|
|
||||||
if (pen == null)
|
|
||||||
throw new ArgumentNullException("pen");
|
|
||||||
|
|
||||||
using (GraphicsPath path = RoundedRect(x, y, width, height, cornerRadius))
|
|
||||||
{
|
|
||||||
graphics.DrawPath(pen, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ namespace VAR.PdfTools
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
public PdfDictionary BaseData { get { return _baseData; } }
|
public PdfDictionary BaseData { get { return _baseData; } }
|
||||||
|
|
||||||
public byte[] Content { get { return _content; } }
|
public byte[] Content { get { return _content; } }
|
||||||
|
|
||||||
public Dictionary<string, PdfFont> Fonts { get { return _fonts; } }
|
public Dictionary<string, PdfFont> Fonts { get { return _fonts; } }
|
||||||
|
|
||||||
public List<PdfContentAction> ContentActions { get { return _contentActions; } }
|
public List<PdfContentAction> ContentActions { get { return _contentActions; } }
|
||||||
@@ -69,7 +69,8 @@ namespace VAR.PdfTools
|
|||||||
{
|
{
|
||||||
PdfParser parser = new PdfParser(_content);
|
PdfParser parser = new PdfParser(_content);
|
||||||
_contentActions = parser.ParseContent();
|
_contentActions = parser.ParseContent();
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_contentActions = new List<PdfContentAction>();
|
_contentActions = new List<PdfContentAction>();
|
||||||
}
|
}
|
||||||
|
|||||||
146
VAR.PdfTools/PdfPageRenderer.cs
Normal file
146
VAR.PdfTools/PdfPageRenderer.cs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace VAR.PdfTools
|
||||||
|
{
|
||||||
|
public class PdfPageRenderer
|
||||||
|
{
|
||||||
|
private PdfDocumentPage _page;
|
||||||
|
private PdfTextExtractor _pdfTextExtractor;
|
||||||
|
|
||||||
|
private const int MaxSize = 10000;
|
||||||
|
|
||||||
|
public PdfTextExtractor Extractor { get { return _pdfTextExtractor; } }
|
||||||
|
|
||||||
|
public PdfPageRenderer(PdfDocumentPage page)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
_pdfTextExtractor = new PdfTextExtractor(_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap Render()
|
||||||
|
{
|
||||||
|
double pageXMin = double.MaxValue;
|
||||||
|
double pageYMin = double.MaxValue;
|
||||||
|
double pageXMax = double.MinValue;
|
||||||
|
double pageYMax = double.MinValue;
|
||||||
|
|
||||||
|
// Preprocess page to get max size
|
||||||
|
foreach (PdfTextElement textElement in _pdfTextExtractor.Elements)
|
||||||
|
{
|
||||||
|
double textElementXMin = textElement.GetX();
|
||||||
|
double textElementYMax = textElement.GetY();
|
||||||
|
double textElementXMax = textElementXMin + textElement.VisibleWidth;
|
||||||
|
double textElementYMin = textElementYMax - textElement.VisibleHeight;
|
||||||
|
|
||||||
|
if (textElementXMax > pageXMax) { pageXMax = textElementXMax; }
|
||||||
|
if (textElementYMax > pageYMax) { pageYMax = textElementYMax; }
|
||||||
|
if (textElementXMin < pageXMin) { pageXMin = textElementXMin; }
|
||||||
|
if (textElementYMin < pageYMin) { pageYMin = textElementYMin; }
|
||||||
|
}
|
||||||
|
// Prepare page image
|
||||||
|
int pageWidth = (int)Math.Ceiling(pageXMax - pageXMin);
|
||||||
|
int pageHeight = (int)Math.Ceiling(pageYMax - pageYMin);
|
||||||
|
int Scale = 10;
|
||||||
|
while ((pageWidth * Scale) > MaxSize) { Scale--; }
|
||||||
|
while ((pageHeight * Scale) > MaxSize) { Scale--; }
|
||||||
|
if (Scale <= 0) { Scale = 1; }
|
||||||
|
Bitmap bmp = new Bitmap(pageWidth * Scale, pageHeight * Scale, PixelFormat.Format32bppArgb);
|
||||||
|
using (Graphics gc = Graphics.FromImage(bmp))
|
||||||
|
using (Pen penTextElem = new Pen(Color.Blue))
|
||||||
|
{
|
||||||
|
gc.Clear(Color.White);
|
||||||
|
|
||||||
|
// Draw text elements
|
||||||
|
foreach (PdfTextElement textElement in _pdfTextExtractor.Elements)
|
||||||
|
{
|
||||||
|
DrawTextElement(textElement, gc, penTextElem, Scale, pageHeight, pageXMin, pageYMin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawTextElement(PdfTextElement textElement, Graphics gc, Pen penTextElem, int Scale, int pageHeight, double pageXMin, double pageYMin)
|
||||||
|
{
|
||||||
|
double textElementX = textElement.GetX() - pageXMin;
|
||||||
|
double textElementY = textElement.GetY() - pageYMin;
|
||||||
|
double textElementWidth = textElement.VisibleWidth;
|
||||||
|
double textElementHeight = textElement.VisibleHeight;
|
||||||
|
string textElementText = textElement.VisibleText;
|
||||||
|
string textElementFontName = (textElement.Font == null ? string.Empty : textElement.Font.Name);
|
||||||
|
|
||||||
|
if (textElementHeight < 0.0001) { return; }
|
||||||
|
|
||||||
|
double textElementPageX = textElementX;
|
||||||
|
double textElementPageY = pageHeight - textElementY;
|
||||||
|
|
||||||
|
DrawRoundedRectangle(gc, penTextElem,
|
||||||
|
(int)(textElementPageX * Scale),
|
||||||
|
(int)(textElementPageY * Scale),
|
||||||
|
(int)(textElementWidth * Scale),
|
||||||
|
(int)(textElementHeight * Scale),
|
||||||
|
5);
|
||||||
|
|
||||||
|
using (Font font = new Font("Arial", (int)(textElementHeight * Scale), GraphicsUnit.Pixel))
|
||||||
|
{
|
||||||
|
foreach (PdfCharElement c in textElement.Characters)
|
||||||
|
{
|
||||||
|
gc.DrawString(c.Char,
|
||||||
|
font,
|
||||||
|
Brushes.Black,
|
||||||
|
(int)((textElementPageX + c.Displacement) * Scale),
|
||||||
|
(int)(textElementPageY * Scale));
|
||||||
|
gc.FillRectangle(Brushes.Red,
|
||||||
|
(int)((textElementPageX + c.Displacement) * Scale),
|
||||||
|
(int)(textElementPageY * Scale),
|
||||||
|
2, 2);
|
||||||
|
gc.FillRectangle(Brushes.Green,
|
||||||
|
(int)((textElementPageX + c.Displacement + c.Width) * Scale),
|
||||||
|
(int)(textElementPageY * Scale),
|
||||||
|
2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GraphicsPath RoundedRect(int x, int y, int width, int height, int radius)
|
||||||
|
{
|
||||||
|
int diameter = radius * 2;
|
||||||
|
Size size = new Size(diameter, diameter);
|
||||||
|
Rectangle arc = new Rectangle(x, y, diameter, diameter);
|
||||||
|
GraphicsPath path = new GraphicsPath();
|
||||||
|
|
||||||
|
// top left arc
|
||||||
|
path.AddArc(arc, 180, 90);
|
||||||
|
|
||||||
|
// top right arc
|
||||||
|
arc.X = (x + width) - diameter;
|
||||||
|
path.AddArc(arc, 270, 90);
|
||||||
|
|
||||||
|
// bottom right arc
|
||||||
|
arc.Y = (y + height) - diameter;
|
||||||
|
path.AddArc(arc, 0, 90);
|
||||||
|
|
||||||
|
// bottom left arc
|
||||||
|
arc.X = x;
|
||||||
|
path.AddArc(arc, 90, 90);
|
||||||
|
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, int x, int y, int width, int height, int cornerRadius)
|
||||||
|
{
|
||||||
|
if (graphics == null)
|
||||||
|
throw new ArgumentNullException("graphics");
|
||||||
|
if (pen == null)
|
||||||
|
throw new ArgumentNullException("pen");
|
||||||
|
|
||||||
|
using (GraphicsPath path = RoundedRect(x, y, width, height, cornerRadius))
|
||||||
|
{
|
||||||
|
graphics.DrawPath(pen, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
@@ -81,6 +82,7 @@
|
|||||||
<Compile Include="PdfElements\PdfStream.cs" />
|
<Compile Include="PdfElements\PdfStream.cs" />
|
||||||
<Compile Include="PdfElements\PdfString.cs" />
|
<Compile Include="PdfElements\PdfString.cs" />
|
||||||
<Compile Include="PdfParser.cs" />
|
<Compile Include="PdfParser.cs" />
|
||||||
|
<Compile Include="PdfPageRenderer.cs" />
|
||||||
<Compile Include="PdfStandar14FontMetrics.cs" />
|
<Compile Include="PdfStandar14FontMetrics.cs" />
|
||||||
<Compile Include="PdfTextExtractor.cs" />
|
<Compile Include="PdfTextExtractor.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user