Opengl - Loading .png images

After searching different libraries that can load .png images, i’v settled with libPNG. I’v googled for days through other peoples posts and tutorials but to no avail.

So i started by taking the sample loading function for libpng directly from opengl’s wiki page.

The function it took from opengl’s wiki looks this, with my global includes and such:


#include <iostream>
#include <stdlib.h>
#include <gl/glut.h>
#include <png.h>
#include <string>

#define TEXTURE_LOAD_ERROR 0;

using namespace std;

GLuint loadTexture(const string filename, int &width, int &height) 
 {
   //header for testing if it is a png
   png_byte header[8];
 
   //open file as binary
   FILE *fp = fopen(filename.c_str(), "vtr.png");
   if (!fp) {
     return TEXTURE_LOAD_ERROR;
   }
 
   //read the header
   fread(header, 1, 8, fp);
 
   //test if png
   int is_png = !png_sig_cmp(header, 0, 8);
   if (!is_png) {
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //create png struct
   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
       NULL, NULL);
   if (!png_ptr) {
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //create png info struct
   png_infop info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) {
     png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //create png info struct
   png_infop end_info = png_create_info_struct(png_ptr);
   if (!end_info) {
     png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //png error stuff, not sure libpng man suggests this.
   if (setjmp(png_jmpbuf(png_ptr))) {
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //init png reading
   png_init_io(png_ptr, fp);
 
   //let libpng know you already read the first 8 bytes
   png_set_sig_bytes(png_ptr, 8);
 
   // read all the info up to the image data
   png_read_info(png_ptr, info_ptr);
 
   //variables to pass to get info
   int bit_depth, color_type;
   png_uint_32 twidth, theight;
 
   // get info about png
   png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
       NULL, NULL, NULL);
 
   //update width and height based on png info
   width = twidth;
   height = theight;
 
   // Update the png info struct.
   png_read_update_info(png_ptr, info_ptr);
 
   // Row size in bytes.
   int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
 
   // Allocate the image_data as a big block, to be given to opengl
   png_byte *image_data = new png_byte[rowbytes * height];
   if (!image_data) {
     //clean up memory and close stuff
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
 
   //row_pointers is for pointing to image_data for reading the png with libpng
   png_bytep *row_pointers = new png_bytep[height];
   if (!row_pointers) {
     //clean up memory and close stuff
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     delete[] image_data;
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
   // set the individual row_pointers to point at the correct offsets of image_data
   for (int i = 0; i < height; ++i)
     row_pointers[height - 1 - i] = image_data + i * rowbytes;
 
   //read the png into image_data through row_pointers
   png_read_image(png_ptr, row_pointers);
 
   //Now generate the OpenGL texture object
   GLuint texture;
   glGenTextures(1, &texture);
   glBindTexture(GL_TEXTURE_2D, texture);
   glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, width, height, 0,
       GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
   //clean up memory and close stuff
   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   delete[] image_data;
   delete[] row_pointers;
   fclose(fp);
 
   return texture;
 }

I don’t have any red lines, so i figure i have included all the files correctly, but i get errors immeadiatly after i try to compile my program with this function. And note i havent even tried to use the function elsewhere in my program yet, and i get 10 linking errors ->


1>------ Build started: Project: Light, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\shawn\documents
ew folder\first project - visual\light\light\main.cpp(25): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdio.h(234) : see declaration of 'fopen'
1>main.obj : error LNK2019: unresolved external symbol _png_read_image referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_get_rowbytes referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_read_update_info referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_get_IHDR referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_read_info referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_set_sig_bytes referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_init_io referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_set_longjmp_fn referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_destroy_read_struct referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_create_info_struct referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_create_read_struct referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>main.obj : error LNK2019: unresolved external symbol _png_sig_cmp referenced in function "unsigned int __cdecl loadTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int &,int &)" (?loadTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAH1@Z)
1>C:\Users\Shawn\Documents\New folder\First Project - visual\Light\Debug\Light.exe : fatal error LNK1120: 12 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

You don’t seem to link against the libpng. Look up how to add libpng to your linker settings in VS.

Ok, so i changed my linker from “opengl32.lib glu32.lib” to “opengl32.lib glu32.lib libpng.lib”. But what now? I mean i have my libpng package(1.5.9). And i have this gnuwin32 package that has libpng.lib in it, so i placed it in the directory with opengl32.lib and glu32.lib, but the errors didnt change.

bump

This is obviously a problem with your VisualStudio/Linker setup, no OpenGL problem, I can’t really help with that, sorry.

I started with png, but then switched to bmp files instead. They are easier to read. They are also bigger, but that usually doesn’t matter.

I went on a wild goose chase looking for a decent PNG loader. I settled with SOIL. It loads the whole texture in just one line of code so I would recommend that.

I have a different question because im attempting to use SOIL now instead of libPNG which seems to work for a lot more people.

SOIL’s website says how to get SOIL working:
[b]"Usage:

SOIL is meant to be used as a static library (as it’s tiny and in the public domain). You can use the static library file included in the zip (libSOIL.a works for MinGW and Microsoft compilers…feel free to rename it to SOIL.lib if that makes you happy), or compile the library yourself. The code is cross-platform and has been tested on Windows, Linux, and Mac. (The heaviest testing has been on the Windows platform, so feel free to email me if you find any issues with other platforms.)

Simply include SOIL.h in your C or C++ file, link in the static library, and then use any of SOIL’s functions. The file SOIL.h contains simple doxygen style documentation. (If you use the static library, no other header files are needed besides SOIL.h) Below are some simple usage examples: "
[/b]
Ok, so i added the #include “soil.h”, renamed libSOIL.a to SOIL.lib and placed in the directory with my other linked libraries(opengl32.lib etc…). I feel like i have done everything correct but i always get errors…


1>main.obj : error LNK2019: unresolved external symbol _SOIL_load_OGL_texture referenced in function "unsigned int __cdecl GetTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?GetTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>C:\Users\Shawn\Documents\New folder\First Project - visual\Light\Debug\Light.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

placed in the directory with my other linked libraries(opengl32.lib etc…).

Please stop putting libraries in Visual Studio’s directories. Those directories belong to VS, not to you.

If you want a centralized respository for libraries, then by all means, make one. But it needs to be in your directories, not VS’s.

Also, did you link to this library? Because just copying it into a directory isn’t going to help.

My links are “SOIL.lib glu32.lib opengl32.lib” and the each of these .lib files are located in “OS(C:) -> program files (x86) - > Microsoft SDKs -> Windows -> v7.0a -> Lib”. I dont think i’v ever been more desperate to get a problem solved.

Avoid BMP, it is a pretty messy format. I would suggest TGA instead. It has a much cleaner structure, no problems with pixel padding/byte alignment, supports the same formats and more (paletted 8-bit, 8-bit grayscale, 24-bit) and additionally supports alpha transparancy (32-bit, which you’ll like for texturing especially). Even MS’s own Paint hasn’t managed to output valid BMP files (IIRC, palette size is always zero) for the last few decades, go figure.

As Alfonse already said, don’t put stuff in the MSVC directories! This will unlikely work, and probably screw up if you ever decide to update MS VC++ Framework package.
You put your libraries somewhere else on your disk (e.g. C:\SDK\libpng), and add the directories to your IDE. In MSVC this is something like: Tools > Options > Projects and Solutions > VC++ Directories . Under “Include”, add the libpng /include/ directory. Under “Libraries”, add the libpng “/lib/” directory. E.g. "C:\SDK\libpng\lib" . Then add the .lib to your project settings, as you already did.

Well im starting to think my library files arnt the problem.

I loaded one of NeHe’s tutorials that uses SOIL, and it worked.

So why is it that i still get this one error,


1>main.obj : error LNK2019: unresolved external symbol _SOIL_load_OGL_texture referenced in function "unsigned int __cdecl GetTexture(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?GetTexture@@YAIV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

By looking at the error, i see there is a problem with the “SOIL_load_OGL_texture()” function. This function is in soil.h, and i’v already included this in my program(#include “soil.h”). I’v been trying to get this working to days. I just dont understand =S

I’m afraid that does look like a linker error to me. Have you tried re-downloading SOIL.lib from a reliable source (I got mine from here http://nehe.gamedev.net/tutorial/lesson_06_texturing_update/47002/), putting it in a sensible folder location and then linking it like remdul described?

I took it from the same website, and linked it correctly. I still dont know whats wrong and its driving me nuts

Solved!

Thanks for everyone who posted their advice i really appreciate it.

why dont you explain what you did then?

You’ve replied to a 7 year post. If you are having a similar issue, you should start a new topic and reference this topic.