孢子,一种另类的WP7第三方应用数据交换方式
《孢子》这个游戏玩过的人应该对里面的模型很有印象,尤其会对里面只靠一张PNG就能在游戏中还原成3D很感兴趣,今天要介绍的就是这种技术:在PNG里隐藏我们需要的数据,利用Zune同步到WP7,然后使用MediaLibrary或者PhotoChooserTask读取后经过解析获取隐藏的数据,从而达到想WP7导入任何数据的目的!
因为其来源于孢子,所以我也将其命名为“孢子”!
首先,有兴趣的朋友先可以看看PNG格式规范,这里有一排你文章详细讲解了PNG数据格式:[url]http://wenku.baidu.com/view/c495bf4569eae009581bec99.html[/url]
我们要做的,就是向PNG写入一个自定义数据块!
这是目前我定义一套数据存储规范,如有不当或更好的方案我们一起来完善
写入数据的核心代码如下:
public void Write(string[] filenames)
{
this.start = this.SourceStream.Length - IEND.Length;
// 提取结束标记
this.SourceStream.Position = this.start;
this.SourceStream.Read(this.IEND, 0, this.IEND.Length);
this.SourceStream.Position = this.start;
// 生成数据块标记
Array.Copy(Encoding.ASCII.GetBytes("IMHD"), 0, this.IMHD, 8, 4);
// 写入数据块起始标记
this.SourceStream.Write(this.IMHD, 0, this.IMHD.Length);
this.length += this.IMHD.Length;
// 写入数据内容
//byte[] h2 = Encoding.Unicode.GetBytes(BOUNDARY_HEADER);
//this.SourceStream.Write(h2, 0, h2.Length);
//this.length += h2.Length;
foreach (var file in filenames)
{
if (File.Exists(file))
{
var b1 = Encoding.Unicode.GetBytes(Path.GetFileName(file));
var b2 = BitConverter.GetBytes(b1.Length);
// 写入文件名长度
this.SourceStream.Write(b2, 0, b2.Length);
this.length += b2.Length;
// 写入文件名
this.SourceStream.Write(b1, 0, b1.Length);
this.length += b1.Length;
using (var fs = new FileStream(file, FileMode.Open))
{
var b3 = BitConverter.GetBytes(fs.Length);
// 写入文件长度
this.SourceStream.Write(b3, 0, b3.Length);
this.length += b3.Length;
// 写入文件内容
var buffer = new byte[8192];
var count = 0;
while (fs.Position < fs.Length)
{
count = fs.Read(buffer, 0, buffer.Length);
this.SourceStream.Write(buffer, 0, count);
}
this.length += fs.Length;
var b4 = BitConverter.GetBytes(CRC.CRC32(fs));
// 写入CRC校验
this.SourceStream.Write(b4, 0, b4.Length);
this.length += b4.Length;
}
}
}
// 写入数据总长度
var lenBytes = BitConverter.GetBytes(this.length - 4);
this.SourceStream.Position = this.start;
this.SourceStream.Write(lenBytes, 0, lenBytes.Length);
Debug.WriteLine("[w]length:" + (this.length - 4));
// 写入数据CRC
var crc = CRC.CRC32(this.SourceStream, this.start, this.length);
var crcBytes = BitConverter.GetBytes(crc);
this.SourceStream.Position = this.start + this.length;
this.SourceStream.Write(crcBytes, 0, crcBytes.Length);
Debug.WriteLine("[w]crc:" + crc);
// 回写结束标记
this.SourceStream.Write(this.IEND, 0, this.IEND.Length);
依赖此技术,WP7的数据同步障碍将不复存在,例如,我的书中圣,我可以将一本书打包进PNG,在阅读器里读出来;再比如,将一个rmvb文件打包进PNG,你可以开发个播放器,播放它!其他更多创意尽在你的想象!
本来想做个完整的Demo再放,但是看了下工作计划,貌似如果等完整Demo昨晚不知道猴年马月了,那就先放出来核心代码吧
包括了写入数据读取数据,测试用例是命令行项目,但放到WP7上也很简单,因为操作的都是流,只要你能获取图片流就能搞定,例如MediaLibrary,PhotoChooserTask等
希望这种技术能为大家带来帮助,另外本文提供的源代码,你可以随意修改,使用,但是如果你对其作了改进,希望能反馈给我一份,谢谢
源代码下载:http://files.cnblogs.com/zjfeiye/MoHooSpore.Demo.zip
最后说个事,有人宣称:
1)在图片中隐藏数据是他的专利,其他人要用这种方式必须提到是他发明的
2)在WP7中用PhotoChooserTask读取图片数据流是他的专利,其他人要用这种方式必须提到是他发明的
大家是否觉得可笑?本人在此不做任何评论,但本人也不声明此技术是本人原创,因为这种技术可以说早就被用烂了