jiv.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 1,047 行 · 第 1/2 页

C
1,047
字号
/*
 * Copyright (c) 2002-2003 Michael David Adams.
 * All rights reserved.
 */

/* __START_OF_JASPER_LICENSE__
 * 
 * JasPer License Version 2.0
 * 
 * Copyright (c) 1999-2000 Image Power, Inc.
 * Copyright (c) 1999-2000 The University of British Columbia
 * Copyright (c) 2001-2003 Michael David Adams
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person (the
 * "User") obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 * 
 * 1.  The above copyright notices and this permission notice (which
 * includes the disclaimer below) shall be included in all copies or
 * substantial portions of the Software.
 * 
 * 2.  The name of a copyright holder shall not be used to endorse or
 * promote products derived from the Software without specific prior
 * written permission.
 * 
 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
 * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
 * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
 * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
 * 
 * __END_OF_JASPER_LICENSE__
 */

/******************************************************************************\
* Includes
\******************************************************************************/

#include <jasper/jasper.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>

/******************************************************************************\
*
\******************************************************************************/

#define MAXCMPTS	256
#define BIGPAN		0.90
#define SMALLPAN	0.05
#define	BIGZOOM		2.0
#define	SMALLZOOM	1.41421356237310

#define	min(x, y)	(((x) < (y)) ? (x) : (y))
#define	max(x, y)	(((x) > (y)) ? (x) : (y))

typedef struct {

	/* The number of image files to view. */
	int numfiles;

	/* The names of the image files. */
	char **filenames;

	/* The title for the window. */
	char *title;

	/* The time to wait before advancing to the next image (in ms). */
	int tmout;

	/* Loop indefinitely over all images. */
	int loop;

	int verbose;

} cmdopts_t;

typedef struct {

	int width;

	int height;

	GLshort *data;

} pixmap_t;

typedef struct {

	/* The index of the current image file. */
	int filenum;

	/* The image. */
	jas_image_t *image;
	jas_image_t *altimage;

	/* The x-coordinate of viewport center. */
	float vcx;

	/* The y-coordinate of viewport center. */
	float vcy;

	/* The x scale factor. */
	float sx;

	/* The y scale factor. */
	float sy;

	/* The viewport pixmap buffer. */
	pixmap_t vp;

	/* The active timer ID. */
	int activetmid;

	/* The next available timer ID. */
	int nexttmid;

	int monomode;

	int cmptno;

	int dirty;

} gs_t;

/******************************************************************************\
*
\******************************************************************************/

static void display(void);
static void reshape(int w, int h);
static void keyboard(unsigned char key, int x, int y);
static void special(int key, int x, int y);
static void timer(int value);

static void usage(void);
static void nextimage(void);
static void previmage(void);
static void nextcmpt(void);
static void prevcmpt(void);
static int loadimage(void);
static void unloadimage(void);
static void adjust(void);
static int jas_image_render2(jas_image_t *image, int cmptno, float vtlx, float vtly,
  float vsx, float vsy, int vw, int vh, GLshort *vdata);
static int jas_image_render(jas_image_t *image, float vtlx, float vtly,
  float vsx, float vsy, int vw, int vh, GLshort *vdata);

static void dumpstate(void);
static int pixmap_resize(pixmap_t *p, int w, int h);
static void pixmap_clear(pixmap_t *p);
static void cmdinfo(void);

static void cleanupandexit(int);
static void init(void);

/******************************************************************************\
*
\******************************************************************************/

jas_opt_t opts[] = {
	{'V', "version", 0},
	{'v', "v", 0},
	{'h', "help", 0},
	{'w', "wait", JAS_OPT_HASARG},
	{'l', "loop", 0},
	{'t', "title", JAS_OPT_HASARG},
	{-1, 0, 0}
};

char *cmdname = 0;
cmdopts_t cmdopts;
gs_t gs;
jas_stream_t *streamin = 0;

/******************************************************************************\
*
\******************************************************************************/

