zoukankan      html  css  js  c++  java
  • 用电脑“自动生成”的图书

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

    收集优秀网页设计

    之所以有编写这本书的想法,主要是因为出版社的策划编辑们知道我手头有一个收录了近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月

  • 相关阅读:
    What is Split Brain in Oracle Clusterware and Real Application Cluster (文档 ID 1425586.1)
    Oracle Grid Infrastructure: Understanding Split-Brain Node Eviction (文档 ID 1546004.1)
    代理模式和装饰者模式区别
    偏向锁、轻量级锁、重量级锁
    理解HTTP幂等性
    Java8 lambda表达式10个示例
    IDEA debug断点调试技巧
    【1】【leetcode-115 动态规划】 不同的子序列
    【leetcode-91 动态规划】 解码方法
    【leetcode-78 dfs+回溯】 子集
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157212.html
Copyright © 2011-2022 走看看