图像蒙版:现在支持矢量路径






3.61/5 (6投票s)
蒙版图像和指定软蒙版
引言
我将讨论在揭示解决方案并讨论它之前,你可以掩盖图像的其他方法,因为在PDF中掩盖图像有很多种方法,所以这比你想象的要有趣。如果你搜索PDF规范(就像我现在做的),你会发现基本上有两个部分讨论了蒙版:第8.9.6节 蒙版图像和第11.6.5节 指定软蒙版,但两者都没有讨论使用矢量路径进行蒙版。
背景
软蒙版是透明度章节的一部分,有两种形式:图像和字典。如果你熟悉RGBA图像,图像软蒙版本质上是将Alpha(透明度)通道从RGB图像中分离出来,并使其在父图像XObject中独立存在。这本质上是DLE处理包含RGBA图像的PNG文件的方式。另一方面,软蒙版字典是扩展图形状态的一部分,虽然它们包含一个透明度组表单XObject,其中可以包含矢量路径,但这并不是将矢量路径用于图像蒙版的理想机制。
蒙版图像有三种形式;模版蒙版、显式蒙版和色彩键蒙版。显式蒙版类似于图像软蒙版,除了alpha通道像素只能完全开启或完全关闭,因此没有透明度的程度。色彩键蒙版有点像GIF文件中透明度的工作方式,其中一种索引颜色被指定为透明颜色,但使用色彩键蒙版,你可以为图像的每个颜色分量指定一个范围;如果所有分量值都落在这些范围内,则该像素将被蒙版(或不被蒙版,具体取决于Decode参数,但这就是想法)。模版蒙版类似于显式蒙版,除了你已经丢弃了主图像,并且正在蒙版已经存在的背景。
使用代码
这些变体都不允许使用矢量路径,那么如何使用矢量路径进行蒙版呢?蒙版是正确的概念,但在这个例子中用词不当,因为要用矢量路径蒙版图像,你只需将剪切路径应用于图像。或者至少,这就是理论,我需要一些代码来证明它。我决定使用以下代码创建的17点星形来剪切此图像:
var center = new Point(pageRect.Left+pageRect.Width/2,pageRect.Bottom+pageRect.Height/2); var smallDim = Math.Min(img2.BoundingBox.Width,img2.BoundingBox.Height); var cPath = createStar(center,smallDim/2,smallDim/3, 17); static Path createStar(Point Center, double r1, double r2, int rays) { var starPath = new Path(); Point start = new Point(Center.H+ r1 *Math.Cos(0), Center.V+r1*Math.Sin(0)); starPath.MoveTo(start); double angle =2*Math.PI/rays; var halfAngle = angle /2.0; for(int i=0; i < rays; i++) { var theta1 = (i * angle) + halfAngle; var theta2 = theta1 + halfAngle; var Point1 = new Point(Center.H + r2 * Math.Cos(theta1), Center.V + r2 * Math.Sin(theta1)); var Point2 = new Point(Center.H + r1 * Math.Cos(theta2), Center.V + r1 * Math.Sin(theta2)); starPath.AddLine(Point1); starPath.AddLine(Point2); } starPath.ClosePath(); return starPath; }
结果是
然而,我的邻居挑战我将剪切反转过来,或者有效地从外到内(!)。
// Challenge #2: use the inverse of the Path as the mask for an image var page3 = doc.CreatePage(Document.LastPage, pageRect); var img3 = newimage.Clone(); // Solved by surrounding the Path with a Rect around the image. var clipPath2 = new Path(); clipPath2.AddRect(new Point(72,72), img3.BoundingBox.Width, img3.BoundingBox.Height); AppendStar(ref clipPath2, center, smallDim / 2, smallDim / 3, 17); Clip clip2 = new Clip(); clip2.AddElement(clipPath2); img3.Clip = clip2; page3.Content.AddElement(img3); page3.UpdateContent();
将星形附加到现有的剪切路径,其中包含围绕整个图像的矩形,需要对创建星形的方式进行轻微的修改
static void AppendStar(ref Path existingPath, Point Center, double r1, double r2, int rays) { Point start = new Point(Center.H + r1 * Math.Cos(0), Center.V + r1 * Math.Sin(0)); existingPath.MoveTo(start); double angle = 2 * Math.PI / rays; var halfAngle = angle / 2.0; for (int i = 0; i < rays; i++) { var theta1 = (i * angle) + halfAngle; var theta2 = theta1 + halfAngle; var Point1 = new Point(Center.H + r2 * Math.Cos(theta1), Center.V + r2 * Math.Sin(theta1)); var Point2 = new Point(Center.H + r1 * Math.Cos(theta2), Center.V + r1 * Math.Sin(theta2)); existingPath.AddLine(Point1); existingPath.AddLine(Point2); } existingPath.ClosePath(); }
这次结果是
任务完成:使用矢量路径蒙版的图像。