pixel.cpp #11

  • //
  • guest/
  • sam_stafford/
  • scenesaver/
  • pixel.cpp
  • View
  • Commits
  • Open Download .zip Download (5 KB)
#include <math.h>
#include <qimage.h> 

#include "pixel.h"
#include "globals.h"

void compute_diff( Pixel* p )
{
	p->d_r = float( fabs( p->f_r - p->b_r ) );
	p->d_g = float( fabs( p->f_g - p->b_g ) );
	p->d_b = float( fabs( p->f_b - p->b_b ) );
}

void consume_diff( Pixel* p, float d, char color )
{
	float *f_p, *b_p, *d_p;
	switch( color )
	{
	case 'r':
		f_p = &p->f_r;
		d_p = &p->d_r;
		b_p = &p->b_r;
		break;
	case 'g':
		f_p = &p->f_g;
		d_p = &p->d_g;
		b_p = &p->b_g;
		break;
	default:
	case 'b':
		f_p = &p->f_b;
		d_p = &p->d_b;
		b_p = &p->b_b;
		break;
	}
	if ( d >= *d_p )
	{
		*f_p = *b_p;
		*d_p = 0.0;
	}
	else if ( *f_p < *b_p )
	{
		*f_p += d;
		compute_diff( p );
	}
	else if ( *f_p > *b_p )
	{
		*f_p -= d;
		compute_diff( p );
	}	
}

int image_width( char* file )
{
	QImage image( file );
	if ( image.isNull() ) return 0;
	return image.width();
}

int image_height( char* file )
{
	QImage image( file );
	if ( image.isNull() ) return 0;
	return image.height();	
}

//returns "diff amount" as a sum of diffs over entire image
float load_pixels( Pixel** p, char* file, int width, int height )
{
	if ( !file ) return load_random( p, width, height );

	QImage image( file );
	if ( image.isNull() ) return load_random( p, width, height );

	image = image.mirror(); 

	if  ( 
			settings.autoscale &&
 			( image.width() != width || image.height() != height )
		)
	{
		QImage::ScaleMode sm;
		switch( settings.autoscale )
		{
		case 'L':
			sm = QImage::ScaleMin;
			break;
		case 'M':
			sm = QImage::ScaleMax;
		default:
		case 'S':
			sm = QImage::ScaleFree;
		}
		image = image.smoothScale( width, height, sm );
	}

	float d_t = 0.0;

	int sx = ( width - image.width() ) / 2;
	int sy = ( height - image.height() ) / 2;

	int ix, iy;

	for ( int x = 0 ; x < width ; x++ )
	{
		ix = x - sx;
		if ( ix < 0 ) ix = 0;
		else if ( ix >= image.width() )  ix = image.width() - 1;

		for ( int y = 0 ; y < height ; y++ )
		{
			iy = y - sy;
			if ( iy < 0 ) iy = 0;
			else if ( iy >= image.height() ) iy = image.height() - 1;

			p[x][y].b_r = qRed  ( image.pixel( ix, iy ) ) / 255.0 ;
			p[x][y].b_g = qGreen( image.pixel( ix, iy ) ) / 255.0 ;
			p[x][y].b_b = qBlue ( image.pixel( ix, iy ) ) / 255.0 ;

			compute_diff( & p[x][y] );
			d_t += p[x][y].d_r + p[x][y].d_g + p[x][y].d_b;
		}
	}

	if ( sx > 0 )
	{
		//Average color along left edge.
		double l_r = 0;
		double l_g = 0;
		double l_b = 0;
		for ( int y = 0 ; y < image.height() ; y++ )
		{
			l_r += p[0][y].b_r;
			l_g += p[0][y].b_g;
			l_b += p[0][y].b_b;
		}
		l_r /= image.height();
		l_g /= image.height();
		l_b /= image.height();
		for ( int x = 0 ; x < sx ; x++ )
		{
			for ( int y = 0 ; y < height ; y++ )
			{
				p[x][y].b_r = l_r;
				p[x][y].b_g = l_g;
				p[x][y].b_b = l_b;
			}
		}
		//Average color along right edge.
		double r_r = 0;
		double r_g = 0;
		double r_b = 0;
		for ( int y = 0 ; y < image.height() ; y++ )
		{
			r_r += p[width-1][y].b_r;
			r_g += p[width-1][y].b_g;
			r_b += p[width-1][y].b_b;
		}
		r_r /= image.height();
		r_g /= image.height();
		r_b /= image.height();
		for ( int x = sx + image.width() ; x < width ; x++ )
		{
			for ( int y = 0 ; y < height ; y++ )
			{
				p[x][y].b_r = r_r;
				p[x][y].b_g = r_g;
				p[x][y].b_b = r_b;
			}
		}
	}
	if ( sy > 0 )
	{
		//Average color along upper edge.
		double u_r = 0;
		double u_g = 0;
		double u_b = 0;
		for ( int x = 0 ; x < image.width() ; x++ )
		{
			u_r += p[x][0].b_r;
			u_g += p[x][0].b_g;
			u_b += p[x][0].b_b;
		}
		u_r /= image.width();
		u_g /= image.width();
		u_b /= image.width();
		for ( int y = 0 ; y < sy ; y++ )
		{
			for ( int x = 0 ; x < width ; x++ )
			{
				p[x][y].b_r = u_r;
				p[x][y].b_g = u_g;
				p[x][y].b_b = u_b;
			}
		}
		//Average color along bottom edge.
		double b_r = 0;
		double b_g = 0;
		double b_b = 0;
		for ( int x = 0 ; x < image.width() ; x++ )
		{
			b_r += p[x][height-1].b_r;
			b_g += p[x][height-1].b_g;
			b_b += p[x][height-1].b_b;
		}
		b_r /= image.width();
		b_g /= image.width();
		b_b /= image.width();
		for ( int y = sy + image.height() ; y < height ; y++ )
		{
			for ( int x = 0 ; x < width ; x++ )
			{
				p[x][y].b_r = b_r;
				p[x][y].b_g = b_g;
				p[x][y].b_b = b_b;
			}
		}
	}

	return d_t;
}

