<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mingbo &#187; 教育技术学</title>
	<atom:link href="http://shao.mingbo.de/category/%e6%95%99%e8%82%b2%e6%8a%80%e6%9c%af%e5%ad%a6/feed/" rel="self" type="application/rss+xml" />
	<link>http://shao.mingbo.de</link>
	<description>包括教育技术，编程，互联网等方面的文章及随想。</description>
	<lastBuildDate>Sun, 25 Jul 2010 05:18:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>超文本转移协议与万维网高速缓存</title>
		<link>http://shao.mingbo.de/2010/02/26/proxy-server-with-web-cache-and-http/</link>
		<comments>http://shao.mingbo.de/2010/02/26/proxy-server-with-web-cache-and-http/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 07:50:04 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[教育技术学]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[ipv6]]></category>
		<category><![CDATA[web cache]]></category>
		<category><![CDATA[代理服务器]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=472</guid>
		<description><![CDATA[HTTP协议
HTTP是一个客户端和服务器端请求和应答的标准。从层次的角度看，HTTP是面向事务（所谓事务就是指一系列的信息交换，而这一系列交换是一个不可分割的整体，即要么所有的信息交换都完成，要么一次交换都不进行）的应用层协议，是万维网上能够可靠地交换文件的重要基础。
服务器进程不断的监听指定端口（默认端口为80），用来判断是否有浏览器（网络爬虫或其他客户进程）向它发出连接建立请求。当判断为真并建立连接之后，客户进程向源服务器（Origin Server）发出HTTP请求，源服务器响应，最后连接被释放。这样的操作交互遵循一定的规则与格式标准，而这个标准就是超文本转移协议HTTP。
HTTP虽然使用了TCP，但其本身是无状态的（stateless）。换句话说，同一个客户端第二次访问同一个服务器上的页面时，服务器的响应与第一次的相同。虽然TCP是面向连接的向上提供服务，但HTTP协议本身是无连接的。
尽管TCP/IP协议是互联网上最流行的应用，但HTTP协议并没有规定必须使用它和（基于）它支持的层。 事实上，HTTP可以在任何其他互联网协议上，或者在其他网络上实现。HTTP只假定（其下层协议提供）可靠的传输，任何能够提供这种保证的协议都可以被其使用。
HTTP报文
HTTP有两类报文，一种是请求报文，另一种是响应报文。它们都由三个部分组成。从下图不难看出，两种报文结构的开始行略有不同。



方法
空格
URL
空格
版本
CRLF


首部字段名：
空格
值
CRLF
 
 


…


首部字段名：
空格
值
CRLF
 
 


CRLF


实体主体（通常不用）



(a)  请求报文



版本
空格
状态码
空格
短语
CRLF


首部字段名：
空格
值
CRLF
 
 


…


首部字段名：
空格
值
CRLF
 
 


CRLF


实体主体（有些响应报文不用）



(b)  响应报文
1)    开始行，用于区分是请求报文还是响应报文。所有HTTP请求的第一行都是请求行，主要包含请求方法，请求资源的URL，以及HTTP的版本；而响应报文的开始行叫做状态行，主要包含HTTP的版本，状态码以及其对应的短语。它们都用空格隔开，CR代表回车，LF代表换行。
2)    首部（Head）行，用来描述浏览器（网络爬虫等）或服务器的一些信息。它可以有好几行，每一行都必须有CR与LF。整个首部行结束之后，还用一个CRLF将其与实体隔开。
3)    实体主体（Entity Body），请求报文中一般不用这个字段（只有请求方法要求时才会被放在请求消息中），而响应报文里也可以没有。
其中值得注意的是，状态代码的第一个数字代表当前响应的类型：

1xx 消息——请求已被服务器接收，继续处理
2xx 成功——请求已成功被服务器接收、理解、并接受
3xx 重定向——需要后续操作才能完成这一请求
4xx 请求错误——请求含有词法错误或者无法被执行
5xx 服务器错误——服务器在处理某个正确请求时发生错误

