Archives

Archive for the ‘技术’ Category

前段时间做了一段时间塞班平台的图像处理研究,想要做出类似于instagram、Q拍那样的滤镜特效,在手机拍完照后可以用我们提供的滤镜对照片进行美化处理(有空再做个ios版的)。看了一些instagram、Q拍、美图秀秀、可牛快拍等软件做出来的效果,对于图像处理零基础的我表示鸭梨很大。从RGB通道、alpha通道、位图结构、灰度图、图层、颜色表等概念看起,然后了解基本的图像处理方法如锐化、柔化、扩散、雕刻、黑白、反色等基本特效的原理,到高斯模糊、图像混合、柏林噪声等进阶的玩法,到最后总结出了一套做图像特效的方法,给我一个.psd的photoshop源文件,我便可以根据里面的拆分步骤用程序去实现该效果。其中参考了不少国外站点的东西,尤其是StackOverflow上找到了很多有用的东东,东拼西凑组成了我图像处理这块的一些心得。先上图吧。 原图如下:   a. 基础效果 这里说基础是因为这些效果不涉及图像混合等更加复杂的东东,只是对每个像素的RGB通道做一些处理。 有的算法一行代码就能解决了,有的稍微复杂些,不过基本国内的网上都能找得到。 黑白 浮雕 素描 lomo 马赛克 扫描线 波普 鱼眼 b. 进阶效果 这里仅作了图像混合,并没有用函数去处理每个RGB分量,毕竟不是专门搞ps的,不知道怎么弄算好看.. 不过貌似可牛快拍里有些效果就是做了图像混合,然后稍做了些处理。这种做法比较没技术含量.. 不适合单独作为产品级的效果,可以作为复杂特效的某些步骤。 早晨 星光 这里就放出两张图了,因为做法其实都一样,最多传的参数不同罢了。当然图像混合也是有学问的,可以参考国外一哥们的系列文章:http://jswidget.com/blog/2011/03/11/image-blending-algorithmpart-i/ c.高级特效 下面两个效果挺花时间的,主要要知道怎么做比较费时间,做的过程的话第二个效果也比较复杂,是根据.psd文件的拆分步骤一步步做出来的,所以在移动平台上跑有些慢… 老照片 Nostalgia 做的方法受这个老外的影响很大:http://taptaptap.com/blog/creating-a-camera-plus-fx/ 这是个开发ios上滤镜app的老外设计师写的,而且是夫妻档,貌似老婆是设计师,她将做好的photoshop效果图给源文件给老公,然后老公根据.psd文件做成ios应用放到app store里去卖。我的Nostalgia特效就是模仿的他们的效果。不过老外没有把源代码放上来,就截了段核心函数,然后我自己摸索了好多天,不断的尝试,最后才搞成的效果。里面还涉及到了用Matlab模拟出曲线的函数,竟然用到了四次函数。。不过整个过程还是很享受的,很有乐趣。如果组内有需求,可以帮着搞一下。

Nov 13th, 2011 | Posted by | Filed under symbian, 图像处理

客户端(v3版本)原先在处理服务器端传回gzip数据时采用的策略是先将gzip流保存成.gz文件,再用解压文件的方式将数据解压出来。这种方式显然不如直接从内存中实现gzip解压来得高效,但由于Symbian SDK中zlib的版本过低(1.1.3)等原因,网上介绍的很多内存流解压方法并不适用于此: http://apps.hi.baidu.com/share/detail/8355062 http://blog.sina.com.cn/s/blog_4d6f62190100md6k.html http://blog.sina.com.cn/s/blog_65db99840100kwh9.html http://www.devdiv.com/thread-8625-1-1.html http://www.developer.nokia.com/Community/Discussion/showthread.php?155614-GZip-and-RReadStream-problem 在解决过程中遇到了一些困难,开始使用http://apps.hi.baidu.com/share/detail/8355062 中的方法,并且将服务器返回的gzip数据去掉开头的10个gzip header,但程序始终卡在第13行: CBufFlat* CETNetOperator::DeCompressMemL(const TDesC8& aData)         {         TInt nBufferSize = 128;         HBufC8* nSrc = NULL;         HBufC8* nTemp = aData.Mid(10).Alloc();   //去掉开头10个字节         nSrc = nTemp;         CleanupStack::PushL(nSrc);         CBufFlat* nBufFlat = CBufFlat::NewL(nBufferSize);         CleanupStack::PushL(nBufFlat);         CBufferManager* nBufferManager = CBufferManager::NewLC(*nSrc, *nBufFlat,                     nBufferSize);         CEZDecompressor* decompressor = CEZDecompressor::NewLC(*nBufferManager);         while (decompressor->InflateL())               {// loop here until the file is compressed               }         //    nBufFlat->Ptr(0);         CleanupStack::PopAndDestroy(3);         return nBufFlat;         }    然后尝试使用Symbian SDK自带的zlib库,include <ezlib.h>,代码如下: int ungzip(char* source, int len, char* des)        {        int ret, have; [...]

