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命令列出的是当前那些进程的快照,就是执 ...
随机推荐
- HDU 5185 Equation (DP)
题目:LINK 题意:求满足题目要求的x序列的种类数. 能够发现符合条件的序列去重后是一个0, 1, ..., k的连续序列(k满足k*(k+1)/2 <= n) ,则这个去重后的序列长度最长为 ...
- JSP之项目路径问题(${pageContext.request.contextPath},<%=request.getContextPath()%>以及绝对路径获取)
本随笔这是作为一个记录使用,以备后查.项目完成之后本地部署OK,本地Linux部署OK,都可以正常的访问,可是当我把它部署到服务器上面的时候,首页可以正常访问,可是当发出请求的时候却报错误了,说找不到 ...
- C#中IList<T>与List<T>的区别
首先IList 泛型接口是 ICollection 泛型接口的子代,并且是所有泛型列表的基接口.它仅仅是所有泛型类型的接口,并没有太多方法可以方便实用,如果仅仅是作为集合数据的承载体,确实,IList ...
- BackgroundWorker组件使用总结
首先在窗体拖入一个BackgroundWorker组件,根据功能需要设置BackgroundWorker的属性 WorkerSupportsCancellation = true; 允许取消后台正在执 ...
- 实时预览的在线 Markdown 编辑器 - Markdoc
实时预览的在线 Markdown 编辑器 - Markdoc 最近组内需要为一些项目和系统写文档,发表在公司内的文档平台上,这个平台并不支持markdown,所以打算做一个在线markdown编辑器, ...
- messageBox以及新窗体的使用
DialogResult dr = MessageBox.Show("你确定要点击吗", "安全提示", MessageBoxButtons.YesNo); ...
- UVA 408 (13.07.28)
Uniform Generator Computer simulations often require random numbers. One way to generatepseudo-ran ...
- 设计模式18---设计模式之策略模式(Strategy)(行为型)
1.场景模拟 简单的报价管理系统: 对于普通用户和新用户报全价 对于老客户统一折扣5% 对于大客户统一折扣10% 2.不用模式的解决方案 package demo16.strategy.example ...
- OAuth的一个.NET开源实现
从编译DotNetOpenAuth中学到的程序集强签名知识 OAuth的一个.NET开源实现,官方网站:http://dotnetopenauth.net/ . 从GitHub签出DotNetOpen ...
- 上传组件uploadify的使用
上传组件uploadify的使用 大概一年前,我还在用Asp.NET开发一些行业管理系统的时候,就曾经使用这个组件作为文件的上传操作,在随笔<Web开发中的文件上传组件uploadify的使用& ...