Invert (mirror) a bitmap

http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/Rotate-a-bitmap-image.htm

Rotate a bitmap image

http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1725/Invert-mirror-a-bitmap.htm

Invert (mirror) a bitmap

Posted by Zafir Anjum on August 5th, 1998

We can invert an image either laterally or vertically. The effect of the inversions is shown in the image below. The image on the top left is the normal image, the image on the top right is laterally inverted, the image on the bottom left is vertically inverted and the image on the bottom right has been inverted twice - once laterally and once vertically. The effect of applying both kinds of inversion is that the image gets rotated by 180 degrees.

Two functions have been listed below, one of them will draw the image onto a device context after inverting it and the other will create a new bitmap with the inverted image.

Function 1: DrawInvertedBitmap

The DrawInvertedBitmap() function draws an inverted image of a bitmap at the specified location. It uses StretchBlt() to do the actual inversion. When the signs of the source width and the destination width are different then the image is inverted along the x-axis. When the signs of the source height and the destination height are different then the image is inverted along the y-axis.

复制代码
// DrawInvertedBitmap    - Draws the bitmap after inverting it
// hBimtap        - Bitmap handle
// hPal            - Palette to use when drawing the bitmap
// bLateral        - Flag to indicate whether to invert laterally or vertically
// xDest        - X coordinate of top left corner to draw at
// yDest        - Y coordinate of top left corner to draw at
void DrawInvertedBitmap( CDC *pDC, HBITMAP hBitmap, HPALETTE hPal, BOOL bLateral, 
                            int xDest, int yDest )
{
    // Create a memory DC compatible with the destination DC
    CDC memDC;
    memDC.CreateCompatibleDC( pDC );
 
    // Get logical coordinates
    BITMAP bm;
    ::GetObject( hBitmap, sizeof( bm ), &bm );
 
    //memDC.SelectObject( &bitmap );
    HBITMAP hBmOld = (HBITMAP)::SelectObject( memDC.m_hDC, hBitmap );
    
    
    // Select and realize the palette
    if( hPal && pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
    {
        SelectPalette( pDC->GetSafeHdc(), hPal, FALSE );
        pDC->RealizePalette();
    }
    if( bLateral )
        pDC->StretchBlt( xDest, yDest, bm.bmWidth, bm.bmHeight, &memDC, 
                bm.bmWidth-1, 0, -bm.bmWidth, bm.bmHeight, SRCCOPY );
    else
        pDC->StretchBlt( xDest, yDest, bm.bmWidth, bm.bmHeight, &memDC, 
                0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, SRCCOPY );
 
    // Restore the old bitmap
    ::SelectObject( memDC.m_hDC, hBmOld );
}
复制代码

Function 2: GetInvertedBitmap

The GetInvertedBitmap() function creates a new bitmap to store the inverted image. This function too uses the StretchBlt() function for the actual inversion. In this case the destination device context is another memory device context so that the image is rendered into a bitmap.

复制代码
// GetInvertedBitmap    - Creates a new bitmap with the inverted image
// Returns        - Handle to a new bitmap with inverted image
// hBitmap        - Bitmap to invert
// bLateral        - Flag to indicate whether to invert laterally or vertically
HBITMAP GetInvertedBitmap( HBITMAP hBitmap, BOOL bLateral )
{
    // Create a memory DC compatible with the display
    CDC sourceDC, destDC;
    sourceDC.CreateCompatibleDC( NULL );
    destDC.CreateCompatibleDC( NULL );
 
    // Get logical coordinates
    BITMAP bm;
    ::GetObject( hBitmap, sizeof( bm ), &bm );
 
    // Create a bitmap to hold the result
    HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), 
                        bm.bmWidth, bm.bmHeight);
 
    // Select bitmaps into the DCs
    HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
    HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
    
    if( bLateral )
        destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 
                bm.bmWidth-1, 0, -bm.bmWidth, bm.bmHeight, SRCCOPY );
    else
        destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 
                0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, SRCCOPY );
 
    // Reselect the old bitmaps
    ::SelectObject( sourceDC.m_hDC, hbmOldSource );
    ::SelectObject( destDC.m_hDC, hbmOldDest );
 
    return hbmResult;
}
复制代码

 

 

posted @   IAmAProgrammer  阅读(527)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
历史上的今天:
2012-05-10 vhdl 状态机
2012-05-10 How can I discribe a ROM in VHDL
2012-05-10 VHDL 整数 小数 分数 分频
2012-05-10 source file for the Image Package image_pkg
2012-05-10 The Dual-Modulus Divider in VHDL
2012-05-10 synthesisable VHDL for a fixed ratio frequency divider
2012-05-10 Dual-Port Block RAM with Two Write Ports and Byte-wide Write Enable in Read-First Mode
点击右上角即可分享
微信分享提示