paint.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:6k
- #include <assert.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <GL/glut.h>
- #include "texture.h"
- /* Some <math.h> files do not define M_PI... */
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
- #ifndef __sgi
- #define trunc(x) ((double)((int)(x)))
- #endif
- #define RW 0.3086
- #define GW 0.6094
- #define BW 0.0820
- static char defaultFile0[] = "../data/mandrill.rgb";
- static char defaultFile1[] = "../data/sgi.bw";
- static char defaultBrushFile[] = "../data/brush.rgb";
- GLuint *img0, *img1, *brush;
- GLsizei w0, w1, wbrush, h0, h1, hbrush;
- GLsizei w, h;
- GLint comp;
- void init(void)
- {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- }
- GLuint *load_img(const char *fname, GLsizei *imgW, GLsizei *imgH)
- {
- GLuint *img;
- img = read_texture(fname, imgW, imgH, &comp);
- if (!img) {
- fprintf(stderr, "Could not open %sn", fname);
- exit(1);
- }
- return img;
- }
- GLuint *
- resize_img(GLuint *img, GLsizei curW, GLsizei curH)
- {
- /* save & set buffer settings */
- glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT);
- glDrawBuffer(GL_BACK);
- glReadBuffer(GL_BACK);
- glPixelZoom((float)w / (float)curW, (float)h / (float)curH);
- glRasterPos2i(0, 0);
- glDrawPixels(curW, curH, GL_RGBA, GL_UNSIGNED_BYTE, img);
- free(img);
- img = (GLuint *)malloc(w * h * sizeof(GLuint));
- if (!img) {
- fprintf(stderr, "Malloc of %d bytes failed.n",
- curW * curH * sizeof(GLuint));
- exit(1);
- }
- glPixelZoom(1, 1);
- glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img);
- glPopAttrib();
- return img;
- }
- GLuint *
- convert_to_luminance(GLuint *img, GLsizei w, GLsizei h)
- {
- GLubyte *newImg, *src, *dst;
- GLfloat val;
- int i;
- newImg = (GLubyte *)malloc(w * h);
- if (!newImg) {
- fprintf(stderr, "malloc of %d bytes failedn", w*h);
- exit(1);
- }
- src = (GLubyte *)img;
- dst = newImg;
- for (i = 0; i < w*h; i++) {
- val = ((float)(*src++) * RW +
- (float)(*src++) * GW +
- (float)(*src++) * BW);
- src++;
- if (val > 255) val = 255;
- *dst++ = val;
- }
- free(img);
- /* casting a ubyte ptr to a uint pointer is sloppy since it can
- * lead to alignment errors, but since the pointer came from
- * malloc we know it's legal in this case... */
- return (GLuint *)newImg;
- }
- void reshape(GLsizei winW, GLsizei winH)
- {
- glViewport(0, 0, w, h);
- glLoadIdentity();
- glOrtho(0, winW, 0, winH, 0, 5);
- }
- void draw(void)
- {
- static int first = 1;
- GLenum err;
- if (first) {
- printf("Scaling images to %d by %dn", w, h);
- if (w0 != w || h0 != h) {
- img0 = resize_img(img0, w0, h0);
- }
- if (w1 != w || h1 != h) {
- img1 = resize_img(img1, w1, h1);
- }
- first = 0;
- }
-
- glClear(GL_COLOR_BUFFER_BIT);
- glRasterPos2i(0, 0);
- glDrawBuffer(GL_BACK);
- glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img1);
- glDrawBuffer(GL_FRONT);
- glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img0);
-
- err = glGetError();
- if (err != GL_NO_ERROR) printf("Error: %sn", gluErrorString(err));
- }
- int lastX, lastY, curX, curY;
- int get_msecs(void)
- {
- return glutGet(GLUT_ELAPSED_TIME) / 1000.0;
- }
- void idle(void)
- {
- int x = curX - (wbrush/2);
- int y = h - (curY + (hbrush/2));
- int msecs;
- static int last_msecs = -1;
- /* do not do this more than 60 times a second. Otherwise it's
- * to fast for use on high-end systems */
- msecs = get_msecs();
- if (fabs(last_msecs - msecs) < 1000./60.) {
- return;
- }
- last_msecs = msecs;
- /* we draw the brush using a drawpixels command. on systems with
- * hardware-accelerated texture mapping it would be better to use
- * that.
- *
- * we use the bitmap hack to set the rasterpos because we don't
- * know that the position will be within the window.
- */
- glRasterPos2i(0, 0);
- glBitmap(0, 0, 0, 0, x, y, 0);
- glColorMask(0, 0, 0, 1);
- glDrawBuffer(GL_BACK);
- glDrawPixels(wbrush, hbrush, GL_ALPHA, GL_UNSIGNED_BYTE, brush);
- glColorMask(1, 1, 1, 1);
-
- glReadBuffer(GL_BACK);
- glDrawBuffer(GL_FRONT);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glCopyPixels(x, y, wbrush, hbrush, GL_COLOR);
- glDisable(GL_BLEND);
-
- glColorMask(1, 1, 1, 1);
- }
- void motion(int xpos, int ypos)
- {
- curX = xpos;
- curY = ypos;
- }
- /* ARGSUSED */
- void button(int button, int state, int xpos, int ypos)
- {
- if (state == GLUT_DOWN) {
- glutIdleFunc(idle);
- lastX = lastY = -1;
- curX = xpos;
- curY = ypos;
- return;
- } else {
- glutIdleFunc(0);
- }
- }
- /* ARGSUSED1 */
- void key(unsigned char key, int x, int y)
- {
- if (key == 27) exit(0);
- }
- void
- show_usage(void)
- {
- fprintf(stderr, "Usage:n");
- fprintf(stderr, "paint [imagefile0] [imagefile1] [brush]n");
- }
- main(int argc, char *argv[])
- {
- const char *fileName0 = defaultFile0, *fileName1 = defaultFile1,
- *brushName = defaultBrushFile;
-
- glutInit(&argc, argv);
- if (argc > 1) {
- fileName0 = argv[1];
- }
- if (argc > 2) {
- fileName1 = argv[2];
- }
- if (argc > 3) {
- brushName = argv[3];
- }
- if (argc > 4) {
- show_usage();
- exit(1);
- }
- printf("Image file 1 is %sn", fileName0);
- printf("Image file 2 is %sn", fileName1);
- printf("Brush file is %sn", brushName);
- img0 = load_img(fileName0, &w0, &h0);
- img1 = load_img(fileName1, &w1, &h1);
- brush = load_img(brushName, &wbrush, &hbrush);
- brush = convert_to_luminance(brush, wbrush, hbrush);
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- w = MAX(w0, w1);
- h = MAX(h0, h1);
- glutInitWindowSize(w, h);
- glutInitWindowPosition(0, 0);
- glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA);
- glutCreateWindow(argv[0]);
- glutDisplayFunc(draw);
- glutKeyboardFunc(key);
- glutReshapeFunc(reshape);
- glutMouseFunc(button);
- glutMotionFunc(motion);
- init();
- glutMainLoop();
- return 0;
- }