缘起

大概三个月前,我刚刚来到公司实习,老大说我们要做一个与斗鱼主播端功能相近的视频直播软件,界面用 C# 实现,让我来负责这一块,问我该用 WinForm 还是别的来做? /(ㄒoㄒ)/~~ 当时我不知道怎的就选了 WPF ,最近,我们要为程序加上预览功能,即要播放 YUV/RGB 数据。 然而,从视频设备那里采集到了 YUV 数据后,转为 Bitmap ,然后再转为 BitmapSource ,到最终呈现出来,非常低效。

这几天,我们发现通过 SDL 进行渲染能有效的降低 CPU 使用率。

然而,坑还是有的,我把 WPF Image 对象和图片数据传给 SDL ,它却直接把整个窗体霸占了 T_T 。

因此,只能把整个窗体给 SDL 了。

阅读全文 »

SDL简介

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

阅读全文 »

方案一: 使用 MemoryStream

先将 Bitmap 储存成 MemoryStream ,然后指定给 BitmapImage 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void UpdateImageByMemoryStream()
{

using (MemoryStream memory = new MemoryStream())
{

int w = 0, h = 0;

MyDll.GetBitmapSize(ref w, ref h);
System.Drawing.Bitmap bitmap;

bitmap = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);


System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);

while (true)
{
System.Drawing.Imaging.BitmapData bmpData =
bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);

// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;

var status = MyDll.GetBitmapData(ptr) >= 0 ? true : false;

// Unlock the bits.
bitmap.UnlockBits(bmpData);

if (status)
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
UpdateUI(() =>
{
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();

imgPreview.Source = bitmapimage;
});
}
}
}
}

方案二: 调用 Imaging.CreateBitmapSourceFromHBitmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void UpdateImageByBitmap()
{


int w = 0, h = 0;

MyDll.GetBitmapSize(ref w, ref h);
var bitmap = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
while (true)
{
System.Drawing.Imaging.BitmapData bmpData =
bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);

// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;

var status = MyDll.GetBitmapData(ptr) >= 0 ? true : false;

// Unlock the bits.
bitmap.UnlockBits(bmpData);

if (status)
UpdateUI(() =>
{
imgPreview.Source = BitmapHelper.BitmapToBitmapSource(bitmap);
});

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BitmapHelper
{
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
{
IntPtr ptr = bitmap.GetHbitmap();
BitmapSource result = Imaging.CreateBitmapSourceFromHBitmap(
ptr, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
//release resource
DeleteObject(ptr);

return result;
}
}

方案三: 使用 WriteableBitmap

注:这个方法会长时间占用 UI 线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void UpdateImageByWriteBitmap()
{
int w = 0, h = 0;

MyDll.GetBitmapSize(ref w, ref h);
var rect = new System.Windows.Int32Rect(0, 0, w, h);

UpdateUI(() =>
{
imgPreview.Source =
writeBitmap = new WriteableBitmap(rect.Width, rect.Height, 96, 96, PixelFormats.Bgra32, null);
});
while (true)
{
UpdateUI(() =>
{
writeBitmap.Lock();
if (MyDll.GetBitmapData(writeBitmap.BackBuffer) >= 0)
writeBitmap.AddDirtyRect(rect);
writeBitmap.Unlock();
});
}
}
阅读全文 »

JavaScript + Canvas 实现数字雨效果。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div id="display_background" style="display: block;  z-index: 1001;">
<canvas id="my_canvas" style="height: 400px; width: 600px;" ></canvas>
</div>
<script type="text/javascript">
var c = document.getElementById("my_canvas");
var ctx = c.getContext("2d");

c.height = window.innerHeight;
c.width = window.innerWidth;

var txts = "01";
txts = txts.split("");

var font_size = 16;
var columns = c.width/font_size;
var drops = [];
for(var x = 0; x < columns; x++) {
drops[x] = 1;
}

function draw()
{
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, c.width, c.height);

ctx.fillStyle = "#0F0"; //green text
ctx.font = font_size + "px arial";
for(var i = 0; i < drops.length; i++)
{
var text = txts[Math.floor(Math.random()*txts.length)];
ctx.fillText(text, i*font_size, drops[i]*font_size);
if(drops[i]*font_size > c.height || Math.random() > 0.95)
drops[i] = 0;

drops[i]++;
}
}
setInterval(draw, 33);
</script>

引入命名空间:

using System.Windows.Interop;

窗体:

IntPtr hwnd = new WindowInteropHelper(this).Handle;

控件:

IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(uielement)).Handle;

缘起

