📄 xtiff.c
字号:
/* * xtiff - view a TIFF file in an X window * * Dan Sears * Chris Sears * * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts. * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Digital not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR 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. * * Revision 1.0 90/05/07 * Initial release. * Revision 2.0 90/12/20 * Converted to use the Athena Widgets and the Xt Intrinsics. * * Notes: * * According to the TIFF 5.0 Specification, it is possible to have * both a TIFFTAG_COLORMAP and a TIFFTAG_COLORRESPONSECURVE. This * doesn't make sense since a TIFFTAG_COLORMAP is 16 bits wide and * a TIFFTAG_COLORRESPONSECURVE is tfBitsPerSample bits wide for each * channel. This is probably a bug in the specification. * In this case, TIFFTAG_COLORRESPONSECURVE is ignored. * This might make sense if TIFFTAG_COLORMAP was 8 bits wide. * * TIFFTAG_COLORMAP is often incorrectly written as ranging from * 0 to 255 rather than from 0 to 65535. CheckAndCorrectColormap() * takes care of this. * * Only ORIENTATION_TOPLEFT is supported correctly. This is the * default TIFF and X orientation. Other orientations will be * displayed incorrectly. * * There is no support for or use of 3/3/2 DirectColor visuals. * TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE are not supported. * * Only TIFFTAG_BITSPERSAMPLE values that are 1, 2, 4 or 8 are supported. */#include <math.h>#include <stdio.h>#include <tiffio.h>#include <X11/Xatom.h>#include <X11/Intrinsic.h>#include <X11/StringDefs.h>#include <X11/Xproto.h>#include <X11/Shell.h>#include <X11/Xaw/Form.h>#include <X11/Xaw/List.h>#include <X11/Xaw/Label.h>#include <X11/cursorfont.h>#define XK_MISCELLANY#include <X11/keysymdef.h>#include "xtifficon.h"#define TIFF_GAMMA "2.2" /* default gamma from the TIFF 5.0 spec */#define ROUND(x) (u_short) ((x) + 0.5)#define SCALE(x, s) (((x) * 65535L) / (s))#define MCHECK(m) if (!m) { fprintf(stderr, "malloc failed\n"); exit(0); }#define MIN(a, b) (((a) < (b)) ? (a) : (b))#define MAX(a, b) (((a) > (b)) ? (a) : (b))#define VIEWPORT_WIDTH 700#define VIEWPORT_HEIGHT 500#define KEY_TRANSLATE 20#ifdef __STDC__#define PP(args) args#else#define PP(args) ()#endifvoid main PP((int argc, char **argv));void OpenTIFFFile PP((void));void GetTIFFHeader PP((void));void SetNameLabel PP((void));void CheckAndCorrectColormap PP((void));void SimpleGammaCorrection PP((void));void GetVisual PP((void));Boolean SearchVisualList PP((int image_depth, int visual_class, Visual **visual));void GetTIFFImage PP((void));void CreateXImage PP((void));XtCallbackProc SelectProc PP((Widget w, caddr_t unused_1, caddr_t unused_2));void QuitProc PP((void));void NextProc PP((void));void PreviousProc PP((void));void PageProc PP((int direction));void EventProc PP((Widget widget, caddr_t unused, XEvent *event));void ResizeProc PP((void));int XTiffErrorHandler PP((Display *display, XErrorEvent *error_event));void Usage PP((void));int xtVersion = XtSpecificationRelease; /* xtiff depends on R4 or higher *//* * Xt data structures */Widget shellWidget, formWidget, listWidget, labelWidget, imageWidget;enum { ButtonQuit = 0, ButtonPreviousPage = 1, ButtonNextPage = 2 };String buttonStrings[] = { "Quit", "Previous", "Next" };static XrmOptionDescRec shellOptions[] = { { "-help", "*help", XrmoptionNoArg, (caddr_t) "True" }, { "-gamma", "*gamma", XrmoptionSepArg, NULL }, { "-usePixmap", "*usePixmap", XrmoptionSepArg, NULL }, { "-viewportWidth", "*viewportWidth", XrmoptionSepArg, NULL }, { "-viewportHeight", "*viewportHeight", XrmoptionSepArg, NULL }, { "-translate", "*translate", XrmoptionSepArg, NULL }, { "-verbose", "*verbose", XrmoptionSepArg, NULL }};typedef struct { Boolean help; float gamma; Boolean usePixmap; int viewportWidth; int viewportHeight; int translate; Boolean verbose;} AppData, *AppDataPtr;AppData appData;XtResource clientResources[] = { { "help", XtCBoolean, XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, help), XtRImmediate, (XtPointer) False }, { "gamma", "Gamma", XtRFloat, sizeof(float), XtOffset(AppDataPtr, gamma), XtRString, (XtPointer) TIFF_GAMMA }, { "usePixmap", "UsePixmap", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, usePixmap), XtRImmediate, (XtPointer) True }, { "viewportWidth", "ViewportWidth", XtRInt, sizeof(int), XtOffset(AppDataPtr, viewportWidth), XtRImmediate, (XtPointer) VIEWPORT_WIDTH }, { "viewportHeight", "ViewportHeight", XtRInt, sizeof(int), XtOffset(AppDataPtr, viewportHeight), XtRImmediate, (XtPointer) VIEWPORT_HEIGHT }, { "translate", "Translate", XtRInt, sizeof(int), XtOffset(AppDataPtr, translate), XtRImmediate, (XtPointer) KEY_TRANSLATE }, { "verbose", "Verbose", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, verbose), XtRImmediate, (XtPointer) True }};Arg formArgs[] = { { XtNresizable, True }};Arg listArgs[] = { { XtNresizable, False }, { XtNborderWidth, 0 }, { XtNdefaultColumns, 3 }, { XtNforceColumns, True }, { XtNlist, (int) buttonStrings }, { XtNnumberStrings, XtNumber(buttonStrings) }, { XtNtop, XtChainTop }, { XtNleft, XtChainLeft }, { XtNbottom, XtChainTop }, { XtNright, XtChainLeft }};Arg labelArgs[] = { { XtNresizable, False }, { XtNwidth, 200 }, { XtNborderWidth, 0 }, { XtNjustify, XtJustifyLeft }, { XtNtop, XtChainTop }, { XtNleft, XtChainLeft }, { XtNbottom, XtChainTop }, { XtNright, XtChainLeft }};Arg imageArgs[] = { { XtNresizable, True }, { XtNborderWidth, 0 }, { XtNtop, XtChainTop }, { XtNleft, XtChainLeft }, { XtNbottom, XtChainTop }, { XtNright, XtChainLeft }};XtActionsRec actionsTable[] = { { "quit", QuitProc }, { "next", NextProc }, { "previous", PreviousProc }, { "notifyresize", ResizeProc }};char translationsTable[] = "<Key>q: quit() \n \ <Key>Q: quit() \n \ <Message>WM_PROTOCOLS: quit()\n \ <Key>p: previous() \n \ <Key>P: previous() \n \ <Key>n: next() \n \ <Key>N: next() \n \ <Configure>: notifyresize()";/* * X data structures */Colormap xColormap;Display * xDisplay;Pixmap xImagePixmap;Visual * xVisual;XImage * xImage;GC xWinGc;int xImageDepth, xScreen, xRedMask, xGreenMask, xBlueMask, xOffset = 0, yOffset = 0, grabX = -1, grabY = -1;u_char basePixel = 0;/* * TIFF data structures */TIFF * tfFile = NULL;u_long tfImageWidth, tfImageHeight;u_short tfBitsPerSample, tfSamplesPerPixel, tfPlanarConfiguration, tfPhotometricInterpretation, tfGrayResponseUnit, tfImageDepth, tfBytesPerRow;int tfDirectory = 0, tfMultiPage = False;double tfUnitMap, tfGrayResponseUnitMap[] = { -1, -10, -100, -1000, -10000, -100000 };/* * display data structures */double *dRed, *dGreen, *dBlue;/* * shared data structures */u_short * redMap = NULL, *greenMap = NULL, *blueMap = NULL, *grayMap = NULL, colormapSize;u_char * imageMemory;char * fileName;voidmain(argc, argv) int argc; char ** argv;{ XSetWindowAttributes window_attributes; Widget widget_list[3]; Arg args[5]; setbuf(stdout, NULL); setbuf(stderr, NULL); shellWidget = XtInitialize(argv[0], "XTiff", shellOptions, XtNumber(shellOptions), &argc, argv); XSetErrorHandler(XTiffErrorHandler); XtGetApplicationResources(shellWidget, &appData, (XtResourceList) clientResources, (Cardinal) XtNumber(clientResources), (ArgList) NULL, (Cardinal) 0); if ((argc <= 1) || (argc > 2) || appData.help) Usage(); if (appData.verbose == False) { TIFFSetErrorHandler(0); TIFFSetWarningHandler(0); } fileName = argv[1]; xDisplay = XtDisplay(shellWidget); xScreen = DefaultScreen(xDisplay); OpenTIFFFile(); GetTIFFHeader(); SimpleGammaCorrection(); GetVisual(); GetTIFFImage(); /* * Send visual, colormap, depth and iconPixmap to shellWidget. * Sending the visual to the shell is only possible with the advent of R4. */ XtSetArg(args[0], XtNvisual, xVisual); XtSetArg(args[1], XtNcolormap, xColormap); XtSetArg(args[2], XtNdepth, xImageDepth == 1 ? DefaultDepth(xDisplay, xScreen) : xImageDepth); XtSetArg(args[3], XtNiconPixmap, XCreateBitmapFromData(xDisplay, RootWindow(xDisplay, xScreen), xtifficon_bits, xtifficon_width, xtifficon_height)); XtSetArg(args[4], XtNallowShellResize, True); XtSetValues(shellWidget, args, 5); /* * widget instance hierarchy */ formWidget = XtCreateManagedWidget("form", formWidgetClass, shellWidget, formArgs, XtNumber(formArgs)); widget_list[0] = listWidget = XtCreateWidget("list", listWidgetClass, formWidget, listArgs, XtNumber(listArgs)); widget_list[1] = labelWidget = XtCreateWidget("label", labelWidgetClass, formWidget, labelArgs, XtNumber(labelArgs)); widget_list[2] = imageWidget = XtCreateWidget("image", widgetClass, formWidget, imageArgs, XtNumber(imageArgs)); XtManageChildren(widget_list, XtNumber(widget_list)); /* * initial widget sizes - for small images let xtiff size itself */ if (tfImageWidth >= appData.viewportWidth) { XtSetArg(args[0], XtNwidth, appData.viewportWidth); XtSetValues(shellWidget, args, 1); } if (tfImageHeight >= appData.viewportHeight) { XtSetArg(args[0], XtNheight, appData.viewportHeight); XtSetValues(shellWidget, args, 1); } XtSetArg(args[0], XtNwidth, tfImageWidth); XtSetArg(args[1], XtNheight, tfImageHeight); XtSetValues(imageWidget, args, 2); /* * formWidget uses these constraints but they are stored in the children. */ XtSetArg(args[0], XtNfromVert, listWidget); XtSetValues(imageWidget, args, 1); XtSetArg(args[0], XtNfromHoriz, listWidget); XtSetValues(labelWidget, args, 1); SetNameLabel(); XtAddCallback(listWidget, XtNcallback, (XtCallbackProc) SelectProc, (XtPointer) NULL); XtAddActions(actionsTable, XtNumber(actionsTable)); XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(translationsTable)); XtSetValues(formWidget, &args[0], 1); XtSetValues(imageWidget, &args[0], 1); /* * This is intended to be a little faster than going through * the translation manager. */ XtAddEventHandler(imageWidget, ExposureMask | ButtonPressMask | ButtonReleaseMask | Button1MotionMask | KeyPressMask, False, EventProc, NULL); XtRealizeWidget(shellWidget); window_attributes.cursor = XCreateFontCursor(xDisplay, XC_fleur); XChangeWindowAttributes(xDisplay, XtWindow(imageWidget), CWCursor, &window_attributes); CreateXImage(); XtMainLoop();}voidOpenTIFFFile(){ if (tfFile != NULL) TIFFClose(tfFile); if ((tfFile = TIFFOpen(fileName, "r")) == NULL) { fprintf(appData.verbose ? stderr : stdout, "xtiff: can't open %s as a TIFF file\n", fileName); exit(0); } tfMultiPage = (TIFFLastDirectory(tfFile) ? False : True);}voidGetTIFFHeader(){ register int i; if (!TIFFSetDirectory(tfFile, tfDirectory)) { fprintf(stderr, "xtiff: can't seek to directory %d in %s\n", tfDirectory, fileName); exit(0); } TIFFGetField(tfFile, TIFFTAG_IMAGEWIDTH, &tfImageWidth); TIFFGetField(tfFile, TIFFTAG_IMAGELENGTH, &tfImageHeight); /* * If the following tags aren't present then use the TIFF defaults. */ TIFFGetFieldDefaulted(tfFile, TIFFTAG_BITSPERSAMPLE, &tfBitsPerSample); TIFFGetFieldDefaulted(tfFile, TIFFTAG_SAMPLESPERPIXEL, &tfSamplesPerPixel); TIFFGetFieldDefaulted(tfFile, TIFFTAG_PLANARCONFIG, &tfPlanarConfiguration); TIFFGetFieldDefaulted(tfFile, TIFFTAG_GRAYRESPONSEUNIT, &tfGrayResponseUnit); tfUnitMap = tfGrayResponseUnitMap[tfGrayResponseUnit]; colormapSize = 1 << tfBitsPerSample; tfImageDepth = tfBitsPerSample * tfSamplesPerPixel; dRed = (double *) malloc(colormapSize * sizeof(double)); dGreen = (double *) malloc(colormapSize * sizeof(double));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -