开发者

Fast accessing pixel values of jpeg images

CompVision once again, I'm 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 don't 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 can't wait for hours to get results.


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.


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] << " "; 
}


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