PostScript学习:另一种缩写为PS的技术
1.前言
PostScript是一种编程语言,直译为"后处理脚本"[相对印刷过程而言],学名为页面描述语言。更为详细的解释见维基百科,以及其翻译版百度百科。
值得一提的是,PostScript于1985年由Adobe推出,而Adobe的软件Photoshop 1.0版本于1990发布,两者的缩写均为PS。虽然就知名度而言,PhotoShop更为人所熟知,但是在Adobe的发家史中,PostScript扮演着非常重要的作用,时至今日PostScript的衍生技术PDF已经是一项ISO标准。
老实说,关于PostScript的基础知识,大家看维基百科的介绍以及附录的四本书就够了,四本书分别是:PostScript语言参考,PostScript语言教程与手册,PostScript程序设计,数学图表:几何与PostScript手册 。本文只是介绍PostScript的简单绘图知识。
大多数人开始接触PostScript大概是因为LaTeX,参考如何在论文中画出漂亮的插图?中 地铁风 的回答。LaTeX中常用的矢量图格式是EPS[Encapsulated PostScript],不过对PDF格式的支持应该是最好的。大多数与LaTeX相关的绘图与渲染都是基于PostScript技术的,如PSTricks、TikZ /PGF、MetaPost以及Asymptote。Texample.net上有大量关于Tikz的例子。Asymptote官网也有大量 asy的例子。
2.简单例子
在学习之前,你需要两个软件:GhostScript和SumatraPDF。GhostScript是PostScript的一个开源解释器;SumatraPDF是一个文档阅读器,默认支持PDF,结合GhostScript可以支持PostScript。
HelloWorld的例子,保存到文本文件HelloWorld.ps, 用SumatraPDF打开:
%!PS
/Courier % name the desired font
selectfont % choose the size in points and establish
% the font as the current one
moveto % position the current point at
% coordinates , (the origin is at the
% lower-left corner of the page)
(Hello world!) show % stroke the text in parentheses
showpage % print all on the page
下面给出C语言生成PostScript图案的一个简单例子:
#include <math.h>
#include <stdio.h>
void init(FILE* fp)
{
int w=,h=;
fputs("%!PS-Adobe-3.0 EPSF-3.0\n",fp);
fprintf(fp,"%%%%BoundingBox: 0 0 %d %d\n",w,h);
fputs("/rgb {setrgbcolor} def\n",fp);
fputs("/np {newpath} def\n",fp);
fputs("/cp {closepath} def\n",fp);
fputs("/mt {moveto} def\n",fp);
fputs("/ll {lineto} def\n",fp);
fputs("/st {stroke} def\n",fp);
fputs("/lw {setlinewidth} def\n",fp);
fputs("/line {np mt ll st} def\n",fp);
}
void close(FILE* fp)
{
fputs("showpage\n%%EOF",fp);
fclose(fp);
}
void line(FILE* fp,float x[],float y[],int n)
{
fprintf(fp,"0 0 1 rgb\nnp\n%.3f %.3f mt\n",x[],y[]);
for(int i=;i<n;i++){
fprintf(fp,"%.3f %.3f ll\n",x[i],y[i]);
}
fprintf(fp,"st\n");
}
#define N 628
int main()
{ FILE* fp=fopen("main.ps","wb");
init(fp);
//
float x[N],y[N],t;
for(int i=;i<N;i++){
t=-3.14+i/100.0;
x[i]=*sin(*t)*cos(t)+;
y[i]=*sin(*t)*sin(t)+;
}
line(fp,x,y,N);
//
close(fp);
return ;
}
如图所示,更多的例子可以看之前提到的四本书,三维绘图请看第四本数学图表:几何与PostScript手册:

另一个简单例子,可以作为一个练习,更多例子见我的GitHub:LearnPostScript。

