Compile and Run - Programmer Tutorials and Tips and General Thoughts

Python Decorators are Functions that Return Functions

December 15th, 2011

If you’ve ever seen this kind of syntax and been bewildered:

@decorator
def function( x ):
    return x

Then you are not alone. This is an example of using decorators in python. The @ indicates that the function will be “decorated” with “decorator.” What is decorator exactly?

It’s a function that takes a function as an argument and returns a function.

def decorator( your_function ):
    return math.sin

@decorator
def function( x ):
    return x

You have just made a decorator. The function “function” is now whatever “decorator” returns, which is in this case math.sin. Now when you run:

print function( 5 )

You will really be calling math.sin( 5 ), because that’s what your decorator returned. Of course, this is a silly example because it does not make use of your function. Let’s make one that does.

def decorator( your_function ):
    def new_function( x ):
        return 5 + your_function( x )
    return new_function

@decorator
def function( x ):
    return x

Don’t be thrown off by the fact that I defined a function within a function. This is just fine by the Python compiler.
What’s happening here is that I defined a function called new_function that takes a single argument. It calls your function, giving it the value x, and then adds 5 to it and returns it. At the end of the decorator function, new_function is returned. Now when you call

print function( 10 )

You will see 15. What you really called was the function new_function, with an argument 10. That’s because the function decorator returned new_function, which runs your old function and adds 5 to it. So the entire code would be this:

def decorator( your_function ):
	def new_function( x ):
		return 5 + your_function( x )
	return new_function

@decorator
def function( x ):
	return x

print function(5)

I hope that was a good explanation for some tricky Python stuff.

Basic LibPNG usage with C++ and Opengl

December 15th, 2011

I am using LibPNG and Zlib in my game engine. After much frustration, I was finally able to get it to work. The following is my LoadImage function:

void Image::LoadImage( const char *filename ) {
	// Open up the file as a binary
	FILE *file_pointer = fopen( filename, "rb");

	if( file_pointer == 0 ) {
		Engine::console << "LoadImage failed: file '" << filename << "'does not exist." << std::endl;
		// The file does not exist. Create a false image that is just red.
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		return;
	}

	// First we check the header, stored in the first 8 bytes of the file
	char header[8];
	fread(header, 1, 8, file_pointer );
	// png_sig_cmp will return 0 if the file read is not a PNG
	if (png_sig_cmp( (png_const_bytep) header, 0, 8) != 0 ) {
		Engine::console << "LoadImage failed: file '" << filename << "' is not a PNG." << std::endl;
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		fclose( file_pointer );
		return;
	}

	// Initialize the two structures that will represent the PNG file.
	png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
	png_infop info_ptr  = png_create_info_struct( png_ptr );

	// This is an old C way to handle errors, and franky is not very good because it
	// can jump over class destructors if you're not careful.
	if ( setjmp( png_jmpbuf(png_ptr) ) ) {
		Engine::console << "LoadImage failed: file '" << filename << "' caused LibPNG to trigger an error response." << std::endl;
		GenerateImage( 64, 64, 255, 128, 128, 255 );
		// This block is called if there was an error reading the file
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		if ( file_pointer ) { fclose( file_pointer); }
		return;
	}

	// Initialize the reading of the file, skip the 8 signature bytes, and then read the file information
	png_init_io( png_ptr, file_pointer );
	png_set_sig_bytes( png_ptr, 8 );
	png_read_info( png_ptr, info_ptr );

	// Get the information, including image width, height, bit depth and color type.
	// Bit depth is the number of bits per channel, a channel being red, green, blue, or alpha.
	// Typically bit depth will be 8, meaning each channel gets 1 byte.
	image_width    = png_get_image_width ( png_ptr, info_ptr );
	image_height   = png_get_image_height( png_ptr, info_ptr );
	int bit_depth  = png_get_bit_depth( png_ptr, info_ptr );
	int color_type = png_get_color_type( png_ptr, info_ptr );
	int channels   = png_get_channels(png_ptr, info_ptr);

	// Allocate the data for the texture using its width and height. Reserve 4 bytes for RGBA pixels.
	image_data = new unsigned char[ image_width * image_height * 4 ];

	// Read the pixel data from the PNG into an array of rows.
	// First allocate memory for row structure.
	png_bytepp  row_pointers = new png_bytep[image_height];

	// Then go through each row, and allocate space for that row.
	for ( int i = 0; i < image_height; i++) {
		row_pointers[i] = new png_byte[ image_width * channels ];
	}
	// Finally, read the image into the row structure we just made.
	png_read_image(png_ptr, row_pointers);

	// Copy the image data into the image class's image_data, which
	// must be an array of RGBA pixels.
	for( int y = 0; y < image_height; y++ ) {
		// Get one row of pixels for the row structure
		png_bytep row = row_pointers[y];
		for( int x = 0; x < image_width; x++ ) {
			// Our data is stored in image_data, and the PNG pixels are stored in row
			image_data[ y * image_width * 4 + x*4 + 0 ] = row[ x * channels + 0 ];
			image_data[ y * image_width * 4 + x*4 + 1 ] = row[ x * channels + 1 ];
			image_data[ y * image_width * 4 + x*4 + 2 ] = row[ x * channels + 2 ];

			// If there is an alpha channel, be sure to copy it
			if( channels == 4 ) {
				image_data[ y * image_width + x*4 + 3 ] = row[ x * channels + 3 ];
			} else {
				image_data[ y * image_width + x*4 + 3 ] = 255;
			}
		}
	}

	// Free all memory that we used to avoid leaks, starting with each individual row
	for ( int i = 0; i < image_height; i++) {
		delete [] row_pointers[i];
	}
	// And finally, delete the row structure
	delete [] row_pointers;

	// Final PNG closing things
	png_destroy_read_struct( &png_ptr, &info_ptr, NULL );

	// Close our file pointer
	fclose( file_pointer );
}

There are some premade things in this snippet. For one, the GenerateImage function just creates a blank, solid color image instead of a loaded PNG, in the case of an error. Engine::console is just a singleton that outputs to some error stream, usually a file. Finally, image_data is an unsigned char array. I allocated 4 bytes per pixel so that the buffer is always RGB.

If you’re getting crashes with LibPNG, make sure you are linking the right library: compile LibPNG with the same compiler options as your project. This is due to the fact that LibPNG uses some internal functions to read from a file pointer.

Next time I might just use stb_image.