ImageLinks.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;
using DsPdfWeb.Demos.Common;
using GrapeCity.Documents.Pdf.Annotations;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;
namespace DsPdfWeb.Demos
{
// 此示例加载目录中找到的所有图像,然后渲染每个图像
// 在 PDF 的单独页面上以最大可能的尺寸。
// 最后,它插入链接到大图像的图像缩略图目录
// 到文档中。
// 另请参阅SlidePages。
public class ImageLinks
{
private class ImageInfo
{
public string Name;
public IImage Image;
public int PageIdx;
}
public int CreatePDF(Stream stream)
{
var doc = new GcPdfDocument();
var font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
// 四周 1/4 英寸页边距:
const float margin = 36;
// 从 Resources/Images 文件夹加载所有图像:
List<ImageInfo> imageInfos = new List<ImageInfo>();
foreach (var fname in Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories))
imageInfos.Add(new ImageInfo() { Name = Path.GetFileName(fname), Image = Util.ImageFromFile(fname) });
imageInfos.Shuffle();
// 设置图像对齐方式,使图像水平居中并垂直顶部对齐:
var ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, true, true, true, false, false);
// 全尺寸图像的图像矩形 - 整个页面:
var rBig = new RectangleF(margin, margin, doc.PageSize.Width - margin * 2, doc.PageSize.Height - margin * 2);
// 将所有图像渲染为全尺寸,每页一张图像:
for (int i = 0; i < imageInfos.Count; ++i)
{
var g = doc.NewPage().Graphics;
var ii = imageInfos[i];
g.DrawImage(ii.Image, rBig, null, ia);
ii.PageIdx = i;
}
// 将带有缩略图的页面作为 4x5 网格插入到文档的开头(请参阅SlidePages):
const int rows = 5;
const int cols = 4;
float gapx = 72f / 4, gapy = gapx;
float sWidth = (doc.PageSize.Width - margin * 2 + gapx) / cols;
float sHeight = (doc.PageSize.Height - margin * 2 + gapy) / rows;
if (sWidth > sHeight)
{
gapx += sWidth - sHeight;
sWidth = sHeight;
}
else
{
gapy += sHeight - sWidth;
sHeight = sWidth;
}
const float sMargin = 72f / 6;
// 缩略图也垂直居中:
ia.AlignVert = ImageAlignVert.Center;
// 图像标题的文本格式:
var tf = new TextFormat() { Font = font, FontSize = sMargin * 0.65f };
// 插入点:
var ip = new PointF(margin, margin);
var page = doc.Pages.Insert(0);
for (int i = 0; i < imageInfos.Count(); ++i)
{
var ii = imageInfos[i];
var rect = new RectangleF(ip, new SizeF(sWidth - gapx, sHeight - gapy));
// 添加全尺寸图像所在页面的链接(页面索引
// 当我们知道目录中有多少页时,将会更新,见下文):
page.Annotations.Add(new LinkAnnotation(rect, new DestinationFit(ii.PageIdx)));
// 绘制缩略图:
var g = page.Graphics;
g.FillRectangle(rect, Color.LightGray);
g.DrawRectangle(rect, Color.Black, 0.5f);
rect.Inflate(-sMargin, -sMargin);
g.DrawImage(ii.Image, rect, null, ia, out RectangleF[] imageRect);
g.DrawRectangle(imageRect[0], Color.DarkGray, 1);
// 在幻灯片底部边距中打印图像文件名作为标题:
g.DrawString(ii.Name, tf,
new RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
TextAlignment.Center, ParagraphAlignment.Near, false);
ip.X += sWidth;
if (ip.X + sWidth > doc.PageSize.Width)
{
ip.X = margin;
ip.Y += sHeight;
if (ip.Y + sHeight > doc.PageSize.Height)
{
page = doc.Pages.Insert(doc.Pages.IndexOf(page) + 1);
ip.Y = margin;
}
}
}
// 我们现在浏览所有目录页面,更新链接目的地中的页面索引
// 考虑到文档开头插入的目录页:
int tocPages = doc.Pages.IndexOf(page) + 1;
for (int i = 0; i < tocPages; ++i)
{
foreach (var ann in doc.Pages[i].Annotations)
if (ann is LinkAnnotation link && link.Dest is DestinationFit dest)
link.Dest = new DestinationFit(dest.PageIndex.Value + tocPages);
}
// 完毕:
doc.Save(stream);
imageInfos.ForEach((ii_) => ii_.Image.Dispose());
return doc.Pages.Count;
}
}
}