Pladnius Brooks
Pladnius Brooks

Reputation: 1308

Converting 256 color bitmap to RGBA bitmap

I am writing a renderer in C++. I see that a similar question has been answered, I was just looking for a bit more information. I have a 256 color bitmap that I load into memory and then into OpenGL. I am UNABLE to convert the files before hand and need to do it in memory. I want to be able to convert it to an RGBA bitmap to make use of the alpha channel. Does anyone have any code or suggestions about libraries that may help me with this?

Upvotes: 3

Views: 2811

Answers (2)

Radu
Radu

Reputation: 973

I have some code somewhere, but it's just 20 lines or less. The BMP format is pretty simple, just read the header, then read every color, which serves as an index in the palette array. And keep in mind that BMPs are upside down:

//load a bmp texture, with the specified global alpha
GLuint load_bmp8_fixed_alpha(char * FileName, Uint8 a)
{
   int x,y,x_padding,x_size,y_size,colors_no,r,g,b,current_pallete_entry; //i unused?
   Uint8 * file_mem;
   Uint8 * file_mem_start;
   Uint8 * texture_mem;
   Uint8 * read_buffer;
   Uint8 * color_pallete;
   FILE *f = NULL;
   GLuint texture;

     f = fopen (FileName, "rb");
     if (!f) return 0;
     file_mem = (Uint8 *) calloc ( 20000, sizeof(Uint8));
     file_mem_start=file_mem;
     fread (file_mem, 1, 50, f);//header only
     //now, check to see if our bmp file is indeed a bmp file, and if it is 8 bits, uncompressed
     if(*((short *) file_mem)!=19778)//BM (the identifier)
       {
           free(file_mem_start);
           fclose (f);
           return 0;
       }
   file_mem+=18;
   x_size=*((int *) file_mem);
   file_mem+=4;
   y_size=*((int *) file_mem);
   file_mem+=6;
   if(*((short *)file_mem)!=8)//8 bit/pixel?
       {
           free(file_mem_start);
           fclose (f);
           return 0;
       }

   file_mem+=2;
   if(*((int *)file_mem)!=0)//any compression?
       {
           free(file_mem_start);
           fclose (f);
           return 0;
       }
   file_mem+=16;

   colors_no=*((int *)file_mem);
   if(!colors_no)colors_no=256;
   file_mem+=8;//here comes the pallete

   color_pallete=file_mem+4;
   fread (file_mem, 1, colors_no*4+4, f);//header only
   file_mem+=colors_no*4;

   x_padding=x_size%4;
   if(x_padding)x_padding=4-x_padding;

   //now, allocate the memory for the file
   texture_mem = (Uint8 *) calloc ( x_size*y_size*4, sizeof(Uint8));
   read_buffer = (Uint8 *) calloc ( 2000, sizeof(Uint8));


   for(y=0;y<y_size;y++)
       {
           //fread (texture_mem+y*x_size, 1, x_size-x_padding, f);
           fread (read_buffer, 1, x_size-x_padding, f);

           for(x=0;x<x_size;x++)
               {
                   current_pallete_entry=*(read_buffer+x);
                   b=*(color_pallete+current_pallete_entry*4);
                   g=*(color_pallete+current_pallete_entry*4+1);
                   r=*(color_pallete+current_pallete_entry*4+2);
                   *(texture_mem+(y*x_size+x)*4)=r;
                   *(texture_mem+(y*x_size+x)*4+1)=g;
                   *(texture_mem+(y*x_size+x)*4+2)=b;
                   *(texture_mem+(y*x_size+x)*4+3)=a;
               }

       }

   free(file_mem_start);
   free(read_buffer);
   fclose (f);
   //ok, now, hopefully, the file is loaded and converted...
   //so, assign the texture, and such

   glGenTextures(1, &texture);
   glBindTexture(GL_TEXTURE_2D, texture);    //failsafe
   bind_texture_id(texture);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

   if(poor_man)
       {
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
       }
   else if(use_mipmaps)
       {
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
           glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
       }
   else
       {
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
       }

   if(have_arb_compression)
       {
           if(have_s3_compression)
           glTexImage2D(GL_TEXTURE_2D,0,COMPRESSED_RGBA_S3TC_DXT5_EXT,x_size, y_size,0,GL_RGBA,GL_UNSIGNED_BYTE,texture_mem);
           else
           glTexImage2D(GL_TEXTURE_2D,0,COMPRESSED_RGBA_ARB,x_size, y_size,0,GL_RGBA,GL_UNSIGNED_BYTE,texture_mem);

       }
   else
   glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,x_size, y_size,0,GL_RGBA,GL_UNSIGNED_BYTE,texture_mem);

   check_gl_errors();
   free(texture_mem);
   return texture;
}

Upvotes: 4

Nicol Bolas
Nicol Bolas

Reputation: 473312

You could use most of these libraries to do it (and you get to use any number of other formats). I would suggest the unofficial OpenGL SDK. But then again, I wrote it, so take that for what it's worth ;)

I want to be able to convert it to an RGBA bitmap to make use of the alpha channel.

That's going to be rather difficult, as the BMP format does not in fact have an alpha channel. We are talking about an image in BMP format, yes?

Upvotes: 3

Related Questions