void texture::submit( int format, bool build_mip_maps ) { std::vector<unsigned char> pixels = ( format == GL_RGBA ? rgba_data() : rgb_data() ); // Set unpack alignment to one byte GLint UnpackAlignment; glGetIntegerv( GL_UNPACK_ALIGNMENT, &UnpackAlignment ); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // Submit decoded data to texture GLint ret; if( build_mip_maps ) ret = gluBuild2DMipmaps(GL_TEXTURE_2D, format, w, h, format, GL_UNSIGNED_BYTE, pixels.data() ); else glTexImage2D(GL_TEXTURE_2D, 0 /*LOD*/, format, w, h, 0 /*border*/, format, GL_UNSIGNED_BYTE, pixels.data() ); // Restore old unpack alignment glPixelStorei( GL_UNPACK_ALIGNMENT, UnpackAlignment ); }
//saves the given SDL structure into a given filename. void save_image(surface surf, const std::string &filename) { //opens the actual file const util::scoped_FILE file(fopen(filename.c_str(),"wb")); //initializes PNG write structures //TODO: review whether providing NULL error handlers is something //sensible png_struct* png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, reinterpret_cast<png_voidp>(png_voidp_NULL), png_error_ptr_NULL, png_error_ptr_NULL); if(!png_ptr) throw exploder_failure("Unable to initialize the png write structure"); png_info* info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, static_cast<png_infopp>(NULL)); throw exploder_failure("Unable to initialize the png info structure"); } //instructs the PNG library to use the open file png_init_io(png_ptr, file); //sets compression level to the maximum png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); //configures the header png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //puts the actual image data in the row_pointers array png_byte **row_pointers = new png_byte *[surf->h]; surface_lock lock(surf); //converts the data to the RGBA format. We cannot pass SDL data //directly to the png lib, even if we know its pixel format, because of //endianness problems. util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]); Uint32 *surf_data = lock.pixels(); int pos = 0; for(int y = 0; y < surf->h; ++y) { row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos); for(int x = 0; x < surf->w; ++x) { Uint8 red, green, blue, alpha; SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha); rgba_data[pos].r = red; rgba_data[pos].g = green; rgba_data[pos].b = blue; rgba_data[pos].a = alpha; pos++; surf_data++; } } png_set_rows(png_ptr, info_ptr, row_pointers); //writes the actual image data png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); //cleans everything png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; }