Popescu Flaviu
Popescu Flaviu

Reputation: 135

C++ SOIL does not load small images

I've got some problems while trying to load smaller textures for my pixel-art game using SOIL. This is the result while loading a 40 x 40 image: enter image description here

enter image description here

But when I switch to 30 x 40: enter image description here

enter image description here

I checked my code if there are any problems when width is smaller than height, and for 40 x 50 everything is alright. I checked that 30 x 40 with Windows' image viewer, and it seems alright there too. Single thing that may influence in any way the loader is when using the coordinate axis to set the position, but, it works right. This is the code for loading the texture:

glGenTextures(1, &actor.texture);
glBindTexture(GL_TEXTURE_2D, actor.texture);
unsigned char* image = SOIL_load_image(("App/Textures/" + name + ".png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

Upvotes: 4

Views: 600

Answers (2)

Rabbid76
Rabbid76

Reputation: 210928

When the image is loaded to a texture object, then GL_UNPACK_ALIGNMENT has to be set to 1:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); 

Note, by default the parameter is 4. This means that each line of the image is assumed to be aligned to a size which is a multiple of 4. Since the image data are tightly packed and each pixel has a size of 3 bytes, the alignment has to be changed.

When the size of the image is 40 x 50 then the size of a line in bytes is 120, which is divisible by 4.
But if the size of the image is 30 x 40, the the size of a line in bytes is 90, which is not divisible by 4.

Upvotes: 6

datenwolf
datenwolf

Reputation: 162164

The problem does not lie in the small size, but that 30 isn't divisible by 4: 30 = 2 * 3 * 5. The default pixel store setting OpenGL assumes, that rows are aligned to 4-byte boundaries. For the 40×40 image that condition happens to be fulfilled, because no matter what pixel format you use, there's a factor 4 in the width.

The solution is to tell OpenGL, that pixel rows start at a different n-byte boundary:

unsigned char* image = SOIL_load_image(…);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(…);

Upvotes: 5

Related Questions