move through an image

Started by
7 comments, last by beloni 16 years, 11 months ago
Hello, I need move the screen window through an large image.bmp:

//pixmap.h
typedef char byte;
typedef unsigned char ubyte;

struct pixmap
{
	unsigned width, 
					 height;
	ubyte *data;

	enum {RED = 0, GREEN, BLUE};

	pixmap(const char *fname);
	pixmap();
	~pixmap();

	void read(const char *fname);
	ubyte pixel_elem(int x, int y, int elem);
	ubyte *pixel_pos(int x, int y);
};


//pixmap.cpp

#include "pixmap.h"

#include <fstream>
#include <iostream>
#include <cstdlib>


pixmap::pixmap(const char *fname)
	: width(0), height(0), data(0)
{
	this->read(fname);
}

pixmap::pixmap()
	: width(0), height(0), data(0) {}

pixmap::~pixmap()
{
	if( data )
		delete[] data;
}

void pixmap::read(const char *fname)
{
	using namespace std;

	unsigned short planes;	// number of planes in image (must be 1) 
	unsigned short bpp;			// number of bits per pixel (must be 24)

	ifstream fin(fname, ios::in | ios::binary);
	if( !fin )
	{
		cerr << "File not found " << fname << '\n';
		exit(1);
	}
  
	fin.seekg(18, ios::cur);

	fin.read((byte *)&width, sizeof(unsigned));
	fin.read((byte *)&height, sizeof(unsigned));
	cout << "width: " << width << " height: " << height << '\n';

	fin.read((byte *)&planes, sizeof(unsigned short));
	if( planes != 1 )
	{
		cout << "Planes from " << fname << " is not 1: " << planes << "\n";
		exit(1);
	}

	fin.read((byte *)&bpp, sizeof(unsigned short));
	if( bpp != 24 )
	{
		cout << "Bpp from " << fname << " is not 24: " << bpp << "\n";
		exit(1);
	}
	
	fin.seekg(24, ios::cur);

	unsigned size(width * height * 3);				// size of the image in bytes (3 is to RGB component).
	data = new ubyte[size];
	fin.read((byte *)data, size);

	ubyte tmp;					// temporary color storage for bgr-rgb conversion.
	for( int i(0); i < size; i += 3 )
	{
		tmp = data;
		data = data[i+2];
		data[i+2] = tmp;
	}
}

ubyte pixmap::pixel_elem(int x, int y, int elem)
{
	int pos = (y*width+x) * 3 + elem;
	return data[pos];
}

ubyte *pixmap::pixel_pos(int x, int y)
{
	int pos = (y * width + x) * 3;
	return &data[pos];
}

//test program

#include <GL/glut.h>
#include <iostream>
#include <cstdlib>

#include "pixmap.h"

#define MAX_WIDTH 300
#define MAX_HEIGHT 200


pixmap *img(0);
GLfloat transx(0.0), transy(0.0);

void init_gl()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLfloat)MAX_WIDTH, 0.0, (GLfloat)MAX_HEIGHT);
}

void reshape(int w, int h)
{
	glViewport (0, 0, (GLint)w, (GLint)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLfloat)w, 0.0, (GLfloat)h);
//	gluOrtho2D(-(GLfloat)MAX_WIDTH, (GLfloat)MAX_WIDTH, -(GLfloat)MAX_HEIGHT, (GLfloat)MAX_HEIGHT);
}

void render_scene()
{
	glClear(GL_COLOR_BUFFER_BIT);

// drawing it manually
/*	glBegin(GL_POINTS);
	for( int i(0); i < img->width; i++ )
		for( int j(0); j < img->height; j++ )
		{
//			glColor3ub(img->pixel_elem(i, j, pixmap::RED),
//								 img->pixel_elem(i, j, pixmap::GREEN),
//								 img->pixel_elem(i, j, pixmap::BLUE));
			glColor3ubv(img->pixel_pos(i, j));
			glVertex2i(i+(int)transx, j+(int)transy); 
		}
	glEnd();*/

// draw using OpenGL functions
	glTranslatef(transx, transy, 0.0);
	glRasterPos2i(0, 0);
	glDrawPixels(img->width, img->height, GL_RGB, GL_UNSIGNED_BYTE, img->data);

	glutSwapBuffers();
	glFlush();
}