Aug 17th, 2011 | Posted by | Filed under symbian

本文内容非原创,属于网上资源的整理。 ======================================== 二阶段构造 问题1:为什么需要二阶段构造? 首先考虑如下的语句: CClassName* ptr = new (ELeave) CClassName();   在内存有足够空间的情况下,代码首先在堆上分配一个CClassName类型的对象,并将地址赋给ptr指针,然后调用类的构造函数初始化这个对象。 这样,如果类的构造函数出现了异常,则会发生问题,这种异常发生时没有任何指针指向成功分配给CClassName对象的内存区域,因此这些内存成为孤立内存,发生内存泄漏。这就引出了symbian内存处理的一个重要规则:构造函数绝对不能异常退出。 问题2:为什么二阶段函数能够避免内存泄漏? 二阶段构造函数,顾名思义就是将一个对象的构造分为两个阶段: 第一个阶段是常规的的构造函数,在该构造函数中,没有可能导致异常退出的代码; 第二个阶段是可能会产生异常的构造阶段,实现为函数ConstructL(); 这样,对象的构造过程就应当包括了如下的代码: CClassName* self = new (ELeave) CClassName();    CleanupStack::PushL(self);    self->ConstructL();    CleanupStack::Pop(self);   这样的构造方式为什么就能够避免内存泄漏呢?下面我们来逐行分析代码: CClassName* self = new (ELeave) CClassName();   重载的运算符new首先将内存分配给新的self实例,如果分配失败,那么程序异常退出,如果成功给新的对象分配了内存,那么接着执行不会异常退出的第一阶段构造函数; CleanupStack::PushL(self);   接着我们将本地指针self推入清除栈,因为下面要调用可能发生异常的退出函数。 self->ConstructL();   如果该二阶段构造函数在执行时异常退出,那么新的CClassName的指针由清楚栈负责清楚,避免了内存泄漏;另外,如果该函数没有异常退出,则拥有了一个完全构造的CClassName实例。 CleanupStack::Pop(self);   安全的将本地指针从清除栈中弹出; 每实例化一个对象就要写上述代码确实有些啰嗦了,Symbian OS为了简化实例化的步骤,又引入了NewL(),NewLC()两个函数(其实也可以写成一个NewL(),然而大家都比较推崇同时创建NewL()和NewLC()),其具体的实现方式见问题3; 问题3:如何在新的类中创建二阶段构造函数? .h头文件: Class CClassName : public CBase    {    public:           static CClassName* NewL();           static CClassName* NewlC();           ~CClassName();    private:           CClassName(); //第一阶段构造           void ConstructL(); //第二阶段构造    ……    }   cpp源文件: [...]

Aug 1st, 2011 | Posted by | Filed under symbian

本文内容非原创,属于网上资源的整理。 ======================================== 8位:(TDesC8),用于二进制数据或者ASCII字符串 16位:(TDesC16),默认,Unicode 描述符可以分为五类: 抽象类(Abstract):(TDes、TDesC、Tdes8、TdesC8),其他描述符的基类,仅提供接口和基本功能,不能被实例化,一般只用作函数的参数。  文字常量(Literal):(TlitC、_LIT()),用于存储文字字符串(literal string),即C中字符串常量,通常使用_LIT()这种方式(当然还有_L()和_L8()的描述方式,但都不提倡用)。  栈类(Buffer):(Tbuf、TbufC、 Tbuf8、TbufC8),数据存储于栈上,最基本的描述符变量类型,大小在编译时确定,包含描述符本身数据,使用最为普遍 堆类(Heap):(HbufC、HbufC8),数据存储于堆上,大小在运行时确定,也就是是用来处理动态申请的描述符类。 指针类(Pointer):(TPtr、TPtrC、TPtr8、TPtrC8),本身不包含描述符数据,但是包含长度数据,而且还包含一个指向位于描述符之外数据的指针。 1、  文字描述符常量 LIT(KMyFile, “c:\System\Apps\MyApp\MyFile.jpg”);   _L()可以生成一个指向字符值的地址(TPtrC),它经常被用来传递字符串到函数中(包括描述符的构造函数和格式化函数);同理_L8()则可以生成一个指向二进制数据的地址(TPtrC8)举例如下: NEikonEnvironment::MessageBox(_L(“Error: init file not found!”));    //数字转字符串    TBuf16<20> buf;    TInt iNum = 20;    buf.Format( _L( “%d” ) , iNum  );   2、  栈描述符 LIT(Ktext , “Test Text”);    _LIT(Ktext1 , “Test1 Text”);    _LIT(KXtraText , “New:”);    _LIT(NewText , “New1″);    _LIT(NewText1 , “New2″);    TBufC<10> Buf1 ( Ktext );//Buf1长度为9 内容 “Test Text”    TBufC<10> Buf2 ( Ktext1 );//Buf2长度为10 内容 “Test1 Text”    // 通过赋值的方式改变数据    Buf2 = Buf1; //Buf2长度变为9 内容 “Test Text”    //通过使用Des()生成指针改变TBufC的数据    TPtr Pointer = Buf1.Des();    // 删除后四个字符    Pointer.Delete(Pointer.Length()-4, 4 ); //Buf1长度变为5 内容“Test ”//但是内存应该没变    // 增加新的数据    [...]

Aug 1st, 2011 | Posted by | Filed under symbian

本文内容非原创,属于网上资源的整理。 ======================================== 基本数据类型  在Symbian中,很多C++基本类型都被重新定义了,最好使用Symbian的,理由如下: 所有Symbian API都是用的Symbianc重定义的 将来Symbian OS由32位转为64位时,支持性更好 这本身就是Symbian C++ Coding Standards所要求的 1.  Integers     typedef signed int TInt;  C++中的signed int,32位,基本用法类似。     typedef unsigned int TUint;  一般用于计数器(Counter)或者标记(Flags)。     其他Int类型:TInt64, TInt32, TInt16,TInt8; 同时有一份TUint的版本。 2. Text  text类型在Symbian编程中基本不用,而一般采用描述符(descriptor)。TText默认是16位的。 3. Boolean      typedef int TBool;有两个枚举值:ETrue和EFalse。TBool变量最好不要直接和ETure和EFalse比较。如下: TBool flag = ETrue; if (flag)  // if (!flag) { flag = EFalse; [...]

Jul 27th, 2011 | Posted by | Filed under symbian

12213123 123 12 3   _LIT(KHello, “Hello!”);    _LIT(KWorld, “World!”);     HBufC* heapBuf = HBufC::NewL(KHello().Length());    *heapBuf = KHello;    //buf holds ”Hello!”       heapBuf = heapBuf->ReAllocL(KHello().Length() + KWorld().Length());    CleanupStack::PushL(heapBuf);       TPtr ptr (heapBuf->Des());  //DON’T use TPtr ptr = heapBuf->Des(); this will set maxlen to 6 but not 12…    ptr[KHello().Length() - 1] = ’ ’;    ptr += KWorld;    iTopLabel -> SetTextL(ptr);    CleanupStack::PopAndDestroy();    DrawNow();      

Jul 1st, 2011 | Posted by | Filed under symbian

在流量统计服务中都有Traffic source这个功能。Traffic source是针对访次级别的概念,换句话说,当访次建立的时候,landing page的流量来源即是该访次的Traffic source。虽然Traffic source有很多种,不过不幸的是依据现在JS,获得Traffic source的途径只有两种——document.referrer、window.opener.更不幸的是,window.opener适用的场景不 多,而document.referrer非常的弱,以至于很多场景下无法准确判断出流量来源。 document.referrer的覆盖 从使用意义上来说document.referrer希望能够追踪到的是浏览器端行为。如果一张页面A被打开,那么浏览器端可能会发生的动作有用户操作、JS代码两种。 先来看看用户打开页面A可能会进行的操作: 1 直接在地址栏中输入A的地址 2 从B页面左击link A,跳转至A页面 3 从B页面右击link A,在新窗口中打开 4 从B页面右击link A,在新标签页中打开 5 拖动link A至地址栏 6 拖动link A至标签栏 7 使用浏览器的前进、后退按钮 注意这里的link即指<A>标签,但是如果有事件或者target还要另当别论。 JS打开页面可能的方式: 1 修改window.location 2 使用window.open 3 点击flash 上面列出了客户端打开页面的一些方法,此外,如果通过服务端的重定向技术,也能够使得页面A呈现给访客。 下面来针对具体的浏览器测试,如果是上述的这些情况,document.referrer表现如何: 序号 场景 IE8.0 FF3.6 FF4.0 chrome 1 直接在地址栏中输入A的地址 ” “ ” “ ” “ ” [...]

Apr 4th, 2011 | Posted by | Filed under javascript

前不久blog频道有人发表了一篇讲js里各种trim实现的 http://justjavac.iteye.com/blog/933093 不过没有提及Dojo中的trim。Dojo中有两种trim实现: 1.较为常用的: dojo.trim = String.prototype.trim ? function(str){ return str.trim(); } : function(str){ return str.replace(/^\s\s*/, ”).replace(/\s\s*$/, ”); }; 2.速度快但是实现较为复杂: dojo.string.trim = String.prototype.trim ? dojo.trim : // aliasing to the native function function(str){ str = str.replace(/^\s+/, ”); for(var i = str.length – 1; i >= 0; i–){ if(/\S/.test(str.charAt(i))){ str = str.substring(0, i + 1); break; [...]

Mar 12th, 2011 | Posted by | Filed under javascript

最近想学下python,搞了个电子版的《Head First Python》读下,才看了前言部分,作者关于阅读技术书籍有几条tip,目的是为了让读者理解透彻,让阅读有趣味,不至于瞌睡,现摘录如下: Slow down. The more you understand, the less you have to memorize. 多思,重在理解。 Do the exercises. Write your own notes. 身边放一支笔和一张纸,做点题,在纸上涂涂画画。 Read the “There are No Dumb Questions.” 书中的问题试着去解答。 Make this the last thing you read before bed. Or at least the last challenging thing. 作者的意思是最好睡前读,因为学习了新的知识后大脑需要时间去消化记忆,如果这时间做了别的事情,学到的东西会遗忘。这条不太同意。 Talk about it. Out loud. 直到能向别人清晰讲述一个知识点后,才算真正掌握了它。 [...]

Jan 28th, 2011 | Posted by | Filed under 技术

今天翻“Effective Java”的时候看到了改写hashCode()方法的三条约定,突然想到了某些问题,故记录之。 1.在每个改写了equasl方法的类中,你也必须要改写hashCode方法。 2.如果equals相等,两个对象的hashCode必须相等。 3.不相等的对象倾向于产生 不相等的散列码,但是不相等的对象可以有相等的散列码。 我在写代码的时候曾遇到过如下情况: class Person { String name ; int age ; public Person (String name , int age ){ this . name = name ; this . age = age ; } public boolean equals (Object o ){ if (o instanceof Person ){ Person p=( Person )o ; return name [...]

Mar 23rd, 2010 | Posted by | Filed under java
Tags: ,