FotoVision学习手记(1)

注:本文翻译自微软官网的《FotoVision Desktop Application》

FotoVision概述
 
      有两种用户:拥有者和浏览者。前者在本地系统上使用桌面应用来修改和管理照片。当照片要发布时,可以通过桌面应用使用一个Web服务来同步Web站点上的文件。通过在SOAP头部中传递Credentials(证书)可以防止非授权用户修改站点上的照片。浏览者通过一个Web浏览器来查看照片。Pocket PC应用使用另一个Web服务来下载和存储照片到本机上,以便可以离线查看。
fotovision_desktop_fig01.png
桌面应用概述
 
      桌面应用有三个主要功能:管理本地系统中的照片,处理照片,同步网站上的照片。它包含三个不同的面板:左边的管理相册,中间的显示照片,右边的显示照片的细节,还有一些象对比,亮度等工具。实现面板的类都在panes文件夹下,并且都继承自基类BasePane.

fotovision_desktop_fig02.png

相册和照片存储
 
      FotoVision使用文件系统和XML文件来作为一个简单的数据库。文件系统中的每个文件夹代表一个相册,而文件夹中的每个图象文件代表一个照片。可选的相册和照片元数据信息(例子的描述)储存在相应的XML文件中。
 
      任何引入到应用中的照片都会进行备份,这样原始的照片就不会被修改或者被删除。拷贝被放在MyDocuments\FotoVision\My Albums文件夹下。
 
缩略图
 
      当检测到新照片或已有照片被修改,FileManager类就会自动产生缩略图。这个类通过移除可疑图象(那些父图象已经被删除的缩略图)来同步缩略图。
 
      PhotoListView类在中间面板上显示照片缩略图。.net framework不支持用户-拖拉的列表视图控件,因此这个类从ListView类继承,并且捕获信息来创建一个用户自拖拉控件。它使用帮助类DropData来作为一个拖拽的目标和源。
fotovision_desktop_fig03.png

显示图片
 
PhotoViewer类以完整的大小显示图片。图片被重新调整大小来占据可有的画图区域。

fotovision_desktop_fig04.png

操纵大图片会是一个很耗费时间的操作。为了达到更好的性能,类中包含了一个工作图片,这是一个全额大小照片的缩小版本。当用户浏览时动作就应用到这个工作图片上,而当保存照片时就应用到全额大小图片上。类中定义了一些常量,这些常量定义了工作图片的分辨率和性能:

' these affect the quality of the working image and performance, they
' do not affect the quality of saved and published photos (affects 
' what you see on the screen but not what is saved to the file system)
Public Const WorkingInterpolationMode As _
  InterpolationMode = InterpolationMode.Bilinear
Public Const ViewingInterpolationMode As _
  InterpolationMode = InterpolationMode.Bilinear
Public Const WorkingScale As Single = 0.65F


为多个图片设置元数据
 
桌面应用的一个设计目标就是为了能够尽快输入元数据信息。DetailPhote类在一个可伸缩的列表中显示多个照片的细节信息。这使用户可以通过列表中的各个字段框来快速更新元数据。

 fotovision_desktop_fig05.png

这个类是一个用户拖拽的ListBox控件。ListBox中的每项包含了一张照片的元数据。列表可以包含成百照片。这个类使用三个文本框控件并且在适当的时候移动到合适的位置。这样,所有项都好象拥有活动的文本框控件,但实际上只使用了三个窗口指针。不活动区域可以通过用户拖拽来看起来象文本框。
 
操纵图片
 
      在上传到Web站点前,图片可以进行修改。DetailAction类包含了slider,updown控件和按纽来操纵图片。

fotovision_desktop_fig06.png

所有的图片操纵都封装在PhotoHelper类中。类大量使用ColorMatrix类,这个类使用一个5*5阵列来操纵图片而不是对图片每个象素进行循环和修改。除次以外,阵列也能够被拼凑并且在一次调用中应用到图片上,这就提供了更好的性能了。这个类支持以下操作:
1)              调整亮度,对比,饱和度,伽马
2)              转换至灰度以及Sepia
3)              旋转和翻转
4)              剪切大小和图象

下面这个例子使用了PhotoHelper类:

' increase the brightness of an image
Dim image As New Bitmap("sample.jpg")
PhotoHelper.AdjustBrightness(image, 50)//调整图片亮度

' convert an image to grayscale
Dim image As New Bitmap("sample.jpg")
PhotoHelper.ConvertToGrayscale(image)//转换至灰度

' do both operations in one call
Dim image As New Bitmap("sample.jpg")
Dim m1 As Single()() = PhotoHelper.GetBrightnessMatrix(50)
Dim m2 As Single()() = PhotoHelper.GetGrayscaleMatrix()
PhotoHelper.AdjustUsingCustomMatrix(image, _
   PhotoHelper.CombineMatrix(m1, m2))//拼凑亮度矩阵和灰度矩阵


动作列表
 
      ActionItem对象在每次图片被修改时就附加到一个列表(ActionList)中,例如,改变伽玛30%,转换至灰度或者水平翻转图片。这就可以允许动作能够不做(从列表中删除最后一个动作)并且能够把动作应用到不同图片上。如下图所示,当在屏幕上浏览图片时,动作列表就应用到工作图片上,并且当保存,打印和复制到剪切板时就应用到原始图片上。

fotovision_desktop_fig07.png

   OptimizeActions类通过将尽可能多个动作结合进一个单个动作来对动作进行优化。例如,颜色阵列动作亮度,对比,饱和度,灰度以及sepia都可以整合进一个单一动作中。另一个例子是多个旋转,执行3次左旋转和一次右旋转是一样的。你可以右键一个图片,选择“Properties”,”Actions”来查看当前的动作列表。
fotovision_desktop_fig08.png

使用JPEG图片
 
      代码中包含两个帮助类来方便JPEG图片的使用。
 
分辨率
      当保存图片时,.net framework中的Image类不允许你指定分辨率,至少没有任何一个Save方法有任何分辨率参数。你可以使用EncoderParameter和Image这两个类创建不同分辨率的JPEG图片。EncoderParameter类允许你指定介于1(低分辨率,高压缩率)和100(高分辨率,低压缩率)之间的分辨率。Image类默认使用的分辨率近似75。JpegQuality类将这进行了封装,你可以如下调用:

' save a high quality jpeg image
JpegQuality.Save("sample.jpg", image, 90)

' save a low quality jpeg image
JpegQuality.Save("sample.jpg", image, 30)


可交换的图片文件格式
 
      另一个.net framework不直接支持的地方是可交换图片文件(EXIF)数据。这是嵌入到图片文件内部的额外元数据信息;几乎所有的数码像机都存储EXIF信息。
      当你使用Image类来复制一个图片时这个信息就会丢失。在保存图片前你必须从PropertyItems集合中手动复制集合中的各项。Exif类封装了这个功能,这样你就可以在你的图片中维护EXIF数据。除次以外,类还可以抽取常见的EXIF标记,象照相机模型,暴光时间和用户评语等。
fotovision_desktop_fig09.png


反馈机制
 
      桌面应用程序有三种反馈机制:快速,中度,慢速。目标是以为用户提供足够的反馈。适当的反馈可以使用户的感知时间看起来更少,或者说当用户在屏幕上有有趣的东西看时不会发火。
 
快速反馈

      当一个操作只需要几秒钟时就发生快速反馈。在操作发生时显示一个等待光标并且应用程序锁定。用户可能感觉不到应用程序正忙。

中度反馈
     
当操作时间长于1秒而小于1分就会发生中度反馈。在状态栏的左边会显示一个等待图标和信息,而右边会显示一个进度条。应用程序会锁定至操作结束。
fotovision_desktop_fig10.png

桌面应用会调用DoEvents方法使得它可以重画,并且对WndProc方法进行重写以便只有画图信息会被处理。
 
 
慢速反馈
      若任务需要耗费很长的时间完成的话就会发生慢速反馈。在应用中有两种很耗时的操作:当照片发布时(调整大小),以及当文件上传到网站上。
 
      当这些操作进行时会显示一个进度条和其他信息。这样用户就可以知道系统正在进行的操作并且知道还剩余多少时间。在调整照片大小的时候应用程序会阻塞住,但当上传文件到站点时却不会被阻塞(用户还是可以删除照片,修改照片等)。

fotovision_desktop_fig11.png

上传文件到Web站点
 
      用于上传的代码在upload文件夹下,应用中有两个部分会上传文件到Web站点:发布文件和上传文件。
 
      Publish类通过对图片进行复制并且以一定的大小和JPEG分辨率(在SettingsForm类中指定)保存来准备要上传的图片。通过使用Hash值来对每个文件进行唯一识别,这样就使得只有修改过的图片才会调整大小。操作在一个工作线程中执行并且会引发事件来更新用户接口。
 
      当发布操作完成后,Upload类通过一个Web服务来对站点上的文件和本地系统上的文件进行同步。这包括相册,照片和元数据XML文件。它会从Web站点下载Hash值,这个值可以唯一识别站点上的文件,这样它就可以决定要上传的最小数据量。这个操作也在一个工作线程中执行并且会引发事件来更新用户接口。
 
      UploadForm类显示从两个工作线程中获取的信息,并且在更新用户界面元素之前通过调用Control.Invoke来对数据进行混淆。在使用Web服务时需要密码,密码以加密值的形式存储在应用程序的配置文件中。Upload类从配置文件中读取值(Settings类),通过DataProtection类的Data Protection接口来对值进行解密,对数据进行Hash(Hash类),并且在一个客户端的SOAP头部中储存这个值。下图显示了Upload类:
fotovision_desktop_fig12.png
 
      打印
     
      如下图,通过使用Windows XP图片打印向导来对打印图片。这个向导在系统文件photowiz.dll中实现。Print类封装在打印代码。
fotovision_desktop_fig13.png
 
小技巧
 
释放bitmap对象

      调用Dispose来释放Bitmap对象,否则将会阻塞并且若你尝试删除或者重写bitmap文件时会抛出一个异常。

' rotate an image, call Dispose when done
Dim image As New Bitmap("sample.jpg")
image.RotateFlip(RotateFlipType.Rotate90FlipX)
image.Save("new sample.jpg", Imaging.ImageFormat.Jpeg)
image.Dispose()    



本文转自Phinecos(洞庭散人)博客园博客,原文链接http://www.cnblogs.com/phinecos/archive/2006/09/30/518798.html,如需转载请自行联系原作者,如需转载请自行联系原作者
上一篇:ECS训练营——day4


下一篇:ECS训练营——day3