void keyb_handler(unsigned char key, int x, int y)
{
	if( key == 27 )
		std::exit(0);
}

void special_key(int key, int x, int y)
{
	switch( key )
	{
		case GLUT_KEY_UP:
		{
			transy = -5.0;
			transx = 0.0;
			break;
		}

		case GLUT_KEY_DOWN:
		{
			transy = +5.0;
			transx = 0.0;
			break;
		}

		case GLUT_KEY_LEFT:
		{
			transx = +5.0;
			transy = 0.0;
			break;
		}

		case GLUT_KEY_RIGHT:
		{
			transx = -5.0;
			transy = 0.0;
			break;
		}
	}
	glutPostRedisplay();
}

void special_key2(int key, int x, int y)
{
	switch( key )
	{
		case GLUT_KEY_UP:
		{
			if( transy < MAX_HEIGHT ) transy += 5.0;
			break;
		}

		case GLUT_KEY_DOWN:
		{
			if( transy > 0 ) transy -= 5.0;
			break;
		}

		case GLUT_KEY_LEFT:
		{
			if( transx > 0 ) transx -= 5.0;
			break;
		}

		case GLUT_KEY_RIGHT:
		{
			if( transx < MAX_WIDTH ) transx += 5.0;
			break;
		}
	}
	glutPostRedisplay();
}

int main(int argc, char **argv)
{
	if( argc != 2 )
	{
		std::cerr << "INVALID ARGUMENTS\n";
		std::cerr << "You should specify the pixmap to load!\n";
		return 1;
	}

	img = new pixmap(argv[1]);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("A pixmap loader - by Beloni");

	init_gl();

	glutDisplayFunc(&render_scene);
	glutReshapeFunc(&reshape);
	glutKeyboardFunc(&keyb_handler);
	glutSpecialFunc(&special_key);
//	glutFullScreen();

	glutMainLoop();
	delete img;
	return 0;
}


Can you help me to do that? [Edited by - beloni on May 17, 2007 12:48:21 PM]
Advertisement
You seem to have the right approach, but it's hard to see what's going wrong. Could you describe which part exactly is giving you troubles?

Also, when posting large segments of code, try to encase your code within source tags, like so (without spaces in the tags):

[ source ] _code_here_ [ /source ]

That will format your code nicely, making it easier for others to read.
Thanks for posting source tips.
The right and up translations are done nicely, so the window actually seems to move through the image.
The problem occurs when the translation must affect the image down and left, in which image coordinates tends to zero: the image simply disappear (reasonably).
so the question is:
Quote:
How to move through an image? This like in RPG game (but this is not a game), where whatever the avatar moves, the background image (scenario) moves.


In my program, to move the image you should use the cursor keys...
I'm not positive about this, but I'm pretty sure that using glTranslate will have no effect on glRasterPos or glDrawPixels, as those deal in window coordinates rather than 3d coordinates. One possibility would be to get rid of the glTranslate call and call glRasterPos with transx and transy instead, but I think that a better alternative would be to create a texture out of your image and then render it on a quad.
Ok, thanks.
But how do can I create a texture of the image and render it on a quad?
Quote:Original post by beloni
Ok, thanks.
But how do can I create a texture of the image and render it on a quad?

NeHe has a great tutorial with sample code that shows you exactly how to do this. See the tutorial located here.
Thanks a lot, I got it!
But it has some problems when the window is resized. Can I not allow the user resize the window in GLUT library?

