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命令列出的是当前那些进程的快照,就是执 ...
随机推荐
- leetcode第39题--Combination Sum II
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- 织梦不仅是链接到其他调用next
//打开系统文件织梦 /include/arc.archives.class.php 找到GetPreNext函数 function GetPreNext($gtype='') { $rs = ''; ...
- C++中的左值和右值
左值和右值的定义 在C++中,能够放到赋值操作符=左边的是左值,能够放到赋值操作符右边的是右值.有些变量既能够当左值又能够当右值.进一步来讲,左值为Lvalue,事实上L代表Location,表示在内 ...
- 使用AdvancedInstaller打包web工程设置tomcat端口的方法
原文:使用AdvancedInstaller打包web工程设置tomcat端口的方法 1.首先,要把你要打包的tomcat下的server.xml文件删掉,因为tomcat自带的serv ...
- ASP.NET vNext 在 Mac OS
让 ASP.NET vNext 在 Mac OS 中飞呀飞... 写在前面 阅读目录: 娓娓道来 Install ASP.NET vNext Command Line Tools 安装 Homeb ...
- C#快速随机按行读取大型文本文件
原文:C#快速随机按行读取大型文本文件 下面是我实现的一个数据文件随机读取类,可以随机读取大型文本文件的某一行.在我机器上对一个130MB的文本文件,读取第200000的速度从传统做法的400ms提高 ...
- 使用javaservice 将jboss 注册为服务
近来做项目,需要jboss定期重新启动.不想再看到jboss启动那个黑洞洞的窗口,就想着把它注册为服务,然后在net start.恰好objectweb上有个open source的javaservi ...
- C++关于数字逆序输出的两种思路,及字符串逆序输出
C++关于数字逆序输出的两种思路,及字符串逆序输出 作者:GREATCOFFEE 发布时间:NOVEMBER 15, 2012 分类:编程的艺术 最近在跟女神一起学C++(其实我是不怀好意),然后女神 ...
- MVC程序中实体框架的连接恢复和命令拦截
MVC程序中实体框架的连接恢复和命令拦截 这是微软官方SignalR 2.0教程Getting Started with Entity Framework 6 Code First using MVC ...
- (转载)Log4Net 在多层项目中的使用小记
(原创)Log4Net 在多层项目中的使用小记 这几天刚好在调整一个项目,把一些自己不是很清楚的东西先试验一下,这篇文章主要是对我在项目中需要使用Log4Net的一些记录.网上有很多相关的教程,但是各 ...