今天突然发现一件怪事,我博客的一篇文章的地址变了,原本是

https://naturalwill.github.io/2016/02/24/Modify-wine-default-webbrowser-in-archlinux/

却突然变成了

https://naturalwill.github.io/2016/02/23/Modify-wine-default-webbrowser-in-archlinux/

日期部分早了一天。

回想最近做了什么,唯一与这博客有关的事情就是我在 archlinux as the WSL (Windows Subsystem for Linux) 里生成了一次博客。

打开 alwsl 重新生成一次,发现,果然如此。

阅读全文 »

简介

e-mail 系统共有三个主要的组成功能。首先是 Mail User Agent (MUA),这是用户发送和读取邮件的程序。然后是 Mail Transfer Agent (MTA),用来将邮件从一台计算机传递到另一台。最后是 Mail Delivery Agent (MDA),用于将收到的邮件投递到用户的收件箱。

这三项功能可以由不同的程序执行,但也能合并到一个或两个程序里。还可以用不同的程序处理不同类型的邮件。

在 Linux 和 Unix 系统上 mutt 是历史悠久的常用 MUA。像其他传统的 Linux 程序一样,是基于纯文本的。它常与作为 MTA 的 exim 或 sendmail、作为 MDA 的 procmail 一起使用。

Debian 8 默认会安装 exim4 和 mutt 软件包。 exim4 组合了 MTA/MDA 功能并相对小巧和灵活。它默认配置为只处理系统本地的 e-mail 。

阅读全文 »

JavaScript: 世界上最被误解的语言

JavaScript , 亦称为 Mocha 、 LiveScript 、 JScript 或 ECMAScript ,是世界上流行的编程语言之一。事实上世界上差不多每台个人电脑都至少安装了一个 JavaScript 解释器。JavaScript 的流行完全是由于他在 WWW 脚本语言领域中的地位决定的。

不管它有多么流行,极少有人了解 JavaScript 是一个十分动态的通用面向对象编程语言。这怎能成为一个秘密呢?为什么这个语言如此被误解?

关于名字

这个 Java- 前缀暗示了 JavaScript 和 Java 的关系,也就是 JavaScript 是 Java 的一个子集也就是不如 Java 强大。看上去这个名称就故意制造混乱,然后随之而来的是误解。 JavaScript 并不是解释型的 Java 语言。 Java 是解释型的 Java , JavaScript 是另一种语言。

JavaScript 和 Java 的语法很相似,就象 Java 和 C 的语法相似一样。但它也不是 Java 的子集就像 Java 也不是 C 的子集一样。在应用上, Java 要远比原先设想的好得多( Java 原称 Oak )。

JavaScript 并不是由 Sun 公司开发的。 JavaScript 是由 Netscape 公司开发。它本来叫做 LiveScript ,这个名字并不是那样容易混淆。

-Script 后缀暗示了它不是一个真正的编程语言——脚本语言好象不是真正的编程语言。但其实这是一个专长的问题。相对 C 而言, JavaScript 牺牲性能但带来更强的表达力和动态性。

阅读全文 »

Reference How To Create Facade On Laravel 5.1

Here is step by step to create facade on laravel 5.2

  1. Create PHP Class File.
  2. Bind that class to Service Provider
  3. Register that ServiceProvider to config\app.php as providers
  4. Create Class which is this class extends to Illuminate\Support\Facades\Facade
  5. Register point 4 to config\app.php as aliases

Step 1 - Create PHP Class File, for example in App\Classes\UauthHelper.php

<?php

namespace App\Classes;

class UauthHelper {
    public function foo()
    {
        echo "foo";
    }
}

Step 2 - Bind that class to Service Provider

In case i create a new serviceprovider by execute

php artisan make:provider 'UauthServiceProvider'

then add

        $this->app->bind('uauth', function () {
            return new \App\Classes\UauthHelper;
        });
        
        
阅读全文 »

本教程将会涉及以下工具:

  • Ubuntu 14.04
  • MySQL
  • PHP
  • Nginx

安装

更新软件源

sudo apt-get update

安装必要组件

sudo apt-get install mysql-server   # 安装 MySQL

sudo apt-get install nginx-full     # 安装 Nginx

sudo apt-get install php5-fpm       # 安装 php5
sudo apt-get install php5-cli       # 安装 php5 命令行工具
sudo apt-get install php5-mcrypt php5-mysql php5-curl    # 安装常用 php5 扩展

安装 PHP 依赖管理工具 composer (可选)

sudo apt-get install git     # 安装 git

# 安装 composer
cd ~
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
阅读全文 »