That is my new source. The pixmap.h is the same as above
#include <GL/glut.h>#include <iostream>#include <exception>#include <cstdlib>#include "pixmap.h"#define MAX_WIDTH 600#define MAX_HEIGHT 400pixmap *img(0);GLfloat trans[] = {0.0, 0.0};unsigned pos[] = {0ul, MAX_WIDTH, MAX_HEIGHT, 0ul};GLuint texid(0);void init_gl(){	glClearColor(0.0, 0.0, 0.0, 0.0);// loading texture	glGenTextures(1, &texid);	glBindTexture(GL_TEXTURE_2D, texid);	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, img->data);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	gluOrtho2D(0.0, (GLfloat)MAX_WIDTH, 0.0, (GLfloat)MAX_HEIGHT);}void reshape(int w, int h){	glViewport (0, 0, (GLint)w, (GLint)h);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	gluOrtho2D(0.0, (GLfloat)w, 0.0, (GLfloat)h);}void render_scene(){	glClear(GL_COLOR_BUFFER_BIT);	glEnable (GL_TEXTURE_2D); /* enable texture mapping */	glBindTexture (GL_TEXTURE_2D, texid); /* bind to our texture, has id of 13 */	glBegin(GL_QUADS);		glTexCoord2f(0.0f, 0.0f); /* lower left corner of image */		glVertex2i(0, 0);		glTexCoord2f(1.0f, 0.0f); /* lower right corner of image */		glVertex2i(img->width, 0);		glTexCoord2f(1.0f, 1.0f); /* upper right corner of image */		glVertex2i(img->width, img->height);		glTexCoord2f(0.0f, 1.0f); /* upper left corner of image */		glVertex2i(0, img->height);	glEnd ();	glDisable(GL_TEXTURE_2D); /* disable texture mapping */	glutSwapBuffers();}void keyb_handler(unsigned char key, int x, int y){	if( key == 27 )		std::exit(0);}void special_key(int key, int x, int y){	bool flag(false);	switch( key )	{		case GLUT_KEY_UP:			if( pos[2] < (img->height-1) )			{				trans[1] = -5.0;				trans[0] = 0.0;				flag = true;				pos[2] += 5;				pos[0] += 5;			}			break;		case GLUT_KEY_DOWN:			if( pos[0] > 0 )			{				trans[1] = +5.0;				trans[0] = 0.0;				flag = true;				pos[0] -= 5;				pos[2] -= 5;			}			break;		case GLUT_KEY_LEFT:			if( pos[3] > 0 )			{				trans[0] = +5.0;				trans[1] = 0.0;				flag = true;				pos[3] -= 5;				pos[1] -= 5;			}			break;		case GLUT_KEY_RIGHT:			if( pos[1] < (img->width-1) )			{				trans[0] = -5.0;				trans[1] = 0.0;				flag = true;				pos[1] += 5;				pos[3] += 5;			}			break;	}	if( flag )	{		glTranslatef(trans[0], trans[1], 0.0);				glutPostRedisplay();	}}int main(int argc, char **argv){	if( argc != 2 )	{		std::cerr << "INVALID ARGUMENTS\n";		std::cerr << "You should specify the pixmap to load!\n";		return 1;	}	try	{		img = new pixmap(argv[1]);	}	catch( std::bad_alloc &ex )	{		std::cerr << ex.what() << '\n';		return 2;	}	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);	glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);	glutInitWindowPosition(0, 0);	glutCreateWindow("A pixmap loader - by Beloni");	init_gl();	glutDisplayFunc(&render_scene);	glutReshapeFunc(&reshape);	glutKeyboardFunc(&keyb_handler);	glutSpecialFunc(&special_key);//	glutFullScreen();	glutMainLoop();	delete img;	return 0;}


thanks
Quote:Original post by beloni
Thanks a lot, I got it!
But it has some problems when the window is resized. Can I not allow the user resize the window in GLUT library?

You should be able to. What's the problem you're noticing? I haven't worked much with the GLUT library, so I'm probably not the best to answer, but if you can describe what's going on, I'm sure someone else could give some insight.
I am so sorry...
Just not allowing the user to resize the window will solve my problem.
That is the problem: not allow the user to resize the window.

This topic is closed to new replies.

Advertisement