Archived

This topic is now archived and is closed to further replies.

LordLethis

RLE & Bitmaps

Recommended Posts

LordLethis    122
I wrote these functions to RLE compress a bitmap. But after compressing and decompressing the bitmap, i looks somewhat messed up (what I mean by 'messed up' can be seen here. Any ideas why? compress:
    
void rle(char* filename)
{
	BITMAPINFOHEADER ih;
	BITMAPFILEHEADER fh;
	RLEHEADER h;
	FILE* file = fopen(filename,"rb");
	fread(&fh,sizeof(fh),1,file);
	fread(&ih,sizeof(ih),1,file);
	if (fh.bfType!='MB' || ih.biBitCount != 24)
		return;
	RGB* data = (RGB*)malloc(ih.biWidth*ih.biHeight*3);
	int check = fread(data,3,ih.biWidth*ih.biHeight,file);
	fclose(file);
	RGBA* com = (RGBA*)calloc(ih.biWidth*ih.biHeight,sizeof(RGBA)); //make space for the worst case size -> every pixel has a different color

	h.quads = 0;
	memcpy(com,data,3);
	for (int i = 1; i < ih.biWidth*ih.biHeight; i++)
	{
		if (com[h.quads].r==data[i].r && com[h.quads].g==data[i].g && com[h.quads].b==data[i].b && com[h.quads].a < 255)
		{
			com[h.quads].a++;
		}
		else
		{
			h.quads++;
			memcpy(&com[h.quads],&data[i],3);
		}
	}
	h.type = 'ELR';
	h.height = ih.biHeight;
	h.width = ih.biWidth;
	h.bpp = ih.biBitCount;
	file = fopen("test.rle","wb");
	fwrite(&h,sizeof(h),1,file);
	check = fwrite(com,4,h.quads,file);
	fclose(file);
}
  

decompress:
      
void dec(char* filename)
{
	RLEHEADER h;
	BITMAPINFOHEADER ih;
	BITMAPFILEHEADER fh;
	FILE* file = fopen(filename,"rb");
	fread(&h,sizeof(h),1,file);
	if (h.type != 'ELR')
		return;
	RGBA* com = (RGBA*)malloc(4*h.quads);
	int check = fread(com,4,h.quads,file);
	fclose(file);
	RGB* data = (RGB*)malloc(3*h.height*h.width);
	memset(data,0,3*h.height*h.width);

	int c = 0, a = 0;
	
	for (int i = 0; i < h.height*h.width; i++)
	{
		if (a < com[c].a+1)
		{
			memcpy(&data[i],&com[c],3);
			a++;
		}
		else
		{
			c++;
			a = 0;
		}
	}

	fh.bfType = 'MB';
	fh.bfSize = sizeof(fh);
	fh.bfReserved1 = 0;
	fh.bfReserved2 = 0;
	fh.bfOffBits = sizeof(fh)+sizeof(ih);

	ih.biSize = sizeof(ih);
	ih.biWidth = h.width;
	ih.biHeight = h.height;
	ih.biPlanes = 1;
	ih.biBitCount = h.bpp;
	ih.biCompression = BI_RGB;
	ih.biSizeImage = 3*h.width*h.height;
	ih.biXPelsPerMeter = 2835; // 72 dpi

	ih.biYPelsPerMeter = 2835; // 72 dpi

	ih.biClrUsed = 0;
	ih.biClrImportant = 0;

	file = fopen("test.rle.bmp","w");
	fwrite(&fh,sizeof(fh),1,file);
	fwrite(&ih,sizeof(ih),1,file);
	fwrite(data,ih.biSizeImage,1,file);
	fclose(file);
}
    
[My Lousy Page|Kings Of Chaos | email.me] [edited by - LordLethis on January 28, 2003 11:51:29 AM]

Share this post


Link to post
Share on other sites
Glyph    122
I don''t really know anything about implmentation of the RLE algorithm but I saw some stuff in your code that may contribute to the screwed up bitmap. The loop in your rle function initializes its loop variable to 1... should this be 0 instead? Another suspicious line of code reads


h.type = ''ELR'';


I''m not quite sure what happens when you put three characters inside single quotes... should these be double quotes? And if so, should you be using a string copy? Also, when returning from that same function about 8 lines into it you should make sure to close the file.

Like I said, I don''t really know what the heck I''m talking about, so I wouldn''t be surprised if any (or all, more likely!) of this is flat out wrong. Good luck!

-Glyph

Share this post


Link to post
Share on other sites
Yohumbus    152
although I didnt look over your code that thouroghly there is only one thing I can think of that could twist the bitmap like that is that you might not be padding the bytes at the end. Say for example you had a 63 pixel long bitmap, when you write the bitmap it should have 63 bytes worth of data (compressed of corse) but at the end of it needs to be null so that it is 64 bytes long. Bitmaps have to be compressed to the 4 byte boundery

Share this post


Link to post
Share on other sites
LordLethis    122
OK, I forgot to mention, the functions don''t performthe RLE used for .bmp''s, it''s an own developed RLE using the alpha channel to store the run length.
The counter var in the for loop is initialized with 1 on purpose. (Damnit, would be happy to find a fault )
Thanks for the help anyway!

- Lethis

[My Lousy Page|Kings Of Chaos | email.me]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Try changing the start loop variable to 0. Just humor us.

-- John

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Ok, there''s two errors in the code.

1) The compression algorithm doesn''t save out the last run length (so if you had a 10x10 single colour bitmap, no colour data would be written to the output). To fix this, add
if (com [h.quads].a > 0)
{
++h.quads;
}
after the ''for'' loop in the ''rle'' function.

2) The decompressor is skipping pixels whenever a change of colour is occuring. This initially confused me when looking at the output image as the number of red pixels was correct but the number of black pixels to the left and right of the red block had gone up by two! To fix this, remove the ''i++'' form the ''for'' loop in the ''dec'' function and add it after the ''a++'' and before the ''}''.

Sorted.

If the background was not black, the problems would have been easier to spot and fix.

Skizz

Share this post


Link to post
Share on other sites