Click here to Skip to main content
15,886,422 members
Articles / Programming Languages / C++

A fast way to work on Windows bitmap pixel data without using the slow GetPixel and SetPixel methods

Rate me:
Please Sign up or sign in to vote.
3.50/5 (6 votes)
4 Jun 2010CPOL1 min read 78.2K   1.1K   24   23
When GetPixel() and SetPixel() are very slow, try this solution.

Introduction

This article shows a fast way to view and change pixel color data (Windows bitmaps) without using the GetPixel and SetPixel methods.

Background

I spent a couple of months in trouble not knowing a fast way to edit images with C++ (I was using the Windows API functions GetPixel and SetPixel). I lost a couple of clients. I then spent a couple of weeks browsing through forums trying to find answers. But eventually, I got through this by myself and learned this easy pointer arithmetic method.

Using the Code

We use a pointer to bitmap bits: bitmapzor.GetBits();. Then, we use a pointer offset to get to another line in the bitmap pixel colors array: bitmapzor.GetPitch();.

The complete code with comments is listed here:

C++
// FastImageManipulations.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
    //Okay Now you need a bitmap to work with. Find any bmp file on your PC and
    //Put it to C:\\1.bmp location. You can enter any name, just alter the file
    //path below:

    CImage bitmapzor;
    bitmapzor.Load(_T("C:\\1.bmp"));

    //I use ATL CImage class because it is easy to use. Low number of code lines
    //You can use HBITMAP, HGDIOBJ of GDIplus and other methods,
    //They work the same way and at the same speed, but take tons of code lines 
    //For instance you can use HBITMAP bitmapzor = (HBITMAP)ImageLoad(...)
    //And then you are to use GDI and API functions
    //Let us see the difference between standard API and pointer way:
    printf ("Now we use ATL (Api) GetPixel and SetPixel functions to " 
            "enforce (for example) all green pixels by 30%\n please " 
            "press any key to start and start counting minutes :)");

    getchar();
    COLORREF PixColor=0; //This is a color data
    int R=0,G=0,B=0; //These are the channel values

    //First we shall for instance allter all pixel colors to green using standard way
    for (int i=0; i<bitmapzor.GetWidth(); i++) //along line
        for (int j=0; j<bitmapzor.GetHeight(); j++) //new line
        {
            //This evil slow function extracts 24bit pixel color as BGR value
            PixColor = bitmapzor.GetPixel(i,j);
            R=GetRValue(PixColor);//This macro extracts red channel value
            G=GetGValue(PixColor);//This macro extracts green channel value
            B=GetBValue(PixColor);//This extracts blue pixel color
            G=(int)((float)G*1.3); //There we enforce green color by 30%.
            if (G>255) G=255; //There we ensure G is within 0-255 range
            //We can assemble the BGR 24 bit number that way
            //PixColor = B*0x10000+G*0x100+R;
            PixColor = RGB(R,G,B);//Or we can use this function
            //Now we save a new "green" pixel value back to bitmap
            bitmapzor.SetPixel(i,j,PixColor);
        }

    //Now we need to save this result to a HD:
    LPCTSTR filename=_T("C:\\GetPixel.bmp");
    //you can change the location of this file

    bitmapzor.Save(filename);
    printf ("Done, file is saved to: %s\n Please press " 
            "any key for another method demo", filename);
    getchar();

    //Okay now another way with the pointer arithmetics:
    printf ("Pointer arithmetics demo (without GetPixel and SetPixel functions): \n");
    bitmapzor.Destroy(); //Unload the changed bitmap from memory
    bitmapzor.Load("C:\\1.bmp");
    //this is a pointer to the exact bitmap pixel color array location
    BYTE* byteptr = (BYTE*)bitmapzor.GetBits();

    //You can use other functions for HBITMAP and HGDIOBJ methods to find out the 
    //container for bitmap color table.
    //For instance when you use GDI and HBITMAPS, you should use
    //BYTE* byteptr = (BYTE*)(HBITMAPINFOHEADER + HBITMAPINFOHEADER->biSize);
    //simple pointer arithmetics

    int pitch = bitmapzor.GetPitch(); //This is a pointer offset to get new line of the bitmap

    for (int i=0; i<bitmapzor.GetWidth();i++)
        for (int j=0; j<bitmapzor.GetHeight();j++)
        {
            //pointer arithmetics to find (i,j) pixel colors:
            R= *(byteptr+pitch*j+3*i);
            G= *(byteptr+pitch*j+3*i+1);
            B= *(byteptr+pitch*j+3*i+2); 

            //allter pixel G color:
            G=(int)((float)G*1.3);
            if (G>255) G=255;
            //write down the new G-Color
            *(byteptr+pitch*j+3*i+1)=G;
        }

    //Save the bitmap:
    LPCTSTR filename2 = _T("C:\\ptrarithm.bmp"); //you can use any other file name
    bitmapzor.Save(filename2);
    printf ("Done, file is saved to: %s\n Please press any key to exit program", filename2);
    getchar();
    bitmapzor.Destroy(); //destroy the bitmap
    return 0;
}

