《优秀网页设计速查与赏析》是一本用电脑“自动生成”的图书。
怎么,你不相信吗?我现在就来讲讲这本书的编写过程。

收集优秀网页设计

之所以有编写这本书的想法,主要是因为出版社的策划编辑们知道我手头有一个收录了近2000个国外优秀网页设计的“数据库”。每逢设计网页时,我自己都会在这个数据库里检索那些可以“借鉴”的内容。如果把这个数据库转换为一本公开发行的图书,其他网页设计师不也可以拥有类似的便利了吗?
积累这个数据库并没有花太大的力气,这主要得力于我自己编写的一个IE插件程序。在这个插件程序的帮助下,我平时上网浏览时,一旦发现优秀的网页设计,点一下鼠标就可以把网页截图及其相关信息记录下来,非常方便。
所谓的IE插件,就是可以在IE的指挥下运行、可以访问IE的资源的小程序。我这个IE插件程序是用Visual C++/ATL编写的COM组件。组件对象需要实现IObjectWithSiteImpl接口,只有这样才能访问宿主程序也就是IE中的资源。
被IE激活后,组件主要执行以下代码逻辑:

// 从宿主对象获取IID_IServiceProvider接口
m_pSite->QueryInterface(IID_IServiceProvider, ...);
// 从IID_IServiceProvider接口获取浏览器对象的服务接口
isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, ...);
isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, ...);
// 获取浏览器的当前视图窗口
m_pSite->QueryActiveShellView(&view);
// 获取当前URL
browser->get_LocationURL(&bURL);
// 将URL、当前系统时间等信息保存至XML数据库
...
// 截获当前视图窗口的像素信息
GetDIBits( hdc, hBmp, 0, bmpinfo.bmHeight, ... );
// 利用libpng库将截获的像素信息保存为PNG格式的图片文件
png_write_image(...);
// 显示对话框,提示用户输入网页关键词和点评文字
DialogBox(...);
// 将关键词和点评信息保存至XML数据库
...

将组件编译成DLL后,需要按照IE的要求在注册表中注册组件信息。此后,只要看到值得收藏的网页设计,我就点击IE工具栏上的按钮,IE会立即弹出如图 1所示的对话框。

我会在对话框中输入网页的关键词,心情好时也会输入一句我自己对该网页设计的评语,这些信息都会与网页截图、URL等信息一起被程序自动保存在XML数据库中。
如此日积月累,大概用了一年左右的时间,电脑里的网页设计数据库就已经初具规模了。当然,我还用Python/wxPython为这个数据库做了一个简单的查询系统——只要输入关键词就可以快速定位到相关网页。

自动分类和人工标引

为了符合书稿的要求,我必须按内容或主题将每个网页分入特定的类目,如“传媒?广告”、“建筑?园林”等等。这个分类工作可以由电脑自动完成。其实,我只是用XML创建了一张关键词与类目名称的对照表,然后用Python写了一个简单的程序,通过查表的方法将网页分入了特定的类目。
此外还需要按主色调将网页分入“红色”、“蓝色”等色彩类目。这个工作电脑一时还承担不了——我们当然可以用电脑自动统计出网页中分布面积最广的色彩,但分布面积最广并不一定意味着该色彩的视觉感染力最强,所以,我决定通过人工标引的方式,将每个网页分入不同的色彩类目中。
值得一提的是,为了方便人工标引工作,我还特意用Excel/VBA开发了一个基于图片的标引程序。我将网页数据库中的所有信息导入Excel工作表中,然后为该工作表的SelectionChange事件写了如下几行VBA代码:

Private LastRow As Long
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row = LastRow Then
Exit Sub
End If
LastRow = Target.Row
s = Worksheets("index").Cells(Target.Row, 3).Text
If Left(s, 2) = "wp" Then
Worksheets("image").Pictures.Delete
s = "original_images" & "\" & s & ".png"
Set p = Worksheets("image").Pictures.Insert(s)
p.Height = p.Height / 3 * 2
p.Width = p.Width / 3 * 2
Else
Worksheets("image").Pictures.Delete
End If
End Sub

