bliting a 24bit image on an SDL_texture raw

I tried doing this on my own but I'm just stumped. This reason why I'm trying to do is because I'm interested in file formats and how it works.

So, I have David's Linux port set up with something like this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
	Texture = SDL_CreateTexture(Renderer,
			SDL_PIXELFORMAT_ARGB8888,
			SDL_TEXTUREACCESS_STREAMING,
			Width,
			Height);
	BitmapWidth = Width;
	BitmapHeight = Height;
	BitmapMemory = mmap(0,
			Width * Height * BytesPerPixel,
			PROT_READ | PROT_WRITE,
			MAP_PRIVATE | MAP_ANONYMOUS,
			-1,
			0);
}


I'm trying to blit the image http://imgur.com/PKYWQnS by doing this:

 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
void ShowImage(BMPFILE* bmpStruct)
{
	int x=0;
	int y=0;

	uint8 *Pixel = (uint8 *)BitmapMemory;   
	uint32 *pixel = (uint32 *)Pixel;
	uint8 *dataPointer = (uint8 *) bmpStruct->data;

	for (y=0;y <bmpStruct->info->height;y++)
	{
	
		for (x=0;x < bmpStruct->info->width;x++)
		{
			
			int pitch=0;

			
			SDL_LockTexture(Texture,NULL,(void**) pixel,&pitch);

			uint32 it = *(dataPointer);
			it <<= 8;
			it |= *(dataPointer+1);
			it <<= 8;
			it |= *(dataPointer+2);


			*(pixel++) = (uint32) it;

			dataPointer+=3;
			SDL_UnlockTexture(Texture);
		}
	}
#endif

}


I figured since this is a 24bit map I would just grab a byte, or it into a 32bit int and shift it.

But I get this:

http://imgur.com/AeVLRgf

The only think I can think of that's not prob right is that it's compressed?

Edited by popcorn on
What is BMPFILE structure? Where do you get it? Are you sure it is 3 bytes per pixel? Are you sure rows are tightly packed (next row starts where previous one ends) without any padding?
This problem is asking for some structured art.

Edited by Miguel Lechón on
I'm so excited that i can finally answer a question in this forum rather than ask it, because i ran into the very same thing.
the problem you have is that although the picture is 3 byte per pixel, the row must start on a offset that is dividable by 4, and the format just inserts some 0 bytes into the end of the row to make the offset dividable. if you don't account for those 0 bytes, you get a wrong number of bytes per row (pitch). wrong pitch makes straight vertical lines into diagonal lines, and that's what you see in the picture.
if you want to check for yourself, search for the BMP format or look at the memory tab in visual studio, or both.
i solved it by just not dealing with it, and converting the image into 4 bytes AARRGGBB format, the other solution was to make bitmaps width dividable by 4. making something special for each row would make my one copy loop from one for loop into two, and i didn't want that, but i see you can edit your code to handle it.
i hope i was clear about that,
the mage.
That's why you don't code bitmap processing loops like this:
1
2
3
4
5
6
7
8
9
u8* Pixel = ...;
for (int y=0; y<H; y++)
{
  for (int x=0; x<W; x++)
  {
    ... // use pixel here
    Pixel += BytesPerPixel;
  }
}


You do following where you use bitmap pitch:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
u8* Row = ...;
for (int y=0; y<H; y++)
{
  u8* Pixel = Row;
  for (int x=0; x<W; x++)
  {
    ... // use pixel here
    Pixel += BytesPerPixel;
  }
  Row += Pitch;
}


While for simple bitmaps the first code fragment could work, once you get into optimization and especially SIMD stuff, you want to use second code fragment. That way you can make pitch bigger than Width * BytesPerPixel, so every row actually begins on 16-byte aligned address (or 32-byte for AVX).

If you look carefully what code Casey writes on stream you'll see that he always uses Pitch to advance to next row.

Edited by Mārtiņš Možeiko on

What is BMPFILE structure? Where do you get it? Are you sure it is 3 bytes per pixel? Are you sure rows are tightly packed (next row starts where previous one ends) without any padding?

I was thinking the same thing..I checked if it was compressed and it wasn't compressed like the body parts of our hero.
Yes, It's 24bits, so I get a byte from the image and then OR and SHIFT it leaving the alpha 0.

1
2
3
4
5
6
I'm so excited that i can finally answer a question in this forum rather than ask it, because i ran into the very same thing.
the problem you have is that although the picture is 3 byte per pixel, the row must start on a offset that is dividable by 4, and the format just inserts some 0 bytes into the end of the row to make the offset dividable. if you don't account for those 0 bytes, you get a wrong number of bytes per row (pitch). wrong pitch makes straight vertical lines into diagonal lines, and that's what you see in the picture.
if you want to check for yourself, search for the BMP format or look at the memory tab in visual studio, or both.
i solved it by just not dealing with it, and converting the image into 4 bytes AARRGGBB format, the other solution was to make bitmaps width dividable by 4. making something special for each row would make my one copy loop from one for loop into two, and i didn't want that, but i see you can edit your code to handle it.
i hope i was clear about that,
the mage. 


I haven't even done putting it on an X and Y cords yet. Right now it's at 0,0, and I will keep that mind when I do add X and Y cords, thanks! and Also, yes you are right, I forgot to add the pitch.

This problem is asking for some structured art.

Thanks I did review the video again and found the problem and a solution.

While for simple bitmaps the first code fragment could work, once you get into optimization and especially SIMD stuff, you want to use second code fragment. That way you can make pitch bigger than Width * BytesPerPixel, so every row actually begins on 16-byte aligned address (or 32-byte for AVX).

If you look carefully what code Casey writes on stream you'll see that he always uses Pitch to advance to next row.

yes, the pitch was exactly what I needed! And I think I will try to optimize, because it's the only way I can learn, then just watching.

Thanks to all, Handmade hero community is awesome. Now I just need to figure out how to flip the image. I already watch how Casey did it but it didn't quite work out. I prob just need to think it out more. Thanks Again.