Logo Search packages:      
Sourcecode: gaia version File versions  Download package

void Texture::LoadPNG ( int  source,
  ... 
)

Loads texture from PNG file

See LoadJPEG

Definition at line 247 of file Texture.cc.

References m_glFormat, m_glInternalFormat, m_Height, m_ID, m_Pixels, and m_Width.

Referenced by PreloadedTextureManager::LoadPNG().

                                     {
      if (m_Pixels || m_ID)
            throw Exception("texture already loaded");

      va_list va;
      png_structp png_ptr = 0;
      png_infop   info_ptr = 0;
      png_bytep   *row_pointers = 0;

      FILE        *infile = 0;

      /* variable arguments stuff */
      va_start(va, source);

      my_png_error_ptr  perr;

      try {
            if (setjmp(perr.jmpbuf)) {
                  throw perr.err;
            }

            if (source == TEXTURE_SOURCE_FILE) {
                  if ((infile = fopen(va_arg(va, char*), "rb")) == 0)
                        throw ErrnoException("fopen() failed", errno);
            } else {
                  throw Exception("bad source in png loaging");
            }
      
            /* read signature */
            png_byte sig[8] = {0};

            fread(sig, 8, 1, infile);

            if (!png_check_sig(sig, 8))
                  throw Exception("bad PNG signature");

            /* create structures */
            if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)&perr, my_png_error_fn, 0)) == 0)
                  throw Exception("cannot create PNG read struct");

            if ((info_ptr = png_create_info_struct(png_ptr)) == 0)
                  throw Exception("cannot create PNG info struct");

            /* init read function */
            png_set_read_fn(png_ptr, (void*)infile, my_png_read_fn);

            /* read header */
            png_set_sig_bytes(png_ptr, 8);

            png_read_info(png_ptr, info_ptr);

            png_uint_32 width = 0, height = 0;
            int bit_depth = 0;
            int color_type = 0;

            png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);

            /* adjust some color transformations */
            if (bit_depth == 16)
                  png_set_strip_16(png_ptr);

            switch (color_type) {
            case PNG_COLOR_TYPE_GRAY:
                  if (bit_depth < 8)
                        png_set_gray_1_2_4_to_8(png_ptr);
                  m_glInternalFormat = GL_LUMINANCE8;
                  m_glFormat = GL_LUMINANCE;
                  break;
            case PNG_COLOR_TYPE_PALETTE:
                  png_set_palette_to_rgb(png_ptr);
                  m_glInternalFormat = GL_RGB8;
                  m_glFormat = GL_RGB;
                  break;
            case PNG_COLOR_TYPE_RGB:
                  m_glInternalFormat = GL_RGB8;
                  m_glFormat = GL_RGB;
                  break;
            case PNG_COLOR_TYPE_RGB_ALPHA:
                  m_glInternalFormat = GL_RGBA8;
                  m_glFormat = GL_RGBA;
                  break;
            case PNG_COLOR_TYPE_GRAY_ALPHA:
                  m_glInternalFormat = GL_LUMINANCE8_ALPHA8;
                  m_glFormat = GL_LUMINANCE_ALPHA;
                  break;
            default:
                  throw Exception("PNG color_type confusion");
            }

            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
                  png_set_tRNS_to_alpha(png_ptr);

            /* setup gamma */
            double gamma = 0.0f;
            if (png_get_gAMA(png_ptr, info_ptr, &gamma))
                  png_set_gamma(png_ptr, 2.2, gamma);
            else
                  png_set_gamma(png_ptr, 2.2, 0.45455);

            /* update info */
            png_read_update_info(png_ptr, info_ptr);
            png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);

            m_Width = width;
            m_Height = height;

            /* initialize buffers */
            png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr);

            if ((m_Pixels = (unsigned char *)malloc(row_bytes*height)) == 0)
                  throw std::bad_alloc();

            if ((row_pointers = (png_bytep*)malloc(sizeof(png_bytep)*height)) == 0)
                  throw std::bad_alloc();

            for (unsigned int i = 0; i < height; i++)
                  row_pointers[i] = m_Pixels + i*row_bytes;

            /* read image */
            png_read_image(png_ptr, row_pointers);
      } catch (...) {
            /* error encountered - cleanup and rethrow */
            if (png_ptr && info_ptr)
                  png_destroy_read_struct(&png_ptr, &info_ptr, 0);
            else if (png_ptr)
                  png_destroy_read_struct(&png_ptr, 0, 0);

            if (row_pointers)
                  free(row_pointers);

            if (infile)
                  fclose(infile);

            if (m_Pixels)
                  free(m_Pixels);

            m_Pixels = 0;

            va_end(va);

            throw;
      }

      /* successfully loaded - cleanup */
      png_destroy_read_struct(&png_ptr, &info_ptr, 0);

      free(row_pointers);

      if (infile)
            fclose(infile);

      va_end(va);
}


Generated by  Doxygen 1.6.0   Back to index