views:

89

answers:

3

CompVision once again, im working with jpeg images in my application. Just because i'm a bit familiar with MFC and ATL, i used CImage to access pixel values.

For my needs i calculate brightness matrix for the image during initialization. Function goes like this(Image is the name of my own class, unimportant, bright is float[][]):

 void Image::fillBrightnessMatrix(){
    COLORREF val;
    for(int i=0;i<width;i++){
        for(int j=0; j<height;j++){
          val=src.GetPixel(i,j);
              bright[i][j]=rgb_to_L(val);
        }
    }
}

Where src is an instance of CImage class, rgb_to_L - some function that calculates brightness of the color.

Examining the performance of my app, i discovered that GetPixel is the most expensive operation, and it significantly(really, ~700 times slower than any other operation) slows down the whole initializing of image. The question is, which library can you suggest for fast access to single pixel values? I dont need any other operations but loading jpeg image and accessing single pixels. Performance is important, because my application works with set of ~3000 images and i cant wait for hours to get results.

A: 

I always recommend OpenCV.

This is a humble code snippet to get you started:

IplImage* pRGBImg = cvLoadImage("c:\\test.jpg", CV_LOAD_IMAGE_UNCHANGED); 
if (!pRGBImg)
{
  std::cout << "!!! cvLoadImage failed !!!" << std::endl;
  exit(1);
}

int width = pRGBImg->width; 
int height = pRGBImg->height;
int bpp = pRGBImg->nChannels; 
for (int i=0; i < width*height*bpp; i+=bpp) 
{
  if (!(i % (width*bpp))) // print empty line for better readability
      std::cout << std::endl;

  std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<  
                          " G:" << (int) pRGBImg->imageData[i+1] <<  
                          " B:" << (int) pRGBImg->imageData[i+2] << " "; 
}
karlphillip
I cant use OpenCV. Frankly, i dont want to use it. It's to heavy and too compilcated for the task im talking about.
Anton
@Anton You could have stated that you didn't like OpenCV on your question. OpenCV is used even on the iPhone, so I don't know what heavy actually means to you. As my code above shows, OpenCV is not complicated at all. But I think that's a matter of experience. Good luck.
karlphillip
A: 

You should probably extract the jpeg to raw data, then access the raw data instead of GetPixel.

Viktor Sehr
I believe its the best way to solve my problem, all i want is the exact name of library that programmers have been using and can advise :)
Anton
+2  A: 

Use CBitmap::GetBits() to get a raw pointer to the pixel data. You can now directly party on the pixels without going through the expensive GetPixel() method. There are a number of things you need to be careful with when you do this:

  • You have to use CBitmap::GetPitch() to calculate the offset to the start of a line. The pitch is not the same as the width.
  • Lines in the bitmap are stored upside-down
  • You have to deal with the pixel format yourself. A 24bpp image stores 3 bytes per pixel. An indexed format like 8bpp requires looking up the color in the color table. 32bpp is the easy one, 4 bytes per pixel and the pitch is always the same as the width.
Hans Passant
Damn, i knew there must be something better than GetPixel! Thanks. Now i have to find a working example of using this methods, cuz the whole web is filled with messages from noobs like me asking why dont their snippets work.
Anton