首页 > 其他分享 >什么是转换矩阵以及如何使用它

什么是转换矩阵以及如何使用它

时间:2024-02-24 16:44:06浏览次数:23  
标签:转换 变换 SetMatrix 矩阵 旋转 如何 对象 坐标系

项目地址:

Pdfium.Net:https://github.com/1000374/Pdfium.Net

PdfiumViewer:https://github.com/1000374/PdfiumViewer

当您使用 PDFium 库处理 PDF 文件中的对象时,您可以使用 SetMatrix 函数以各种方式转换对象(通常是图像,但也包括任何其他嵌入对象)。使用变换矩阵,您可以旋转、平移(移动)、缩放或剪切图像。可以在此处找到使用矩阵将图像缩放到 PDF 文档中页面大小的示例。

本文更深入地解释了什么是转换矩阵,以及为什么它的工作方式如此。

 矩阵

简介

如果您对线性代数非常陌生,那么矩阵只是一组值,它们组合在一起形成矩形或正方形。以下是矩阵的示例:

 许多物理值可以(并且通常)以矩阵形式表示。例如,坐标;它们通常表示为向量 - 一个矩阵,其中包含一列和每个空间维度的行数(2D 为 2 行,3D 为 3 行,依此类推)。这种矩阵中的每个元素都是相应轴上的坐标。向量的示例如上所示。

PDF 文档也使用坐标系。这两个轴是页面的垂直和水平尺寸,每个坐标表示该轴上的 PDF 点数。因此,如果页面上的给定对象放置在距底部 3500 个点和从左侧 100 个点处,则其坐标向量为:

,这本质上是相同的。

 

矩阵可以像普通数字一样求和、减去、乘法和除法(反转)。加法和减法是最简单的操作,这里是示例:

加法、减法


要将一个矩阵添加到另一个矩阵,您应该简单地将第一个矩阵的每个元素添加到第二个矩阵的相应元素中。当然,矩阵必须具有相等的维度。

 减法 除了算术符号之外,减法也是如此:

 加法和减法是可交换的。您可以更改矩阵的顺序,但仍然得到相同的结果(减法时的算术符号除外):

A + B = B + A A - B = -(B - A)其中 A和 B 是矩阵。

 


乘法矩阵是一个更棘手的过程。要将矩阵 A 乘以矩阵 B,应将第一个矩阵的每一行乘以第二个矩阵的每一列。每个这样的乘积都是在(i,j)位置所得矩阵的元素。其中 i 是 A 中行的索引,j 是 B 中列的索引。
听起来很复杂?下面是一个示例:

 首先,我们将第一个矩阵的第一行乘以第二个矩阵的第一列。这为我们提供了结果矩阵中 (1,1) 处的元素:然后,我们将第二行和第一列相乘以计算 (1,2) 处的元素:然后,我们计算 (2,1) 处的元素:最后是 (2,2) 处的元素:

 

 

 

 矩阵的相乘方式有两个重要影响:

    1. A 的列数必须与 B 的行数匹配。如上所示,您可以使用多个 2×2 和 2×2 矩阵。您还可以将 2×6 到 4×2(结果为 6×4 矩阵)或 3×3 到 1×3(结果为 3×3 矩阵)。但是,例如,您不能将 3 乘以 3 乘以 1 乘 2。
    2. 矩阵的乘法不是交换的。.

如果以上面的例子为例,改变矩阵的顺序,结果会有所不同,即:

 

 除法

如果您认为矩阵的乘法很难理解,那么我们有个坏消息要告诉您:将它们相乘更加棘手。但是,您不需要划分矩阵来执行 PDF 对象的转换,可查看百度百科: https://baike.baidu.com/item/%E5%8F%AF%E9%80%86%E7%9F%A9%E9%98%B5/11035614?fr=ge_ala

 

什么是变换矩阵

PDF 在二维坐标系中表示其内容。每个点的坐标都可以表示为向量:(x, y)。 变换矩阵允许更改默认坐标系并将原始坐标 (x, y) 映射到这个新坐标系:(x', y')。根据我们改变坐标系的方式,我们以这种方式有效地旋转、缩放、移动(平移)或剪切对象。

变换矩阵是一个 3×3 矩阵:

 矩阵的元素对应于各种变换(见下文)。要变换坐标系,应将原始坐标向量乘以变换矩阵。由于矩阵是 3×3,向量是 1×2,我们需要向它添加一个元素,使向量的大小与乘法规则要求的矩阵匹配(见上文)。

