jtg | afb833d | 1999-08-19 00:55:39 +0000 | [diff] [blame^] | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | void Animate(void) |
| 267 | { |
| 268 | |
| 269 | switch (op) { |
| 270 | case OP_STRETCH: |
| 271 | Stretch(); |
| 272 | break; |
| 273 | case OP_DRAWPOINT: |
| 274 | DrawPoint(); |
| 275 | break; |
| 276 | case OP_DRAWIMAGE: |
| 277 | DrawImage(); |
| 278 | break; |
| 279 | default: |
| 280 | break; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | static GLenum Args(int argc, char **argv) |
| 285 | { |
| 286 | GLint i; |
| 287 | |
| 288 | doubleBuffer = GL_FALSE; |
| 289 | |
| 290 | for (i = 1; i < argc; i++) { |
| 291 | if (strcmp(argv[i], "-sb") == 0) { |
| 292 | doubleBuffer = GL_FALSE; |
| 293 | } else if (strcmp(argv[i], "-db") == 0) { |
| 294 | doubleBuffer = GL_TRUE; |
| 295 | } else if (strcmp(argv[i], "-f") == 0) { |
| 296 | if (i+1 >= argc || argv[i+1][0] == '-') { |
| 297 | printf("-f (No file name).\n"); |
| 298 | return GL_FALSE; |
| 299 | } else { |
| 300 | fileName = argv[++i]; |
| 301 | } |
| 302 | } else { |
| 303 | printf("%s (Bad option).\n", argv[i]); |
| 304 | return GL_FALSE; |
| 305 | } |
| 306 | } |
| 307 | return GL_TRUE; |
| 308 | } |
| 309 | |
| 310 | void GLUTCALLBACK glut_post_redisplay_p(void) |
| 311 | { |
| 312 | glutPostRedisplay(); |
| 313 | } |
| 314 | |
| 315 | int main(int argc, char **argv) |
| 316 | { |
| 317 | GLenum type; |
| 318 | |
| 319 | glutInit(&argc, argv); |
| 320 | |
| 321 | if (Args(argc, argv) == GL_FALSE) { |
| 322 | exit(1); |
| 323 | } |
| 324 | |
| 325 | if (fileName == 0) { |
| 326 | printf("No image file.\n"); |
| 327 | exit(1); |
| 328 | } |
| 329 | |
| 330 | image = LoadPPM(fileName); |
| 331 | |
| 332 | /* changed powf and logf to pow and log -Brian */ |
| 333 | imageSizeX = (int)pow(2.0, (float)((int)(log(image->sizeX)/log(2.0)))); |
| 334 | imageSizeY = (int)pow(2.0, (float)((int)(log(image->sizeY)/log(2.0)))); |
| 335 | |
| 336 | glutInitWindowPosition(0, 0); glutInitWindowSize( imageSizeX, imageSizeY); |
| 337 | |
| 338 | type = GLUT_RGB; |
| 339 | type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; |
| 340 | glutInitDisplayMode(type); |
| 341 | |
| 342 | if (glutCreateWindow("Stretch") == GL_FALSE) { |
| 343 | exit(1); |
| 344 | } |
| 345 | |
| 346 | glViewport(0, 0, imageSizeX, imageSizeY); |
| 347 | gluOrtho2D(0, imageSizeX, 0, imageSizeY); |
| 348 | glClearColor(0.0, 0.0, 0.0, 0.0); |
| 349 | |
| 350 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 351 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 352 | |
| 353 | ScaleImage(imageSizeX, imageSizeY); |
| 354 | |
| 355 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); |
| 356 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); |
| 357 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); |
| 358 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 359 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 360 | glTexImage2D(GL_TEXTURE_2D, 0, 3, image->sizeX, image->sizeY, 0, |
| 361 | GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)image->data); |
| 362 | |
| 363 | cCount = 0; |
| 364 | cIndex[0] = 0; |
| 365 | cIndex[1] = 0; |
| 366 | cStep = 0; |
| 367 | op = OP_DRAWIMAGE; |
| 368 | |
| 369 | glutKeyboardFunc(Key); |
| 370 | glutMouseFunc(Mouse); |
| 371 | glutDisplayFunc(Animate); |
| 372 | glutIdleFunc(glut_post_redisplay_p); |
| 373 | glutMainLoop(); |
| 374 | return 0; |
| 375 | } |