jiv.c.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 1,047 行 · 第 1/2 页
SVN-BASE
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 + -
显示快捷键?