话虽如此,转换后的向量如下:

 例如,要在页面的位图上旋转图像,PDF 渲染器应获取图像每个点的坐标,使用上述公式更改它们,并在新坐标处渲染该像素。


这就是调用 SetMatrix 函数时要执行的操作:告诉呈现器应如何转换对象的每个渲染像素。

变换操作

移 :
将坐标系移动给定偏移量。该操作将生成一个新坐标系,该坐标系沿 x 轴移动 e,沿 y 轴移动 f。

平移操作的变换矩阵为:示例:

 原始坐标系中点的坐标为 (240 651 1)。我们想将坐标系向左平移 10 个点,向上平移 20 个点。所需的变换矩阵为:生成的坐标为:

 

 如您所见,坐标已按计划更改。图像的所有其他像素的转换方式相同。

要传递给 SetMatrix 方法的参数包括:

 

SetMatrix(1, 0, 0, 1, -10, 20).

  

 缩放:

缩放放一个对象,我们需要更改它的一个维度或两个维度。

尺度运算的变换矩阵为:

 式中 a 和 d 分别是水平和垂直尺度因子。如果它们大于 1,则对象将按比例放大。如果它们小于 1,则对象将从其原始大小缩小。

示例:

 此矩阵将对象沿 x 轴向上放大 40%,沿 y 轴向下缩放 20%。

SetMatrix(1.4, 0, 0, 0.8, 0, 0)

 翻转/反射

此操作类似于缩放。我们只需要反转其中一个坐标进行水平/垂直翻转或两者兼而有之,以反映原点。

  

 水平翻转:

SetMatrix(-1, 0, 0, 1, 0, 0)

垂直翻转:

SetMatrix(1, 0, 0, -1, 0, 0)

中央翻转:

SetMatrix(-1, 0, 0, -1, 0, 0)

 

旋转:

旋转操作将给定角度的顺时针或逆时针旋转原始坐标系。

旋转操作的矩阵为:

 

 
其中是旋转角度。

矩阵的形式来自简单的三角函数,但形式证明超出了本文的范围。

假设我们想将一个对象顺时针旋转 30 度。然后,对象的每个像素都按如下方式进行转换:

 

SetMatrix(0.87, -0.5, 0.5, 0.87, 0, 0)

  

 剪切

x 方向剪切的变换矩阵为:假设我们想将对象剪切 20 个 PDF 点对:

 

 

SetMatrix(1, 0, 20, 1, 0, 0)

 对于 y 方向的剪切:将物体剪切 45 PDF 指向下方:

 

 

SetMatrix(1, -45, 0, 1, 0, 0)

 多个转换

如果需要对同一对象应用多个转换,该怎么办?比如,扩大规模和轮换?或者水平翻转镜像图像并将其转换为页面上的所需位置?

在这种情况下,您只需要几个变换矩阵。为了执行一系列变换,将各个变换的矩阵相乘。然而,如上所述,乘法运算不是可交换的,因此变换矩阵的顺序有很大的不同。

例如,如果要旋转对象,然后平移它,则生成的变换矩阵为:对于变换矩阵的相反顺序,生成的矩阵是不同的:

 

 第一次可能看起来不明显。您可以将对象移动 10 厘米,然后将其旋转 45 度。或者您可以将其旋转 45 度,然后将旋转的对象移动 10 厘米。为什么会有这种差异?由于变换矩阵不会旋转(平移、缩放等)对象,因此它会旋转包含对象的坐标系

这样想吧。把一支铅笔放在桌子上。当您变换对象时,变换的顺序将是“将铅笔旋转 45 度,然后向左移动 10 厘米”。但是当你变换坐标系时,你会得到“将桌子旋转 45 度,然后将桌子向左移动 10 厘米”。

 结论

现在您知道FS_MATRIX中的这些 a、b、c、d、e 和 f 系数是什么意思了。由这些元素组成的转换矩阵允许几乎任意调整任何 PDF 位图或其他对象。

  

 

标签:转换,变换,SetMatrix,矩阵,旋转,如何,对象,坐标系
From: https://www.cnblogs.com/xiaohemiao/p/18024001