上述代码的意思是说,如果用户在Excel工作表中切换到了新的记录,Excel就会根据记录中存储的图片文件名调入相应的网页截图,并将截图显示在另一张工作表中。有了这样的代码,我将数据和图片两个工作表并列摆放在Excel窗口内。然后使用Excel提供的列表、汇总、排序、筛选等功能自由编辑和浏览数据,同时又可以在右侧窗口内看到当前数据对应的网页截图(如图 2所示)——这种感觉真是太好了!如果用C++或Java编写一个功能类似的程序,那该需要多少行代码呀!

自动提取网页的配色方案

书中每个网页设计旁边都附有该设计使用的配色方案(主要色彩的图样及其RGB值)。这些配色方案是从哪里来的呢?如果由人工标引,那该有多费事呀?!
像提取网页配色方案这种高强度、重复性的劳动当然要交给电脑来做了!
首先,每个网页截图都是真彩色图片,这不利于电脑自动分析和提取主要色彩。我用Photoshop将所有网页截图批量地转换成色彩数目较少的图片(比如16色或256色图片)。怎么,你不知道Photoshop提供了批量处理功能?没关系,只要在Photoshop中录制一个新的动作,该动作包含将图片转换为索引颜色的操作,然后从Photoshop菜单选取“文件\自动\批处理”即可对某文件夹中的所有图片重复播放已录制好的动作。需要注意的是,将图片转换为索引颜色时需要使用“局部可感知调板”、“强制黑白”、“保留实际颜色”等选项,以保证图片中的主要色彩不发生大的变化。
接下来,我用Java编写了一个小程序,自动提取出每个16色或256色图片中的色彩信息,并统计每种色彩的分布面积。这个程序的主要代码逻辑如下:

// 读如PNG格式的图片
Image image = toolkit.createImage(filename);
// 获取图片的所有像素信息
PixelGrabber pg = new PixelGrabber(image, 0, 0, ...);
// 遍历每个像素,将色彩置入色彩表中,并增加相应色彩的计数值
for (int c : pixels)
{
Color color = new Color(c);
Integer weight = colorTable.get(color);
if (weight == null) weight = new Integer(1);
else weight = new Integer(weight.intValue() + 1);
colorTable.put(color, weight);
}
// 将统计结果输出为XML格式的数据库文件
for (Map.Entry<Integer, Color> s : colorSet)
...

利用由此得到的色彩数据库,我们就可以直接编程序生成每个网页设计的配色方案了(生成结果也是一张PNG图片)。这时,我选用的编程语言是Python/wxPython。生成配色方案图片的主要代码逻辑如下:

# 读入网页数据库和配色数据库中的相关信息
imagesFile = file(IMAGES_FILE, "rU")
imagesLines = imagesFile.readlines()
...
# 在配色数据库中找出与当前网页截图匹配的记录
# 并根据色彩分布面积选出其中最重要的几种色彩来
matchlines = filter(lambda x: x.startswith(...), imagesLines)
...
# 在一个wx.App的派生类中创建DeviceContent
# 画出配色方案的色彩图样,以及表示RGB值的文字信息
# 然后将结果存入新的PNG图片文件中
class iDesignApp(wx.App):
def OnInit(self):
bmp = wx.EmptyBitmap(CANVAS_WIDTH, CANVAS_HEIGHT, 24)
dc = wx.MemoryDC()
dc.SelectObject(bmp)
DrawPalette(dc)
dc.SelectObject(wx.NullBitmap)
bmp.SaveFile(g_OutputFile, wx.BITMAP_TYPE_PNG)
return False

自动生成全部书稿

