Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC
Article

Image Processing Using GDI+

Rate me:
Please Sign up or sign in to vote.
4.66/5 (36 votes)
8 May 20062 min read 153K   5.5K   97   36
This article describes the implementation of an image processing tool.

Introduction

There are many image processing tools similar to what I describe in this article. In this personal tool, I have used very basic image processing algorithms. Here I have focused on brightness, color inversion, contrast, blur, sharpness, and black and white color algorithms. I have used GDI+ for loading the image into memory, with the help of formulas mentioned for each kind of image processing. The code includes the CImageProcess.cpp and CImageProcess.h files. I would like to suggest that for image processing, do not use GetPixel and SetPixel. Performance wise, they are very slow. For more information, check this article: Rotate a Bitmap at Any Angle Without GetPixel/SetPixel.

Original Image

Image 1

Algorithm and Code

  1. Brightness

    An image can be light or sark. If we want to have more light in the image, we should decrease the RGB value. If we want an image to be darker, we should increase the RGB value.

    Image 2

    Formula

    Color = Color + Value(may be –ve)
    if (Color <0) Color = 0; if (Color>255) Color = 255;

    For example, if we want to decrease the red color component:

    Red = Red - DecrementVal

    To increase the red color component:

    Red = Red + IncrementVal

    The code

    BITMAPINFO bi;
    BOOL bRes;
    char *buf;
    
    // Bitmap header
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
    bi.bmiHeader.biWidth = m_nWidth;
    bi.bmiHeader.biHeight = m_nHeight;
    bi.bmiHeader.biPlanes = 1;
    bi.bmiHeader.biBitCount = 32;
    bi.bmiHeader.biCompression = BI_RGB;
    bi.bmiHeader.biSizeImage = m_nWidth * 4 * m_nHeight;
    bi.bmiHeader.biClrUsed = 0;
    bi.bmiHeader.biClrImportant = 0;
    
    // Buffer
    buf = (char *) malloc(m_nWidth * 4 * m_nHeight);
    // Don't use getPixel and SetPixel.It's very slow.
    // Get the all scanline.
    bRes = GetDIBits(hMemDC, m_hBitmap, 0, m_nHeight, buf, &bi,
                           DIB_RGB_COLORS);
    long nCount=0;
    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {
            long lVal=0;
            memcpy(&lVal, &buf[nCount], 4);
            // Get the reverse order
            int b = GetRValue(lVal);
            int g = GetGValue(lVal);
            int r = GetBValue(lVal);
            
            // Red
            r += nRedVal;
            if (r >255)
            {
                r = 255;
            }
            if (r <0)
            {
                r = 0;
            }
    
            // Green
            g += nGreenVal;
            if (g>255)
            {
                g = 255;
            }
            if (g<0)
            {
                g = 0;
            }
    
            // Blue
            b += nBlueVal;
            if (b >255)
            {
                b = 255;
            }
            if (b<0)
            {
                b = 0;
            }
            
            // Store reverse order
            lVal = RGB(b, g, r);
            memcpy(&buf[nCount], &lVal, 4);
    
        // Increment with 4. RGB color take 4 bytes. 
        // The high-order byte must be zero
        // See in MSDN COLORREF
            nCount+=4;
          }
        }
    
        // Set again
        SetDIBits(hMemDC, m_hBitmap, 0, bRes, buf,  &bi,
                           DIB_RGB_COLORS);    
        free(buf);
  2. Invert Color

    When we invert color, we get the opposite colors of the current pixels.

    Image 3

    Formula

    Color = 255 – Color; if (Color <0) Color = 0;
    if (Color>255) Color = 255;

    The code

    // Same header format
    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {
            long lVal=0;
            memcpy(&lVal, &buf[nCount], 4);
            int b = 255-GetRValue(lVal);
            int g = 255-GetGValue(lVal);
            int r = 255-GetBValue(lVal);
                
            lVal = RGB(b, g, r);
                
            memcpy(&buf[nCount], &lVal, 4);
            nCount+=4;
        }
    }
  3. Contrast Color

    Contrasting colors are colors that are opposite on the color wheel. In a high contrast image, you can see definite edges, and the different elements of that image are accented. In a low contrast image, all the colors are nearly the same, and it's hard to make out the details.

    Image 4

    Formula

    Color = (((Color - 128) * ContrastVal) / 100) +128
    if (Color <0) Color = 0; if (Color>255) Color = 255;

    Here, the contrast value is between 0 and 200.

    The code

    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {            
            long lVal=0;
            memcpy(&lVal, &buf[nCount], 4);
            // Get from buffer in reverse order
            int b = GetRValue(lVal);
            int g = GetGValue(lVal);
            int r = GetBValue(lVal);
    
            r = ((r-128)*nContrastVal)/100 +128;
            g = ((g-128)*nContrastVal)/100 +128;
            b = ((b-128)*nContrastVal)/100 +128;            
            
            // Red
            if (r >255)
            {
                r = 255;
            }
            if (r <0)
            {
                r = 0;
            }
                
            // Green
            if (g>255)
            {
                g = 255;
            }
            if (g<0)
            {
                g = 0;
            }
    
            // Blue            
            if (b >255)
            {
                b = 255;
            }
            if (b<0)
            {
                b = 0;
            }
    
            // Store in reverse order            
            lVal = RGB((int)b, (int)g, (int)r);
            
            memcpy(&buf[nCount], &lVal, 4);
            nCount+=4;
        }
    }
  4. Blur

    Blur is the well-known effect on computer screens, in fact on all pixel devices, where the diagonal and curved lines are displayed as a series of little zigzag horizontal and vertical lines.

    Image 5

    Formula

    Color = (C1+C2+C3+C4+C5)/5

    For more details about blur and anti-aliasing check this article: Creating graphics for the Web: Anti-aliasing.

    Here, C1 is the current pixel. C2, C3, C4, and C5 are the nearby pixels.

    Image 6

    The code

    pOriBuf = (char *) malloc(m_nWidth * 4 * m_nHeight);
    // Store new value into tempravary buffer
    char *tmpBuf = (char *) malloc(m_nWidth * 4 * m_nHeight);
    bRes = GetDIBits(hMemDC, m_hBitmap, 0, m_nHeight, pOriBuf, &bi,
                           DIB_RGB_COLORS);    
    long nCount=0;
    long c1, c2, c3, c4, c5;
    
    // Retrive from original buffer
    // Caluculate the value and store new value into tmpBuf
    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {
            long lVal=0;
            memcpy(&lVal, &pOriBuf[nCount], 4);
            int b = GetRValue(lVal);
            int g = GetGValue(lVal);
            int r = GetBValue(lVal);
    
            c1 = r;
            // Red
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && 
                (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[nCount-(m_nWidth*4l)], 4);
                c2 = GetBValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetBValue(lVal);
        
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetBValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetBValue(lVal);
                        
                r = (c1+c2+c3+c4+c5)/5;
            }
    
            // Green
            c1 = g;
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && 
                (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[(nCount-(m_nWidth*4l))], 4);
                c2 = GetGValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetGValue(lVal);
        
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetGValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetGValue(lVal);
        
                g = (c1+c2+c3+c4+c5)/5;
            }
    
            // Blue
            c1 = b;
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && 
                (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[(nCount-(m_nWidth*4l))], 4);
                c2 = GetRValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetRValue(lVal);
        
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetRValue(lVal);
        
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetRValue(lVal);
        
                b = (c1+c2+c3+c4+c5)/5;
            }
    
            // Store in reverse order
            lVal = RGB(b, g, r);
                    
            memcpy(&tmpBuf[nCount], &lVal, 4);
        
            nCount+=4;
        }
    }
    
    // Store tmpBuf
    SetDIBits(hMemDC, m_hBitmap, 0, bRes, 
              tmpBuf,  &bi, DIB_RGB_COLORS);
    
    free(pOriBuf);
    free(tmpBuf);
  5. Sharpness

    Image 7

    Formula

    Color = (C1*5) – (C2+C3+C4+C5).
    if (Color <0) Color = 0; if (Color>255) Color = 255;

    The code

    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {
            long lVal=0;
            memcpy(&lVal, &pOriBuf[nCount], 4);
            int b = GetRValue(lVal);
            int g = GetGValue(lVal);
            int r = GetBValue(lVal);
        
            c1 = r;
            // Red
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[nCount-(m_nWidth*4l)], 4);
                c2 = GetBValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetBValue(lVal);
            
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetBValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetBValue(lVal);
            
                r = (c1*5) - (c2+c3+c4+c5);
            }
    
            // Green
            c1 = g;
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[(nCount-(m_nWidth*4l))], 4);
                c2 = GetGValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetGValue(lVal);
            
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetGValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetGValue(lVal);
            
                g = (c1*5) - (c2+c3+c4+c5);
            }
    
            // Blue
            c1 = b;
            if ((nCount < ((m_nHeight-1)*m_nWidth*4l)) && (nCount > (m_nWidth*4)))
            {
                memcpy(&lVal, &pOriBuf[(nCount-(m_nWidth*4l))], 4);
                c2 = GetRValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount+4], 4);
                c3 = GetRValue(lVal);
            
                memcpy(&lVal, &pOriBuf[(nCount+(m_nWidth*4l))], 4);
                c4 = GetRValue(lVal);
            
                memcpy(&lVal, &pOriBuf[nCount-4], 4);
                c5 = GetRValue(lVal);
            
                b = (c1*5) - (c2+c3+c4+c5);
            }
    
            // Red
            if (r >255)
            {
                r = 255;
            }
            if (r <0)
            {
                r = 0;
            }
            
            // Green
            if (g>255)
            {
                g = 255;
            }
            if (g<0)
            {
                g = 0;
            }
    
            // Blue
            if (b >255)
            {
                b = 255;
            }
            if (b<0)
            {
                b = 0;
            }
            
            // Store in reverse order
            lVal = RGB(b, g, r);
            
            memcpy(&tmpBuf[nCount], &lVal, 4);
            
            nCount+=4;
        }
    }
  6. Black and white color

    Black and white images can be arrived at by giving the same color value for Red, Green, and Blue.

    Image 8

    Formula

    Color = (R+G+B)/3; R = Color; G = Color; B = Color;

    The code

    for (int i=0; i<m_nHeight; ++i)
    {
        for (int j=0; j<m_nWidth; ++j)
        {
            long lVal=0;
            memcpy(&lVal, &buf[nCount], 4);
            // Get the color value from buffer
            int b = GetRValue(lVal);
            int g = GetGValue(lVal);
            int r = GetBValue(lVal);
    
            // get the average color value
            lVal = (r+g+b)/3;
    
            // assign to RGB color            
            lVal = RGB(lVal, lVal, lVal);
            memcpy(&buf[nCount], &lVal, 4);
    
            nCount+=4;
        }
    }

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Japan Japan
Skills: VC++, ATL COM, Embeded VC++, BREW for Mobile and TCP/IP

