Merge branch '7.8'
[mesa.git] / progs / samples / stretch.c
1 /*
2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that (i) the above copyright notices and this permission notice appear in
7 * all copies of the software and related documentation, and (ii) the name of
8 * Silicon Graphics may not be used in any advertising or
9 * publicity relating to the software without the specific, prior written
10 * permission of Silicon Graphics.
11 *
12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
13 * ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29 #include <GL/glut.h>
30
31
32 #define STEPCOUNT 40
33 #define FALSE 0
34 #define TRUE 1
35 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
36 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
37
38
39 enum {
40 OP_NOOP = 0,
41 OP_STRETCH,
42 OP_DRAWPOINT,
43 OP_DRAWIMAGE
44 };
45
46
47 typedef struct _cRec {
48 float x, y;
49 } cRec;
50
51 typedef struct _vertexRec {
52 float x, y;
53 float dX, dY;
54 float tX, tY;
55 } vertexRec;
56
57
58 #include "loadppm.c"
59
60 GLenum doubleBuffer;
61 int imageSizeX, imageSizeY;
62 char *fileName = 0;
63 PPMImage *image;
64 cRec cList[50];
65 vertexRec vList[5];
66 int cCount, cIndex[2], cStep;
67 GLenum op = OP_NOOP;
68
69
70 static void DrawImage(void)
71 {
72
73 glRasterPos2i(0, 0);
74 glDrawPixels(image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
75 image->data);
76
77 glFlush();
78 if (doubleBuffer) {
79 glutSwapBuffers();
80 }
81
82 glRasterPos2i(0, 0);
83 glDrawPixels(image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE,
84 image->data);
85 }
86
87 static void DrawPoint(void)
88 {
89 int i;
90
91 glColor3f(1.0, 0.0, 1.0);
92 glPointSize(3.0);
93 glBegin(GL_POINTS);
94 for (i = 0; i < cCount; i++) {
95 glVertex2f(cList[i].x, cList[i].y);
96 }
97 glEnd();
98
99 glFlush();
100 if (doubleBuffer) {
101 glutSwapBuffers();
102 }
103 }
104
105 static void InitVList(void)
106 {
107
108 vList[0].x = 0.0;
109 vList[0].y = 0.0;
110 vList[0].dX = 0.0;
111 vList[0].dY = 0.0;
112 vList[0].tX = 0.0;
113 vList[0].tY = 0.0;
114
115 vList[1].x = (float)imageSizeX;
116 vList[1].y = 0.0;
117 vList[1].dX = 0.0;
118 vList[1].dY = 0.0;
119 vList[1].tX = 1.0;
120 vList[1].tY = 0.0;
121
122 vList[2].x = (float)imageSizeX;
123 vList[2].y = (float)imageSizeY;
124 vList[2].dX = 0.0;
125 vList[2].dY = 0.0;
126 vList[2].tX = 1.0;
127 vList[2].tY = 1.0;
128
129 vList[3].x = 0.0;
130 vList[3].y = (float)imageSizeY;
131 vList[3].dX = 0.0;
132 vList[3].dY = 0.0;
133 vList[3].tX = 0.0;
134 vList[3].tY = 1.0;
135
136 vList[4].x = cList[0].x;
137 vList[4].y = cList[0].y;
138 vList[4].dX = (cList[1].x - cList[0].x) / STEPCOUNT;
139 vList[4].dY = (cList[1].y - cList[0].y) / STEPCOUNT;
140 vList[4].tX = cList[0].x / (float)imageSizeX;
141 vList[4].tY = cList[0].y / (float)imageSizeY;
142 }
143
144 static void ScaleImage(int sizeX, int sizeY)
145 {
146 GLubyte *buf;
147
148 buf = (GLubyte *)malloc(3*sizeX*sizeY);
149 gluScaleImage(GL_RGB, image->sizeX, image->sizeY, GL_UNSIGNED_BYTE,
150 image->data, sizeX, sizeY, GL_UNSIGNED_BYTE, buf);
151 free(image->data);
152 image->data = buf;
153 image->sizeX = sizeX;
154 image->sizeY = sizeY;
155 }
156
157 static void SetPoint(int x, int y)
158 {
159
160 cList[cCount].x = (float)x;
161 cList[cCount].y = (float)y;
162 cCount++;
163 }
164
165 static void Stretch(void)
166 {
167
168 glBegin(GL_TRIANGLES);
169 glTexCoord2f(vList[0].tX, vList[0].tY);
170 glVertex2f(vList[0].x, vList[0].y);
171 glTexCoord2f(vList[1].tX, vList[1].tY);
172 glVertex2f(vList[1].x, vList[1].y);
173 glTexCoord2f(vList[4].tX, vList[4].tY);
174 glVertex2f(vList[4].x, vList[4].y);
175 glEnd();
176
177 glBegin(GL_TRIANGLES);
178 glTexCoord2f(vList[1].tX, vList[1].tY);
179 glVertex2f(vList[1].x, vList[1].y);
180 glTexCoord2f(vList[2].tX, vList[2].tY);
181 glVertex2f(vList[2].x, vList[2].y);
182 glTexCoord2f(vList[4].tX, vList[4].tY);
183 glVertex2f(vList[4].x, vList[4].y);
184 glEnd();
185
186 glBegin(GL_TRIANGLES);
187 glTexCoord2f(vList[2].tX, vList[2].tY);
188 glVertex2f(vList[2].x, vList[2].y);
189 glTexCoord2f(vList[3].tX, vList[3].tY);
190 glVertex2f(vList[3].x, vList[3].y);
191 glTexCoord2f(vList[4].tX, vList[4].tY);
192 glVertex2f(vList[4].x, vList[4].y);
193 glEnd();
194
195 glBegin(GL_TRIANGLES);
196 glTexCoord2f(vList[3].tX, vList[3].tY);
197 glVertex2f(vList[3].x, vList[3].y);
198 glTexCoord2f(vList[0].tX, vList[0].tY);
199 glVertex2f(vList[0].x, vList[0].y);
200 glTexCoord2f(vList[4].tX, vList[4].tY);
201 glVertex2f(vList[4].x, vList[4].y);
202 glEnd();
203
204 glFlush();
205 if (doubleBuffer) {
206 glutSwapBuffers();
207 }
208
209 if (++cStep < STEPCOUNT) {
210 vList[4].x += vList[4].dX;
211 vList[4].y += vList[4].dY;
212 } else {
213 cIndex[0] = cIndex[1];
214 cIndex[1] = cIndex[1] + 1;
215 if (cIndex[1] == cCount) {
216 cIndex[1] = 0;
217 }
218 vList[4].dX = (cList[cIndex[1]].x - cList[cIndex[0]].x) / STEPCOUNT;
219 vList[4].dY = (cList[cIndex[1]].y - cList[cIndex[0]].y) / STEPCOUNT;
220 cStep = 0;
221 }
222 }
223
224 static void Key(unsigned char key, int x, int y)
225 {
226
227 switch (key) {
228 case 27:
229 free(image->data);
230 exit(1);
231 case 32:
232 if (cCount > 1) {
233 InitVList();
234 cIndex[0] = 0;
235 cIndex[1] = 1;
236 cStep = 0;
237 glEnable(GL_TEXTURE_2D);
238 op = OP_STRETCH;
239 }
240 break;
241 default:
242 return;
243 }
244
245 glutPostRedisplay();
246 }
247
248 static void Mouse(int button, int state, int mouseX, int mouseY)
249 {
250
251 if (state != GLUT_DOWN)
252 return;
253
254 if (op == OP_STRETCH) {
255 glDisable(GL_TEXTURE_2D);
256 cCount = 0;
257 op = OP_DRAWIMAGE;
258 } else {
259 SetPoint(mouseX, imageSizeY-mouseY);
260 op = OP_DRAWPOINT;
261 }
262
263 glutPostRedisplay();
264 }
265
266 static void Animate(void)
267 {
268 static double t0 = -1.;
269 double t, dt;
270 t = glutGet(GLUT_ELAPSED_TIME) / 1000.;
271 if (t0 < 0.)
272 t0 = t;
273 dt = t - t0;
274
275 if (dt < 1./60.)
276 return;
277
278 t0 = t;
279
280 switch (op) {
281 case OP_STRETCH:
282 Stretch();
283 break;
284 case OP_DRAWPOINT:
285 DrawPoint();
286 break;
287 case OP_DRAWIMAGE:
288 DrawImage();
289 break;
290 default:
291 break;
292 }
293 }
294
295 static GLenum Args(int argc, char **argv)
296 {
297 GLint i;
298
299 doubleBuffer = GL_TRUE;
300
301 for (i = 1; i < argc; i++) {
302 if (strcmp(argv[i], "-sb") == 0) {
303 doubleBuffer = GL_FALSE;
304 } else if (strcmp(argv[i], "-db") == 0) {
305 doubleBuffer = GL_TRUE;
306 } else if (strcmp(argv[i], "-f") == 0) {
307 if (i+1 >= argc || argv[i+1][0] == '-') {
308 printf("-f (No file name).\n");
309 return GL_FALSE;
310 } else {
311 fileName = argv[++i];
312 }
313 } else {
314 printf("%s (Bad option).\n", argv[i]);
315 return GL_FALSE;
316 }
317 }
318 return GL_TRUE;
319 }
320
321 #if !defined(GLUTCALLBACK)
322 #define GLUTCALLBACK
323 #endif
324
325 static void GLUTCALLBACK glut_post_redisplay_p(void)
326 {
327 glutPostRedisplay();
328 }
329
330 int main(int argc, char **argv)
331 {
332 GLenum type;
333
334 glutInit(&argc, argv);
335
336 if (Args(argc, argv) == GL_FALSE) {
337 exit(1);
338 }
339
340 if (fileName == 0) {
341 printf("No image file.\n");
342 exit(1);
343 }
344
345 image = LoadPPM(fileName);
346
347 /* changed powf and logf to pow and log -Brian */
348 imageSizeX = (int)pow(2.0, (float)((int)(log(image->sizeX)/log(2.0))));
349 imageSizeY = (int)pow(2.0, (float)((int)(log(image->sizeY)/log(2.0))));
350
351 glutInitWindowPosition(0, 0); glutInitWindowSize( imageSizeX, imageSizeY);
352
353 type = GLUT_RGB;
354 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
355 glutInitDisplayMode(type);
356
357 if (glutCreateWindow("Stretch") == GL_FALSE) {
358 exit(1);
359 }
360
361 glViewport(0, 0, imageSizeX, imageSizeY);
362 gluOrtho2D(0, imageSizeX, 0, imageSizeY);
363 glClearColor(0.0, 0.0, 0.0, 0.0);
364
365 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
366 glPixelStorei(GL_PACK_ALIGNMENT, 1);
367
368 ScaleImage(imageSizeX, imageSizeY);
369
370 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
371 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
375 glTexImage2D(GL_TEXTURE_2D, 0, 3, image->sizeX, image->sizeY, 0,
376 GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)image->data);
377
378 cCount = 0;
379 cIndex[0] = 0;
380 cIndex[1] = 0;
381 cStep = 0;
382 op = OP_DRAWIMAGE;
383
384 glutKeyboardFunc(Key);
385 glutMouseFunc(Mouse);
386 glutDisplayFunc(Animate);
387 glutIdleFunc(glut_post_redisplay_p);
388 glutMainLoop();
389 return 0;
390 }