Merge branch '7.8'
[mesa.git] / progs / redbook / convolution.c
1 /*
2 * Copyright (c) 1993-2003, Silicon Graphics, Inc.
3 * All Rights Reserved
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose and without fee is hereby granted, provided that the above
7 * copyright notice appear in all copies and that both the copyright
8 * notice and this permission notice appear in supporting documentation,
9 * and that the name of Silicon Graphics, Inc. not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission.
12 *
13 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" AND
14 * WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
16 * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
17 * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
18 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, LOSS OF
20 * PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD
21 * PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF
22 * THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE
24 * OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 * US Government Users Restricted Rights
27 * Use, duplication, or disclosure by the Government is subject to
28 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
29 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
30 * clause at DFARS 252.227-7013 and/or in similar or successor clauses
31 * in the FAR or the DOD or NASA FAR Supplement. Unpublished - rights
32 * reserved under the copyright laws of the United States.
33 *
34 * Contractor/manufacturer is:
35 * Silicon Graphics, Inc.
36 * 1500 Crittenden Lane
37 * Mountain View, CA 94043
38 * United State of America
39 *
40 * OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
41 */
42
43 /*
44 * convolution.c
45 * Use various 2D convolutions filters to find edges in an image.
46 *
47 */
48 #include <GL/glew.h>
49 #include <GL/glut.h>
50 #include <assert.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53
54
55 static GLuint bswap(GLuint x)
56 {
57 const GLuint ui = 1;
58 const GLubyte *ubp = (const GLubyte *) &ui;
59 if (*ubp == 1) {
60 /* we're on little endiang so byteswap x */
61 GLsizei y = ((x >> 24)
62 | ((x >> 8) & 0xff00)
63 | ((x << 8) & 0xff0000)
64 | ((x << 24) & 0xff000000));
65 return y;
66 }
67 else {
68 return x;
69 }
70 }
71
72
73 static GLubyte *
74 readImage( const char* filename, GLsizei* width, GLsizei *height )
75 {
76 int n;
77 GLubyte* pixels;
78 size_t num_read;
79
80 FILE* infile = fopen( filename, "rb" );
81
82 if ( !infile ) {
83 fprintf( stderr, "Unable to open file '%s'\n", filename );
84 exit(1);
85 }
86
87 num_read = fread( width, sizeof( GLsizei ), 1, infile );
88 assert(num_read == 1);
89 num_read = fread( height, sizeof( GLsizei ), 1, infile );
90 assert(num_read == 1);
91
92 *width = bswap(*width);
93 *height = bswap(*height);
94
95 assert(*width > 0);
96 assert(*height > 0);
97
98 n = 3 * (*width) * (*height);
99
100 pixels = (GLubyte *) malloc( n * sizeof( GLubyte ));
101 if ( !pixels ) {
102 fprintf( stderr, "Unable to malloc() bytes for pixels\n" );
103 fclose( infile );
104 return NULL;
105 }
106
107 num_read = fread( pixels, sizeof( GLubyte ), n, infile );
108 assert(num_read == n);
109
110 fclose( infile );
111
112 return pixels;
113 }
114
115
116 GLubyte *pixels;
117 GLsizei width, height;
118
119 GLfloat horizontal[3][3] = {
120 { 0, -1, 0 },
121 { 0, 1, 0 },
122 { 0, 0, 0 }
123 };
124
125 GLfloat vertical[3][3] = {
126 { 0, 0, 0 },
127 { -1, 1, 0 },
128 { 0, 0, 0 }
129 };
130
131 GLfloat laplacian[3][3] = {
132 { -0.125, -0.125, -0.125 },
133 { -0.125, 1.0 , -0.125 },
134 { -0.125, -0.125, -0.125 },
135 };
136
137
138 static void init(void)
139 {
140 if (!glutExtensionSupported("GL_ARB_imaging")) {
141 fprintf(stderr, "Sorry, this program requires GL_ARB_imaging.\n");
142 exit(1);
143 }
144
145 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
146 glClearColor(0.0, 0.0, 0.0, 0.0);
147
148 printf("Using the horizontal filter\n");
149 glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE,
150 3, 3, GL_LUMINANCE, GL_FLOAT, horizontal);
151 glEnable(GL_CONVOLUTION_2D);
152 }
153
154 static void display(void)
155 {
156 glClear(GL_COLOR_BUFFER_BIT);
157 glRasterPos2i( 1, 1);
158 glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
159 glFlush();
160 }
161
162 static void reshape(int w, int h)
163 {
164 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
165 glMatrixMode(GL_PROJECTION);
166 glLoadIdentity();
167 glOrtho(0, w, 0, h, -1.0, 1.0);
168 glMatrixMode(GL_MODELVIEW);
169 }
170
171 static void keyboard(unsigned char key, int x, int y)
172 {
173 switch (key) {
174 case 'h' :
175 printf("Using a horizontal filter\n");
176 glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3,
177 GL_LUMINANCE, GL_FLOAT, horizontal);
178 break;
179
180 case 'v' :
181 printf("Using the vertical filter\n");
182 glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3,
183 GL_LUMINANCE, GL_FLOAT, vertical);
184 break;
185
186 case 'l' :
187 printf("Using the laplacian filter\n");
188 glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE, 3, 3,
189 GL_LUMINANCE, GL_FLOAT, laplacian);
190 break;
191
192 case 27:
193 exit(0);
194 }
195 glutPostRedisplay();
196 }
197
198 /* Main Loop
199 * Open window with initial window size, title bar,
200 * RGBA display mode, and handle input events.
201 */
202 int main(int argc, char** argv)
203 {
204 pixels = readImage("leeds.bin", &width, &height);
205
206 glutInit(&argc, argv);
207 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
208 glutInitWindowSize(width, height);
209 glutInitWindowPosition(100, 100);
210 glutCreateWindow(argv[0]);
211 glewInit();
212 init();
213 glutReshapeFunc(reshape);
214 glutKeyboardFunc(keyboard);
215 glutDisplayFunc(display);
216 glutMainLoop();
217 return 0;
218 }