【问题标题】:How to extract bitmap from spritesheet in Win32 C++?如何在 Win32 C++ 中从 spritesheet 中提取位图?
【发布时间】:2014-12-28 08:15:06
【问题描述】:

我正在尝试根据花色和等级从卡片精灵表中加载单独的卡片,但我不确定如何通过剪切源图像中的 Rectangle 坐标来构造新的 Bitmap 对象。我目前正在使用<windows.h>,并试图找到一种简单的方法来实现这一点。我正在寻找这样的东西:

HBITMAP* twoOfHearts = CutOutFromImage(sourceImage, new Rectangle(0, 0, 76, 116));

来源:http://i.stack.imgur.com/WZ9Od.gif

【问题讨论】:

  • 你在使用 gdiplus 吗?如果是这样,Bitmap::Clone 可能就是您想要的。
  • 不只是 Win32 =( 没有额外的图形库
  • 使用CreateCompatibleBitmapCreateDIBitmap 或类似方法创建一个新位图,将其选择到DC,然后使用BitBlt 从源中对相应部分进行blit。

标签: c++ winapi graphics bitmap


【解决方案1】:

这是我前一周为或多或少相同的任务而玩的一个函数。就我而言,我想返回一个可以与 FillRect 一起使用的 HBRUSH。在这种情况下,我们仍然需要创建感兴趣区域的位图,然后再从它创建画笔。

在您的情况下,只需返回 dstBmp 即可。 spriteSheet 是一个已加载 256x256 spritesheet 的全局变量。我已将精灵的大小硬编码为 16x16,您需要将其更改为 81x117 之类的大小。

这里有一些代码可以获取所需区域的副本,还有一些代码使用这些“标记”来绘制关卡地图。也就是说 - 这种方法存在各种各样的问题。速度是一个,过度工作是另一个影响第一个的因素。最后,滚动这样绘制的窗口会产生伪像。

// grabs a 16x16px section from the spriteSheet HBITMAP
HBRUSH getSpriteBrush(int col, int row)
{
    HDC memDC, dstDC, curDC;
    HBITMAP oldMemBmp, oldDstBmp, dstBmp;
    curDC = GetDC(HWND_DESKTOP);

    memDC = CreateCompatibleDC(NULL);
    dstDC = CreateCompatibleDC(NULL);

    dstBmp = CreateCompatibleBitmap(curDC, 16, 16);
    int xOfs, yOfs;
    xOfs = 16 * col;
    yOfs = 16 * row;

    oldMemBmp = (HBITMAP)SelectObject(memDC, spriteSheet);
    oldDstBmp = (HBITMAP)SelectObject(dstDC, dstBmp);
    BitBlt(dstDC,0,0,16,16, memDC, xOfs,yOfs, SRCCOPY);

    SelectObject(memDC, oldMemBmp);
    SelectObject(dstDC, oldDstBmp);
    ReleaseDC(HWND_DESKTOP, curDC);
    DeleteDC(memDC);
    DeleteDC(dstDC);

    HBRUSH result;
    result = CreatePatternBrush(dstBmp);
    DeleteObject(dstBmp);
    return result;
}

void drawCompoundSprite(int x, int y, HDC paintDC, char *tileIndexes, int numCols, int numRows)
{
    int mapCol, mapRow;
    HBRUSH curSprite;
    RECT curDstRect;

    for (mapRow=0; mapRow<numRows; mapRow++)
    {
        for (mapCol=0; mapCol<numCols; mapCol++)
        {
            int curSpriteIndex = tileIndexes[mapRow*numCols + mapCol];
            int spriteX, spriteY;

            spriteX = curSpriteIndex % 16;
            spriteY = curSpriteIndex / 16;

            curDstRect.left = x + 16*mapCol;
            curDstRect.top = y + 16 * mapRow;
            curDstRect.right = curDstRect.left + 16;
            curDstRect.bottom = curDstRect.top + 16;
            curSprite = getSpriteBrush(spriteX, spriteY);
            FillRect(paintDC, &curDstRect, curSprite);
            DeleteObject(curSprite);
        }
    }
}

后一个函数已被以下替换:

void drawCompoundSpriteFast(int x, int y, HDC paintDC, unsigned char *tileIndexes, int numCols, int numRows, pMapInternalData mData)
{

    int mapCol, mapRow;
    HBRUSH curSprite;
    RECT curDstRect;
    HDC memDC;
    HBITMAP oldBmp;
    memDC = CreateCompatibleDC(NULL);
    oldBmp = (HBITMAP)SelectObject(memDC, mData->spriteSheet);

    for (mapRow=0; mapRow<numRows; mapRow++)
    {
        for (mapCol=0; mapCol<numCols; mapCol++)
        {
            int curSpriteIndex = tileIndexes[mapRow*numCols + mapCol];
            int spriteX, spriteY;

            spriteX = curSpriteIndex % mData->tileWidth;
            spriteY = curSpriteIndex / mData->tileHeight


// Draw sprite as-is
//            BitBlt(paintDC, x+16*mapCol, y+16*mapRow,
//                   mData->tileWidth, mData->tileHeight,
//                   memDC,
//                   spriteX * 16, spriteY*16,
//                   SRCCOPY);

// Draw sprite with magenta rgb(255,0,255) areas treated as transparent (empty)
            TransparentBlt(
                           paintDC,
                           x+mData->tileWidth*mapCol, y+mData->tileHeight*mapRow,
                           mData->tileWidth, mData->tileHeight,

                           memDC,
                           spriteX * mData->tileWidth, spriteY*mData->tileHeight,
                           mData->tileWidth, mData->tileHeight,
                           RGB(255,0,255)
                           );
        }
    }
    SelectObject(memDC, oldBmp);
    DeleteObject(memDC);
}

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多