免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4784 | 回复: 19
打印 上一主题 下一主题

[算法] 坑啊,求大牛设计个算法解这个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-04-28 15:02 |只看该作者 |倒序浏览
因为要解析flash文件的文件头,掉到坑里了,目的是为了解出flash文件播放的原始尺寸,尺寸一共有四个值,分别是left,right,top,button。flash的奇葩就在于,他是这样存这个数据的,从文件头部的第9个字节开始,就是这个原始尺寸数据,首先,有一段5位(注意是位,不是字节)的数据用来表示尺寸值所占的位数,因为是5位无符号二进制数的值所以每个尺寸所占的位数最大不超过31,但是后面几很奇葩了,每个尺寸数值是按照这个位数来表达的,也就是说是跨字节的,我想了很多办法也不知道该怎么把跨字节的值从整体的二进制数里拆出来,网上的算法看的云里雾里的,现在主要问题在于,即使用指针位移的办法,最小也是8位一读,怎么弄都拆不出这个数来,我该咋办?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2013-04-28 15:16 |只看该作者
当年写过,贴给你参考一下。因为后来没用过,所以不知道是否有错误
  1. bool CflashplayerApp::GetParam( CString& filename, bool& bTransparent, unsigned long& width, unsigned long& height, DWORD& ParentPID )
  2. {
  3.     CString flashfilename;
  4.     CString flashvmode;
  5.     DWORD dwProcessId = 0;

  6.     if( __argc > 1 )
  7.         flashfilename = __targv[1];
  8.     if( __argc > 2 )
  9.         flashvmode = __targv[2];
  10.     ParentPID = 0;
  11.     if( __argc > 3 )
  12.     {
  13.         int r = _stscanf_s( __targv[3], _T("PID=%lu"), &dwProcessId );
  14.         if( r == 1 )
  15.             ParentPID = dwProcessId;
  16.     }

  17.     //MessageBox( NULL, __targv[2], __targv[1], 0 );

  18.     CString CurrentDirectory;
  19.     GetModuleFileName( NULL, CurrentDirectory.GetBuffer(MAX_PATH*2), MAX_PATH*2 );
  20.     CurrentDirectory.ReleaseBuffer();
  21.     int pos = CurrentDirectory.ReverseFind( _T('\\') );
  22.     CurrentDirectory.Delete( pos+1, CurrentDirectory.GetLength()-(pos+1) );
  23.     SetCurrentDirectory( CurrentDirectory );

  24.     flashfilename.Trim();
  25.     flashvmode.Trim();
  26.     if( flashfilename.IsEmpty() )
  27.     {
  28.         flashfilename = _T("flash_begin.swf");
  29.     }
  30.     if( flashvmode.CompareNoCase(_T("transparent")) == 0 )
  31.         bTransparent = true;
  32.     else
  33.         bTransparent = false;

  34.     CFile flashfile;
  35.     if( flashfile.Open(flashfilename,CFile::modeRead|CFile::typeBinary) )
  36.     {
  37.         flashfilename = flashfile.GetFilePath();

  38.         char id[3];
  39.         if( sizeof(id) != flashfile.Read(id,sizeof(id)) )
  40.         {
  41.             return false;
  42.         }

  43.         BYTE buf[17]; // (5 + 4*31)/8 = 17
  44.         if( id[0]=='C' && id[1]=='W' && id[2]=='S' ) // 带压缩
  45.         {
  46.             try {
  47.                 flashfile.Seek( 8, CFile::begin );
  48.             } catch( CFileException* e ) {
  49.                 e->Delete();
  50.                 return false;
  51.             }
  52.             BYTE tmp[128];
  53.             UINT tmplen = flashfile.Read( tmp, sizeof(tmp) );
  54.             
  55.             int err = 0;
  56.             z_stream d_stream;
  57.             d_stream.zalloc = (alloc_func)0;
  58.             d_stream.zfree = (free_func)0;
  59.             d_stream.opaque = (voidpf)0;
  60.             d_stream.next_in = tmp;
  61.             d_stream.avail_in = tmplen;
  62.             d_stream.next_out = buf;
  63.             if( inflateInit(&d_stream) != Z_OK )
  64.                 return false;
  65.             while( d_stream.total_out<sizeof(buf) && d_stream.total_in<tmplen )
  66.             {
  67.                 d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
  68.                 if( (err = inflate(&d_stream,Z_NO_FLUSH)) == Z_STREAM_END )
  69.                     break;
  70.                 if( err != Z_OK )
  71.                     return false;
  72.             }
  73.             if( d_stream.total_out != sizeof(buf) )
  74.                 return false;

  75.             //uLongf buflen = sizeof(buf);
  76.             //int err = uncompress( buf, &buflen, tmp, tmplen );
  77.             //if( Z_OK!=err && Z_BUF_ERROR!=err  )
  78.             //    return false;
  79.         }
  80.         else if( id[0]=='F' && id[1]=='W' && id[2]=='S' )
  81.         {
  82.             try {
  83.                 flashfile.Seek( 8, CFile::begin );
  84.             } catch( CFileException* e ) {
  85.                 e->Delete();
  86.                 return false;
  87.             }

  88.             if( sizeof(buf) != flashfile.Read(buf,sizeof(buf)) )
  89.             {
  90.                 return false;
  91.             }
  92.         }
  93.         else
  94.         {
  95.             return false;
  96.         }

  97.         struct BitStream
  98.         {
  99.             BitStream( const BYTE* bs_, size_t len_ ) : bs(bs_), len(len_), offset(0)
  100.             {
  101.             }
  102.             unsigned long GetULONG( size_t n )
  103.             {
  104.                 if( len*8 - offset < n )
  105.                     return 0; // false;
  106.                 if( n > sizeof(unsigned long)*8 )
  107.                     return 0; // false;

  108.                 unsigned long ret = 0;

  109.                 size_t a = offset%8;
  110.                 if( a != 0 )
  111.                 {
  112.                     ret = BYTE(bs[offset/8] << a);
  113.                     if( n < 8-a )
  114.                     {
  115.                         ret >>= (8-n);
  116.                         offset += n;
  117.                         return ret;
  118.                     }
  119.                     ret >>= a;
  120.                     offset += 8-a;
  121.                     n -= 8-a;
  122.                 }

  123.                 for( ; n>=8; )
  124.                 {
  125.                     ret = ret*256 + bs[offset/8];
  126.                     offset += 8;
  127.                     n -= 8;
  128.                 }

  129.                 ret = ret*(1<<n) + (bs[offset/8] >> (8-n));
  130.                 offset += n;
  131.                 return ret;
  132.             }
  133.             long GetLONG( size_t n )
  134.             {
  135.                 if( n==0 )
  136.                     return 0;

  137.                 unsigned long tmp = GetULONG(n);
  138.                 if( (tmp & (1ul<<(n-1))) == 0 ) // 正
  139.                     return long(tmp);

  140.                 tmp |= ~((1ul<<n)-1);
  141.                 return long(tmp); // 负
  142.             }

  143.         private:
  144.             const BYTE* bs;
  145.             size_t len;
  146.             size_t offset;
  147.         };
  148.         
  149.         BitStream bitstream( buf, sizeof(buf) );
  150.         unsigned long len = bitstream.GetULONG(5);
  151.         long xmin = bitstream.GetLONG(len);
  152.         long xmax = bitstream.GetLONG(len);
  153.         long ymin = bitstream.GetLONG(len);
  154.         long ymax = bitstream.GetLONG(len);

  155.         long w = xmax-xmin;
  156.         long h = ymax-ymin;
  157.         //if( w%20!=0 || h%20!=0 )
  158.         //    return false;
  159.         width = abs(w/20);
  160.         height = abs(h/20);
  161.         filename = flashfilename;
  162.         return true;
  163.     }

  164.     return false;
  165. }

  166. /*
  167. FWS,CWS
  168. 如果是CWS格式,从第8字节处还需要用zlib解压

  169. 第8字节开始
  170. 01111000 00000000 00000111 10011001 00000000 00000000 00000111 11111000 0
  171. -----___ ________ ____---- -------- ---_____ ________ __------ -------- -
  172.   15                         778*20                        204*20

  173. 01111000 00000000 00000101 01011111 00000000 00000000 00001111 10100000 00000000
  174. _____~~~ ~~~~~~~~ ~~~~____ ________ ___~~~~~ ~~~~~~~~ ~~______ ________ _
  175.   15                         11000                            8000

  176. 01111100 11100111 00000010 11000110 11111010 01110000 11000011 01010101 1
  177. ~~~~~___ ________ ____~~~~ ~~~~~~~~ ~~~_____ ________ __~~~~~~ ~~~~~~~~ ~
  178. 15       -12688           5687             -5693             1707

  179. 5687 - -12688 = 18375/20 = 918.75
  180. 1707 - -5693 = 370*20

  181. */
复制代码

论坛徽章:
0
3 [报告]
发表于 2013-04-28 15:40 |只看该作者
请大致解释一下GetULONG和GetLONG函数的原理是什么还是看的不是很明白。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
4 [报告]
发表于 2013-04-28 16:12 |只看该作者
其实你只要实现一个函数,int  getbits(const char *bytes, int start, int end), 那么所有复杂度都就没了.

每个字段不超过31比特, 自然可以存在一个int中, getbits内部不过是getbit获取某一个bit, 然后做位运算拼接到int上, 最终getbits返回.

即:

static inline _getbit(const char *bytes, int index);
int getbits(const char *bytes, int start, int end) {
      int n = 0;
      foreach (index in start, end) do
      n = (n << 1) | _getbit(bytes,index);
      return n;
}

简单吗

论坛徽章:
0
5 [报告]
发表于 2013-04-28 16:44 |只看该作者
linux_c_py_php 发表于 2013-04-28 16:12
其实你只要实现一个函数,int  getbits(const char *bytes, int start, int end), 那么所有复杂度都就没了.
...


问题是,怎么才能把二进制流里的数据转化为“1010101010”........这样的字符串char数组呢?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
6 [报告]
发表于 2013-04-28 17:03 |只看该作者
我哪里说要转二进制成字符串了?

论坛徽章:
0
7 [报告]
发表于 2013-04-28 17:11 |只看该作者
linux_c_py_php 发表于 2013-04-28 17:03
我哪里说要转二进制成字符串了?


那怎么实现指针按位移动,我做试验发现char *指针一次移动8位,如何让他一次移动1位

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
8 [报告]
发表于 2013-04-28 17:29 |只看该作者
回复 7# abcbuzhiming


    >> , <<

论坛徽章:
0
9 [报告]
发表于 2013-04-28 17:35 |只看该作者
idi0t 发表于 2013-04-28 17:29
回复 7# abcbuzhiming

啥时候指针能做位运算了,你给我写个例子

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
10 [报告]
发表于 2013-04-29 18:03 |只看该作者
对于支持位运算的C/C++来说,这根本不是问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP