use OpenGL;
#1 Image capture
This program shows how to get an image of an OpenGL window using ImageMagick.
The famous Utah teapot is used as an example.
For Windows users, the modules OpenGL
, OpenGL::Image
and Image::Magick
are available in my ppm repositories:
#!/usr/local/bin/perl
#
# teapotgif.pl : make an animated gif image of a rotating teapot
# (c) 2013 jl_morel@bribes.org - http://http://bribes.org/perl
use strict;
use warnings;
use OpenGL qw/ :all /;
use OpenGL::Image;
use Image::Magick;
my $animatedgifname = "teapot.gif";
my $animatedgif = Image::Magick->new();
my @light0_position = ( 2.0, 8.0, 2.0, 0.0 );
my @light_diffuse = ( 1.0, 1.0, 1.0, 1.0 );
my @light_ambient = ( 0.15, 0.15, 0.15, 0.15 );
my @mat_amb_diff_color = ( 0.4, 0.2, 0.8, 1.0 );
#------ Initialization routine
sub init {
glClearColor( 1, 1, 1, 1 ); # White background
glShadeModel(GL_SMOOTH); # Smooth shading
glEnable(GL_DEPTH_TEST); # Enable hidden surface removal
glEnable(GL_MULTISAMPLE); # Enable multisample antialiasing
glEnable(GL_LIGHTING); # Enable lighting
glEnable(GL_LIGHT0);
glLightfv_p( GL_LIGHT0, GL_POSITION, @light0_position );
glLightfv_p( GL_LIGHT0, GL_DIFFUSE, @light_diffuse );
glLightfv_p( GL_LIGHT0, GL_AMBIENT, @light_ambient );
glMaterialfv_p( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @mat_amb_diff_color );
glEnable(GL_CLIP_PLANE0); # One clip plane needed
}
#------ Draw the teapot
my $size = 3.5; # teapot size
my $spin = 0; # rotation angle
sub display {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
gluLookAt( 2.0, 4.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
glPushMatrix();
glRotatef( $spin, 0.0, 1.0, 0.0 );
# The plane equation is 0x+0y+1z=0 with normal vector (0,0,1)
glClipPlane_p( GL_CLIP_PLANE0, 0, 0, 1, 0 );
glutSolidTeapot($size);
# Same plane but with normal vector (0,0,-1)
glClipPlane_p( GL_CLIP_PLANE0, 0, 0, -1, 0 );
glutWireTeapot($size);
glPopMatrix();
glutSwapBuffers();
}
#------ GLUT Callback called when the window is resized
sub reshape {
my ( $w, $h ) = @_;
glViewport( 0, 0, $w, $h );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 45.0, $h ? $w / $h : 0, 1.0, 20.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
#------ Routine for rotating the teapot
my $WaitUntil = 0;
sub spinDisplay {
my $TimeNow = glutGet(GLUT_ELAPSED_TIME);
if ( $TimeNow >= $WaitUntil ) {
$spin += 1.0;
if ( $spin > 360 ) {
# 10/100ths of a second between images, loop indefinitely
$animatedgif->Set( delay => 10, loop => 0 );
$animatedgif->Write($animatedgifname);
unlink "tmp.gif";
exit;
}
if ( $spin % 5 == 0 ) { # One capture every 5 degree
IMCapture("tmp.gif"); # Save as gif image
$animatedgif->Read("tmp.gif");
}
glutPostRedisplay();
$WaitUntil = $TimeNow + 1000 / 25; # 25 frames/s
}
}
#------ Main
glutInit();
glutInitDisplayMode(
GLUT_DOUBLE # Double buffering
| GLUT_RGB # RGB color mode
| GLUT_DEPTH # Hidden surface removal
| GLUT_MULTISAMPLE # Multisample antialiasing
);
glutInitWindowSize( 420, 240 );
glutCreateWindow("Teapot");
init();
glutDisplayFunc( \&display );
glutReshapeFunc( \&reshape );
glutIdleFunc( \&spinDisplay );
glutMainLoop();
#------ Image capture function with ImageMagick
# Usage: IMCapture( $imgname [, $x, $y, $width, $height ] );
# $imgname is the image name with extension (.gif, .jpeg, .png ...)
# The optional part [ $x, $y, $width, $height ] defines the dimensions
# of the rectangle to capture.
# If not supplied, the dimensions of the current window are used.
sub IMCapture {
my $file = shift;
my ( $x, $y, $width, $height ) = @_ == 4 ? @_ : glGetIntegerv_p(GL_VIEWPORT);
my $img = new OpenGL::Image(
engine => 'Magick',
width => $width,
height => $height
);
my ( $def_fmt, $def_type ) = $img->Get( 'gl_format', 'gl_type' );
glFinish();
glReadPixels_c( $x, $y, $width, $height, $def_fmt, $def_type, $img->Ptr() );
$img->Save($file);
}
The script as .txt for download:
teapotgif.pl.txt
Back to Top
BðP © 2013 J-L Morel - Contact : jl_morel@bribes.org