相关文章

  • windows如何同时安装两个不同版本的Mysql(Mysql8.0+Mysql5.7)
    1.问题由于公司要求使用mysql版本为Mysql5.7,而我之前的项目均是使用Mysql8.0,为了避免卸载重新安装Mysql5.7可能导致的问题,便寻找了可以同时在Windows上安装两个不同版本Mysql的方法2.解决参考:windows如何同时安装两个不同版本的Mysql(Mysql8.0+Mysql5.7)2.1进入你下载解压后......
  • C# 的显示转换 *.Parse(string) Convert.ToInt32(double value)
    //显式转换(类型)///(int)表示使用强制的显示转换,是一种类型转换,C#默认的整形是int32,///因此使用此方法转成int32不遵循四舍五入,直截取整数部分///(int)5.12结果是5///Int.Parse()指把string类型转换int......
  • delphi Byte 与 AnsiChar、WideChar 相互转换
    Byte与AnsiChar、WideChar相互转换代码Byte转AnsiChar、WideCharprocedureTForm1.Button1Click(Sender:TObject);varac:AnsiChar;wc:WideChar;bys:TBytes;begin//ANSI编码ac:='a';bys:=BytesOf(ac);Memo1.Lines.Add(bys[0].ToString);......
  • R语言时变面板平滑转换回归模型TV-PSTR分析债务水平对投资的影响|附代码数据
    全文下载链接:http://tecdat.cn/?p=21506最近我们被客户要求撰写关于TV-PSTR的研究报告,包括一些图形和统计输出。在本文中,当采用两种状态时,单转换函数PSTR模型具有两个变量:我们的经验方法的基础包括评估N个国家的资本流动性。相应的模型定义如下:其中,Iit是第i个国家在时间t时观......
  • 在K8S中,如何具体实现Pod被删除后,还能被自动拉起功能?
    在Kubernetes中,Pod被删除后能够自动拉起的功能是通过Deployment、StatefulSet或ReplicaSet等控制器来实现的。这些控制器负责维护指定数量的Pod副本,并确保在某个Pod实例由于任何原因(包括手动删除)消失时,会有一个新的Pod实例被创建以替换它。以下是具体实现方式:使用Deployment:D......
  • 在K8S中,Pod能否实现对容器健康检查,如果服务有异常,该如何处理?
    在Kubernetes(K8S)中,Pod可以配置健康检查来监控容器的运行状态。Kubernetes提供了两种类型的健康检查:就绪探针(ReadinessProbe):就绪探针用于确定Pod中的容器是否准备好服务请求。如果探针失败,则Pod会被从对应的Service后端列表中移除,直到它通过就绪探针为止。这确保了只有健康的......
  • 在K8S中,如何实现创建多个名为"Linux"的Pod?
    在Kubernetes(K8S)中,创建多个名为"Linux"的Pod并不是通过直接指定相同的Pod名称来实现的,因为每个Pod必须具有唯一的名称。然而,您可以创建多个使用相同模板或配置文件的Pod,这些Pod可以共享类似的标签(label),从而可以通过标签来逻辑上归类为“Linux”类型。例如,如果您想要创建10个运行L......
  • 在K8S中,如何具体实现Pod的IP地址发生变化时,不影响正常服务使用?
    在Kubernetes中,Pod的IP地址变化通常是由调度器重新调度Pod、节点故障、Pod升级或缩放等原因引起的。为了确保PodIP变化时服务不受影响,你可以采取以下具体步骤:使用Service:创建一个Service,指定其Selector以匹配你的Pod标签。当Pod的IP地址发生变化时,Kubernetes会自动更新Serv......
  • 陪玩程序源码,如何引导用户进行点赞操作?
    引导点赞我们需要让按钮做出一些视觉效果来引导用户进行点赞操作,那持续震动无疑是一种好的选择。//love.jsconstlikeBtn=document.getElementById('likeBtn');constheart=document.getElementById('heart')likeBtn.addEventListener('mousemove',()=>{heart.cl......
  • 读人工不智能:计算机如何误解世界笔记01_技术沙文主义
    1. 人工智能的学术范畴1.1. 知识表示与知识推理1.2. 逻辑学1.3. 机器学习1.4. 自然语言处理1.5. 搜索1.6. 规划1.7. 力学1.8. 伦理学2. 广义人工智能2.1. GOFAI2.1.1. GoodOld-FashionedArtificialIntelligence,老式人工智能2.2. 好莱坞版本的人工智......