3.复杂一点的例子
这个例子需要一点三维旋转矩阵的知识,代码仅作演示:
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define Random rand()%255
#define Length(x) (sizeof(x)/sizeof(x[0])/3)
const float PI=3.1415926536;
typedef float vector3[];
//三维点数组结构
typedef struct {
int length;
float *x, *y, *z;
}PointArray ;
//
//三维点初始化
PointArray Array3d(int n)
{
PointArray r;
r.length = n;
r.x = (float*)malloc(n*sizeof(float));
r.y = (float*)malloc(n*sizeof(float));
r.z = (float*)malloc(n*sizeof(float));
for (int i = ; i < n; i++) {
r.x[i] = r.y[i] = r.z[i] = 0.0;
}
return r;
}
//三维点通过数组赋值
PointArray eval(float *a, int n)
{
PointArray r;
r.length = n;
r.x = (float*)malloc(n*sizeof(float));
r.y = (float*)malloc(n*sizeof(float));
r.z = (float*)malloc(n*sizeof(float));
for (int i = ; i < n; i++) {
r.x[i] = a[*i];
r.y[i] = a[*i + ];
r.z[i] = a[*i + ];
}
return r;
}
//输出三维点数组的数据
void print(PointArray r)
{
for (int i = ; i < r.length; i++) {
printf("%f %f %f\n", r.x[i], r.y[i], r.z[i]);
}
}
//
void fileprint(FILE* fp,PointArray r)
{
for (int i = ; i < r.length; i++) {
fprintf(fp,"%f %f ", r.x[i], r.y[i], r.z[i]);
}
fprintf(fp," quad\n");
}
//
//对三维点进行旋转
void Rotate(PointArray pa, vector3 vec,float t)
{
float x,y,z,a,b,c;
float base=sqrt(vec[]*vec[]+vec[]*vec[]+vec[]*vec[]);
a=vec[]/base,b=vec[]/base,c=vec[]/base;
for (int i = ; i < pa.length; i++) {
x=pa.x[i],y=pa.y[i],z=pa.z[i];
//
pa.x[i]=(cos(t)+(-cos(t))*a*a)*x+
((-cos(t))*a*b-sin(t)*c)*y+
((-cos(t))*a*c+sin(t)*b)*z;
//
pa.y[i]=((-cos(t))*b*a+sin(t)*c)*x+
(cos(t)+(-cos(t))*b*b)*y+
((-cos(t))*b*c-sin(t)*a)*z;
//
pa.z[i]=((-cos(t))*c*a-sin(t)*b)*x+
((-cos(t))*c*b+sin(t)*a)*y+
(cos(t)+(-cos(t))*c*c)*z;
}
}
//
void RotateX(PointArray pa,float t)
{
float x,y,z; for (int i = ; i < pa.length; i++) {
x=pa.x[i],y=pa.y[i],z=pa.z[i]; pa.x[i]=x;
//
pa.y[i]=y*cos(t)-z*sin(t);
//
pa.z[i]=y*sin(t)+z*cos(t);
}
}
//
void RotateY(PointArray pa,float t)
{
float x,y,z;
for (int i = ; i < pa.length; i++) {
x=pa.x[i],y=pa.y[i],z=pa.z[i];
//
pa.x[i]=z*sin(t)+x*cos(t);
pa.y[i]=y;
pa.z[i]=z*cos(t)-x*sin(t);
}
}
//
void RotateZ(PointArray pa,float t)
{
float x,y,z;
for (int i = ; i < pa.length; i++) {
x=pa.x[i],y=pa.y[i],z=pa.z[i];
pa.x[i]=x*cos(t)-y*sin(t);
pa.y[i]=x*sin(t)+y*cos(t);
pa.z[i]=z;
}
}
//透视投影
void Perspective(PointArray pa,float ez,float n,float f)
{
float x,y,z;
for (int i = ; i < pa.length; i++) {
x=pa.x[i],y=pa.y[i],z=pa.z[i];
pa.x[i]=(ez-z)/(n-f)*x;
pa.y[i]=(ez-z)/(n-f)*y;
pa.z[i]=z;
}
}
//
static float yrot=;
//
inline float fun(float x,float y)
{
//Matlab Peaks Function
float z=*(-x)*(-x)*exp(-x*x - (y+)*(y+))
- *(x/ - x*x*x - y*y*y*y*y)*exp(-x*x-y*y)
- 1.0/*exp(-(x+)*(x+) - y*y);
return z*;
}
//
void display()
{
float a[];
PointArray ptsa,ptsb;
float d=0.1,factor=;
float x,y,z1,z2,z3,z4;
FILE* fp=fopen("main.ps","wb");
fprintf(fp,"%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: -250 -250 250 250\n/rgb {setrgbcolor} def\n/np {newpath} def\n/cp {closepath} def\n/mt {moveto} def\n/rmt {rmoveto} def\n/ll {lineto} def\n/rl {rlineto} def\n/st {stroke} def\n/lw {setlinewidth} def\n/line {np mt ll st} def\n/quad {np mt ll ll ll cp st} def\n0 0 1 rgb\n0.2 lw\n");
for(x=-; x<; x+=d) {
for(y=-; y<; y+=d) {
z1=fun(x,y);
a[]=x*factor,a[]=z1,a[]=y*factor;
z2=fun(x+d,y);
a[]=(x+d)*factor,a[]=z2,a[]=y*factor;
z3=fun(x+d,y+d);
a[]=(x+d)*factor,a[]=z3,a[]=(y+d)*factor;
z4=fun(x,y+d);
a[]=x*factor,a[]=z4,a[]=(y+d)*factor;
//
ptsa=eval(a,Length(a));
RotateY(ptsa,yrot);
RotateX(ptsa,**PI/);
//ptsb=RotateZ(ptsb,6);
fileprint(fp,ptsa);
}
}
fprintf(fp,"\nshowpage\n%%%%EOF\n");
fclose(fp);
yrot+=0.1;
}
int main()
{
display();
}

4.结束语
虽然越来越多的新技术涌现出来,但是它们都不是凭空产生的。PostScript作为一项古老的技术,对于文档的排版和印刷而言,依然是值得学习的。
PostScript学习:另一种缩写为PS的技术的更多相关文章
- linux命令学习笔记(41):ps命令
Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前 那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程 ...
- WebGL three.js学习笔记 6种类型的纹理介绍及应用
WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...
- 《BI那点儿事》浅析十三种常用的数据挖掘的技术
一.前沿 数据挖掘就是从大量的.不完全的.有噪声的.模糊的.随机的数据中,提取隐含在其中的.人们事先不知道的但又是潜在有用的信息和知识的过程.数据挖掘的任务是从数据集中发现模式,可以发现的模式有很多种 ...
- 浅析十三种常用的数据挖掘的技术&五个免费开源的数据挖掘软件
一.前 沿 数据挖掘就是从大量的.不完全的.有噪声的.模糊的.随机的数据中,提取隐含在其中的.人们事先不知道的但又是潜在有用的信息和知识的过程.数据挖掘的任务是从数据集中发现模式,可以发现的模式有很多 ...
- 一文读懂四种常见的XML解析技术
之前的文章我们讲解了<XML系列教程之Schema技术_上海尚学堂java培训技术干货><XML的概念.特点与作用.XML申明_上海Java培训技术干货>,大家可以点击回顾一下 ...
- OpenVZ安装指南,一种操作系统级别的虚拟化技术
鼎鼎大名的 OpenVZ 谁不知道?在主机行业被使用(滥用)很多年,依然在茁壮发展.作为一种操作系统级别的虚拟化技术,运行 OpenVZ 没有硬性的硬件要求.OpenVZ 能够创建被称为容器(cont ...
- C# 桌面软件开发-深入学习[2]- AY-C#人爱学不学-aaronyang技术分享
原文:C# 桌面软件开发-深入学习[2]- AY-C#人爱学不学-aaronyang技术分享 1 : C# Assembly.GetEntryAssembly().GetName().Version. ...
- C# 桌面软件开发-深入学习 [1]- AY-C#人爱学不学-aaronyang技术分享
原文:C# 桌面软件开发-深入学习 [1]- AY-C#人爱学不学-aaronyang技术分享 曾经我做office,不想依赖别人dll,就使用了 Type.GetTypeFromProgID 可以根 ...
- shell学习五十天----查看进程ps命令
进程列表 列出进程中最重要的命令便是进程状态命令:ps. ps命令是进程状态(Process Status)的缩写.ps命令用来列出系统中当前执行的那些进程.ps命令列出的是当前那些进程的快照,就是执 ...
随机推荐
- js 实现复制粘贴文本过滤(保留文字和图片)
实现复制粘贴文本过滤(保留文字和图片) demo如下: <head> <meta http-equiv="Content-Type" content=" ...
- 安装Visual Source Safe 2005 - 初学者系列 - 学习者系列文章
本文介绍微软的文档管理工具Visual Source Safe 2005的安装 从下列地址获取该工具: ed2k://|file|en_vss_2005.iso|108048384|C4BEC1EC3 ...
- 使用Excel快速发送大量的电子邮件
使用Excel快速发送大量的电子邮件.两个步骤: 1. 准备发送数据: a.) 打开Excel,新Book1.xlsx b.) 填写以下内容. 第一列:接受者,第二列:邮件标题,第三列:文,第四列:附 ...
- 九度OJ 1035:找出直系亲属(二叉树)
题目1035:找出直系亲属 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1309 解决:521 题目描述: 如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如 ...
- css优先级机制说明
原文:css优先级机制说明 首先说明下样式的优先级,样式有三种: 1. 外部样式(External style sheet) 示例: <!-- 外部样式 bootstrap.min.css -- ...
- Repository 仓储
Repository 仓储 写在前面 首先,本篇博文主要包含两个主题: 领域服务中使用仓储 SELECT 某某某(有点晕?请看下面.) 上一篇:Repository 仓储,你的归宿究竟在哪?(二)-这 ...
- 【值得收藏】符号计算软件Maple的学习资料汇编【可免费下载】
Maple学习教程 Maple是目前世界上最为通用的数学和工程计算软件之一,在数学和科学领域享有盛誉,有“数学家的软件”之称.Maple在全球拥有数百万用户,被广泛地应用于科学.工程和教育等领域,用户 ...
- 【推荐分享】Python电子书,视频教程(Let's Python系列视频教程等)(百度网盘)
资源都放在百度网盘里了. Python视频教程(Python Django视频教程全集—台湾辅仁大学):http://pan.baidu.com/s/1dDgiWIt Python视频教程(let's ...
- NUnit单元测试资料汇总
NUnit单元测试资料汇总 从安装到配置 首先到官网http://www.nunit.org/下载如下图的资料,安装NUnit-2.6.1.msi包. 然后挂在VS2010外部工具这个地方来使用,工具 ...
- GoLang获取struct的tag
GoLang获取struct的tag内容:beego的ORM中也通过tag来定义参数的. 获取tag的内容是利用反射包来实现的.示例代码能清楚的看懂! package main import ( &q ...