Added support for RLE encoded tga images

dev
Shariq Shah 10 years ago
parent fc10cb9357
commit 77b93bc480
  1. 2
      src/game.c
  2. 4
      src/model.c
  3. 108
      src/texture.c

@ -106,7 +106,7 @@ void scene_setup(void)
transform_set_position(ground_tran, &pos);
transform_scale(ground_tran, &scale_ground);
texture_create_from_file("test.tga");
texture_create_from_file("test_comp.tga");
}
void debug(float dt)

@ -93,7 +93,7 @@ void model_cleanup(void)
void model_render_all(struct Camera* camera)
{
int texture = texture_find("test.tga");
int texture = texture_find("test_comp.tga");
mat4 mvp;
for(int i = 0; i < array_len(model_list); i++)
{
@ -103,7 +103,7 @@ void model_render_all(struct Camera* camera)
mat4_identity(&mvp);
shader_bind(model->shader);
/* shader_set_uniform_int(model->shader, "sampler", (GL_TEXTURE0 + 4) - GL_TEXTURE0); */
shader_set_uniform_int(model->shader, "sampler", (GL_TEXTURE0 + 4) - GL_TEXTURE0);
texture_bind(texture, 4);
renderer_check_glerror("model:render_all");
mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat);

@ -41,7 +41,8 @@ static struct Texture* texture_list;
static int* empty_indices;
int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt, int* internal_fmt);
void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data);
void debug_write_tga(struct Tga_Header* header, GLubyte* image_data);
void copy_tga_pixel(GLubyte* source, GLubyte* dest, size_t bytes_per_pixel);
void texture_init(void)
{
@ -157,13 +158,13 @@ void texture_cleanup(void)
void texture_bind(int index, int texture_unit)
{
assert(index > -1 && index < array_len(texture_list));
//glActiveTexture(GL_TEXTURE0 + texture_unit);
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, texture_list[index].handle);
}
void texture_unbind(int texture_unit)
{
//glActiveTexture(GL_TEXTURE0 + texture_unit);
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, 0);
}
@ -192,7 +193,6 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
if(header.datatypecode == 0)
{
log_error("texture:load_img", "No image data in file");
success = 0;
}
else
{
@ -200,7 +200,6 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
if(header.datatypecode != 2 && header.datatypecode != 10)
{
log_error("texture:load_img", "Unsupported image data type");
success = 0;
return success;
}
@ -208,14 +207,12 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
{
log_error("texture:load_img",
"Unsupported bitsperpixel size(%d), only 24 and 32 supported", header.bitsperpixel);
success = 0;
return success;
}
if(header.width <= 0 || header.height <= 0)
{
log_error("texture:load_img", "Invalid width and height (%d:%d)", header.width, header.height);
success = 0;
return success;
}
@ -225,7 +222,6 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
if(!*image_data)
{
log_error("texture:load_img", "Out of memory");
success = 0;
return success;
}
@ -236,35 +232,70 @@ int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt
fseek(file, skipover, SEEK_CUR);
/* Start reading pixel by pixel */
GLubyte pixel[bytes_per_pixel];
GLubyte* curr_pixel = *image_data;
for(int i = 0; i < header.width * header.height; i++)
if(header.datatypecode == 2) /* uncompressed image data */
{
if(header.datatypecode == 2) /* uncompressed image data */
{
if(fread(&pixel, 1, bytes_per_pixel, file) != bytes_per_pixel)
{
success = 0;
log_error("texture:load_img", "Unexpected end of file at pixel %d", i);
free(image_data);
return success;
}
GLubyte pixel[bytes_per_pixel];
GLubyte* curr_pixel = *image_data;
for(int i = 0; i < header.width * header.height; i++)
{
if(fread(&pixel, 1, bytes_per_pixel, file) != bytes_per_pixel)
{
log_error("texture:load_img", "Unexpected end of file at pixel %d", i);
free(image_data);
return success;
}
/* Swap BGR to RGB */
curr_pixel[0] = pixel[2];
curr_pixel[1] = pixel[1];
curr_pixel[2] = pixel[0];
if(bytes_per_pixel == 4) curr_pixel[3] = pixel[3];
curr_pixel += bytes_per_pixel;
}
else if(header.datatypecode == 10) /* compressed image data */
{
log_message("Not implemented yet!");
}
/* Copy pixel and change BGR to RGB */
copy_tga_pixel(&pixel[0], curr_pixel, bytes_per_pixel);
curr_pixel += bytes_per_pixel;
}
}
else if(header.datatypecode == 10) /* RLE encoded image data */
{
GLubyte chunk[bytes_per_pixel + 1];
GLubyte* curr_chunk = *image_data;
for(int i = 0; i < header.width * header.height;)
{
/* read chunk (header+pixel) */
if(fread(chunk, 1, sizeof(chunk), file) != sizeof(chunk))
{
log_error("texture:img_load", "Unexpected end of file at chunk %d", i);
free(*image_data);
return success;
}
i++;
copy_tga_pixel(&chunk[1], curr_chunk, bytes_per_pixel);
curr_chunk += bytes_per_pixel;
GLubyte chunk_identifier = chunk[0];
int count = chunk[0] & 0x7f;
if(chunk_identifier & 0x80) /* RLE chunk */
{
for(int j = 0; j < count; j++)
{
copy_tga_pixel(&chunk[1], curr_chunk, bytes_per_pixel);
curr_chunk += bytes_per_pixel;
i++;
}
}
else /* Normal chunk */
{
for(int j = 0; j < count; j++)
{
if(fread(&chunk[1], 1, bytes_per_pixel, file) != bytes_per_pixel)
{
log_error("texture:img_load", "Unexpected end of file at pixel %d", i);
free(*image_data);
return success;
}
copy_tga_pixel(&chunk[1], curr_chunk, bytes_per_pixel);
curr_chunk += bytes_per_pixel;
i++;
}
}
}
}
texture_debug_write_tga(&header, *image_data);
debug_write_tga(&header, *image_data);
*height = header.height;
*width = header.width;
*fmt = bytes_per_pixel == 3 ? GL_RGB : GL_RGBA;
@ -298,7 +329,7 @@ void texture_param_set(int index, int parameter, int value)
glBindTexture(GL_TEXTURE_2D, curr_texture);
}
void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data)
void debug_write_tga(struct Tga_Header* header, GLubyte* image_data)
{
/* Debug only, write the loaded image to file */
FILE* fptr = NULL;
@ -306,6 +337,7 @@ void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data)
fprintf(stderr,"Failed to open outputfile\n");
exit(-1);
}
if(header->datatypecode == 10) header->datatypecode = 2; /* Only uncompressed supported currently */
fwrite(header, sizeof(struct Tga_Header), 1, fptr);
for (int i = 0; i < header->height * header->width; i++)
{
@ -316,3 +348,11 @@ void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data)
}
fclose(fptr);
}
void copy_tga_pixel(GLubyte* source, GLubyte* dest, size_t bytes_per_pixel)
{
dest[0] = source[2];
dest[1] = source[1];
dest[2] = source[0];
if(bytes_per_pixel == 4) dest[3] = source[3];
}

Loading…
Cancel
Save