2014-10-31 44 views
0

我正在嘗試從一張基於套裝和排名的卡片的spritesheet加載個人卡,但我不確定如何構建一個新的位圖對象從源圖像中切出矩形座標。我目前正在使用<windows.h>並試圖找到一個簡單的方法來完成此操作。我在尋找這樣的事情:如何從Win32 C++的spritesheet中提取位圖?

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

從來源:http://i.stack.imgur.com/WZ9Od.gif

+0

是否使用gdiplus?如果是這樣,「Bitmap :: Clone」可能就是你想要的。 – 2014-10-31 23:30:32

+0

不只是Win32 =(沒有額外的圖形庫 – 2014-10-31 23:40:38

+1

用'CreateCompatibleBitmap'或'CreateDIBitmap'或類似的方法創建一個新的位圖,選擇它到一個DC中,並用'BitBlt'從源文件中選取適當的部分。 – 2014-11-01 01:53:26

回答

0

這是我用一週打了更多或更少的這種相同的任務的功能。就我而言,我想返回一個可以與FillRect一起使用的HBRUSH。在這種情況下,我們仍然需要創建一個感興趣區域的位圖,然後再從中創建一個畫筆。

在你的情況下,只需要返回dstBmpspriteSheet是一個已加載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); 
     } 
    } 
} 

enter image description here

後者的功能已經被替換爲以下內容:

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); 
}