Updated. Added a few tweaks to the code to squeeze a few more bytes of compression. In some cases, it is significant, but on average, reduction of a couple hundred bytes achieved. See Post #2 for which ones I included & which still may be doable. Also updated the zip to include 2 more bitmaps: 1) one that this project & Windows can't compress smaller & 2) one where Windows can't compress, but this project compresses pretty well
Microsoft allows 8-bit bitmaps to be compressed using a somewhat simple, not terribly efficient, run length encoding (RLE). Strict rules apply, but is rather easy to encode/decode
Whether you are aware of it or not, you can actually get the API GetDibits to compress these 8-bit bitmaps for you. Niffty, fast, but unfortunately, what is returned can actually be larger than the original uncompressed image at times. In any case, I think we can do a bit better than Windows in this area.
Attached is a sample project wrapped around the key routine: pvCompressRLE8. Also included are 2 simple bitmaps to play with. Now trying to go out and find 8-bit bitmaps can be a bit painful, pun intended ;)
Suggestion: for playing around, use Microsoft Paint. Open image in Paint, save image as 256 color bitmap & don't care if the colors get messed up a bit. It's just for playing anyway
The routine I've written is not guaranteed to compress smaller than the total uncompressed size. But it should 99.9% of the time. In fact, it out-performs GetDibits every time (so far). I'm sure there are a few bitmaps that Windows can compress better via GetDibits.
This routine was created simply because I was inquisitive, wanted to see if I could possibly do it better (given how poorly Windows seems to do it). If there are better routines out there, please link them. Think many would like to learn from those also, me included.
Last but not least, I'm not touting this as the best RLE8 routine for VB6ers. But it ain't bad for a 1st attempt. The one I've included could use a little tune-up also. See post #2
Edited: Senior moment. Didn't include a browser class in the zip. It's there now.
FYI: If you want to see how Windows does when the routine fails to compress a bitmap, rem-out the "GoTo ExitRoutine" line after the msgbox displaying the failure
Best case scenario for failure and the "compressed" data being larger than the original data size would be a size equal to that shown below (assuming width < 256 else worse results). This is because if no bytes repeated on any scanline, the scanline would be coded with a 2 byte prefix + the entire scanline bytes + 2 byte scanline terminator. The encoding also requires a 2 byte EOF maker. But when compressing fails, the routine aborts so user can write bitmap in original bytes vs writing an even larger bitmap. Note: standard bitmaps without any compression algo applied have their pixels DWord aligned. This means for an 8-bit bitmap, a maximum of 3 padding bytes per scanline can be used for standard bitmaps. Even if that is the case, the minimum extra bytes used in RLE8 compression would be 4 per scanline. In other words, RLE8 without being able to compress any bytes, would be a larger file than not using RLE8 at all:
Microsoft allows 8-bit bitmaps to be compressed using a somewhat simple, not terribly efficient, run length encoding (RLE). Strict rules apply, but is rather easy to encode/decode
Quote:
Originally Posted by paraphrased from msdn
Attached is a sample project wrapped around the key routine: pvCompressRLE8. Also included are 2 simple bitmaps to play with. Now trying to go out and find 8-bit bitmaps can be a bit painful, pun intended ;)
Suggestion: for playing around, use Microsoft Paint. Open image in Paint, save image as 256 color bitmap & don't care if the colors get messed up a bit. It's just for playing anyway
The routine I've written is not guaranteed to compress smaller than the total uncompressed size. But it should 99.9% of the time. In fact, it out-performs GetDibits every time (so far). I'm sure there are a few bitmaps that Windows can compress better via GetDibits.
This routine was created simply because I was inquisitive, wanted to see if I could possibly do it better (given how poorly Windows seems to do it). If there are better routines out there, please link them. Think many would like to learn from those also, me included.
Last but not least, I'm not touting this as the best RLE8 routine for VB6ers. But it ain't bad for a 1st attempt. The one I've included could use a little tune-up also. See post #2
Edited: Senior moment. Didn't include a browser class in the zip. It's there now.
FYI: If you want to see how Windows does when the routine fails to compress a bitmap, rem-out the "GoTo ExitRoutine" line after the msgbox displaying the failure
Best case scenario for failure and the "compressed" data being larger than the original data size would be a size equal to that shown below (assuming width < 256 else worse results). This is because if no bytes repeated on any scanline, the scanline would be coded with a 2 byte prefix + the entire scanline bytes + 2 byte scanline terminator. The encoding also requires a 2 byte EOF maker. But when compressing fails, the routine aborts so user can write bitmap in original bytes vs writing an even larger bitmap. Note: standard bitmaps without any compression algo applied have their pixels DWord aligned. This means for an 8-bit bitmap, a maximum of 3 padding bytes per scanline can be used for standard bitmaps. Even if that is the case, the minimum extra bytes used in RLE8 compression would be 4 per scanline. In other words, RLE8 without being able to compress any bytes, would be a larger file than not using RLE8 at all:
Code:
<best-case "compressed" size when bitmap cannot be compressed (not good)>
even-value image width: ImageHeight * 4 + 2 + (ImageHeight * ImageWidth)
odd-value image width: ImageHeight * 5 + 2 + (ImageHeight * ImageWidth)
^^ extra padding byte needed per scanline