最后,只需要根据各类目的选取原则,从数据库中选择合适的网页设计,并生成全部书稿就可以了。此过程包含两个关键点,一是要保证每个类目中网页数量的相对均衡,二是要根据每个关键词的出现位置自动生成全书的关键词索引。
生成书稿的程序是用Python编写的,其主要代码逻辑如下:

# 读入XML格式的数据库文件
f = file(INDEX_FILE, "rU")
indexLines = f.readlines()
...
# 先将所有记录归入按内容划分的类目中
for line in indexLines:
rec = line.split(FIELD_SEP)
class_table[rec[CLASS_SEQ]].append(rec)
# 然后随机选取一半左右的记录,将它们移动到按主色调划分的类目里
# 移动的同时需要保证各类目中记录数量的均衡
for c in CLASSES:
num1 = len(class_table[c])
num2 = num1 - NUM_PER_CLASS
...
i = random.randint(0, len(class_table[c]) - 1)
rec = class_table[c][i]
color_table[rec[COLOR_SEQ]].append(rec)
del class_table[c][i]
num2 = num2 - 1
# 生成书稿正文,生成的同时记录每个关键词的出现位置
for c in CLASSES:
for rec in class_table[c]:
image_no = image_no + 1
output_item(bookFile, rec, image_no, logFile, 0)
for keyword in keywords:
keyword_table[keyword].append(image_no)
# 生成全书的关键词索引
for k in keywordsLines:
bookFile.write(k)
bookFile.write('\t')
bookFile.write(str(keyword_table[k]))

这样生成的书稿就可以交给出版社排版、编辑了。
需要说明一下,因为牵涉到全书的版式设计、纸张选择、印刷方式等问题,后期的排版和编辑工作必须由出版社来做。假如不考虑这些问题,我们也完全可以使用Word或PageMaker提供的自动化功能,直接由电脑自动生成全书最终的排版结果。这样,图书付印之前的绝大多数工序都可以实现“自动化”了。

写在最后的话

这篇后记简单记录了本书的制作过程,也为大家提供了一些相关的编程技巧和源码示例。这些东西看起来似乎与网页设计无关。但我想强调的一点是:无论是网页设计师还是软件工程师,大家都应该善于利用手边的电脑和软件工具,因为只有这样才能把所有重复性的劳动交给电脑,然后把所有创造性的工作留给自己!
拿这本书的制作过程来说,我既使用了Photoshop和Excel软件提供的自动化功能,也使用了C++、VBA、Java、Python这样的编程语言,还与IE的插件打了些交道——看起来有些驳杂,但仔细想想,我为每个环节选用的似乎还都是实现起来最简单、使用起来最便捷的技术方案。
我想,无论是编程序还是设计网页,我们都不必将自己禁锢在某种工作模式或某些平台、工具构成的小圈子里——在需求的指引下,选择那些最灵活、最简单、最便捷的解决方案,这才是一个聪明人应该做的事。

周虹,王咏刚
2005年9月

