GDI高效内存手动绘图

最近一直想要写几篇文章,但是由于懒癌的发作一直都没有写。今天趁着写代码写的闹心并且无力追番的闲心写一下。

最近在参加一个比赛,里面要求百万的图形能够在10s以内能够进行裁剪显示,这对于GDI绘图来说是基本不现实的,不过经过各种优化我在1秒以内完成这个任务(i7 四核 1.8GHz)。实现这个效果的最关键的就是手动绘图替代掉效率底下的GDI。

如果有DOS下图形编程经验的朋友可能都习惯用最基本的绘点函数来完成一些复杂的绘制,到了windows之后遇到GDI之后却发现绘点函数慢的恐怖。比如要SetPixel来绘制一个调色盘,这个效率基本是要让人疯掉的。

这里先分析一下GDI的效率为什么低下。众所周知,现在的Windows是运行在保护模式的,只有系统内核以及驱动程序才能接触到那些关键的显存,而普通的ring3应用程序必须通过操作系统的API才能调用硬件资源。于是每次绘图的时候程序都会调用gdi的dll,这个动态链接库会接受到调用之后在缓冲队列里面记录下操作,在特定的时候会触发CPU陷阱把缓冲队列的数据交给内核来执行。也就是说大量的GDI绘图指令会导致大量的内核切换的开销。

为了加速绘图微软公司也是有不少解决方案,在windows早期就提出过DirectX用来直接操作这些硬件资源。不过今天并不打算采用那种复杂到恐怖的东西。还是用类似于双缓冲的方式实现

GDI里面的重要的一个概念就是DC,而DC需要一个实际的数据区,这个数据区就是一个位图。如果我们能够直接对这个位图内部的内存进行读写那么就能够非常快的完成绘图操作。

关键的代码有下面这几个,如果有问题可以查询MSDN。我一开始也对这几个函数比较有疑惑,现在稍微记录一下吧。

  • CreateCompatibleDC能够创建一个空的兼容的DC,但是这个DC由于没有缓存区所以大小是1*1的。
  • CreateCompatibleBitmap能够创建一个大小一致的兼容的BMP,由于新创建的DC并没有大小,请注意这里要传入旧的DC
  • SelectObject用来把一个BMP绑定到DC上
  • BitBlt用来复制并且光栅操作
  • SetBitmapBits用来设置一个BMP的内容

还有一些其他的API可能也是有用的,不过由于调用并没有这里方便于是我就不介绍了

代码Demo可以看我当时写的代码:https://github.com/manageryzy/lineCircle/blob/master/lineCycle/draw/drawMemory.cpp

 

Microsoft Azure Dreamspark试玩

几个月之前微软宣布Azure在Dreamspark上免费了,抱着试试看的态度几个月之前就打算弄一个玩玩。不过由于中国的特殊情况,中国地区的Azure是由世纪互联运营,但是世纪互联并不认Dreamspark的活动,于是需要一个其他地区的手机号用来验证账户。

网络上有一些虚拟电话号码用来接收短信,不过由于他们大多是VOIP号码被微软禁止使用,所以我一狠心花了三十大洋买了一个香港的手机卡。

注册账号这个没什么说的。去Dreamspark网站一进去就能看到Azure了,激活账号的时候验证手机号,Dreamspark注册Azure不需要信用卡,否则还要信用卡进行验证。注册完账号之后微软要求等几分钟。大概等待了两分半中后账号就绪了。这个时候可以通过访问https://portal.azure.com/ 进入后台。

QQ图片20150502020340

进后台的过程由于网速原因简直就是煎熬。我花了整整十分钟才进入。

QQ图片20150502020340

费半天劲终于成功的进入了主面板。各种操作由于网速的原因……不说了,说多了都是泪

下面看一下Azure Dreamspark提供的免费服务。Dreamspark版本的Azure相当多的内容都不能用,能用的只有最低配置的Web程序以及数据库。大概和烂大街的免费主机是一个水平的。网速上Azure也没有明显的优势。这可能和我选择的节点有关吧,我选择的是日本西部地区可能速度不如亚洲南部地区。总之Azure Dreamspark版本是相当坑爹的东西啦

Microsoft Visual Studio Code Linux上手试玩

在微软2015 build大会上微软推出了最新的跨平台的代码编辑器:Visual Studio Code。这个编辑器可以在Windows、Linux、OS X上运行。

QC)EJ@XDD0KYQ_GAHXAAT5Q

访问visual studio的网站马上就能看到这个的下载页面,下载linux版之后会得到一个zip包(不是tar.gz差评)。解压缩之后能看到一个叫做code的文件,文件已经默认有了执行权限,在ubuntu下面只要双击就可以运行。

虽然说visual studio code是一个编辑器,但是它还是很好的继承了visual studio的一大特色——慢。不过还好只是启动比较慢。运行的速度不是很慢。这可能是由于我的ubuntu分区不是在SSD上的原因吧。启动软件花了我十多秒,并且一开始的时候没有任何提示。这让我以为我没有启动成功。

编辑器的界面总体上讲非常的清爽,没有一坨坨的按钮,只有必要的编辑、浏览、git和调试。

QQ图片20150502020340

怎么说呢,这个界面觉得好像IE的F12的……

使用起来的话初学者可能有一点比较麻烦,这里没有一个个的先导。系统会默认的把项目的配置文件生成并且存在.setting目录下面。项目的配置以及启动配置都是json文件。虽然有英文的说明,但是你不得不把这些全都读一遍。(真是满满的linux的感觉,雾)

编辑器支持许多web开发技术:从nodejs到sass,基本囊括了所有前端后端的最热门的web新技术,代码提示也很好用,而且在没有reshape的时候代码提示就已经能用了(黑vs黑的丧心病狂),但是,他只能开发web,只能开发web,只能开发web(因为很重要,所以要说三遍,但愿不要被微软光速打脸)

总之有时间那它撸个nodejs的项目玩玩好了,刚上手的感觉还算是不错

typecho用户个性签名插件

好久没有更新博客了。最近忙成狗了。随便开源一下我写的代码啦。

 

项目主页:https://github.com/hmoe/typechoSignPlugin

 

typecho 用户个性签名插件

安装方法:

在插件目录下面建立UserSign文件夹,把Plugin.php复制进去

注意:由于typecho的问题,插件的用户配置在读取的时候会自动读取在配置表里面的插件数据。如果要让用户的设置正常运行请修改 ‘/var/Widget/Users/Profile.php’。修改下面这个函数。不修改的话用户的个人页面里面显示用户的当前签名


    /**
     * 输出自定义设置选项
     *
     * @access public
     * @param string $pluginName 插件名称
     * @param string $className 类名称
     * @param string $pluginFileName 插件文件名
     * @param string $group 用户组
     * @return Typecho_Widget_Helper_Form
     */
    public function personalForm($pluginName, $className, $pluginFileName, &$group)
    {
        /** 构建表格 */
        $form = new Typecho_Widget_Helper_Form($this->security->getIndex('/action/users-profile'),
        Typecho_Widget_Helper_Form::POST_METHOD);
        $form->setAttribute('name', $pluginName);
        $form->setAttribute('id', $pluginName);

        require_once $pluginFileName;
        $group = call_user_func(array($className, 'personalConfig'), $form);
        $group = $group ? $group : 'subscriber';

        $options = $this->options->personalPlugin($pluginName);

        if (!empty($options)) {
            foreach ($options as $key => $val) {
				if(!isset($form->getInput($key)->value))
					$form->getInput($key)->value($val);
            }
        }

        $form->addItem(new Typecho_Widget_Helper_Form_Element_Hidden('do', NULL, 'personal'));
        $form->addItem(new Typecho_Widget_Helper_Form_Element_Hidden('plugin', NULL, $pluginName));
		
		$submit = new Typecho_Widget_Helper_Form_Element_Submit(NULL, NULL, _t('保存设置'));
		$submit->input->setAttribute('class', 'btn primary');
        $form->addItem($submit);
		
        return $form;
    }

使用方法

由于已经在users表里面插入了userSign这个字段了,这个字段会自动的被系统读取。只需要在需要的地方输出$user->userSign就可以了

waf绕过-奇淫技巧

传统的waf都有一些比较常见的绕过技巧,最近在网上看到了绕过百度云CDN的攻击拦截的方式……果然是奇淫技巧,故拿出来分享一下。此方法百度云CDN、360网站卫士等均有可能适用

使用百度云CDN等的网站多半是只有一个VPS的小站,而一个网站往往拥有若干域名,于是就可以通过域名解析的方式查看有没有直接解析的子域名。我经手的网站里面就有两个网站有这种问题。一旦发现了真实的ip之后就可以添加真实ip到host文件之后使用扫描器之类的工具进行攻击啦。

alictf2015被虐成狗

前两天参加了AliCTF2015 来玩一玩。本来是和FoeverBear和Naylon组队的,结果Naylon去找妹妹去了(这晒妹还不烧么)结果不得不两个人进行比赛。

这个比赛么由于和大触的实例差距果然被虐啦。简单的说一说这些题啦。下面的文字比起writeup更像是一种日记的形式呢。

  • cake:这道题没有任何难度。直接反编译Android程序就好,虽然说混淆了,但是由于程序实在是太简单了,直接一本来打算拿下这道题的一血,结果我各种犯二,没能拿下一血不说最后只拿了50pt。
  • 密码宝宝:这道题简单的UPX脱壳。FoeverBear很快就直接OD弄出了结果。
  • 简单业务逻辑:这道题我没有做,FoeverBear做的。
  • 简单业务逻辑2:我把这道题引导到错误的方向了……后来好不容易修改cookie进入管理员发现还是不是答案。然后在面前的是Cookie的注射。这时候FB果断上来救场。
  • 前端初赛题:一个XSS,但是限制了好几种。后来得知SVG可以用HTML encoded进行XSS。于是和FoeverBear一起给XSS了。
  • 前端初赛题2:flash 的XSS。我反编译了flash完全看不出来XSS的可能性。后来还是FoeverBear很给力的试了出来。
  • 前端初赛题3:一个很有意思的XSS。这个防御几乎是无敌的呢。还是让FoeverBear看出来了。现在越发的爱上了FB了(雾)。这道题的代码学习了wwwww
  • 谁偷了你的站内信:FB做的,缓存溢出。
  • 代码血案:FB做的,溢出。

其他的题虽然没做出来。也是有进行好多尝试。阿里的那个so文件保护简直丧心病狂,我自己试图直接加载so文件竟然加载不出来,爆破的方式也就被堵上了呢。

至于那个Android的漏洞的回答那道题没有做出来是我的过错呢。都已经把apk破解了得到了问题的网址,可是那六个问题没有回答出来。后来想到apk里面有一个md5,我心想这个md5应该是最后的答案的,于是就开始了暴力枚举(因为这个题是问出错的代码是哪个调用。所以是有穷的)。我一次次的调大搜索范围,跑了500M的数据也没有算出来,后来上网反查了一下这个md5发现明文是alictf的时候我内心几乎是崩溃的。这个时候离比赛结束只剩下不到一分钟……如果我老老实实的回答这个问题的话这100pt肯定能拿下来,拿下这100pt肯定就能进决赛了。最后少80pt进决赛。

实力不行各种抱FoeverBear大神大腿还被虐成狗……惨痛的失败呢

BP神经网络初始权值选择

一直以来尝试着用BP网络解决一些简单的问题的时候出现着各种各样的问题,效果很不理想:用BP网做双螺旋问题,结果正确率不到70%、但是做XOR问题却能很好地解决。和BOSS研究了半天终于明白了长期以来困扰我们的这些奇怪的事情的原因是我们没有对网络进行正确的归一化以及权值初始化

由于网络通畅使用的是sigmod函数,不管哪种形式值域都是很有限的一小段,所以要想做到很好的逼近效果就需要做归一化。也就是吧输出变换到0-1之间。而输入的每个维度通常是变换到-1到1之间。

而初始权值通常使用的是nguyen-widrow算法进行初始化。这个算法的思想比较简单,就是计算每个sigmod函数能覆盖的区间,然后加上随机化出来的。具体的可以看他们的原始的论文:《Improving the Learning Speed in 2-Layered LSTM Network by Estimating the Configuration of Hidden Units and Optimizing Weights Initialization》。在特殊情况下也有用纯粹的随机的权值啦。

以上都是针对BP网络的,至于其他的网络形式可能不太相同但是都差不多吧

ubuntu桌面无限循环登陆

前两天windows系统坏掉了本来打算彻底移居ubuntu。装N卡官方驱动把ubuntu桌面玩坏就不说了了,在安装了某个天杀的的虚拟机之后ubuntu喜闻乐见的循环登陆了……WTF,默默还是滚回windows了

先说一下症状:进入ubuntu的图形登陆界面输入正确的密码,屏幕闪一下,然后重新回到登陆界面。按下ctrl+alt+f1后可以在控制台登陆ubuntu

查看了.xsession-error文件,一大片的错误……总之胡乱的Google一通,发现基本有一下的几种原因:

* 权限不足(我就是这种情况,把把x服务需要的那些都允许root用户能直接访问)
* x服务配置错误
* 服务启动错误

嘛。用N卡的默默滚回windows了

Mediawiki清除全部缓存

(果然百度是不收录https的站点呢,我的wiki百度完全不收录呢QAQ

最近建立了minecraft中文开发wiki虽然没有被百度收录,我倒是练习了不少mediawiki的使用,在使用mediawiki的时候如果你开启了缓存,如果你修改了一个模板页面,引用了模板的页面的内容不会立刻改变。为了更新页面的内容,你不得不手动清除缓存。

清除缓存的最简单的方法就是添加purge参数,但是这样一次只能清除一个页面

google一下发现还专门有清除缓存的插件……果然这是个棘手的问题呢。后来我竟然在百度中找到了一个暴力的解决方案:直接清空缓存的数据库!!!亲测有效,简单暴力

现代浏览器js跨域

js跨域一直是一个让人头疼的问题不过现代浏览器有一种针对API的解决方案就是Access-Control-Allow-Headers。

你可以通过Access-Control-Allow-Headers来控制允许哪些域的js来访问此资源。不过这中方法只是一个折中的方案,如果说使用起来还不如普通的跨域好用。并且ie11以下浏览器并不支持。

不过对于那些开放的API最好还是加上这个头。

nginx可以通过下面的一行来加上这个头,不过域名最好还是限定一下。
add_header Access-Control-Allow-Origin *;