int main(int argc, char **argv)
{
	int c;

	init();

	/* Determine the base name of this command. */
	if ((cmdname = strrchr(argv[0], '/'))) {
		++cmdname;
	} else {
		cmdname = argv[0];
	}

	/* Initialize the JasPer library. */
	if (jas_init()) {
		abort();
	}

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
	glutCreateWindow(cmdname);
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);
	glutSpecialFunc(special);
	glutKeyboardFunc(keyboard);

	cmdopts.numfiles = 0;
	cmdopts.filenames = 0;
	cmdopts.title = 0;
	cmdopts.tmout = 0;
	cmdopts.loop = 0;
	cmdopts.verbose = 0;

	while ((c = jas_getopt(argc, argv, opts)) != EOF) {
		switch (c) {
		case 'w':
			cmdopts.tmout = atof(jas_optarg) * 1000;
			break;
		case 'l':
			cmdopts.loop = 1;
			break;
		case 't':
			cmdopts.title = jas_optarg;
			break;
		case 'v':
			cmdopts.verbose = 1;
			break;
		case 'V':
			jas_eprintf("%s\n", JAS_VERSION);
			jas_eprintf("libjasper %s\n", jas_getversion());
			cleanupandexit(EXIT_SUCCESS);
			break;
		default:
		case 'h':
			usage();
			break;
		}
	}

	if (jas_optind < argc) {
		/* The images are to be read from one or more explicitly named
		  files. */
		cmdopts.numfiles = argc - jas_optind;
		cmdopts.filenames = &argv[jas_optind];
	} else {
		/* The images are to be read from standard input. */
		static char *null = 0;
		cmdopts.filenames = &null;
		cmdopts.numfiles = 1;
	}

	streamin = jas_stream_fdopen(0, "rb");

	/* Load the next image. */
	nextimage();

	/* Start the GLUT main event handler loop. */
	glutMainLoop();

	return EXIT_SUCCESS;
}

/******************************************************************************\
*
\******************************************************************************/

static void cmdinfo()
{
	jas_eprintf("JasPer Image Viewer (Version %s).\n",
	  JAS_VERSION);
	jas_eprintf("Copyright (c) 2002-2003 Michael David Adams.\n"
	  "All rights reserved.\n");
	jas_eprintf("%s\n", JAS_NOTES);
}

static char *helpinfo[] = {
"The following options are supported:\n",
"    --help                  Print this help information and exit.\n",
"    --version               Print version information and exit.\n",
"    --loop                  Loop indefinitely through images.\n",
"    --wait N                Advance to next image after N seconds.\n",
0
};

static void usage()
{
	char *s;
	int i;
	cmdinfo();
	jas_eprintf("usage: %s [options] [file1 file2 ...]\n", cmdname);
	for (i = 0, s = helpinfo[i]; s; ++i, s = helpinfo[i]) {
		jas_eprintf("%s", s);
	}
	cleanupandexit(EXIT_FAILURE);
}

/******************************************************************************\
* GLUT Callback Functions
\******************************************************************************/

/* Display callback function. */

static void display()
{
	float vtlx;
	float vtly;

	if (cmdopts.verbose) {
		jas_eprintf("display()\n");
		dumpstate();
	}

	if (!gs.dirty) {
		glClear(GL_COLOR_BUFFER_BIT);
		glDrawPixels(gs.vp.width, gs.vp.height, GL_RGBA,
		  GL_UNSIGNED_SHORT, gs.vp.data);
		glFlush();
		return;
	}

	glClear(GL_COLOR_BUFFER_BIT);
	pixmap_clear(&gs.vp);
	glDrawPixels(gs.vp.width, gs.vp.height, GL_RGBA, GL_UNSIGNED_SHORT,
	  gs.vp.data);
	glFlush();

	vtlx = gs.vcx - 0.5 * gs.sx * gs.vp.width;
	vtly = gs.vcy - 0.5 * gs.sy * gs.vp.height;
	if (cmdopts.verbose) {
		jas_eprintf("vtlx=%f, vtly=%f, vsx=%f, vsy=%f\n",
		  vtlx, vtly, gs.sx, gs.sy);
	}
	if (gs.monomode) {
		if (cmdopts.verbose) {
			jas_eprintf("component %d\n", gs.cmptno);
		}
		jas_image_render2(gs.image, gs.cmptno, vtlx, vtly,
		  gs.sx, gs.sy, gs.vp.width, gs.vp.height, gs.vp.data);
	} else {
		if (cmdopts.verbose) {
			jas_eprintf("color\n");
		}
		jas_image_render(gs.altimage, vtlx, vtly, gs.sx, gs.sy,
		  gs.vp.width, gs.vp.height, gs.vp.data);
	}
	glClear(GL_COLOR_BUFFER_BIT);
	glDrawPixels(gs.vp.width, gs.vp.height, GL_RGBA, GL_UNSIGNED_SHORT,
	  gs.vp.data);
	glFlush();
	gs.dirty = 0;
}

/* Reshape callback function. */

static void reshape(int w, int h)
{
	if (cmdopts.verbose) {
		jas_eprintf("reshape(%d, %d)\n", w, h);
		dumpstate();
	}

	if (pixmap_resize(&gs.vp, w, h)) {
		cleanupandexit(EXIT_FAILURE);
	}
	pixmap_clear(&gs.vp);
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho( 0, w, 0, h, 0.f, 1.f );

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0, 0, 0);
	glRasterPos2i(0, 0);

	if (gs.vp.width > jas_image_width(gs.image) / gs.sx) {
		gs.vcx = (jas_image_tlx(gs.image) + jas_image_brx(gs.image)) / 2.0;
	}
	if (gs.vp.height > jas_image_height(gs.image) / gs.sy) {
		gs.vcy = (jas_image_tly(gs.image) + jas_image_bry(gs.image)) / 2.0;
	}
	gs.dirty = 1;
}

/* Keyboard callback function. */

static void keyboard(unsigned char key, int x, int y)
{
	if (cmdopts.verbose) {
		jas_eprintf("keyboard(%d, %d, %d)\n", key, x, y);
	}

	switch (key) {
	case ' ':
		nextimage();
		break;
	case '\b':
		previmage();
		break;
	case '>':
		gs.sx /= BIGZOOM;
		gs.sy /= BIGZOOM;
		gs.dirty = 1;
		glutPostRedisplay();
		break;
	case '.':
		gs.sx /= SMALLZOOM;
		gs.sy /= SMALLZOOM;
		gs.dirty = 1;
		glutPostRedisplay();
		break;
	case '<':
		gs.sx *= BIGZOOM;
		gs.sy *= BIGZOOM;
		adjust();
		gs.dirty = 1;
		glutPostRedisplay();
		break;
	case ',':
		gs.sx *= SMALLZOOM;
		gs.sy *= SMALLZOOM;
		gs.dirty = 1;
		adjust();
		glutPostRedisplay();
		break;
	case 'c':
		nextcmpt();
		break;
	case 'C':
		prevcmpt();
		break;
	case 'q':
		cleanupandexit(EXIT_SUCCESS);
		break;
	}
}

/* Special keyboard callback function. */

static void special(int key, int x, int y)
{
	if (cmdopts.verbose) {
		jas_eprintf("special(%d, %d, %d)\n", key, x, y);
	}

	switch (key) {
	case GLUT_KEY_UP:
		{
			float oldvcy;
			float vh;
			float pan;
			if (gs.vp.height < jas_image_height(gs.image) / gs.sy) {
				pan = (glutGetModifiers() & GLUT_ACTIVE_SHIFT) ?
				  BIGPAN : SMALLPAN;
				oldvcy = gs.vcy;
				vh = gs.sy * gs.vp.height;
				gs.vcy = max(gs.vcy - pan * vh, jas_image_tly(gs.image) +
				  0.5 * vh);
				if (gs.vcy != oldvcy) {
					gs.dirty = 1;
					glutPostRedisplay();
				}
			}
		}
		break;
	case GLUT_KEY_DOWN:
		{
			float oldvcy;
			float vh;
			float pan;
			if (gs.vp.height < jas_image_height(gs.image) / gs.sy) {
				pan = (glutGetModifiers() & GLUT_ACTIVE_SHIFT) ?
				  BIGPAN : SMALLPAN;
				oldvcy = gs.vcy;
				vh = gs.sy * gs.vp.height;
				gs.vcy = min(gs.vcy + pan * vh, jas_image_bry(gs.image) -
				  0.5 * vh);
				if (gs.vcy != oldvcy) {
					gs.dirty = 1;
					glutPostRedisplay();
				}
			}
		}
		break;
	case GLUT_KEY_LEFT:
		{
			float oldvcx;
			float vw;
			float pan;
			if (gs.vp.width < jas_image_width(gs.image) / gs.sx) {
				pan = (glutGetModifiers() & GLUT_ACTIVE_SHIFT) ?
				  BIGPAN : SMALLPAN;
				oldvcx = gs.vcx;
				vw = gs.sx * gs.vp.width;
				gs.vcx = max(gs.vcx - pan * vw, jas_image_tlx(gs.image) +
				  0.5 * vw);
				if (gs.vcx != oldvcx) {
					gs.dirty = 1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?