Points of Interest

A normal bitmap is a WxH pixel table with a header. Each value in the pixel table is a 24 bit integer or 3xCHARs. To access these values, we need to know the starting point of the pointer and the offset. Normal bitmaps have a negative offset; e.g., if the pointer to some line of the color table is a byteptr, then the pointer to the next line is byteptr-3*W. But sometimes, bitmaps are upside-down oriented and the pointer to the next line is byteptr+3*W. Anyway, the offset negative or positive is always given by the GetPitch() method.

History

This is version 1.0.2 of the article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Stellar Intelligence
Kazakstan Kazakstan
I saw the atom spectrum splitting in labs. I touched irradiated rocks. I measured the mass and charge of electrons. I made Galileo's telescope, I've modeled the big bang, I saw sunspots, ships and aircrafts on satellite pictures. I touched stingers, patriots and S-300 missiles.
I have eventually understood computers, electronics, cryptography, programming and the Internet. Quite tough for a 25 yrs old guy, huh? That all is to be the first to discover something new within the next 50 years.

you can contact me through atommic@mail.ru mailbox
153428517 ICQ
jkurbanaliev skype

Comments and Discussions

 
GeneralGetBits usage Pin
Darryl Bryk5-Oct-10 12:22
Darryl Bryk5-Oct-10 12:22 
GeneralMy vote of 2 Pin
Member 1657988-Jun-10 22:03
Member 1657988-Jun-10 22:03 
GeneralRe: My vote of 2 Pin
Jan Kurbanaliev10-Jun-10 5:27
Jan Kurbanaliev10-Jun-10 5:27 
GeneralPixels Pin
geoyar8-Jun-10 14:21
professionalgeoyar8-Jun-10 14:21 
GeneralRe: Pixels Pin
Jan Kurbanaliev10-Jun-10 5:27
Jan Kurbanaliev10-Jun-10 5:27 
GeneralRe: Pixels Pin
geoyar10-Jun-10 14:14
professionalgeoyar10-Jun-10 14:14 
NewsI think you've probably missed the point. You've ignored the cpu caching Pin
gavery8-Jun-10 12:01
gavery8-Jun-10 12:01 
GeneralRe: I think you've probably missed the point. You've ignored the cpu caching Pin
Johann Gerell10-Jun-10 1:39
Johann Gerell10-Jun-10 1:39 
GeneralRe: I think you've probably missed the point. You've ignored the cpu caching Pin
Jan Kurbanaliev10-Jun-10 5:24
Jan Kurbanaliev10-Jun-10 5:24 
GeneralRe: I think you've probably missed the point. You've ignored the cpu caching Pin
Jan Kurbanaliev10-Jun-10 5:31
Jan Kurbanaliev10-Jun-10 5:31 
GeneralHey guys in a week or so I shall modify teh article and get rid of bugs and make it looking more like an article so pls do not delete Pin
Jan Kurbanaliev8-Jun-10 3:30
Jan Kurbanaliev8-Jun-10 3:30 
QuestionHow fast? And what about compressed images? Pin
jsc428-Jun-10 1:15
professionaljsc428-Jun-10 1:15 
AnswerRe: How fast? And what about compressed images? Pin
Jan Kurbanaliev8-Jun-10 2:51
Jan Kurbanaliev8-Jun-10 2:51 
GeneralCompressed images? Pin
jsc428-Jun-10 3:37
professionaljsc428-Jun-10 3:37 
GeneralRe: Compressed images? Pin
Jan Kurbanaliev8-Jun-10 6:26
Jan Kurbanaliev8-Jun-10 6:26 
QuestionWhat's with all the negativity? Pin
S.H.Bouwhuis7-Jun-10 22:04
S.H.Bouwhuis7-Jun-10 22:04 
Phew, some harsh commenting!

Although I have used a similar technique myself, I still believe it is worthy of being read by people who are new to programming/imaging.

Thank you for the effort! 3/5 from me.
AnswerRe: What's with all the negativity? Pin
Jan Kurbanaliev7-Jun-10 22:33
Jan Kurbanaliev7-Jun-10 22:33 
GeneralYou are doing it wrong Pin
mluri7-Jun-10 1:28
mluri7-Jun-10 1:28 
GeneralRe: You are doing it wrong [modified] Pin
Jan Kurbanaliev7-Jun-10 22:31
Jan Kurbanaliev7-Jun-10 22:31 
GeneralBout that stuff [modified] Pin
Jan Kurbanaliev5-Jun-10 3:07
Jan Kurbanaliev5-Jun-10 3:07 
GeneralNot quite an article Pin
Dave Kreskowiak5-Jun-10 2:25
mveDave Kreskowiak5-Jun-10 2:25 
GeneralRe: Not quite an article Pin
Jan Kurbanaliev8-Jun-10 6:34
Jan Kurbanaliev8-Jun-10 6:34 
GeneralProblems Pin
#realJSOP5-Jun-10 1:14
mve#realJSOP5-Jun-10 1:14 

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.