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命令列出的是当前那些进程的快照,就是执 ...
随机推荐
- android:由URL载入中ImageView
两种方法: 方法一: Bitmap bimage= getBitmapFromURL(bannerpath); image.setImageBitmap(bimage); public static ...
- navigator获取参数
<script type="text/javascript" language="javascript"> document.write(" ...
- 【推荐】推荐一本学习ExtJS4的好书《ExtJS江湖》(含pdf电子书和源代码下载地址)
最近在网上游逛,突然发现了一本介绍ExtJS 4框架的好书,书名叫<ExtJS江湖>,作者是大漠穷秋,个人感觉非常不错,书写得很幽默,很具有可读性,在此推荐给各位. 以下是这本书的介绍: ...
- MVC使用RDL报表
MVC使用RDL报表 这次我们来演示MVC3怎么显示RDL报表,坑爹的微软把MVC升级到5都木有良好的支持报表,让MVC在某些领域趋于短板 我们只能通过一些方式来使用rdl报表. Razor视图不支持 ...
- KMP算法详解-- 转自Matrix67
6 7 8 9 -- A = a b a b 6 7 7 8 9 -- A = a b a b a 5 6 7 8 9 -- A = a b a b a b 6 7 ...
- 原生Js 两种方法实现页面关键字高亮显示
原生Js 两种方法实现页面关键字高亮显示 上网看了看别人写的,不是兼容问题就是代码繁琐,自己琢磨了一下用两种方法都可以实现,各有利弊. 方法一 依靠正则表达式修改 1.获取obj的html2.统一替换 ...
- 手机APP下单支付序列图
今天安装了Visio,学习了下如何使用,画了一下公司现在项目的下单支付序列图,话就不多说了,直接上图,处女作,欢迎指正!
- Winform 程序嵌入WPF程序 并发送消息
废话不多说,先看解决方案目录 WindowsFormsDemo是主程序,WpfApp是嵌入的WPF程序,先看WPF程序,程序默认启动的页面是MainWindow.xaml,这里注释掉App.xaml里 ...
- let和const关键词
ECMAScript 6中的let和const关键词 2013-11-28 21:46 by BarretLee, 21 阅读, 0 评论, 收藏, 编辑 ECMAScript 6中多了两个定义变量的 ...
- wpf中xps文档合并功能实现
跟着上一篇的xps文档套打的文章,近期一直在研究xps打印技术,其中用户提到了一个需求,要求能够多页面进行打印,我的想法是,先生成xps文件,然后将文件读取出来以后,合并成一个文件来处理. 如果要是直 ...