freeimage is a great library, it uses libpng as well as the other libs for opening image files. It however makes it much easier to do so. glfw has a tga loading function.
If you really want to learn to load a bmp by hand ( it's a good learning experience ) then you need to find the right information. Every image has a file header, its the first part of the file's structure that hold the information that you need to know to read and file. Such as width and height, bits per pixel, things like this. Once you have that its pretty easy
You just read the header into a struct, then your data should be next in the file, from the information in the header you should be able to figure out the total number of bytes in the data section. Read this in as an array of chars ( or bytes ). Then when you create your buffer do the following function call to send that data to openGL.
//mWidth is the image width from the image header
//mHeight is the image height from the image header
// mpBytes is a pointer to the char array, its size should be (mWidth * mHeight * (bitsPerPixel / 8)) ( this is in bytes ).
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, mpBytes );
// You may need to change the GL_BGRA to whatever format your image is in. In my case its R G B and A channels but in BGRA order.
There are other ways to send your image data to openGL such as mapping the buffer, but this way is easier.
If you want to see an example of bmp loading look at this tutorial