diff options
Diffstat (limited to 'tiff/contrib/dbs/xtiff/xtiff.c')
-rwxr-xr-x | tiff/contrib/dbs/xtiff/xtiff.c | 1290 |
1 files changed, 0 insertions, 1290 deletions
diff --git a/tiff/contrib/dbs/xtiff/xtiff.c b/tiff/contrib/dbs/xtiff/xtiff.c deleted file mode 100755 index 97e4ffe..0000000 --- a/tiff/contrib/dbs/xtiff/xtiff.c +++ /dev/null @@ -1,1290 +0,0 @@ -/* - * $Id: xtiff.c,v 1.4 2013-05-02 14:44:29 tgl Exp $ - * - * 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 <stdlib.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) (uint16) ((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) () -#endif - -int 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; - uint32 viewportWidth; - uint32 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; -unsigned char basePixel = 0; - -/* - * TIFF data structures - */ -TIFF * tfFile = NULL; -uint32 tfImageWidth, tfImageHeight; -uint16 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 - */ -uint16 * redMap = NULL, *greenMap = NULL, *blueMap = NULL, - *grayMap = NULL, colormapSize; -char * imageMemory; -char * fileName; - -int -main(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(); - - return 0; -} - -void -OpenTIFFFile() -{ - 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); -} - -void -GetTIFFHeader() -{ - 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)); - dBlue = (double *) malloc(colormapSize * sizeof(double)); - MCHECK(dRed); MCHECK(dGreen); MCHECK(dBlue); - - /* - * If TIFFTAG_PHOTOMETRIC is not present then assign a reasonable default. - * The TIFF 5.0 specification doesn't give a default. - */ - if (!TIFFGetField(tfFile, TIFFTAG_PHOTOMETRIC, - &tfPhotometricInterpretation)) { - if (tfSamplesPerPixel != 1) - tfPhotometricInterpretation = PHOTOMETRIC_RGB; - else if (tfBitsPerSample == 1) - tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK; - else if (TIFFGetField(tfFile, TIFFTAG_COLORMAP, - &redMap, &greenMap, &blueMap)) { - tfPhotometricInterpretation = PHOTOMETRIC_PALETTE; - redMap = greenMap = blueMap = NULL; - } else - tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK; - } - - /* - * Given TIFFTAG_PHOTOMETRIC extract or create the response curves. - */ - switch (tfPhotometricInterpretation) { - case PHOTOMETRIC_RGB: - redMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap); - for (i = 0; i < colormapSize; i++) - dRed[i] = dGreen[i] = dBlue[i] - = (double) SCALE(i, colormapSize - 1); - break; - case PHOTOMETRIC_PALETTE: - if (!TIFFGetField(tfFile, TIFFTAG_COLORMAP, - &redMap, &greenMap, &blueMap)) { - redMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap); - for (i = 0; i < colormapSize; i++) - dRed[i] = dGreen[i] = dBlue[i] - = (double) SCALE(i, colormapSize - 1); - } else { - CheckAndCorrectColormap(); - for (i = 0; i < colormapSize; i++) { - dRed[i] = (double) redMap[i]; - dGreen[i] = (double) greenMap[i]; - dBlue[i] = (double) blueMap[i]; - } - } - break; - case PHOTOMETRIC_MINISWHITE: - redMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap); - for (i = 0; i < colormapSize; i++) - dRed[i] = dGreen[i] = dBlue[i] = (double) - SCALE(colormapSize-1-i, colormapSize-1); - break; - case PHOTOMETRIC_MINISBLACK: - redMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16)); - MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap); - for (i = 0; i < colormapSize; i++) - dRed[i] = dGreen[i] = dBlue[i] = (double) SCALE(i, colormapSize-1); - break; - default: - fprintf(stderr, - "xtiff: can't display photometric interpretation type %d\n", - tfPhotometricInterpretation); - exit(0); - } -} - -void -SetNameLabel() -{ - char buffer[BUFSIZ]; - Arg args[1]; - - if (tfMultiPage) - snprintf(buffer, sizeof(buffer), "%s - page %d", fileName, tfDirectory); - else - snprintf(buffer, sizeof(buffer), "%s", fileName); - XtSetArg(args[0], XtNlabel, buffer); - XtSetValues(labelWidget, args, 1); -} - -/* - * Many programs get TIFF colormaps wrong. They use 8-bit colormaps instead of - * 16-bit colormaps. This function is a heuristic to detect and correct this. - */ -void -CheckAndCorrectColormap() -{ - register int i; - - for (i = 0; i < colormapSize; i++) - if ((redMap[i] > 255) || (greenMap[i] > 255) || (blueMap[i] > 255)) - return; - - for (i = 0; i < colormapSize; i++) { - redMap[i] = SCALE(redMap[i], 255); - greenMap[i] = SCALE(greenMap[i], 255); - blueMap[i] = SCALE(blueMap[i], 255); - } - TIFFWarning(fileName, "Assuming 8-bit colormap"); -} - -void -SimpleGammaCorrection() -{ - register int i; - register double i_gamma = 1.0 / appData.gamma; - - for (i = 0; i < colormapSize; i++) { - if (((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE) - && (i == colormapSize - 1)) - || ((tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK) - && (i == 0))) - redMap[i] = greenMap[i] = blueMap[i] = 0; - else { - redMap[i] = ROUND((pow(dRed[i] / 65535.0, i_gamma) * 65535.0)); - greenMap[i] = ROUND((pow(dGreen[i] / 65535.0, i_gamma) * 65535.0)); - blueMap[i] = ROUND((pow(dBlue[i] / 65535.0, i_gamma) * 65535.0)); - } - } - - free(dRed); free(dGreen); free(dBlue); -} - -static char* classNames[] = { - "StaticGray", - "GrayScale", - "StaticColor", - "PseudoColor", - "TrueColor", - "DirectColor" -}; - -/* - * Current limitation: the visual is set initially by the first file. - * It cannot be changed. - */ -void -GetVisual() -{ - XColor *colors = NULL; - unsigned long *pixels = NULL; - unsigned long i; - - switch (tfImageDepth) { - /* - * X really wants a 32-bit image with the fourth channel unused, - * but the visual structure thinks it's 24-bit. bitmap_unit is 32. - */ - case 32: - case 24: - if (SearchVisualList(24, DirectColor, &xVisual) == False) { - fprintf(stderr, "xtiff: 24-bit DirectColor visual not available\n"); - exit(0); - } - - colors = (XColor *) malloc(3 * colormapSize * sizeof(XColor)); - MCHECK(colors); - - for (i = 0; i < colormapSize; i++) { - colors[i].pixel = (i << 16) + (i << 8) + i; - colors[i].red = redMap[i]; - colors[i].green = greenMap[i]; - colors[i].blue = blueMap[i]; - colors[i].flags = DoRed | DoGreen | DoBlue; - } - - xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen), - xVisual, AllocAll); - XStoreColors(xDisplay, xColormap, colors, colormapSize); - break; - case 8: - case 4: - case 2: - /* - * We assume that systems with 24-bit visuals also have 8-bit visuals. - * We don't promote from 8-bit PseudoColor to 24/32 bit DirectColor. - */ - switch (tfPhotometricInterpretation) { - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - if (SearchVisualList((int) tfImageDepth, GrayScale, &xVisual) == True) - break; - case PHOTOMETRIC_PALETTE: - if (SearchVisualList((int) tfImageDepth, PseudoColor, &xVisual) == True) - break; - default: - fprintf(stderr, "xtiff: Unsupported TIFF/X configuration\n"); - exit(0); - } - - colors = (XColor *) malloc(colormapSize * sizeof(XColor)); - MCHECK(colors); - - for (i = 0; i < colormapSize; i++) { - colors[i].pixel = i; - colors[i].red = redMap[i]; - colors[i].green = greenMap[i]; - colors[i].blue = blueMap[i]; - colors[i].flags = DoRed | DoGreen | DoBlue; - } - - /* - * xtiff's colormap allocation is private. It does not attempt - * to detect whether any existing colormap entries are suitable - * for its use. This will cause colormap flashing. Furthermore, - * background and foreground are taken from the environment. - * For example, the foreground color may be red when the visual - * is GrayScale. If the colormap is completely populated, - * Xt will not be able to allocate fg and bg. - */ - if (tfImageDepth == 8) - xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen), - xVisual, AllocAll); - else { - xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen), - xVisual, AllocNone); - pixels = (unsigned long *) - malloc(colormapSize * sizeof(unsigned long)); - MCHECK(pixels); - (void) XAllocColorCells(xDisplay, xColormap, True, - NULL, 0, pixels, colormapSize); - basePixel = (unsigned char) pixels[0]; - free(pixels); - } - XStoreColors(xDisplay, xColormap, colors, colormapSize); - break; - case 1: - xImageDepth = 1; - xVisual = DefaultVisual(xDisplay, xScreen); - xColormap = DefaultColormap(xDisplay, xScreen); - break; - default: - fprintf(stderr, "xtiff: unsupported image depth %d\n", tfImageDepth); - exit(0); - } - - if (appData.verbose == True) - fprintf(stderr, "%s: Using %d-bit %s visual.\n", - fileName, xImageDepth, classNames[xVisual->class]); - - if (colors != NULL) - free(colors); - if (grayMap != NULL) - free(grayMap); - if (redMap != NULL) - free(redMap); - if (greenMap != NULL) - free(greenMap); - if (blueMap != NULL) - free(blueMap); - - colors = NULL; grayMap = redMap = greenMap = blueMap = NULL; -} - -/* - * Search for an appropriate visual. Promote where necessary. - * Check to make sure that ENOUGH colormap entries are writeable. - * basePixel was determined when XAllocColorCells() contiguously - * allocated enough entries. basePixel is used below in GetTIFFImage. - */ -Boolean -SearchVisualList(image_depth, visual_class, visual) - int image_depth, visual_class; - Visual **visual; -{ - XVisualInfo template_visual, *visual_list, *vl; - int i, n_visuals; - - template_visual.screen = xScreen; - vl = visual_list = XGetVisualInfo(xDisplay, VisualScreenMask, - &template_visual, &n_visuals); - - if (n_visuals == 0) { - fprintf(stderr, "xtiff: visual list not available\n"); - exit(0); - } - - for (i = 0; i < n_visuals; vl++, i++) { - if ((vl->class == visual_class) && (vl->depth >= image_depth) - && (vl->visual->map_entries >= (1 << vl->depth))) { - *visual = vl->visual; - xImageDepth = vl->depth; - xRedMask = vl->red_mask; - xGreenMask = vl->green_mask; - xBlueMask = vl->blue_mask; - XFree((char *) visual_list); - return True; - } - } - - XFree((char *) visual_list); - return False; -} - -void -GetTIFFImage() -{ - int pixel_map[3], red_shift, green_shift, blue_shift; - char *scan_line, *output_p, *input_p; - uint32 i, j; - uint16 s; - - scan_line = (char *) malloc(tfBytesPerRow = TIFFScanlineSize(tfFile)); - MCHECK(scan_line); - - if ((tfImageDepth == 32) || (tfImageDepth == 24)) { - output_p = imageMemory = (char *) - malloc(tfImageWidth * tfImageHeight * 4); - MCHECK(imageMemory); - - /* - * Handle different color masks for different frame buffers. - */ - if (ImageByteOrder(xDisplay) == LSBFirst) { /* DECstation 5000 */ - red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 3 - : (xRedMask == 0xFF0000 ? 2 : (xRedMask == 0xFF00 ? 1 : 0)); - green_shift = pixel_map[1] = xGreenMask == 0xFF000000 ? 3 - : (xGreenMask == 0xFF0000 ? 2 : (xGreenMask == 0xFF00 ? 1 : 0)); - blue_shift = pixel_map[2] = xBlueMask == 0xFF000000 ? 3 - : (xBlueMask == 0xFF0000 ? 2 : (xBlueMask == 0xFF00 ? 1 : 0)); - } else { /* Ardent */ - red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 0 - : (xRedMask == 0xFF0000 ? 1 : (xRedMask == 0xFF00 ? 2 : 3)); - green_shift = pixel_map[0] = xGreenMask == 0xFF000000 ? 0 - : (xGreenMask == 0xFF0000 ? 1 : (xGreenMask == 0xFF00 ? 2 : 3)); - blue_shift = pixel_map[0] = xBlueMask == 0xFF000000 ? 0 - : (xBlueMask == 0xFF0000 ? 1 : (xBlueMask == 0xFF00 ? 2 : 3)); - } - - if (tfPlanarConfiguration == PLANARCONFIG_CONTIG) { - for (i = 0; i < tfImageHeight; i++) { - if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0) - break; - for (input_p = scan_line, j = 0; j < tfImageWidth; j++) { - *(output_p + red_shift) = *input_p++; - *(output_p + green_shift) = *input_p++; - *(output_p + blue_shift) = *input_p++; - output_p += 4; - if (tfSamplesPerPixel == 4) /* skip the fourth channel */ - input_p++; - } - } - } else { - for (s = 0; s < tfSamplesPerPixel; s++) { - if (s == 3) /* skip the fourth channel */ - continue; - for (i = 0; i < tfImageHeight; i++) { - if (TIFFReadScanline(tfFile, scan_line, i, s) < 0) - break; - input_p = scan_line; - output_p = imageMemory + (i*tfImageWidth*4) + pixel_map[s]; - for (j = 0; j < tfImageWidth; j++, output_p += 4) - *output_p = *input_p++; - } - } - } - } else { - if (xImageDepth == tfImageDepth) { - output_p = imageMemory = (char *) - malloc(tfBytesPerRow * tfImageHeight); - MCHECK(imageMemory); - - for (i = 0; i < tfImageHeight; i++, output_p += tfBytesPerRow) - if (TIFFReadScanline(tfFile, output_p, i, 0) < 0) - break; - } else if ((xImageDepth == 8) && (tfImageDepth == 4)) { - output_p = imageMemory = (char *) - malloc(tfBytesPerRow * 2 * tfImageHeight + 2); - MCHECK(imageMemory); - - /* - * If a scanline is of odd size the inner loop below will overshoot. - * This is handled very simply by recalculating the start point at - * each scanline and padding imageMemory a little at the end. - */ - for (i = 0; i < tfImageHeight; i++) { - if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0) - break; - output_p = &imageMemory[i * tfImageWidth]; - input_p = scan_line; - for (j = 0; j < tfImageWidth; j += 2, input_p++) { - *output_p++ = (*input_p >> 4) + basePixel; - *output_p++ = (*input_p & 0xf) + basePixel; - } - } - } else if ((xImageDepth == 8) && (tfImageDepth == 2)) { - output_p = imageMemory = (char *) - malloc(tfBytesPerRow * 4 * tfImageHeight + 4); - MCHECK(imageMemory); - - for (i = 0; i < tfImageHeight; i++) { - if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0) - break; - output_p = &imageMemory[i * tfImageWidth]; - input_p = scan_line; - for (j = 0; j < tfImageWidth; j += 4, input_p++) { - *output_p++ = (*input_p >> 6) + basePixel; - *output_p++ = ((*input_p >> 4) & 3) + basePixel; - *output_p++ = ((*input_p >> 2) & 3) + basePixel; - *output_p++ = (*input_p & 3) + basePixel; - } - } - } else if ((xImageDepth == 4) && (tfImageDepth == 2)) { - output_p = imageMemory = (char *) - malloc(tfBytesPerRow * 2 * tfImageHeight + 2); - MCHECK(imageMemory); - - for (i = 0; i < tfImageHeight; i++) { - if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0) - break; - output_p = &imageMemory[i * tfBytesPerRow * 2]; - input_p = scan_line; - for (j = 0; j < tfImageWidth; j += 4, input_p++) { - *output_p++ = (((*input_p>>6) << 4) - | ((*input_p >> 4) & 3)) + basePixel; - *output_p++ = ((((*input_p>>2) & 3) << 4) - | (*input_p & 3)) + basePixel; - } - } - } else { - fprintf(stderr, - "xtiff: can't handle %d-bit TIFF file on an %d-bit display\n", - tfImageDepth, xImageDepth); - exit(0); - } - } - - free(scan_line); -} - -void -CreateXImage() -{ - XGCValues gc_values; - GC bitmap_gc; - - xOffset = yOffset = 0; - grabX = grabY = -1; - - xImage = XCreateImage(xDisplay, xVisual, xImageDepth, - xImageDepth == 1 ? XYBitmap : ZPixmap, /* offset */ 0, - (char *) imageMemory, tfImageWidth, tfImageHeight, - /* bitmap_pad */ 8, /* bytes_per_line */ 0); - - /* - * libtiff converts LSB data into MSB but doesn't change the FillOrder tag. - */ - if (xImageDepth == 1) - xImage->bitmap_bit_order = MSBFirst; - if (xImageDepth <= 8) - xImage->byte_order = MSBFirst; - - /* - * create an appropriate GC - */ - gc_values.function = GXcopy; - gc_values.plane_mask = AllPlanes; - if (tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK) { - gc_values.foreground = XWhitePixel(xDisplay, xScreen); - gc_values.background = XBlackPixel(xDisplay, xScreen); - } else { - gc_values.foreground = XBlackPixel(xDisplay, xScreen); - gc_values.background = XWhitePixel(xDisplay, xScreen); - } - xWinGc = XCreateGC(xDisplay, XtWindow(shellWidget), - GCFunction | GCPlaneMask | GCForeground | GCBackground, &gc_values); - - /* - * create the pixmap and load the image - */ - if (appData.usePixmap == True) { - xImagePixmap = XCreatePixmap(xDisplay, RootWindow(xDisplay, xScreen), - xImage->width, xImage->height, xImageDepth); - - /* - * According to the O'Reilly X Protocol Reference Manual, page 53, - * "A pixmap depth of one is always supported and listed, but windows - * of depth one might not be supported." Therefore we create a pixmap - * of depth one and use XCopyPlane(). This is idiomatic. - */ - if (xImageDepth == 1) { /* just pass the bits through */ - gc_values.foreground = 1; /* foreground describes set bits */ - gc_values.background = 0; /* background describes clear bits */ - bitmap_gc = XCreateGC(xDisplay, xImagePixmap, - GCForeground | GCBackground, &gc_values); - XPutImage(xDisplay, xImagePixmap, bitmap_gc, xImage, - 0, 0, 0, 0, xImage->width, xImage->height); - } else - XPutImage(xDisplay, xImagePixmap, xWinGc, xImage, - 0, 0, 0, 0, xImage->width, xImage->height); - XDestroyImage(xImage); - free(imageMemory); - } -} - -XtCallbackProc -SelectProc(w, unused_1, unused_2) - Widget w; - caddr_t unused_1; - caddr_t unused_2; -{ - XawListReturnStruct *list_return; - - list_return = XawListShowCurrent(w); - - switch (list_return->list_index) { - case ButtonQuit: - QuitProc(); - break; - case ButtonPreviousPage: - PreviousProc(); - break; - case ButtonNextPage: - NextProc(); - break; - default: - fprintf(stderr, "error in SelectProc\n"); - exit(0); - } - XawListUnhighlight(w); -} - -void -QuitProc(void) -{ - exit(0); -} - -void -NextProc() -{ - PageProc(ButtonNextPage); -} - -void -PreviousProc() -{ - PageProc(ButtonPreviousPage); -} - -void -PageProc(direction) - int direction; -{ - XEvent fake_event; - Arg args[4]; - - switch (direction) { - case ButtonPreviousPage: - if (tfDirectory > 0) - TIFFSetDirectory(tfFile, --tfDirectory); - else - return; - break; - case ButtonNextPage: - if (TIFFReadDirectory(tfFile) == True) - tfDirectory++; - else - return; - break; - default: - fprintf(stderr, "error in PageProc\n"); - exit(0); - } - - xOffset = yOffset = 0; - grabX = grabY = -1; - - GetTIFFHeader(); - SetNameLabel(); - GetTIFFImage(); - - if (appData.usePixmap == True) - XFreePixmap(xDisplay, xImagePixmap); - else - XDestroyImage(xImage); - - CreateXImage(); - - /* - * Using XtSetValues() to set the widget size causes a resize. - * This resize gets propagated up to the parent shell. - * In order to disable this visually disconcerting effect, - * shell resizing is temporarily disabled. - */ - XtSetArg(args[0], XtNallowShellResize, False); - XtSetValues(shellWidget, args, 1); - - XtSetArg(args[0], XtNwidth, tfImageWidth); - XtSetArg(args[1], XtNheight, tfImageHeight); - XtSetValues(imageWidget, args, 2); - - XtSetArg(args[0], XtNallowShellResize, True); - XtSetValues(shellWidget, args, 1); - - XClearWindow(xDisplay, XtWindow(imageWidget)); - - fake_event.type = Expose; - fake_event.xexpose.x = fake_event.xexpose.y = 0; - fake_event.xexpose.width = tfImageWidth; /* the window will clip */ - fake_event.xexpose.height = tfImageHeight; - EventProc(imageWidget, NULL, &fake_event); -} - -void -EventProc(widget, unused, event) - Widget widget; - caddr_t unused; - XEvent *event; -{ - int ih, iw, ww, wh, sx, sy, w, h, dx, dy; - Dimension w_width, w_height; - XEvent next_event; - Arg args[2]; - - if (event->type == MappingNotify) { - XRefreshKeyboardMapping((XMappingEvent *) event); - return; - } - - if (!XtIsRealized(widget)) - return; - - if ((event->type == ButtonPress) || (event->type == ButtonRelease)) - if (event->xbutton.button != Button1) - return; - - iw = tfImageWidth; /* avoid sign problems */ - ih = tfImageHeight; - - /* - * The grabX and grabY variables record where the user grabbed the image. - * They also record whether the mouse button is down or not. - */ - if (event->type == ButtonPress) { - grabX = event->xbutton.x; - grabY = event->xbutton.y; - return; - } - - /* - * imageWidget is a Core widget and doesn't get resized. - * So we calculate the size of its viewport here. - */ - XtSetArg(args[0], XtNwidth, &w_width); - XtSetArg(args[1], XtNheight, &w_height); - XtGetValues(shellWidget, args, 2); - ww = w_width; - wh = w_height; - XtGetValues(listWidget, args, 2); - wh -= w_height; - - switch (event->type) { - case Expose: - dx = event->xexpose.x; - dy = event->xexpose.y; - sx = dx + xOffset; - sy = dy + yOffset; - w = MIN(event->xexpose.width, iw); - h = MIN(event->xexpose.height, ih); - break; - case KeyPress: - if ((grabX >= 0) || (grabY >= 0)) /* Mouse button is still down */ - return; - switch (XLookupKeysym((XKeyEvent *) event, /* KeySyms index */ 0)) { - case XK_Up: - if (ih < wh) /* Don't scroll if the window fits the image. */ - return; - sy = yOffset + appData.translate; - sy = MIN(ih - wh, sy); - if (sy == yOffset) /* Filter redundant stationary refreshes. */ - return; - yOffset = sy; - sx = xOffset; - dx = dy = 0; - w = ww; h = wh; - break; - case XK_Down: - if (ih < wh) - return; - sy = yOffset - appData.translate; - sy = MAX(sy, 0); - if (sy == yOffset) - return; - yOffset = sy; - sx = xOffset; - dx = dy = 0; - w = ww; h = wh; - break; - case XK_Left: - if (iw < ww) - return; - sx = xOffset + appData.translate; - sx = MIN(iw - ww, sx); - if (sx == xOffset) - return; - xOffset = sx; - sy = yOffset; - dx = dy = 0; - w = ww; h = wh; - break; - case XK_Right: - if (iw < ww) - return; - sx = xOffset - appData.translate; - sx = MAX(sx, 0); - if (sx == xOffset) - return; - xOffset = sx; - sy = yOffset; - dx = dy = 0; - w = ww; h = wh; - break; - default: - return; - } - break; - case MotionNotify: - /* - * MotionEvent compression. Ignore multiple motion events. - * Ignore motion events if the mouse button is up. - */ - if (XPending(xDisplay)) /* Xlib doesn't flush the output buffer */ - if (XtPeekEvent(&next_event)) - if (next_event.type == MotionNotify) - return; - if ((grabX < 0) || (grabY < 0)) - return; - sx = xOffset + grabX - (int) event->xmotion.x; - if (sx >= (iw - ww)) /* clamp x motion but allow y motion */ - sx = iw - ww; - sx = MAX(sx, 0); - sy = yOffset + grabY - (int) event->xmotion.y; - if (sy >= (ih - wh)) /* clamp y motion but allow x motion */ - sy = ih - wh; - sy = MAX(sy, 0); - if ((sx == xOffset) && (sy == yOffset)) - return; - dx = dy = 0; - w = ww; h = wh; - break; - case ButtonRelease: - xOffset = xOffset + grabX - (int) event->xbutton.x; - xOffset = MIN(iw - ww, xOffset); - xOffset = MAX(xOffset, 0); - yOffset = yOffset + grabY - (int) event->xbutton.y; - yOffset = MIN(ih - wh, yOffset); - yOffset = MAX(yOffset, 0); - grabX = grabY = -1; - default: - return; - } - - if (appData.usePixmap == True) { - if (xImageDepth == 1) - XCopyPlane(xDisplay, xImagePixmap, XtWindow(widget), - xWinGc, sx, sy, w, h, dx, dy, 1); - else - XCopyArea(xDisplay, xImagePixmap, XtWindow(widget), - xWinGc, sx, sy, w, h, dx, dy); - } else - XPutImage(xDisplay, XtWindow(widget), xWinGc, xImage, - sx, sy, dx, dy, w, h); -} - -void -ResizeProc() -{ - Dimension w_width, w_height; - int xo, yo, ww, wh; - XEvent fake_event; - Arg args[2]; - - if ((xOffset == 0) && (yOffset == 0)) - return; - - XtSetArg(args[0], XtNwidth, &w_width); - XtSetArg(args[1], XtNheight, &w_height); - XtGetValues(shellWidget, args, 2); - ww = w_width; - wh = w_height; - XtGetValues(listWidget, args, 2); - wh -= w_height; - - xo = xOffset; yo = yOffset; - - if ((xOffset + ww) >= tfImageWidth) - xOffset = MAX((int) tfImageWidth - ww, 0); - if ((yOffset + wh) >= tfImageHeight) - yOffset = MAX((int) tfImageHeight - wh, 0); - - /* - * Send an ExposeEvent if the origin changed. - * We have to do this because of the use and semantics of bit gravity. - */ - if ((xo != xOffset) || (yo != yOffset)) { - fake_event.type = Expose; - fake_event.xexpose.x = fake_event.xexpose.y = 0; - fake_event.xexpose.width = tfImageWidth; - fake_event.xexpose.height = tfImageHeight; - EventProc(imageWidget, NULL, &fake_event); - } -} - -int -XTiffErrorHandler(display, error_event) - Display *display; - XErrorEvent *error_event; -{ - char message[80]; - - /* - * Some X servers limit the size of pixmaps. - */ - if ((error_event->error_code == BadAlloc) - && (error_event->request_code == X_CreatePixmap)) - fprintf(stderr, "xtiff: requested pixmap too big for display\n"); - else { - XGetErrorText(display, error_event->error_code, message, 80); - fprintf(stderr, "xtiff: error code %s\n", message); - } - - exit(0); -} - -void -Usage() -{ - fprintf(stderr, "Usage xtiff: [options] tiff-file\n"); - fprintf(stderr, "\tstandard Xt options\n"); - fprintf(stderr, "\t[-help]\n"); - fprintf(stderr, "\t[-gamma gamma]\n"); - fprintf(stderr, "\t[-usePixmap (True | False)]\n"); - fprintf(stderr, "\t[-viewportWidth pixels]\n"); - fprintf(stderr, "\t[-viewportHeight pixels]\n"); - fprintf(stderr, "\t[-translate pixels]\n"); - fprintf(stderr, "\t[-verbose (True | False)]\n"); - exit(0); -} - -/* vim: set ts=8 sts=8 sw=8 noet: */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ |