ソフトウェア開発 Win32プログラミング

ビットマップのきれいな拡大・縮小2

戻る


前回のものを扱いやすいように改良した。

#include <windows.h>

// 注意:
// pbmとpbmSrcは、24bppか32bppのDIBでなければならない。
// 両方ともボトムアップかトップダウンでなければならない。
VOID BilinearStretchBlt(
    BITMAP *pbm, INT x, INT y, INT cx, INT cy,
    BITMAP *pbmSrc, INT xSrc, INT ySrc, INT cxSrc, INT cySrc)
{
    if (cx <= 0 || cy <= 0)
        return;
 
    double wfactor = (double)cxSrc / cx;
    double hfactor = (double)cySrc / cy;
 
    // はみ出た領域があれば幅と高さと位置を修正する
    if (x < 0)
    {
        xSrc += -x * wfactor;
        cxSrc += x * wfactor;
        cx += x;
        x = 0;
    }
    if (y < 0)
    {
        ySrc += -y * hfactor;
        cySrc += y * hfactor;
        cy += y;
        y = 0;
    }
    if (xSrc < 0)
    {
        x += -xSrc / wfactor;
        cx += xSrc / wfactor;
        cxSrc += xSrc;
        xSrc = 0;
    }
    if (ySrc < 0)
    {
        y += -ySrc / hfactor;
        cy += ySrc / hfactor;
        cySrc += ySrc;
        ySrc = 0;
    }
    if (pbm->bmWidth < x + cx)
    {
        cx = pbm->bmWidth - x;
        cxSrc = cx * wfactor;
    }
    if (pbm->bmHeight < y + cy)
    {
        cy = pbm->bmHeight - y;
        cySrc = cy * wfactor;
    }
    if (pbmSrc->bmWidth < xSrc + cxSrc)
    {
        cxSrc = pbmSrc->bmWidth - xSrc;
        cx = cxSrc / wfactor;
    }
    if (pbmSrc->bmHeight < ySrc + cySrc)
    {
        cySrc = pbmSrc->bmHeight - ySrc;
        cy = cySrc / hfactor;
    }
 
    if (cx <= 0 || cy <= 0 || cxSrc <= 0 || cySrc <= 0)
        return;
 
    DWORD wf = wfactor * (1 << 10);
    DWORD hf = hfactor * (1 << 10);
    LPBYTE pb = (LPBYTE)pbm->bmBits;
    LPBYTE pbSrc = (LPBYTE)pbmSrc->bmBits;
    INT ix, iy, x0, y0, x1, y1;
    INT x_, y_, ex0, ex1, ey0, ey1;
    BYTE r0, g0, b0, a0, r1, g1, b1, a1;
 
    // BPPに応じて処理を行う
    if (pbm->bmBitsPixel == 32 && pbmSrc->bmBitsPixel == 32)
    {
        y_ = ySrc << 10;
        for(iy = y; iy < y + cy; iy++)
        {
            y0 = y_ >> 10;
            y1 = min(y0 + 1, (INT)pbmSrc->bmHeight - 1);
            ey1 = y_ & 0x3FF;
            ey0 = 0x3FF - ey1;
            x_ = xSrc << 10;
            for(ix = x; ix < x + cx; ix++)
            {
                x0 = x_ >> 10;
                x1 = min(x0 + 1, (INT)pbmSrc->bmWidth - 1);
                ex1 = x_ & 0x3FF;
                ex0 = 0x3FF - ex1;
                b0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                b1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 0] = (BYTE)((ey0 * b0 + ey1 * b1) >> 10);
                g0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                g1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 1] = (BYTE)((ey0 * g0 + ey1 * g1) >> 10);
                r0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                r1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 2] = (BYTE)((ey0 * r0 + ey1 * r1) >> 10);
                a0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 3] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 3] * ex1) >> 10;
                a1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 3] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 3] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 3] = (BYTE)((ey0 * a0 + ey1 * a1) >> 10);
                x_ += wf;
            }
            y_ += hf;
        }
    }
    else if (pbm->bmBitsPixel == 24 && pbmSrc->bmBitsPixel == 32)
    {
        y_ = ySrc << 10;
        for(iy = y; iy < y + cy; iy++)
        {
            y0 = y_ >> 10;
            y1 = min(y0 + 1, (INT)pbmSrc->bmHeight - 1);
            ey1 = y_ & 0x3FF;
            ey0 = 0x3FF - ey1;
            x_ = xSrc << 10;
            for(ix = x; ix < x + cx; ix++)
            {
                x0 = x_ >> 10;
                x1 = min(x0 + 1, (INT)pbmSrc->bmWidth - 1);
                ex1 = x_ & 0x3FF;
                ex0 = 0x3FF - ex1;
                b0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                b1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 0] = (BYTE)((ey0 * b0 + ey1 * b1) >> 10);
                g0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                g1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 1] = (BYTE)((ey0 * g0 + ey1 * g1) >> 10);
                r0 = (pbSrc[x0 * 4 + y0 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 4 + y0 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                r1 = (pbSrc[x0 * 4 + y1 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 4 + y1 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 2] = (BYTE)((ey0 * r0 + ey1 * r1) >> 10);
                x_ += wf;
            }
            y_ += hf;
        }
    }
    else if (pbm->bmBitsPixel == 32 && pbmSrc->bmBitsPixel == 24)
    {
        y_ = ySrc << 10;
        for(iy = y; iy < y + cy; iy++)
        {
            y0 = y_ >> 10;
            y1 = min(y0 + 1, (INT)pbmSrc->bmHeight - 1);
            ey1 = y_ & 0x3FF;
            ey0 = 0x3FF - ey1;
            x_ = xSrc << 10;
            for(ix = x; ix < x + cx; ix++)
            {
                x0 = x_ >> 10;
                x1 = min(x0 + 1, (INT)pbmSrc->bmWidth - 1);
                ex1 = x_ & 0x3FF;
                ex0 = 0x3FF - ex1;
                b0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                b1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 0] = (BYTE)((ey0 * b0 + ey1 * b1) >> 10);
                g0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                g1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 1] = (BYTE)((ey0 * g0 + ey1 * g1) >> 10);
                r0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                r1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                pb[ix * 4 + iy * pbm->bmWidthBytes + 2] = (BYTE)((ey0 * r0 + ey1 * r1) >> 10);
                pb[ix * 4 + iy * pbm->bmWidthBytes + 3] = 0xFF;
                x_ += wf;
            }
            y_ += hf;
        }
    }
    else if (pbm->bmBitsPixel == 24 && pbmSrc->bmBitsPixel == 24)
    {
        y_ = ySrc << 10;
        for(iy = y; iy < y + cy; iy++)
        {
            y0 = y_ >> 10;
            y1 = min(y0 + 1, (INT)pbmSrc->bmHeight - 1);
            ey1 = y_ & 0x3FF;
            ey0 = 0x3FF - ey1;
            x_ = xSrc << 10;
            for(ix = x; ix < x + cx; ix++)
            {
                x0 = x_ >> 10;
                x1 = min(x0 + 1, (INT)pbmSrc->bmWidth - 1);
                ex1 = x_ & 0x3FF;
                ex0 = 0x3FF - ex1;
                b0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                b1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 0] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 0] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 0] = (BYTE)((ey0 * b0 + ey1 * b1) >> 10);
                g0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                g1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 1] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 1] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 1] = (BYTE)((ey0 * g0 + ey1 * g1) >> 10);
                r0 = (pbSrc[x0 * 3 + y0 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 3 + y0 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                r1 = (pbSrc[x0 * 3 + y1 * pbmSrc->bmWidthBytes + 2] * ex0 +
                      pbSrc[x1 * 3 + y1 * pbmSrc->bmWidthBytes + 2] * ex1) >> 10;
                pb[ix * 3 + iy * pbm->bmWidthBytes + 2] = (BYTE)((ey0 * r0 + ey1 * r1) >> 10);
                x_ += wf;
            }
            y_ += hf;
        }
    }
}

ソース: bilinea2.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system