虽然 RFC 2616 中已经推荐了描述状态的短语，例如&#8221;200 OK&#8221;，&#8221;404 Not Found&#8221;，但是 WEB 开发者仍然能够自行决定采用何种短语，用以显示本地化的状态描述或者自定义信息。
可以看到的是，HTTP仍在不断的发展。现在的较新的版本是1999年公布的HTTP/1.1[RFC 2616]，它已成为因特网草案标准。而下一代HTTP(HTTP-NG)则正在研究之中。
万维网高速缓存
万维网高速缓存（Web cache）是代理服务器的一种功能，它将最近的一些请求与响应暂存在代理服务器的本地磁盘中。如果新的请求与代理服务器的缓存吻合，则直接从代理服务器返回响应；反之，则需要按照请求的URL再次通过Internet访问该资源。其大致过程如下：
1)    客户端（浏览器）需要发送请求时，与带有Web Cache功能的代理服务器建立TCP连接，并向代理服务器发送HTTP请求报文。
2)    如果代理服务器已经存放了所请求的对象，则直接将其放入HTTP响应报文中返回给客户端（浏览器）。
3)    否则，代理服务器就代表客户端（浏览器），与Internet上的源服务器建立TCP连接，并发送HTP请求报文，源服务器把请求对象放在HTTP响应报文中返回给代理服务器。
4)    代理服务器获得该对象之后，先复制保存到本地磁盘（为其日后服务），再将该对象放在HTTP响应报文中，通过之前与客户端建立的TCP返回给用户（浏览器）。
其中，保存到本地磁盘以及返回响应之前，我们Ipv6项目还有很多事要做。
]]></description>
			<content:encoded><![CDATA[<h1><strong>HTTP</strong><strong>协议</strong></h1>
<p>HTTP是一个客户端和服务器端请求和应答的标准。从层次的角度看，HTTP是面向事务（所谓事务就是指一系列的信息交换，而这一系列交换是一个不可分割的整体，即要么所有的信息交换都完成，要么一次交换都不进行）的应用层协议，是万维网上能够可靠地交换文件的重要基础。</p>
<p><strong>服务器进程</strong>不断的监听指定端口（默认端口为80），用来判断是否有浏览器（网络爬虫或其他<strong>客户进程</strong>）向它发出连接建立请求。当判断为真并建立连接之后，客户进程向源服务器（Origin Server）发出HTTP请求，源服务器响应，最后连接被释放。这样的操作交互遵循一定的规则与格式标准，而这个标准就是超文本转移协议HTTP。</p>
<p>HTTP虽然使用了TCP，但其本身是<strong>无状态的（stateless）</strong>。换句话说，同一个客户端第二次访问同一个服务器上的页面时，服务器的响应与第一次的相同。虽然TCP是面向连接的向上提供服务，但HTTP协议本身是<strong>无连接的</strong>。</p>
<p>尽管TCP/IP协议是互联网上最流行的应用，但HTTP协议并没有规定必须使用它和（基于）它支持的层。 事实上，HTTP可以在任何其他互联网协议上，或者在其他网络上实现。<strong>HTTP只假定（其下层协议提供）可靠的传输，任何能够提供这种保证的协议都可以被其使用</strong>。</p>
<h1><strong>HTTP</strong><strong>报文</strong></h1>
<p>HTTP有两类报文，一种是请求报文，另一种是响应报文。它们都由三个部分组成。从下图不难看出，两种报文结构的开始行略有不同。</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">方法</td>
<td valign="top">空格</td>
<td valign="top">URL</td>
<td valign="top">空格</td>
<td valign="top">版本</td>
<td valign="top">CRLF</td>
</tr>
<tr>
<td valign="top">首部字段名：</td>
<td valign="top">空格</td>
<td valign="top">值</td>
<td valign="top">CRLF</td>
<td valign="top"> </td>
<td valign="top"> </td>
</tr>
<tr>
<td colspan="6" valign="top">…</td>
</tr>
<tr>
<td valign="top">首部字段名：</td>
<td valign="top">空格</td>
<td valign="top">值</td>
<td valign="top">CRLF</td>
<td valign="top"> </td>
<td valign="top"> </td>
</tr>
<tr>
<td colspan="6" valign="top">CRLF</td>
</tr>
<tr>
<td colspan="6" valign="top">实体主体（通常不用）</td>
</tr>
</tbody>
</table>
<p>(a)  请求报文</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top">版本</td>
<td valign="top">空格</td>
<td valign="top">状态码</td>
<td valign="top">空格</td>
<td valign="top">短语</td>
<td valign="top">CRLF</td>
</tr>
<tr>
<td valign="top">首部字段名：</td>
<td valign="top">空格</td>
<td valign="top">值</td>
<td valign="top">CRLF</td>
<td valign="top"> </td>
<td valign="top"> </td>
</tr>
<tr>
<td colspan="6" valign="top">…</td>
</tr>
<tr>
<td valign="top">首部字段名：</td>
<td valign="top">空格</td>
<td valign="top">值</td>
<td valign="top">CRLF</td>
<td valign="top"> </td>
<td valign="top"> </td>
</tr>
<tr>
<td colspan="6" valign="top">CRLF</td>
</tr>
<tr>
<td colspan="6" valign="top">实体主体（有些响应报文不用）</td>
</tr>
</tbody>
</table>
<p>(b)  响应报文</p>
<p>1)    开始行，用于区分是请求报文还是响应报文。所有HTTP请求的第一行都是请求行，主要包含请求方法，请求资源的URL，以及HTTP的版本；而响应报文的开始行叫做状态行，主要包含HTTP的版本，状态码以及其对应的短语。它们都用空格隔开，CR代表回车，LF代表换行。</p>
<p>2)    首部（Head）行，用来描述浏览器（网络爬虫等）或服务器的一些信息。它可以有好几行，每一行都必须有CR与LF。整个首部行结束之后，还用一个CRLF将其与实体隔开。</p>
<p>3)    实体主体（Entity Body），请求报文中一般不用这个字段（只有请求方法要求时才会被放在请求消息中），而响应报文里也可以没有。</p>
<p>其中值得注意的是，状态代码的第一个数字代表当前响应的类型：</p>
<ul>
<li>1xx 消息——请求已被服务器接收，继续处理</li>
<li>2xx 成功——请求已成功被服务器接收、理解、并接受</li>
<li>3xx 重定向——需要后续操作才能完成这一请求</li>
<li>4xx 请求错误——请求含有词法错误或者无法被执行</li>
<li>5xx 服务器错误——服务器在处理某个正确请求时发生错误</li>
</ul>
<p>虽然 RFC 2616 中已经推荐了描述状态的短语，例如&#8221;200 OK&#8221;，&#8221;404 Not Found&#8221;，但是 WEB 开发者仍然能够自行决定采用何种短语，用以显示本地化的状态描述或者自定义信息。</p>
<p>可以看到的是，HTTP仍在不断的发展。现在的较新的版本是1999年公布的HTTP/1.1[RFC 2616]，它已成为因特网草案标准。而下一代HTTP(HTTP-NG)则<a title="HTTP-NG" href="http://www.w3.org/Protocols/HTTP-NG/http-ng-status.html" target="_blank">正在研究之中</a>。</p>
<h1><strong>万维网高速缓存</strong></h1>
<p>万维网高速缓存（Web cache）是<a title="代理服务器的功能" href="http://zh.wikipedia.org/zh-cn/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8#.E4.BB.A3.E7.90.86.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84.E5.8A.9F.E8.83.BD" target="_blank">代理服务器的一种功能</a>，它将最近的一些请求与响应暂存在代理服务器的本地磁盘中。如果新的请求与代理服务器的缓存吻合，则直接从代理服务器返回响应；反之，则需要按照请求的URL再次通过Internet访问该资源。其大致过程如下：</p>
<p>1)    客户端（浏览器）需要发送请求时，与带有Web Cache功能的代理服务器建立TCP连接，并向代理服务器发送HTTP请求报文。</p>
<p>2)    如果代理服务器已经存放了所请求的对象，则直接将其放入HTTP响应报文中返回给客户端（浏览器）。</p>
<p>3)    否则，代理服务器就代表客户端（浏览器），与Internet上的源服务器建立TCP连接，并发送HTP请求报文，源服务器把请求对象放在HTTP响应报文中返回给代理服务器。</p>
<p>4)    代理服务器获得该对象之后，先复制保存到本地磁盘（为其日后服务），再将该对象放在HTTP响应报文中，通过之前与客户端建立的TCP返回给用户（浏览器）。</p>
<p>其中，保存到本地磁盘以及返回响应之前，<strong>我们Ipv6项目还有很多事要做</strong>。</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2010/02/26/proxy-server-with-web-cache-and-http/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WMEncoder批处理功能实现</title>
		<link>http://shao.mingbo.de/2009/10/18/wmencoder-batch-function-completed/</link>
		<comments>http://shao.mingbo.de/2009/10/18/wmencoder-batch-function-completed/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 17:20:30 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[教育技术学]]></category>
		<category><![CDATA[碎碎念]]></category>
		<category><![CDATA[ipv6]]></category>
		<category><![CDATA[总结]]></category>
		<category><![CDATA[批处理]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=138</guid>
		<description><![CDATA[这段时间的学习和工作很难用乐观的言语表述。从接到这个任务的那天开始，不知不觉的，提交一份完整可用的代码变成了我生活的中心。可怕的是，周围的人都用异样的眼光看待我宅代码的行为。我能猜到他们在想什么，但，我就是不自觉的被这个中心左右着。
如果接下来的周一和张博后的交流没有问题，那么这个批处理功能的实现，应该就是我功成身退的礼物。第一次做转换工具，第一次看全英文的sdk，第一次和博后级的牛人交流，第一次用c#建立一个工程文件夹，很多个第一次都将变成美好的回忆&#8230;
很自然地，做项目的过程中，看到了自己很多知识还很不到位：本科时，《操作系统》完全没怎么重视，只是等到考试才临时抱佛脚，而今遇到有关线程的问题，又要重头来过；基础的算法思想没有打牢，没有打牢的直接后果是，代码臃肿而低效。工具语言没摸透，使用起来，生搬硬套&#8230;哎，说得自己一无是处了。
不过好在，接下来的日子里，我还有有机会&#8230;呃，希望在转角，命运在手中，笑一个吧？
update: 今天把技术文档写了下，呃，这里是在线浏览地址
]]></description>
			<content:encoded><![CDATA[<p><a href="http://shao.mingbo.de/wp-content/uploads/2009/10/newTool.jpg"><img class="alignleft size-thumbnail wp-image-139" title="批处理" src="http://shao.mingbo.de/wp-content/uploads/2009/10/newTool-150x150.jpg" alt="批处理" width="150" height="150" /></a>这段时间的学习和工作很难用乐观的言语表述。从接到这个任务的那天开始，不知不觉的，提交一份完整可用的代码变成了我生活的中心。可怕的是，周围的人都用异样的眼光看待我宅代码的行为。我能猜到他们在想什么，但，我就是不自觉的被这个中心左右着。</p>
<p>如果接下来的周一和张博后的交流没有问题，那么这个批处理功能的实现，应该就是我功成身退的礼物。第一次做转换工具，第一次看全英文的sdk，第一次和博后级的牛人交流，第一次用c#建立一个工程文件夹，很多个第一次都将变成美好的回忆&#8230;</p>
<p>很自然地，做项目的过程中，看到了自己很多知识还很不到位：本科时，《操作系统》完全没怎么重视，只是等到考试才临时抱佛脚，而今遇到有关线程的问题，又要重头来过；基础的算法思想没有打牢，没有打牢的直接后果是，代码臃肿而低效。工具语言没摸透，使用起来，生搬硬套&#8230;哎，说得自己一无是处了。</p>
<p>不过好在，接下来的日子里，我还有有机会&#8230;呃，希望在转角，命运在手中，笑一个吧？</p>
<p>update: 今天把技术文档写了下，呃，这里是<a href="http://docs.google.com/fileview?id=0B-rB_h6wwwpEODNlMzEwM2UtMDhjNi00ZjVkLTg0ZmItY2MzNDZkMDZiZmVm&amp;hl=zh_CN" target="_blank">在线浏览地址</a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/10/18/wmencoder-batch-function-completed/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>六十岁的中国，二十岁的我(2)</title>
		<link>http://shao.mingbo.de/2009/10/10/ipv6-web-auto-adaptation/</link>
		<comments>http://shao.mingbo.de/2009/10/10/ipv6-web-auto-adaptation/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 07:49:34 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[教育技术学]]></category>
		<category><![CDATA[ipv6]]></category>
		<category><![CDATA[图片压缩]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[网页自适应]]></category>
		<category><![CDATA[视频压缩]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=110</guid>
		<description><![CDATA[这个假期的大部分时间，主要还是宅code。正如上次提到的，我的具体任务是：研制现有资源向移动学习终端系统显示模式的资源转换工具，以及相关的全套技术文档。接单之后，任务很自然的被我分解为：视频、图片和html三个处理模块。（移动学习终端方面，是用的TCL的IOpen来做测试的）。截止至7号凌晨5点16分，整个任务的基本功能全部实现。
图片处理这块，毫无疑问的，我是走了一大圈弯路。 不敢说自己是一个java程序员，但让一个学习了java的人转过头来搞c#，这无疑会带着很复杂的感情。正如Jesse在他的著作里谈的那样：
Java programmers may look at C# with a mixture of trepidation, glee, and resentment. It has been suggested that C# is somehow a &#8220;rip-off&#8221; of Java. I won&#8217;t comment on the religious war between Microsoft and the &#8220;anyone but Microsoft&#8221; crowd, except to acknowledge that C# certainly learned a great deal from Java. But [...]]]></description>
			<content:encoded><![CDATA[<p>这个假期的大部分时间，主要还是宅code。正如上次提到的，我的具体任务是：<strong>研制现有资源向移动学习终端系统显示模式的资源转换工具，以及相关的全套技术文档</strong>。接单之后，任务很自然的被我分解为：视频、图片和html三个处理模块。（移动学习终端方面，是用的TCL的<a href="http://cn.engadget.com/2008/09/12/tcls-iopen-081a-no-lipstick-on-this-pig/" target="_blank">IOpen</a>来做测试的）。截止至7号凌晨5点16分，整个任务的基本功能全部实现。</p>
<p>图片处理这块，毫无疑问的，我是走了一大圈弯路。 不敢说自己是一个java程序员，但让一个学习了java的人转过头来搞c#，这无疑会带着很复杂的感情。正如Jesse在他的著作里谈的那样：</p>
<blockquote><p>Java programmers may look at C# with a mixture of trepidation, glee, and resentment. It has been suggested that C# is somehow a &#8220;rip-off&#8221; of Java. I won&#8217;t comment on the religious war between Microsoft and the &#8220;anyone but Microsoft&#8221; crowd, except to acknowledge that C# certainly learned a great deal from Java. But then Java learned a great deal from C++, which owed its syntax to C, which in turn was built on lessons learned in other languages. We all stand on the shoulders of giants.</p></blockquote>
<p>不管怎么说，凭着自己的那一点小个性，还是会想在java上小冲一把。当天接到的任务，无视老刘给出的要求，晚上就直接开始编写有关图片压缩的代码。并且，很快的取得了成效：（以下为java批量压缩图片的核心代码）</p>
<p>package imageCompress;<br />
import java.util.*;<br />
import java.io.*;<br />
import java.awt.*;<br />
import java.awt.image.BufferedImage;<br />
import com.sun.image.codec.jpeg.JPEGCodec;<br />
import com.sun.image.codec.jpeg.JPEGImageEncoder;</p>
<p>public class doCompress {</p>
<p>	private static String path;</p>
<p>	//获取压缩比例<br />
	public float getRatio(int width, int height, int maxWidth , int maxHeight)<br />
	{<br />
		float ratio=0;</p>
<p>		float widthR=(float)maxWidth/width;<br />
		float heightR=(float)maxHeight/height;</p>
<p>		if(widthR<1.0||heightR<1.0)<br />
		{<br />
			ratio=(widthR<=heightR?widthR:heightR);<br />
		}<br />
		return ratio;<br />
	}</p>
<p>	public void imgCompress(String path,String maxW, String maxH)<br />
	{<br />
		try {<br />
			imageSource iSource=new imageSource(path);<br />
			String[] imgNames=iSource.getImageNames();</p>
<p>			for(int i=0;i<imgNames.length;i++)<br title="六十岁的中国，二十岁的我(2)" alt=" 六十岁的中国，二十岁的我(2)" />
			{<br />
				Image img=javax.imageio.ImageIO.read(new File(path+"/PIC/"+imgNames[i]));;<br />
				int imgWidth=img.getWidth(null);<br />
				int imgHeight=img.getHeight(null);<br />
				float r=this.getRatio(imgWidth, imgHeight, Integer.parseInt(maxW), Integer.parseInt(maxH));</p>
<p>				imgWidth=(int)(imgWidth*r);<br />
				imgHeight=(int)(imgHeight*r);</p>
<p>				BufferedImage bimg=new BufferedImage(imgWidth,imgHeight,BufferedImage.TYPE_INT_RGB);</p>
<p>				Graphics2D g2=bimg.createGraphics();<br />
				g2.drawImage(img, 0, 0, imgWidth, imgHeight, Color.WHITE, null);<br />
				g2.dispose();</p>
<p>				FileOutputStream outputStream=new FileOutputStream(path+"/PIC/"+imgNames[i]);<br />
				JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(outputStream);<br />
				encoder.encode(bimg);<br />
				outputStream.close();<br />
			}</p>
<p>		} catch (Exception e) {<br />
			// TODO: handle exception<br />
			e.printStackTrace();<br />
		}<br />
	}<br />
}</p>
<p>
用java写完图片模块之后，等到我再接触视频模块时才发现，如果弃用WMEncoder提供的Interface（全微软接口），几乎是不能完成任务的。原因在每一次对视频进行ReEncode的时候，视频中存在的header file全部会丢失，导致三分屏课件没有办法让视频与ppt同步，而脚本也无法对视频进行点播控制。百般无奈的开始研究<a title="wmencoder" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5691ba02-e496-465a-bba9-b2f1182cdf24&amp;displaylang=en" target="_blank">WMEncoder</a>提供的<a href="http://www.microsoft.com/downloads/details.aspx?familyid=ACDDAAE1-93A9-4DD5-AAA2-5FB28C3BA43A&amp;displaylang=zh-cn" target="_blank">SDK</a>，开始基础的c#学习。</p>
<p><a href="http://shao.mingbo.de/wp-content/uploads/2009/10/encoder-struct.jpg"><img class="alignright size-thumbnail wp-image-112" title="encoder-struct" src="http://shao.mingbo.de/wp-content/uploads/2009/10/encoder-struct-150x150.jpg" alt="encoder struct 150x150 六十岁的中国，二十岁的我(2)" width="150" height="150" /></a>好在c#和java貌似同父异母的兄弟，语法套路很类似，再加上强大Visual Studio，用了不到3个小时，就可以上手了。呃，废话不多说，在这里想对视频压缩处理的相关核心部分做一下总结。首先是SDK，图中红线标出的即为需要用到的接口对象（点击可以查看大图）。其实对于视频操作的难点在于header file的处理。之前使用java的解决方案，我采用了一款名叫<a href="http://ffmpeg.org/documentation.html" target="_blank">ffmpeg</a>的视频开源项目代码。但处理后的视频没有办法再导入header，以至于让我的整个工作停滞了好几天。学习了sdk后，才发现WMEncBasicEdit Interface就能够较好的处理这一块的工作：</p>
<blockquote><p>The <strong>WMEncBasicEdit</strong> interface provids an Automation interface that  allows you to perform postprocessing on a Windows Media file, such as modifying  the attributes, specifying mark-in and mark-out times to change the length of  the file, adding scripts and markers, and indexing the file so that users can  use seek functions. An XML configuration file can be used to save and load  certain settings.</p></blockquote>
<p>不过，这里不得不谈到接口中的一个BUG。对于config的处理，如果视频文件过长，indexing的数目过多，则无法正常的导入header file.微软自己推出的解决方案中（Encoder Utilities-Windows Media File Editor）直接删除了最后的2个indexing.对于MS封装整个接口的做法，我是深表遗憾的。哎，下面是视频操作的核心代码：</p>
<p>using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using WMEncoderLib;<br />
using System.Windows.Forms;<br />
using System.IO;</p>
<p>namespace webAutoFinal<br />
{<br />
    class doVideoCompress<br />
    {</p>
<p>        public void getVideoConfige(string sourceUrl)<br />
        {<br />
            // bool flag;</p>
<p>            string vPath = sourceUrl + &#8220;\\stream.wmv&#8221;;<br />
            string cPath = sourceUrl + &#8220;\\config.xml&#8221;;<br />
            try<br />
            {<br />
                //创建后期编辑器<br />
                WMEncBasicEdit BasicEdit;<br />
                BasicEdit = new WMEncBasicEdit();</p>
<p>                //设定输入视频<br />
                BasicEdit.MediaFile = vPath;<br />
                BasicEdit.SaveConfigFile(cPath);<br />
                BasicEdit.Start();</p>
<p>            }<br />
            catch (Exception e)<br />
            {<br />
                // Console.WriteLine(e.StackTrace);<br />
                MessageBox.Show(&#8221;  public  void getVideoConfige(string sourceUrl) method has something wrong!(视频文件没找到)&#8221; + e.Message);<br />
            }</p>
<p>        }</p>
<p>        public bool compressVideo(string sourceUrl, string vParam)<br />
        {<br />
            string vPath = sourceUrl + @&#8221;\stream.wmv&#8221;;<br />
            string vPath2 = sourceUrl + @&#8221;\ostream.wmv&#8221;;<br />
            bool flag = false;</p>
<p>            try<br />
            {<br />
                //新建一个编码器<br />
                WMEncoder encoder = new WMEncoder();</p>
<p>                IWMEncSourceGroupCollection srcGroupCollection = encoder.SourceGroupCollection;<br />
                IWMEncSourceGroup srcGroup = srcGroupCollection.Add(&#8220;SG_1&#8243;);</p>
<p>                //输入选项<br />
                //添加音频源<br />
                IWMEncSource srcAudio = srcGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);<br />
                //添加视频源<br />
                IWMEncVideoSource2 srcVideo = (IWMEncVideoSource2)srcGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);<br />
                srcAudio.SetInput(vPath, &#8220;&#8221;, &#8220;&#8221;);<br />
                srcVideo.SetInput(vPath, &#8220;&#8221;, &#8220;&#8221;);</p>
<p>                //输出选项<br />
                IWMEncFile file = encoder.File;<br />
                file.LocalFileName = vPath2;</p>
<p>                IWMEncProfileCollection ProColl = encoder.ProfileCollection;<br />
                IWMEncProfile Pro;<br />
                for (int i = 0; i < ProColl.Count; i++)<br />
                {<br />
                    Pro = ProColl.Item(i);<br />
                    if (Pro.Name == vParam)<br />
                    {<br />
                        srcGroup.set_Profile(Pro);<br />
                        break;<br />
                    }<br />
                }</p>
<p>                //开始压缩<br />
                encoder.PrepareToEncode(true);<br />
                encoder.Start();</p>
<p>                WMENC_ENCODER_STATE iEncoderState; //定义encoder的运行状态<br />
                iEncoderState = encoder.RunState;</p>
<p>                IWMEncStatistics Stats;  //定义 统计对象<br />
                decimal lEncTime;       //定义 已编码的时长</p>
<p>                //获取视频源的时长<br />
                int lVidDuration = srcVideo.Duration / 1000;</p>
<p>                //    Console.WriteLine("****** Now ,Video-Compression Session Working ******");<br />
                while (iEncoderState != WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)<br />
                {<br />
                    //获得当前encoder的运行状态<br />
                    iEncoderState = encoder.RunState;<br />
                    // 获得encoder的统计对象<br />
                    Stats = encoder.Statistics;<br />
                    // 获得当前已编码的市场<br />
                    lEncTime = Stats.EncodingTime * 10;</p>
<p>                    //  MessageBox.Show("Encoder starts..");<br />
                    //  Console.Write("Encoder Status: {0} % of the video has benn encodered.", Math.Round(lEncTime / lVidDuration * 100, 0));</p>
<p>                    //   System.Threading.Thread.Sleep(100);<br />
                    if ((Math.Round(lEncTime / lVidDuration * 100)) == 100)<br />
                    {<br />
                        flag = true;<br />
                        break;<br />
                    }<br />
                    // encoder.AutoStop = true;</p>
<p>                }</p>
<p>                //释放编码器内存<br />
                encoder.Stop();<br />
                while (encoder.RunState != WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)<br />
                {<br />
                    System.Threading.Thread.Sleep(1000);<br />
                }<br />
                encoder.Reset();<br />
                encoder = null;<br />
                return flag;<br />
            }</p>
<p>            catch (Exception e)<br />
            {<br />
                //System.Console.Write(e.StackTrace);<br />
                MessageBox.Show("public bool compressVideo(string sourceUrl, string vParam) method has something wrong!\n" + e.Message);<br />
                return false;<br />
            }</p>
<p>        }</p>
<p>        public void loadVideoConfig(string sourceUrl)<br />
        {<br />
            string vPath = sourceUrl + "\\ostream.wmv";<br />
            string oPath = sourceUrl + "\\stream.wmv";<br />
            string cPath = sourceUrl + "\\config.xml";</p>
<p>            //bool flag = false;<br />
            if (System.IO.File.Exists(vPath)  &#038;&#038; System.IO.File.Exists(cPath))<br />
            {<br />
                try<br />
                {</p>
<p>                    // Create the WMEncBasicEdit object.<br />
                    WMEncBasicEdit BasicEdit;<br />
                    BasicEdit = new WMEncBasicEdit();<br />
                    BasicEdit.MediaFile = vPath;<br />
                    BasicEdit.OutputFile = oPath;<br />
                    BasicEdit.ConfigFile = cPath;</p>
<p>                    // Start the basic edit process.<br />
                    BasicEdit.Start();</p>
<p>                }<br />
                catch (Exception e)<br />
                {<br />
                    // Console.WriteLine(e.StackTrace);<br />
                    MessageBox.Show(" public void loadVideoConfig(string sourceUrl) method has something wrong!" + e.Message);<br />
                }<br />
            }<br />
            else<br />
                MessageBox.Show("some path can not find");<br />
        }</p>
<p>    }<br />
}</p>
<p>至于图片处理模块，我也用c#重写了两份批量压缩的代码。这一次的压缩不仅可以对分辨率控制，还可以对jpg压缩质量进行控制。核心代码如下：</p>
<p>using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.IO;<br />
using System.Drawing;<br />
using System.Windows.Forms;<br />
using System.Drawing.Imaging;</p>
<p>namespace webAutoFinal<br />
{<br />
    class doImageCompress<br />
    {<br />
        //获取资源包中所有图片的URL<br />
       public string[] loadDir(string fileFoldUrl)<br />
        {<br />
            string bg = fileFoldUrl + @"\skin\background.jpg";<br />
            fileFoldUrl += @"\pic\";</p>
<p>            if (System.IO.File.Exists(bg))<br />
                System.IO.File.Copy(bg, fileFoldUrl + @"\background.jpg",true);<br />
            string[] pics = null;<br />
            try<br />
            {<br />
                pics = Directory.GetFiles(fileFoldUrl, "*.jpg");<br />
            }<br />
            catch (Exception e)//未找到图片文件夹给出异常<br />
            {<br />
              //  Console.WriteLine("The source directory has something wrong!");<br />
              //  Console.WriteLine(e.StackTrace);<br />
                MessageBox.Show("doImageCompress.loadDir() Method got something wrong:"+e.Message);<br />
            }<br />
           // pics[pics.Length] = fileFoldUrl + @"\skin\background.jpg";</p>
<p>            return pics;<br />
        }</p>
<p>        //将单个图片文件转换成byte<br />
       public byte[] loadPicture(String filePath)<br />
        {<br />
            byte[] picData = null;<br />
            FileInfo fi = new FileInfo(filePath);</p>
<p>            if (fi.Exists)<br />
            {<br />
                picData = new byte[fi.Length];<br />
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);<br />
                BinaryReader br = new BinaryReader(fs);<br />
                br.Read(picData, 0, Convert.ToInt32(fi.Length));<br />
                fs.Dispose();<br />
            }<br />
            else<br />
            {<br />
               // Console.WriteLine("can not find the picture!");<br />
                MessageBox.Show("doImageCompress.loadPicture() Method got something wrong: can not find the picture!");<br />
            }<br />
            return picData;<br />
        }</p>
<p>        //图片压缩<br />
       public void compressPicuture(string filePath, int width, int height)<br />
        {<br />
            try<br />
            {<br />
                byte[] picByte = this.loadPicture(filePath);<br />
                MemoryStream ms = new MemoryStream(picByte);<br />
                System.Drawing.Image img = System.Drawing.Image.FromStream(ms);<br />
                Bitmap bmp = new Bitmap(img, width, height);<br />
                bmp.Save(filePath);<br />
            }<br />
            catch (Exception e)<br />
            {<br />
                Console.WriteLine(e.StackTrace);<br />
            }<br />
        }</p>
<p>        //新压缩方法</p>
<p>        private ImageCodecInfo GetEncoder(string mimeType)<br />
{</p>
<p>    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();</p>
<p>    foreach (ImageCodecInfo codec in codecs)<br />
    {<br />
        if (codec.MimeType == mimeType)<br />
        {<br />
            return codec;<br />
        }<br />
    }<br />
    return null;<br />
}</p>
<p>        //设置压缩级别   0--100L<br />
        public void jpgLevel(Bitmap bmp, string fileName)<br />
        {</p>
<p>            EncoderParameters ps = new EncoderParameters(1);<br />
            EncoderParameter p = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,100L);<br />
            ps.Param[0] = p;<br />
            bmp.Save(fileName, this.GetEncoder("image/jpeg"), ps);</p>
<p>        }<br />
        //设置分辨率<br />
        public void doCompressNEW(string fileName,int width,int height)<br />
        {<br />
           // Image img = Image.FromFile(fileName);<br />
            byte[] picByte = this.loadPicture(fileName);<br />
            MemoryStream ms = new MemoryStream(picByte);<br />
            System.Drawing.Image img = System.Drawing.Image.FromStream(ms);<br />
            Bitmap bmp = new Bitmap(img, width, height);<br />
            jpgLevel(bmp,fileName);<br />
            GC.Collect();<br />
           // bmp.Dispose();<br />
        }<br />
    }<br />
}</p>
<p>其实，整个程序到这里基本上完成了，整体做下来还是比较有成就感的。接下来的工作，应该是对批量处理资源包的功能进行扩充，以及相关技术文档的整理了。<br />
<a href="http://shao.mingbo.de/wp-content/uploads/2009/10/webAutoFace.jpg"><img class="aligncenter size-full wp-image-124" title="教育资源转换工具" src="http://shao.mingbo.de/wp-content/uploads/2009/10/webAutoFace.jpg" alt="教育资源转换工具" width="558" height="243" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/10/10/ipv6-web-auto-adaptation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>数码乌托邦</title>
		<link>http://shao.mingbo.de/2009/09/07/ubiquitous-computing/</link>
		<comments>http://shao.mingbo.de/2009/09/07/ubiquitous-computing/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 14:51:39 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[教育技术学]]></category>
		<category><![CDATA[从回收站找来的]]></category>
		<category><![CDATA[泛在学习]]></category>
		<category><![CDATA[泛在计算]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=6</guid>
		<description><![CDATA[
毋庸置疑的是，这是微软的设计师为我们勾勒的一副后信息时代的动态场景。你不必意识到计算机的存在，即可在anytime，anywhere，做 anything了。当然，那也是无时不刻，无处不在的浸泡在他们的产品之中。好了，抛开微软那个不光彩的垄断主义不谈，现在可以轻松的使用“你不必…你不必…”这个句式，仿造刚才我写的来造句。上面的podcast已经为你提供了丰富的素材，不是吗？
让我记忆犹新的是，华师大的赵呈领教授在我们研究生考试之前应邀来学校做了一个题为《泛在学习，泛在计算》的演讲。可惜的是，当时忙于备考，无法搜集到当时他的演讲稿。这里只对几个关键字做出注释，有兴趣的朋友，可以通过链接进行延伸阅读。
泛在计算&#124;Ubiquitous computing // 泛在学习&#124;Ubiquitous learning
我们如果把由经验引起的相对持久的行为、态度等方面的变化叫做学习的话，那么可以看到的是，泛在计算实际上为我们构建了一个良好的ubiquitous learning environment (ULE)。虽然，这些数码概念的最终实现面临的是困难重重，但同样是在若干年以前，我们也无法想象今天信息时代的便利景象。实现或者是超越？数码乌托邦令人神往！
]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"></p>
<p>毋庸置疑的是，这是微软的设计师为我们勾勒的一副后信息时代的动态场景。你不必意识到计算机的存在，即可在anytime，anywhere，做 anything了。当然，那也是无时不刻，无处不在的浸泡在他们的产品之中。好了，抛开微软那个不光彩的垄断主义不谈，现在可以轻松的使用“你不必…你不必…”这个句式，仿造刚才我写的来造句。上面的podcast已经为你提供了丰富的素材，不是吗？</p>
<p>让我记忆犹新的是，华师大的<a href="http://it.ccnu.edu.cn/show_teachers.aspx?id=1527">赵呈领教授</a>在我们研究生考试之前应邀来学校做了一个题为《泛在学习，泛在计算》的演讲。可惜的是，当时忙于备考，无法搜集到当时他的演讲稿。这里只对几个关键字做出注释，有兴趣的朋友，可以通过链接进行延伸阅读。</p>
<p style="text-align: center;"><a title="泛在计算" href="http://en.wikipedia.org/wiki/Ubiquitous_computing" target="_blank">泛在计算|Ubiquitous computing</a> // <a title="泛在学习" href="http://en.wikipedia.org/wiki/Ubiquitous_learning" target="_blank">泛在学习|Ubiquitous learning</a></p>
<p>我们如果把由经验引起的相对持久的行为、态度等方面的变化叫做学习的话，那么可以看到的是，泛在计算实际上为我们构建了一个良好的ubiquitous learning environment (ULE)。虽然，这些数码概念的最终实现面临的是困难重重，但同样是在若干年以前，我们也无法想象今天信息时代的便利景象。实现或者是超越？数码乌托邦令人神往！</p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/09/07/ubiquitous-computing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://shao.mingbo.de/flv/MS_Sustainability_web.flv" length="31066185" type="video/x-flv" />
<enclosure url="http://shao.mingbo.de/flv/MS_Sustainability_web.flv" length="31066185" type="video/x-flv" />
<enclosure url="http://shao.mingbo.de/flv/MS_Sustainability_web.flv" length="31066185" type="video/x-flv" />
<enclosure url="http://shao.mingbo.de/flv/MS_Sustainability_web.flv" length="31066185" type="video/x-flv" />
<enclosure url="http://shao.mingbo.de/flv/MS_Sustainability_web.flv" length="31066185" type="video/x-flv" />
		</item>
	</channel>
</rss>