用电脑“自动生成”的图书相关推荐

  1. 3d 自动生成物体_根据 2D 图片自动生成 3D 图书封面的牛逼工具

    小金子 读完需要 2分钟 速读仅需 1 分钟 大家好,我是你们的小金子. 今天要给推荐一个小众但很实用的工具,毕竟要用这个工具,你要么是图书工作者,要么就得自己写过书. 它就是一款能够根据 2D 图片 ...

  2. 根据 2D 图片自动生成 3D 图书封面的牛逼工具

    大家好,我是你们的小金子. 今天要给推荐一个小众但很实用的工具,毕竟要用这个工具,你要么是图书工作者,要么就得自己写过书. 它就是一款能够根据 2D 图片自动生成 3D 图书封面的工具,完全使用 CS ...

  3. movelast对数据记录数有要求吗_客户验厂,电脑坏了,考勤记录数据可以自动生成找回来吗?...

    客户验厂 ,电脑坏了 考勤记录数据可以自动生成找回来吗?工厂验厂 之前考勤记录找不到了,可以自动生成考勤记录和工资数据吗? 工厂电脑突然坏了,好烦啊 重庆江津区的一家工厂的考勤操作人员张小姐,最近碰到 ...

  4. 基于.Net Core Web MVC的图书查询系统——第四章,添加模型并使用EF Core生成基架自动生成控制器和视图

    基于.Net Core Web MVC的图书查询系统 第一章,.Net Core Web MVC配置身份验证和注册登录功能并修改默认页面 第二章,.Net Core Web MVC配置邮件发送服务 第 ...

  5. 电脑表格日期怎么修改原有日期_如何在Excel表中自动生成记录数据的日期和时间...

    几天前有人问我: 在Excel表格中输入信息时,如何在日期单元格中自动生成日期和时间? 输入表格时,我们经常需要输入时间,而不是填写存储时间,为了减少输入工作量,您可以将日期设置为自动生成. 例如,当 ...

  6. Camtasia2023电脑录屏视频自动生成字幕软件

    制作视频通常需要添加字幕,添加字幕比较麻烦的是让字幕和声音同步,使用好的软件可以大大提高剪辑效率,让视频更快制作完成.本文将给大家介绍录制视频自动生成字幕的软件设置字幕语音同步教程. 一.录屏视频自动 ...

  7. DRF 自动生成接口文档

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  8. RESTful之自动生成接口文档

    REST framework可以自动帮助我们生成接口文档.[必须是继承自rest_framework才会自动生成文档] 接口文档以网页的方式呈现. 自动接口文档能生成的是继承自APIView及其子类的 ...

  9. 微页导出为html文件怎么打开吗,h5自动生成工具(示例代码)

    一.前言 写了很多h5之后,对于写手写html和css已经麻木的我决定动手写个工具自动生成h5结构和样式.其实这个想法由来已久,但总是觉得自己技术不够,所以一直没实行.直到某天我真的写够了,我决定动手 ...

最新文章

  1. @Ignore_JUnit - Ignore Test
  2. java 反射 修改字段_Java反射机制-修改字段值
  3. DataTable.DataRow的复制
  4. 一次线上内存报警的研究
  5. spring-data-mongodb与mongo shell的对应关系
  6. 参考例子,学习FuncT, TResult委托
  7. BZOJ 3669 . JZOJ 3754. 【NOI2014】魔法森林
  8. OPenGL模板缓冲区示例程序
  9. php百度搜索框代码,基于jquery的仿百度搜索框效果代码_jquery
  10. Netty源码学习(零)前言
  11. linux 删除分区_详解linux系统架构--文件系统体系
  12. html5的canvas绘制时钟
  13. 什么是Shell、Shell脚本
  14. 金融数据分析与挖掘实战练习-1.9
  15. html设置在父元素底部对齐,如何将div对齐到父元素的底部
  16. 算数编码java_算术编码核心类
  17. 使用qq邮箱服务器来实现laravel的邮件发送
  18. 企业应用快速跨向容器时代的正确姿势
  19. 对比线程,一个VCPU是什么
  20. 高校邮箱账号盗用监控及钓鱼邮件检测-上海交通大学

热门文章

  1. 噩梦射手(SurvivalShooter)教程(一)
  2. 《云计算》SELinux安全防护(案例)
  3. 企业邮箱登录入口首页是哪个,公共电子邮箱怎么申请注册?
  4. IFS认证辅导,国际食品企业认证BRC和IFS起源和发展
  5. 程序员如何利用技术变现?
  6. 图像处理与机器视觉网络资源
  7. TiDB+TiSpark部署--安装,扩缩容及升级操作
  8. 小身板干大事:DATAhawk无人机独创手抛起飞实现3厘米精准测绘
  9. OSChina 周六乱弹 —— 啊,谢谢好心的先生
  10. python爬去百度文库资料_Python在线百度文库爬虫(免下载券)