Software Blitting part 2

Computer graphics are made up of pixels, and pixels are made up of colour channels, specifically Red, Green, and Blue (and Alpha, but we’re not worried about that). You combine all three of those channels to form the colour that you want. As it turns out, if you have a gradation of 0-255 for each of these channels, you can create colours of small enough granularity that the human eye cannot tell the difference between the two most like each other. Since it takes a computer 8 bytes to store 256 values, and we need one byte for each colour channel, we have each of our pixels requiring 24 bits of information, giving us 24 bit colour, giving us over 16.7 million colours.

But we have a bit of a problem. Raw pixel data can be quite large. Consider this, and image at 1920×1080, or 1080p, contains 1920*1080 pixels, or over 2 million pixels. If each pixel takes 3 bytes of information, that image takes 47.46 MB’s of space on the user’s hard drive. And yet, if you find an image of this size on your hard drive odds are that it does not take up anywhere near that amount of space. This is due to compression. There are many types of compression algorithms (such as JPEG, DXT, PNG, GIFF, etc), and therefore formats, but I was dealing simply with PNG. What compression does is take the raw image data, and reduce the data required to store that image. You then need a program to read the PNG (or other format) image file, and decompress the file.

Luckily I had access to the excellent stbi library*, created by Sean T. Barnett, which reduce loading a png image into this:

*No really it’s awesome. A single file library. Was blown away. So much better than libPNG.


unsigned char* pRaw=stbi_load(filePath.c_str(), &pImg->wd, &pImg->ht, &pImg->bpp, 0);
if(pRaw==NULL){
std::cout << "Error loading PNG\n";
return false;
}

Of course, I ended up creating an “Image” struct, and a “Pixel” struct, so I wrote a wrapper that looks like this:


bool LoadImage(Image* pImg, std::string filePath){
unsigned char* pRaw=stbi_load(filePath.c_str(), &pImg->wd, &pImg->ht, &pImg->bpp, 0);
if(pRaw==NULL){
std::cout << "Error loading PNG\n";
return false;
}

//allocate memory for pixels
int size=pImg->wd*pImg->ht;
pImg->pImg=new Pixel[size]();
//convert image to pixel format.
for(int i=0; i<size*pImg->bpp; i+=pImg->bpp){
pImg->pImg[i/pImg->bpp].r=pRaw[i];
pImg->pImg[i/pImg->bpp].g=pRaw[i+1];
pImg->pImg[i/pImg->bpp].b=pRaw[i+2];
}
return true;
}

But the point remains that, thanks to Mr. Barnett and all those who worked on the stbi library, the first step of reconverting a png to raw data is incredibly easy. The second step is a bit more challenging.

Continued in Part 3.

This entry was posted in Programming and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s