//returns "diff amount" as a sum of diffs over entire image
float load_random( Pixel** p, int width, int height )
{
	float d_t = 0.0;

	float r = RandFloat();
	float g = RandFloat();
	float b = RandFloat();

	for ( int x = 0 ; x < width ; x++ )
	{
		for ( int y = 0 ; y < height ; y++ )
		{
			p[x][y].b_r = r;
			p[x][y].b_g = g;
			p[x][y].b_b = b;
			compute_diff( & p[x][y] );
			d_t += p[x][y].d_r + p[x][y].d_g + p[x][y].d_b;
		}
	}
	return d_t;
}

void save_pixels( Pixel** p, char* file, int width, int height )
{
	float r, g, b;
	QImage image( width, height, 32 );
	for ( int x = 0 ; x < width ; x++ )
	{
		for ( int y = 0 ; y < height ; y++ )
		{
			switch( settings.display_buffer )
			{
			case 'b':
				r = p[x][y].b_r;
				g = p[x][y].b_g;
				b = p[x][y].b_b;
				break;
			case 'd':
				r = p[x][y].d_r;
				g = p[x][y].d_g;
				b = p[x][y].d_b;
				break;
			case 'f':
			default:
				r = p[x][y].f_r;
				g = p[x][y].f_g;
				b = p[x][y].f_b;
				break;
			}
			image.setPixel( x, y, qRgb ( r * 255, g * 255, b * 255 ) );
		}
	}
	image.mirror().save( file, "PNG" );
}
# Change User Description Committed
#11 5455 Sam Stafford Average edge colors to determine background color.
#10 4706 Sam Stafford When padding an image that doesn't match the world dimensions, use the
edges of the image instead of black.
#9 4566 Sam Stafford Fix small arithmetic bug (resulting in clipping the image prematurely)
that was introduced in the last change
#8 4563 Sam Stafford Attempt to center the image when scaling it with aspect ratio preserved.
#7 4561 Sam Stafford New smooth autoscaling, with configurable fit-to-screen behavior.
#6 4458 Sam Stafford Allow screenshot to capture the current buffer rather than always
defaulting to the front one.  (This lets people take cool "diff"
screenshots.)
#5 4457 Sam Stafford After the first round of user feedback:

1) Added option to autoscale images if they don't match in size (on by
default)
2) Fixed crash bug if you tried to cycle the chasecam when it had
never been initialized.
#4 4453 Sam Stafford Added screenshot feature, moved SceneSaver files to home directory
rather than system directory, added code to handle invalid or missing
images (loading a random color instead of crashing).

I think this thing's good to go.
#3 4446 Sam Stafford Finished neural inputs, made size hereditary, auto-rotation of images
once a certain amount of diffs have been consumed, saving genomes at
finish.
#2 4433 Sam Stafford More work on this little project.
 The AI is still nonexistent.
#1 4429 Sam Stafford A bit of work in progress that currently works as a crude image diff
tool.