Current Location: Bangalore

Born & Brought : Ayankollankondan,RJPM, India

Work Experience:
6+Years experience in IT field. Now i'm working in MindTree Consulting Ltd, B'lore.

5Digistar Inc, Japan
HCL Technologies Ltd, Chennai
T&B international Pvt ltd, Chennai
Aram menporulagam Pvt Ltd, Chennai


Comments and Discussions

 
Bugcan't download u r code Pin
embeded_zcd29-Dec-12 16:22
embeded_zcd29-Dec-12 16:22 
GeneralMy vote of 5 Pin
spoolrd16-Jul-12 9:14
spoolrd16-Jul-12 9:14 
Generalsave modified image to 24 bit png Pin
LingTec25-Feb-10 13:30
LingTec25-Feb-10 13:30 
GeneralCompiling errorr Pin
marink011-Nov-09 9:17
marink011-Nov-09 9:17 
GeneralRe: Compiling errorr Pin
kim soeong hoon27-Aug-14 22:21
kim soeong hoon27-Aug-14 22:21 
QuestionWhat about lighting? [modified] Pin
Member 13366015-Jul-09 14:54
Member 13366015-Jul-09 14:54 
GeneralExcellent Work...! :-) Pin
Khathar18-Feb-08 21:10
Khathar18-Feb-08 21:10 
Questionhow can i use that code for vb.net ? Pin
Mortezai27-Jun-07 7:31
Mortezai27-Jun-07 7:31 
AnswerRe: how can i use that code for vb.net ? Pin
S.Balasubramanian27-Jun-07 22:08
S.Balasubramanian27-Jun-07 22:08 
GeneralVery badly implemented Pin
Scope3-Dec-06 8:47
Scope3-Dec-06 8:47 
GeneralRe: Very badly implemented Pin
Christian Graus3-Dec-06 9:04
protectorChristian Graus3-Dec-06 9:04 
GeneralRe: Very badly implemented Pin
Scope3-Dec-06 9:13
Scope3-Dec-06 9:13 
GeneralRe: Very badly implemented Pin
S.Balasubramanian3-Dec-06 16:54
S.Balasubramanian3-Dec-06 16:54 
QuestionWhat is 41 ?? Pin
Brandingo15-Jun-06 5:25
Brandingo15-Jun-06 5:25 
AnswerRe: What is 41 ?? Pin
S.Balasubramanian15-Jun-06 16:18
S.Balasubramanian15-Jun-06 16:18 
GeneralRe: What is 41 ?? Pin
Apollo813-Aug-06 13:08
Apollo813-Aug-06 13:08 
GeneralredVal...greenVal...blueVal... Pin
Brandingo15-Jun-06 3:42
Brandingo15-Jun-06 3:42 
GeneralRe: Don't change anything!! Pin
Brandingo15-Jun-06 5:24
Brandingo15-Jun-06 5:24 
Generalwhy? reverse order.. Pin
iegooo1-Jun-06 3:24
iegooo1-Jun-06 3:24 
GeneralRe: why? reverse order.. Pin
S.Balasubramanian1-Jun-06 16:09
S.Balasubramanian1-Jun-06 16:09 
Generaldithering Pin
xianglifeng18-May-06 2:50
xianglifeng18-May-06 2:50 
GeneralRe: dithering Pin
S.Balasubramanian19-May-06 1:18
S.Balasubramanian19-May-06 1:18 
QuestionHow to save modified image ? Pin
Rogerio Silva15-May-06 14:31
Rogerio Silva15-May-06 14:31 
AnswerRe: How to save modified image ? Pin
S.Balasubramanian15-May-06 18:12
S.Balasubramanian15-May-06 18:12 
GeneralRe: How to save modified image ? Pin
kiranchikhale13-Feb-07 23:13
kiranchikhale13-Feb-07 23:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.