node.js 获取中文名长度

// 通过 Node.js 提供的 Buffer 类
var getByBuffer = function(str) {
    var buffer = new Buffer(str);
    var len = buffer.length;
    delete buffer;
    return len;
};

// 通过原生的正则
var getByReg = function(str) {
    var cArr = str.match(/[^x00-xff]/ig);
    return str.length + (cArr == null ? 0 : cArr.length);
};

// 通过原生的字符码
var getByCode = function(str) {
    var realLength = 0,
        len = str.length,
        charCode = -1;
    for (var i = 0; i < len; i++) {
        charCode = str.charCodeAt(i);
        if (charCode >= 0 && charCode <= 128) realLength += 1;
        else realLength += 2;
    }
    return realLength;
};

速度上而言, 使用原生方式的后两者可能会快上 1ms, 编码上来说, 使用 node.js 的 buffer 类可以区别 GBK 和 UTF8, 而原生方法则要自己指定.

Advertisements

Super fast blur 模糊算法

好久没整理GDI 教程了,这东西本来准备跟教程一起发的,但是要直接讲还接不上目前的教程,所以在硬盘里面堆了好久。
今天突然想起来,为了避免忘记先发上来。废话不多说,有图有真相:

superfast_blur算法

源代码:

#include <windows.h>

// 用于注册的窗口类名
const char g_szClassName[] = "myWindowClass";

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 300

#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x>y?y:x)

/*
 * Super Fast Blur v1.1
 * Original author: Mario Klingemann (C++ version)
 * Original address: http://incubator.quasimondo.com/processing/superfastblur.pde
 * C version updated by Lellansin (http://www.lellansin.com)
 */
void superFastBlur(unsigned char *pix, int w, int h, int radius)
{
    int div;
    int wm, hm, wh;
    int *vMIN, *vMAX;
    unsigned char *r, *g, *b, *dv;
    int rsum, gsum, bsum, x, y, i, p, p1, p2, yp, yi, yw;

    if (radius < 1) return;

    wm = w - 1;
    hm = h - 1;
    wh = w * h;
    div = radius + radius + 1;
    vMIN = (int *)malloc(sizeof(int) * max(w, h));
    vMAX = (int *)malloc(sizeof(int) * max(w, h));
    r = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    g = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    b = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    dv = (unsigned char *)malloc(sizeof(unsigned char) * 256 * div);

    for (i = 0; i < 256 * div; i++)
        dv[i] = (i / div);

    yw = yi = 0;

    for (y = 0; y < h; y++)
    {
        rsum = gsum = bsum = 0;
        for (i = -radius; i <= radius; i++)
        {
            p = (yi + min(wm, max(i, 0))) * 3;
            bsum += pix[p];
            gsum += pix[p + 1];
            rsum += pix[p + 2];
        }
        for (x = 0; x < w; x++)
        {
            r[yi] = dv[rsum];
            g[yi] = dv[gsum];
            b[yi] = dv[bsum];

            if (y == 0)
            {
                vMIN[x] = min(x + radius + 1, wm);
                vMAX[x] = max(x - radius, 0);
            }
            p1 = (yw + vMIN[x]) * 3;
            p2 = (yw + vMAX[x]) * 3;

            bsum += pix[p1] - pix[p2];
            gsum += pix[p1 + 1] - pix[p2 + 1];
            rsum += pix[p1 + 2] - pix[p2 + 2];

            yi++;
        }
        yw += w;
    }

    for (x = 0; x < w; x++)
    {
        rsum = gsum = bsum = 0;
        yp = -radius * w;
        for (i = -radius; i <= radius; i++)
        {
            yi = max(0, yp) + x;
            rsum += r[yi];
            gsum += g[yi];
            bsum += b[yi];
            yp += w;
        }
        yi = x;
        for (y = 0; y < h; y++)
        {
            pix[yi * 3] = dv[bsum];
            pix[yi * 3 + 1] = dv[gsum];
            pix[yi * 3 + 2] = dv[rsum];

            if (x == 0)
            {
                vMIN[y] = min(y + radius + 1, hm) * w;
                vMAX[y] = max(y - radius, 0) * w;
            }
            p1 = x + vMIN[y];
            p2 = x + vMAX[y];

            rsum += r[p1] - r[p2];
            gsum += g[p1] - g[p2];
            bsum += b[p1] - b[p2];

            yi += w;
        }
    }

    free(r);
    free(g);
    free(b);

    free(vMIN);
    free(vMAX);
    free(dv);
}

VOID BmpBlur(HDC hSrcDC, int x, int y, int iWidth, int iHeight )
{
    int i;
    int iPixel = 24;
    int iBytesPerPixel = iPixel / 8;
    int iBytesScanLine;

    HDC hMemDC;
    HBITMAP hBitmap, hBitmapOld;

    BYTE *pBmpBitsStart;
    BYTE *pBmpBitsCurrent;
    BYTE *newBitmap;
    BYTE *pNewBitsCurrent;

    //图形格式参数
    LPBITMAPINFO lpbmih = (LPBITMAPINFO)malloc(sizeof(BITMAPINFO));

    lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbmih->bmiHeader.biWidth = iWidth;
    lpbmih->bmiHeader.biHeight = iHeight;
    lpbmih->bmiHeader.biPlanes = 1;
    lpbmih->bmiHeader.biBitCount = iPixel;
    lpbmih->bmiHeader.biCompression = BI_RGB;
    lpbmih->bmiHeader.biSizeImage = 0;
    lpbmih->bmiHeader.biXPelsPerMeter = 0;
    lpbmih->bmiHeader.biYPelsPerMeter = 0;
    lpbmih->bmiHeader.biClrUsed = 0;
    lpbmih->bmiHeader.biClrImportant = 0;

    // 创建一个 缓存DC
    hMemDC = CreateCompatibleDC(hSrcDC);
    // 创建一个与设备无关的位图对象
    hBitmap = CreateDIBSection(hMemDC, lpbmih, DIB_RGB_COLORS, (void **)&pBmpBitsStart, NULL, 0);
    // hOld
    hBitmapOld = (HBITMAP)SelectObject(hMemDC, hBitmap);

    // 将要模糊的图片拷贝到缓存DC上
    BitBlt( hMemDC, 0, 0, iWidth, iHeight, hSrcDC, x, y, SRCCOPY);

    // 当前位指针指向缓存图片
    pBmpBitsCurrent = pBmpBitsStart;
    // 计算一行有多少字节
    iBytesScanLine = ((iBytesPerPixel * iWidth + 3) >> 2) << 2;

    // 新申请一块内存
    newBitmap = (BYTE *)malloc(sizeof(BYTE) * (iWidth * iHeight * 3));
    // current 指针指向这块内存
    pNewBitsCurrent = newBitmap;

    // 将图片拷贝到这块内存上
    for (i = 0; i < iHeight; ++i)
    {
        // 从图片(pBitsCurrent)拷贝到新内存(current), 多少字节每像素 * 宽度
        memcpy(pNewBitsCurrent , pBmpBitsCurrent , iBytesPerPixel * iWidth);
        pNewBitsCurrent += iBytesPerPixel * iWidth;
        pBmpBitsCurrent += iBytesScanLine;
    }

    // 调用模糊算法来修改这块内存上的数据(图片)
    superFastBlur(newBitmap , iWidth , iHeight , 5);

    // 当前位指针指向缓存图片
    pBmpBitsCurrent = pBmpBitsStart;
    // current 指针指向存有被模糊图片的内存
    pNewBitsCurrent = newBitmap;

    // 将被模糊的数据拷贝回图片缓存
    for (i = 0; i < iHeight; ++i)
    {
        // 每一行只拷贝一半
        memcpy(pBmpBitsCurrent , pNewBitsCurrent , iBytesPerPixel * iWidth / 2);
        pNewBitsCurrent += iBytesPerPixel * iWidth;
        pBmpBitsCurrent += iBytesScanLine;
    }

    SelectObject(hMemDC , hBitmapOld);
    SelectObject(hSrcDC, hBitmap);

    DeleteObject(hBitmap);
    DeleteObject(hBitmapOld);
    DeleteObject(hMemDC);
    
    free(newBitmap);
    free(lpbmih);
}

void Paint(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc;
    HDC mdc;
    HBITMAP hbmp; // 位图绘制对象句柄

    hdc = BeginPaint(hwnd, &ps);

    // 加载图片到缓存 DC
    mdc = CreateCompatibleDC(hdc);
    hbmp = (HBITMAP)LoadImage(NULL, "D:\bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE);
    SelectObject(mdc, hbmp);

    // 将当前缓存DC 中的图片模糊
    BmpBlur(mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

    // 将缓存DC中的位图复制到窗口DC上
    BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, mdc, 0, 0, SRCCOPY);

    DeleteObject(hbmp);
    DeleteDC(mdc);
    EndPaint(hwnd, &ps);
}

/*
 * 第四步,窗口过程
 */
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    // 窗口绘制消息
    case WM_PAINT:
        Paint(hwnd); // 调用我们的 GDI 绘制函数
        break;
    // 窗口关闭消息
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    // 窗口销毁消息
    case WM_DESTROY:
        PostQuitMessage(0); // 发送离开消息给系统
        break;
    // 其他消息
    default:
        // pass 给系统,咱不管
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

/*
 * 第一步,注册窗口类
 */
void RegisterMyWindow(HINSTANCE hInstance)
{
    WNDCLASSEX wc;

    // 1)配置窗口属性
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = MyWindowProc; // 设置第四步的窗口过程回调函数
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // 2)注册
    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "窗口注册失败!", "错误", MB_ICONEXCLAMATION | MB_OK);
        exit(0); // 进程退出
    }
}

/*
 * 第二步,创建窗口
 */
HWND CreateMyWindow(HINSTANCE hInstance, int nCmdShow)
{
    HWND hwnd;
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               g_szClassName,
               "Superfast Blur 算法",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, // 出现坐标 x,y 默认分配 窗口宽 400 高 300
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, "窗口创建失败!", "错误", MB_ICONEXCLAMATION | MB_OK);
        exit(0); // 进程退出
    }

    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    return hwnd;
}

/*
 * 主函数
 */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG Msg;

    // 第一步:注册窗口类
    RegisterMyWindow(hInstance);
    // 第二步:创建窗口
    hwnd =  CreateMyWindow(hInstance, nCmdShow);
    // 第三步:消息循环
    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}