抛砖引玉,孢子,一种另类的WP7第三方应用数据交换方式

孢子,一种另类的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等

 

希望这种技术能为大家带来帮助,另外本文提供的源代码,你可以随意修改,使用,但是如果你对其作了改进,希望能反馈给我一份,谢谢

 

源代码下载:https://files.cnblogs.com/zjfeiye/MoHooSpore.Demo.zip

 

最后说个事,有人宣称:

1)在图片中隐藏数据是他的专利,其他人要用这种方式必须提到是他发明的

2)在WP7中用PhotoChooserTask读取图片数据流是他的专利,其他人要用这种方式必须提到是他发明的

大家是否觉得可笑?本人在此不做任何评论,但本人也不声明此技术是本人原创,因为这种技术可以说早就被用烂了

posted @ 2011-07-15 13:06  阿干@NET  阅读(2770)  评论(11编辑  收藏  举报