Byte-by-Byte processing (& file formats)

Hey. I was once a C++ ninja... and now since I've been much less active in programming, and only recently restarted with my C++ "journey", I've been re-learning a lot of old things I was once good at.

I've decided to start some experiments, beginning with image algorithms and software rendering type stuff.

For the sake of retention, rather than starting with OpenGL (which is easy anyway) to display the results directly in a window, I've decided to re-implement my rudimentary Microsoft BMP image support. So I'll just render my image results into BMP files.

The Microsoft Bitmap (*.bmp) format
http://msdn.microsoft.com/en-us/library/dd183391%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/dd183374%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/dd183376%28v=vs.85%29.aspx

I have this so far:

msbmp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#ifndef _MSBMP_H
#define _MSBMP_H

#ifndef w8
# define w8 unsigned char
#endif

#ifndef w16
# define w16 unsigned short int
#endif

#ifndef w32
# define w32 unsigned long int
#endif

#ifndef MemoryChunk
struct MemoryChunk
{
	w32 size;
	w8* data;
};
#endif

#ifndef Mchunk
# define Mchunk MemoryChunk
# define Mchunk MemoryChunk
#endif

#ifndef Color24
struct Color24
{
	w8 red, green, blue;
};
#endif

#ifndef PixelMatrix
struct PixelMatrix
{
	w32 area;
	w16 width, height;
	Color24* pixels;
};
#endif

Mchunk* MsBMPFormat (PixelMatrix&);
//PixelMatrix* MsBMPDeformat (Mchunk&);

#endif 


msbmp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "msbmp.h"

Mchunk* MsBMPFormat (PixelMatrix& image)
{
	// Create a memory chunk.
	Mchunk* code;
	code->size = 0;
	code->data = 0;

	// Figure the size.

	// File Header Size = 14
	// Info Header Size = 40
	// Total Header Size = 54

	w32 size = image.width * image.height * 3;
	code->size = 54 + size;

	// Format Data into Microsoft BMP format.
	code->data = new w8[code->size];
	code->data[0] = 0x4D;
	code->data[1] = 0x42;
	code->data[2] = (w8)((size >> 24) & 0xFF);
	code->data[3] = (w8)((size >> 16) & 0xFF);
	code->data[4] = (w8)((size >> 8) & 0xFF);
	code->data[5] = (w8)(size & 0xFF);
	code->data[6] = 0x0;
	code->data[7] = 0x0;
	code->data[8] = 0x0;
	code->data[9] = 0x0;
	// Work-in progress...

	return code;
}


Please tell me if you see any immediate (minor) problems or have any suggestions to refresh my strife for robustness.

But I'm wonder if doing this
1
2
3
4
code->data[/* byte index */] = /*value*/;
code->data[/* byte index */] = /*value*/;
code->data[/* byte index */] = /*value*/;
// etc. 


For all the determined bytes (like the file/information headers) will cause the generated object code to be bloated, instead of some other method, like a for loop which uses a constant byte array.

Also, I wonder if I should have an extra argument which points to a user defined output/write function, like this:

bool MsBMPFormat (PixelMatrix& image, void(*Out)(w8 byte), w32 *size);

That should be better, right?
I was once a C++ ninja... and only recently restarted with my C++ "journey"
I did C# for a year or so and was surprised at how quickly C++ can go. Quite shocking really.

Please tell me if you see any immediate (minor) problems
1
2
3
4
5
6
7
8
9
10
11
Mchunk* MsBMPFormat (PixelMatrix& image)
{
	// Create a memory chunk.
	Mchunk* code; // = new Mchunck() missing
	code->size = 0;
	code->data = 0;

	// ...

	return code;
}
You don't actually allocate an Mchunk. You create an uninitialised pointer and start writing into the random memory location.
Last edited on
I did C# for a year or so and was surprised at how quickly C++ can go. Quite shocking really.


I was pleasantly surprised that after a few weeks of Scala, Ruby, Java, Smalltalk and others I managed to write a trivial "incremental" implementation of Eratosthenes sieve in C. I was almost certain that I would do something incredibly stupid in those like... 100 loc. (actually... it's not really a sieve. It works the same way though)

For the sake of retention, rather than starting with OpenGL (which is easy anyway) to display the results directly in a window, I've decided to re-implement my rudimentary Microsoft BMP image support.


I don't see how loading BMP's for use with the Win32 API is any harder (or more useful) than it is for OpenGL. The results should be near identical, no?
Last edited on
You don't actually allocate an Mchunk. You create an uninitialised pointer and start writing into the random memory location.


O_o

Hahahaha. Oops.

What about my other questions?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "msbmp.h"

// These should be implemented in a different file; obviously not very safe functions as they are:

void Bytes_w32 (w8* target, w32 n)
{
	target[0] = (w8)((n >> 24) & 0xFF);
	target[1] = (w8)((n >> 16) & 0xFF);
	target[2] = (w8)((n >> 8) & 0xFF);
	target[3] = (w8)(n & 0xFF);
}

void BytesCopy (w8* target, w8* source, w32 byteCount)
{
	while (byteCount != 0)
	{
		target[byteCount] = source[byteCount];
		--byteCount;
	}
}

void BytesFill (w8* target, w8 value, w32 byteCount)
{
	while (byteCount != 0)
	{
		target[byteCount] = value;
		--byteCount;
	}
}

Mchunk* MsBMPFormat (PixelMatrix& image)
{
	// Here I should at least check if the PixelMatrix is valid.

	// Create a memory chunk.
	Mchunk* code = new Mchunk;
	code->size = 0;
	code->data = 0;

	// Figure the size.

	// File Header Size = 14
	// Info Header Size = 40
	// Total Header Size = 54

	w32 size = image.width * image.height * 3;
	code->size = 54 + size;

	// Format Data into Microsoft BMP format.
	code->data = new w8[code->size];

	// I'm not sure if this is any good:
	const w8[2] determined = {0x4D, 0x42};
	BytesCopy(code->data, determined, 2);

	// Valid, right?
	Bytes_w32(code->data+2, code->size);
	BytesFill(code->data+6, 0, 4);

	// Work-in progress...

	return code;
}


Edit:
I suspect my original method would be faster, and potentially less bloated as well? Hmm...

@hanst99
Yeah, I tried other languages too (D, Google Go, Haskell, Python). The experience wasn't so great...

I'm planning to learn some assembly. I think MASM will be a good start, because of its native-ness with Windows (my OS), which should make the process easier for me as a beginner. I think I'll also take a look at YASM some time too.

I don't see how loading BMP's for use with the Win32 API is any harder (or more useful) than it is for OpenGL. The results should be near identical, no?

I just want to have my own utility to start new projects more quickly with... At least some rudimentary support for an existing image format would be a nice start. This isn't for future Win32 API projects. Its just for formatting image data to export as a BMP. I'm not directly using IO, but maybe I could do something like this:

bool MsBMPFormat (PixelMatrix& image, void(*Out)(w8 byte), w32& size);
Last edited on

Yeah, I tried other languages too (D, Google Go, Haskell, Python). The experience wasn't so great...


That's regrettable. I had lots of fun with my language tours. Of course I never actually encountered a language where I didn't at one point think "dammit, why can't this be a bit more like language X?!", but overall it was an interesting experience. I'm probably still going to stay with C/C++ for now, although I do miss the expressiveness of higher level languages sometimes.
I'm trying Smalltalk now, actually (Pharo). By the looks of it, I think I might just fall in love. How much did you like it? I haven't actually done anything with it yet; I got it just barely and I'm focusing on a research paper at the moment.
Topic archived. No new replies allowed.