stretch.c revision 32001f49
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 "glut_wrap.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 39enum { 40 OP_NOOP = 0, 41 OP_STRETCH, 42 OP_DRAWPOINT, 43 OP_DRAWIMAGE 44}; 45 46 47typedef struct _cRec { 48 float x, y; 49} cRec; 50 51typedef struct _vertexRec { 52 float x, y; 53 float dX, dY; 54 float tX, tY; 55} vertexRec; 56 57 58#include "loadppm.c" 59 60GLenum doubleBuffer; 61int imageSizeX, imageSizeY; 62char *fileName = 0; 63PPMImage *image; 64cRec cList[50]; 65vertexRec vList[5]; 66int cCount, cIndex[2], cStep; 67GLenum op = OP_NOOP; 68 69 70static 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 87static 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 105static 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 144static 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 157static void SetPoint(int x, int y) 158{ 159 160 cList[cCount].x = (float)x; 161 cList[cCount].y = (float)y; 162 cCount++; 163} 164 165static 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 224static 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 248static 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 266static 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 295static 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 325static void GLUTCALLBACK glut_post_redisplay_p(void) 326{ 327 glutPostRedisplay(); 328} 329 330int 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} 391