|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* $Id: xtiff.c,v 1.3 2010-06-08 18:55:15 bfriesen Exp $
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* xtiff - view a TIFF file in an X window
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Dan Sears
|
|
roentgen |
b75cab |
* Chris Sears
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* All Rights Reserved
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Permission to use, copy, modify, and distribute this software and its
|
|
roentgen |
b75cab |
* documentation for any purpose and without fee is hereby granted,
|
|
roentgen |
b75cab |
* provided that the above copyright notice appear in all copies and that
|
|
roentgen |
b75cab |
* both that copyright notice and this permission notice appear in
|
|
roentgen |
b75cab |
* supporting documentation, and that the name of Digital not be
|
|
roentgen |
b75cab |
* used in advertising or publicity pertaining to distribution of the
|
|
roentgen |
b75cab |
* software without specific, written prior permission.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
roentgen |
b75cab |
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
roentgen |
b75cab |
* DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
roentgen |
b75cab |
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
roentgen |
b75cab |
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
roentgen |
b75cab |
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
roentgen |
b75cab |
* SOFTWARE.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Revision 1.0 90/05/07
|
|
roentgen |
b75cab |
* Initial release.
|
|
roentgen |
b75cab |
* Revision 2.0 90/12/20
|
|
roentgen |
b75cab |
* Converted to use the Athena Widgets and the Xt Intrinsics.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Notes:
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* According to the TIFF 5.0 Specification, it is possible to have
|
|
roentgen |
b75cab |
* both a TIFFTAG_COLORMAP and a TIFFTAG_COLORRESPONSECURVE. This
|
|
roentgen |
b75cab |
* doesn't make sense since a TIFFTAG_COLORMAP is 16 bits wide and
|
|
roentgen |
b75cab |
* a TIFFTAG_COLORRESPONSECURVE is tfBitsPerSample bits wide for each
|
|
roentgen |
b75cab |
* channel. This is probably a bug in the specification.
|
|
roentgen |
b75cab |
* In this case, TIFFTAG_COLORRESPONSECURVE is ignored.
|
|
roentgen |
b75cab |
* This might make sense if TIFFTAG_COLORMAP was 8 bits wide.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* TIFFTAG_COLORMAP is often incorrectly written as ranging from
|
|
roentgen |
b75cab |
* 0 to 255 rather than from 0 to 65535. CheckAndCorrectColormap()
|
|
roentgen |
b75cab |
* takes care of this.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Only ORIENTATION_TOPLEFT is supported correctly. This is the
|
|
roentgen |
b75cab |
* default TIFF and X orientation. Other orientations will be
|
|
roentgen |
b75cab |
* displayed incorrectly.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* There is no support for or use of 3/3/2 DirectColor visuals.
|
|
roentgen |
b75cab |
* TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE are not supported.
|
|
roentgen |
b75cab |
*
|
|
roentgen |
b75cab |
* Only TIFFTAG_BITSPERSAMPLE values that are 1, 2, 4 or 8 are supported.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
#include <math.h></math.h>
|
|
roentgen |
b75cab |
#include <stdio.h></stdio.h>
|
|
roentgen |
b75cab |
#include <stdlib.h></stdlib.h>
|
|
roentgen |
b75cab |
#include <tiffio.h></tiffio.h>
|
|
roentgen |
b75cab |
#include <x11 xatom.h=""></x11>
|
|
roentgen |
b75cab |
#include <x11 intrinsic.h=""></x11>
|
|
roentgen |
b75cab |
#include <x11 stringdefs.h=""></x11>
|
|
roentgen |
b75cab |
#include <x11 xproto.h=""></x11>
|
|
roentgen |
b75cab |
#include <x11 shell.h=""></x11>
|
|
roentgen |
b75cab |
#include <x11 form.h="" xaw=""></x11>
|
|
roentgen |
b75cab |
#include <x11 list.h="" xaw=""></x11>
|
|
roentgen |
b75cab |
#include <x11 label.h="" xaw=""></x11>
|
|
roentgen |
b75cab |
#include <x11 cursorfont.h=""></x11>
|
|
roentgen |
b75cab |
#define XK_MISCELLANY
|
|
roentgen |
b75cab |
#include <x11 keysymdef.h=""></x11>
|
|
roentgen |
b75cab |
#include "xtifficon.h"
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#define TIFF_GAMMA "2.2" /* default gamma from the TIFF 5.0 spec */
|
|
roentgen |
b75cab |
#define ROUND(x) (uint16) ((x) + 0.5)
|
|
roentgen |
b75cab |
#define SCALE(x, s) (((x) * 65535L) / (s))
|
|
roentgen |
b75cab |
#define MCHECK(m) if (!m) { fprintf(stderr, "malloc failed\n"); exit(0); }
|
|
roentgen |
b75cab |
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
roentgen |
b75cab |
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
roentgen |
b75cab |
#define VIEWPORT_WIDTH 700
|
|
roentgen |
b75cab |
#define VIEWPORT_HEIGHT 500
|
|
roentgen |
b75cab |
#define KEY_TRANSLATE 20
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
#ifdef __STDC__
|
|
roentgen |
b75cab |
#define PP(args) args
|
|
roentgen |
b75cab |
#else
|
|
roentgen |
b75cab |
#define PP(args) ()
|
|
roentgen |
b75cab |
#endif
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int main PP((int argc, char **argv));
|
|
roentgen |
b75cab |
void OpenTIFFFile PP((void));
|
|
roentgen |
b75cab |
void GetTIFFHeader PP((void));
|
|
roentgen |
b75cab |
void SetNameLabel PP((void));
|
|
roentgen |
b75cab |
void CheckAndCorrectColormap PP((void));
|
|
roentgen |
b75cab |
void SimpleGammaCorrection PP((void));
|
|
roentgen |
b75cab |
void GetVisual PP((void));
|
|
roentgen |
b75cab |
Boolean SearchVisualList PP((int image_depth,
|
|
roentgen |
b75cab |
int visual_class, Visual **visual));
|
|
roentgen |
b75cab |
void GetTIFFImage PP((void));
|
|
roentgen |
b75cab |
void CreateXImage PP((void));
|
|
roentgen |
b75cab |
XtCallbackProc SelectProc PP((Widget w, caddr_t unused_1, caddr_t unused_2));
|
|
roentgen |
b75cab |
void QuitProc PP((void));
|
|
roentgen |
b75cab |
void NextProc PP((void));
|
|
roentgen |
b75cab |
void PreviousProc PP((void));
|
|
roentgen |
b75cab |
void PageProc PP((int direction));
|
|
roentgen |
b75cab |
void EventProc PP((Widget widget, caddr_t unused, XEvent *event));
|
|
roentgen |
b75cab |
void ResizeProc PP((void));
|
|
roentgen |
b75cab |
int XTiffErrorHandler PP((Display *display, XErrorEvent *error_event));
|
|
roentgen |
b75cab |
void Usage PP((void));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int xtVersion = XtSpecificationRelease; /* xtiff depends on R4 or higher */
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Xt data structures
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
Widget shellWidget, formWidget, listWidget, labelWidget, imageWidget;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
enum { ButtonQuit = 0, ButtonPreviousPage = 1, ButtonNextPage = 2 };
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
String buttonStrings[] = { "Quit", "Previous", "Next" };
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static XrmOptionDescRec shellOptions[] = {
|
|
roentgen |
b75cab |
{ "-help", "*help", XrmoptionNoArg, (caddr_t) "True" },
|
|
roentgen |
b75cab |
{ "-gamma", "*gamma", XrmoptionSepArg, NULL },
|
|
roentgen |
b75cab |
{ "-usePixmap", "*usePixmap", XrmoptionSepArg, NULL },
|
|
roentgen |
b75cab |
{ "-viewportWidth", "*viewportWidth", XrmoptionSepArg, NULL },
|
|
roentgen |
b75cab |
{ "-viewportHeight", "*viewportHeight", XrmoptionSepArg, NULL },
|
|
roentgen |
b75cab |
{ "-translate", "*translate", XrmoptionSepArg, NULL },
|
|
roentgen |
b75cab |
{ "-verbose", "*verbose", XrmoptionSepArg, NULL }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
typedef struct {
|
|
roentgen |
b75cab |
Boolean help;
|
|
roentgen |
b75cab |
float gamma;
|
|
roentgen |
b75cab |
Boolean usePixmap;
|
|
roentgen |
b75cab |
uint32 viewportWidth;
|
|
roentgen |
b75cab |
uint32 viewportHeight;
|
|
roentgen |
b75cab |
int translate;
|
|
roentgen |
b75cab |
Boolean verbose;
|
|
roentgen |
b75cab |
} AppData, *AppDataPtr;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
AppData appData;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtResource clientResources[] = {
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
"help", XtCBoolean, XtRBoolean, sizeof(Boolean),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, help), XtRImmediate, (XtPointer) False
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"gamma", "Gamma", XtRFloat, sizeof(float),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, gamma), XtRString, (XtPointer) TIFF_GAMMA
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"usePixmap", "UsePixmap", XtRBoolean, sizeof(Boolean),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, usePixmap), XtRImmediate, (XtPointer) True
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"viewportWidth", "ViewportWidth", XtRInt, sizeof(int),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, viewportWidth), XtRImmediate,
|
|
roentgen |
b75cab |
(XtPointer) VIEWPORT_WIDTH
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"viewportHeight", "ViewportHeight", XtRInt, sizeof(int),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, viewportHeight), XtRImmediate,
|
|
roentgen |
b75cab |
(XtPointer) VIEWPORT_HEIGHT
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"translate", "Translate", XtRInt, sizeof(int),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, translate), XtRImmediate, (XtPointer) KEY_TRANSLATE
|
|
roentgen |
b75cab |
}, {
|
|
roentgen |
b75cab |
"verbose", "Verbose", XtRBoolean, sizeof(Boolean),
|
|
roentgen |
b75cab |
XtOffset(AppDataPtr, verbose), XtRImmediate, (XtPointer) True
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
Arg formArgs[] = {
|
|
roentgen |
b75cab |
{ XtNresizable, True }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
Arg listArgs[] = {
|
|
roentgen |
b75cab |
{ XtNresizable, False },
|
|
roentgen |
b75cab |
{ XtNborderWidth, 0 },
|
|
roentgen |
b75cab |
{ XtNdefaultColumns, 3 },
|
|
roentgen |
b75cab |
{ XtNforceColumns, True },
|
|
roentgen |
b75cab |
{ XtNlist, (int) buttonStrings },
|
|
roentgen |
b75cab |
{ XtNnumberStrings, XtNumber(buttonStrings) },
|
|
roentgen |
b75cab |
{ XtNtop, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNleft, XtChainLeft },
|
|
roentgen |
b75cab |
{ XtNbottom, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNright, XtChainLeft }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
Arg labelArgs[] = {
|
|
roentgen |
b75cab |
{ XtNresizable, False },
|
|
roentgen |
b75cab |
{ XtNwidth, 200 },
|
|
roentgen |
b75cab |
{ XtNborderWidth, 0 },
|
|
roentgen |
b75cab |
{ XtNjustify, XtJustifyLeft },
|
|
roentgen |
b75cab |
{ XtNtop, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNleft, XtChainLeft },
|
|
roentgen |
b75cab |
{ XtNbottom, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNright, XtChainLeft }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
Arg imageArgs[] = {
|
|
roentgen |
b75cab |
{ XtNresizable, True },
|
|
roentgen |
b75cab |
{ XtNborderWidth, 0 },
|
|
roentgen |
b75cab |
{ XtNtop, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNleft, XtChainLeft },
|
|
roentgen |
b75cab |
{ XtNbottom, XtChainTop },
|
|
roentgen |
b75cab |
{ XtNright, XtChainLeft }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtActionsRec actionsTable[] = {
|
|
roentgen |
b75cab |
{ "quit", QuitProc },
|
|
roentgen |
b75cab |
{ "next", NextProc },
|
|
roentgen |
b75cab |
{ "previous", PreviousProc },
|
|
roentgen |
b75cab |
{ "notifyresize", ResizeProc }
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
char translationsTable[] = "<key>q: quit() \n \</key>
|
|
roentgen |
b75cab |
<key>Q: quit() \n \</key>
|
|
roentgen |
b75cab |
<message>WM_PROTOCOLS: quit()\n \</message>
|
|
roentgen |
b75cab |
<key>p: previous() \n \</key>
|
|
roentgen |
b75cab |
<key>P: previous() \n \</key>
|
|
roentgen |
b75cab |
<key>n: next() \n \</key>
|
|
roentgen |
b75cab |
<key>N: next() \n \</key>
|
|
roentgen |
b75cab |
<configure>: notifyresize()";</configure>
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* X data structures
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
Colormap xColormap;
|
|
roentgen |
b75cab |
Display * xDisplay;
|
|
roentgen |
b75cab |
Pixmap xImagePixmap;
|
|
roentgen |
b75cab |
Visual * xVisual;
|
|
roentgen |
b75cab |
XImage * xImage;
|
|
roentgen |
b75cab |
GC xWinGc;
|
|
roentgen |
b75cab |
int xImageDepth, xScreen, xRedMask, xGreenMask, xBlueMask,
|
|
roentgen |
b75cab |
xOffset = 0, yOffset = 0, grabX = -1, grabY = -1;
|
|
roentgen |
b75cab |
unsigned char basePixel = 0;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* TIFF data structures
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
TIFF * tfFile = NULL;
|
|
roentgen |
b75cab |
uint32 tfImageWidth, tfImageHeight;
|
|
roentgen |
b75cab |
uint16 tfBitsPerSample, tfSamplesPerPixel, tfPlanarConfiguration,
|
|
roentgen |
b75cab |
tfPhotometricInterpretation, tfGrayResponseUnit,
|
|
roentgen |
b75cab |
tfImageDepth, tfBytesPerRow;
|
|
roentgen |
b75cab |
int tfDirectory = 0, tfMultiPage = False;
|
|
roentgen |
b75cab |
double tfUnitMap, tfGrayResponseUnitMap[] = {
|
|
roentgen |
b75cab |
-1, -10, -100, -1000, -10000, -100000
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* display data structures
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
double *dRed, *dGreen, *dBlue;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* shared data structures
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
uint16 * redMap = NULL, *greenMap = NULL, *blueMap = NULL,
|
|
roentgen |
b75cab |
*grayMap = NULL, colormapSize;
|
|
roentgen |
b75cab |
char * imageMemory;
|
|
roentgen |
b75cab |
char * fileName;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
main(int argc, char **argv)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XSetWindowAttributes window_attributes;
|
|
roentgen |
b75cab |
Widget widget_list[3];
|
|
roentgen |
b75cab |
Arg args[5];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
setbuf(stdout, NULL); setbuf(stderr, NULL);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
shellWidget = XtInitialize(argv[0], "XTiff", shellOptions,
|
|
roentgen |
b75cab |
XtNumber(shellOptions), &argc, argv);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XSetErrorHandler(XTiffErrorHandler);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtGetApplicationResources(shellWidget, &appData,
|
|
roentgen |
b75cab |
(XtResourceList) clientResources, (Cardinal) XtNumber(clientResources),
|
|
roentgen |
b75cab |
(ArgList) NULL, (Cardinal) 0);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((argc <= 1) || (argc > 2) || appData.help)
|
|
roentgen |
b75cab |
Usage();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (appData.verbose == False) {
|
|
roentgen |
b75cab |
TIFFSetErrorHandler(0);
|
|
roentgen |
b75cab |
TIFFSetWarningHandler(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
fileName = argv[1];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xDisplay = XtDisplay(shellWidget);
|
|
roentgen |
b75cab |
xScreen = DefaultScreen(xDisplay);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
OpenTIFFFile();
|
|
roentgen |
b75cab |
GetTIFFHeader();
|
|
roentgen |
b75cab |
SimpleGammaCorrection();
|
|
roentgen |
b75cab |
GetVisual();
|
|
roentgen |
b75cab |
GetTIFFImage();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Send visual, colormap, depth and iconPixmap to shellWidget.
|
|
roentgen |
b75cab |
* Sending the visual to the shell is only possible with the advent of R4.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNvisual, xVisual);
|
|
roentgen |
b75cab |
XtSetArg(args[1], XtNcolormap, xColormap);
|
|
roentgen |
b75cab |
XtSetArg(args[2], XtNdepth,
|
|
roentgen |
b75cab |
xImageDepth == 1 ? DefaultDepth(xDisplay, xScreen) : xImageDepth);
|
|
roentgen |
b75cab |
XtSetArg(args[3], XtNiconPixmap,
|
|
roentgen |
b75cab |
XCreateBitmapFromData(xDisplay, RootWindow(xDisplay, xScreen),
|
|
roentgen |
b75cab |
xtifficon_bits, xtifficon_width, xtifficon_height));
|
|
roentgen |
b75cab |
XtSetArg(args[4], XtNallowShellResize, True);
|
|
roentgen |
b75cab |
XtSetValues(shellWidget, args, 5);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* widget instance hierarchy
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
formWidget = XtCreateManagedWidget("form", formWidgetClass,
|
|
roentgen |
b75cab |
shellWidget, formArgs, XtNumber(formArgs));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
widget_list[0] = listWidget = XtCreateWidget("list",
|
|
roentgen |
b75cab |
listWidgetClass, formWidget, listArgs, XtNumber(listArgs));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
widget_list[1] = labelWidget = XtCreateWidget("label",
|
|
roentgen |
b75cab |
labelWidgetClass, formWidget, labelArgs, XtNumber(labelArgs));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
widget_list[2] = imageWidget = XtCreateWidget("image",
|
|
roentgen |
b75cab |
widgetClass, formWidget, imageArgs, XtNumber(imageArgs));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtManageChildren(widget_list, XtNumber(widget_list));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* initial widget sizes - for small images let xtiff size itself
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (tfImageWidth >= appData.viewportWidth) {
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNwidth, appData.viewportWidth);
|
|
roentgen |
b75cab |
XtSetValues(shellWidget, args, 1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
if (tfImageHeight >= appData.viewportHeight) {
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNheight, appData.viewportHeight);
|
|
roentgen |
b75cab |
XtSetValues(shellWidget, args, 1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNwidth, tfImageWidth);
|
|
roentgen |
b75cab |
XtSetArg(args[1], XtNheight, tfImageHeight);
|
|
roentgen |
b75cab |
XtSetValues(imageWidget, args, 2);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* formWidget uses these constraints but they are stored in the children.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNfromVert, listWidget);
|
|
roentgen |
b75cab |
XtSetValues(imageWidget, args, 1);
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNfromHoriz, listWidget);
|
|
roentgen |
b75cab |
XtSetValues(labelWidget, args, 1);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
SetNameLabel();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtAddCallback(listWidget, XtNcallback, (XtCallbackProc) SelectProc,
|
|
roentgen |
b75cab |
(XtPointer) NULL);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtAddActions(actionsTable, XtNumber(actionsTable));
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNtranslations,
|
|
roentgen |
b75cab |
XtParseTranslationTable(translationsTable));
|
|
roentgen |
b75cab |
XtSetValues(formWidget, &args[0], 1);
|
|
roentgen |
b75cab |
XtSetValues(imageWidget, &args[0], 1);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* This is intended to be a little faster than going through
|
|
roentgen |
b75cab |
* the translation manager.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
XtAddEventHandler(imageWidget, ExposureMask | ButtonPressMask
|
|
roentgen |
b75cab |
| ButtonReleaseMask | Button1MotionMask | KeyPressMask,
|
|
roentgen |
b75cab |
False, EventProc, NULL);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtRealizeWidget(shellWidget);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
window_attributes.cursor = XCreateFontCursor(xDisplay, XC_fleur);
|
|
roentgen |
b75cab |
XChangeWindowAttributes(xDisplay, XtWindow(imageWidget),
|
|
roentgen |
b75cab |
CWCursor, &window_attributes);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
CreateXImage();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtMainLoop();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
return 0;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
OpenTIFFFile()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
if (tfFile != NULL)
|
|
roentgen |
b75cab |
TIFFClose(tfFile);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((tfFile = TIFFOpen(fileName, "r")) == NULL) {
|
|
roentgen |
b75cab |
fprintf(appData.verbose ? stderr : stdout,
|
|
roentgen |
b75cab |
"xtiff: can't open %s as a TIFF file\n", fileName);
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
tfMultiPage = (TIFFLastDirectory(tfFile) ? False : True);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
GetTIFFHeader()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
register int i;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (!TIFFSetDirectory(tfFile, tfDirectory)) {
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: can't seek to directory %d in %s\n",
|
|
roentgen |
b75cab |
tfDirectory, fileName);
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
TIFFGetField(tfFile, TIFFTAG_IMAGEWIDTH, &tfImageWidth);
|
|
roentgen |
b75cab |
TIFFGetField(tfFile, TIFFTAG_IMAGELENGTH, &tfImageHeight);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* If the following tags aren't present then use the TIFF defaults.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tfFile, TIFFTAG_BITSPERSAMPLE, &tfBitsPerSample);
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tfFile, TIFFTAG_SAMPLESPERPIXEL, &tfSamplesPerPixel);
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tfFile, TIFFTAG_PLANARCONFIG, &tfPlanarConfiguration);
|
|
roentgen |
b75cab |
TIFFGetFieldDefaulted(tfFile, TIFFTAG_GRAYRESPONSEUNIT, &tfGrayResponseUnit);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
tfUnitMap = tfGrayResponseUnitMap[tfGrayResponseUnit];
|
|
roentgen |
b75cab |
colormapSize = 1 << tfBitsPerSample;
|
|
roentgen |
b75cab |
tfImageDepth = tfBitsPerSample * tfSamplesPerPixel;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
dRed = (double *) malloc(colormapSize * sizeof(double));
|
|
roentgen |
b75cab |
dGreen = (double *) malloc(colormapSize * sizeof(double));
|
|
roentgen |
b75cab |
dBlue = (double *) malloc(colormapSize * sizeof(double));
|
|
roentgen |
b75cab |
MCHECK(dRed); MCHECK(dGreen); MCHECK(dBlue);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* If TIFFTAG_PHOTOMETRIC is not present then assign a reasonable default.
|
|
roentgen |
b75cab |
* The TIFF 5.0 specification doesn't give a default.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (!TIFFGetField(tfFile, TIFFTAG_PHOTOMETRIC,
|
|
roentgen |
b75cab |
&tfPhotometricInterpretation)) {
|
|
roentgen |
b75cab |
if (tfSamplesPerPixel != 1)
|
|
roentgen |
b75cab |
tfPhotometricInterpretation = PHOTOMETRIC_RGB;
|
|
roentgen |
b75cab |
else if (tfBitsPerSample == 1)
|
|
roentgen |
b75cab |
tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
|
|
roentgen |
b75cab |
else if (TIFFGetField(tfFile, TIFFTAG_COLORMAP,
|
|
roentgen |
b75cab |
&redMap, &greenMap, &blueMap)) {
|
|
roentgen |
b75cab |
tfPhotometricInterpretation = PHOTOMETRIC_PALETTE;
|
|
roentgen |
b75cab |
redMap = greenMap = blueMap = NULL;
|
|
roentgen |
b75cab |
} else
|
|
roentgen |
b75cab |
tfPhotometricInterpretation = PHOTOMETRIC_MINISBLACK;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Given TIFFTAG_PHOTOMETRIC extract or create the response curves.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
switch (tfPhotometricInterpretation) {
|
|
roentgen |
b75cab |
case PHOTOMETRIC_RGB:
|
|
roentgen |
b75cab |
redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++)
|
|
roentgen |
b75cab |
dRed[i] = dGreen[i] = dBlue[i]
|
|
roentgen |
b75cab |
= (double) SCALE(i, colormapSize - 1);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_PALETTE:
|
|
roentgen |
b75cab |
if (!TIFFGetField(tfFile, TIFFTAG_COLORMAP,
|
|
roentgen |
b75cab |
&redMap, &greenMap, &blueMap)) {
|
|
roentgen |
b75cab |
redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++)
|
|
roentgen |
b75cab |
dRed[i] = dGreen[i] = dBlue[i]
|
|
roentgen |
b75cab |
= (double) SCALE(i, colormapSize - 1);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
CheckAndCorrectColormap();
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++) {
|
|
roentgen |
b75cab |
dRed[i] = (double) redMap[i];
|
|
roentgen |
b75cab |
dGreen[i] = (double) greenMap[i];
|
|
roentgen |
b75cab |
dBlue[i] = (double) blueMap[i];
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISWHITE:
|
|
roentgen |
b75cab |
redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++)
|
|
roentgen |
b75cab |
dRed[i] = dGreen[i] = dBlue[i] = (double)
|
|
roentgen |
b75cab |
SCALE(colormapSize-1-i, colormapSize-1);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISBLACK:
|
|
roentgen |
b75cab |
redMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
greenMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
blueMap = (uint16 *) malloc(colormapSize * sizeof(uint16));
|
|
roentgen |
b75cab |
MCHECK(redMap); MCHECK(greenMap); MCHECK(blueMap);
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++)
|
|
roentgen |
b75cab |
dRed[i] = dGreen[i] = dBlue[i] = (double) SCALE(i, colormapSize-1);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
fprintf(stderr,
|
|
roentgen |
b75cab |
"xtiff: can't display photometric interpretation type %d\n",
|
|
roentgen |
b75cab |
tfPhotometricInterpretation);
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
SetNameLabel()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
char buffer[BUFSIZ];
|
|
roentgen |
b75cab |
Arg args[1];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (tfMultiPage)
|
|
roentgen |
b75cab |
sprintf(buffer, "%s - page %d", fileName, tfDirectory);
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
strcpy(buffer, fileName);
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNlabel, buffer);
|
|
roentgen |
b75cab |
XtSetValues(labelWidget, args, 1);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Many programs get TIFF colormaps wrong. They use 8-bit colormaps instead of
|
|
roentgen |
b75cab |
* 16-bit colormaps. This function is a heuristic to detect and correct this.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
CheckAndCorrectColormap()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
register int i;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++)
|
|
roentgen |
b75cab |
if ((redMap[i] > 255) || (greenMap[i] > 255) || (blueMap[i] > 255))
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++) {
|
|
roentgen |
b75cab |
redMap[i] = SCALE(redMap[i], 255);
|
|
roentgen |
b75cab |
greenMap[i] = SCALE(greenMap[i], 255);
|
|
roentgen |
b75cab |
blueMap[i] = SCALE(blueMap[i], 255);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
TIFFWarning(fileName, "Assuming 8-bit colormap");
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
SimpleGammaCorrection()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
register int i;
|
|
roentgen |
b75cab |
register double i_gamma = 1.0 / appData.gamma;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++) {
|
|
roentgen |
b75cab |
if (((tfPhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
|
|
roentgen |
b75cab |
&& (i == colormapSize - 1))
|
|
roentgen |
b75cab |
|| ((tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK)
|
|
roentgen |
b75cab |
&& (i == 0)))
|
|
roentgen |
b75cab |
redMap[i] = greenMap[i] = blueMap[i] = 0;
|
|
roentgen |
b75cab |
else {
|
|
roentgen |
b75cab |
redMap[i] = ROUND((pow(dRed[i] / 65535.0, i_gamma) * 65535.0));
|
|
roentgen |
b75cab |
greenMap[i] = ROUND((pow(dGreen[i] / 65535.0, i_gamma) * 65535.0));
|
|
roentgen |
b75cab |
blueMap[i] = ROUND((pow(dBlue[i] / 65535.0, i_gamma) * 65535.0));
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
free(dRed); free(dGreen); free(dBlue);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
static char* classNames[] = {
|
|
roentgen |
b75cab |
"StaticGray",
|
|
roentgen |
b75cab |
"GrayScale",
|
|
roentgen |
b75cab |
"StaticColor",
|
|
roentgen |
b75cab |
"PseudoColor",
|
|
roentgen |
b75cab |
"TrueColor",
|
|
roentgen |
b75cab |
"DirectColor"
|
|
roentgen |
b75cab |
};
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Current limitation: the visual is set initially by the first file.
|
|
roentgen |
b75cab |
* It cannot be changed.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
GetVisual()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XColor *colors = NULL;
|
|
roentgen |
b75cab |
unsigned long *pixels = NULL;
|
|
roentgen |
b75cab |
unsigned long i;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
switch (tfImageDepth) {
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* X really wants a 32-bit image with the fourth channel unused,
|
|
roentgen |
b75cab |
* but the visual structure thinks it's 24-bit. bitmap_unit is 32.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
case 32:
|
|
roentgen |
b75cab |
case 24:
|
|
roentgen |
b75cab |
if (SearchVisualList(24, DirectColor, &xVisual) == False) {
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: 24-bit DirectColor visual not available\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
colors = (XColor *) malloc(3 * colormapSize * sizeof(XColor));
|
|
roentgen |
b75cab |
MCHECK(colors);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++) {
|
|
roentgen |
b75cab |
colors[i].pixel = (i << 16) + (i << 8) + i;
|
|
roentgen |
b75cab |
colors[i].red = redMap[i];
|
|
roentgen |
b75cab |
colors[i].green = greenMap[i];
|
|
roentgen |
b75cab |
colors[i].blue = blueMap[i];
|
|
roentgen |
b75cab |
colors[i].flags = DoRed | DoGreen | DoBlue;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
|
|
roentgen |
b75cab |
xVisual, AllocAll);
|
|
roentgen |
b75cab |
XStoreColors(xDisplay, xColormap, colors, colormapSize);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case 8:
|
|
roentgen |
b75cab |
case 4:
|
|
roentgen |
b75cab |
case 2:
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* We assume that systems with 24-bit visuals also have 8-bit visuals.
|
|
roentgen |
b75cab |
* We don't promote from 8-bit PseudoColor to 24/32 bit DirectColor.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
switch (tfPhotometricInterpretation) {
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISWHITE:
|
|
roentgen |
b75cab |
case PHOTOMETRIC_MINISBLACK:
|
|
roentgen |
b75cab |
if (SearchVisualList((int) tfImageDepth, GrayScale, &xVisual) == True)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case PHOTOMETRIC_PALETTE:
|
|
roentgen |
b75cab |
if (SearchVisualList((int) tfImageDepth, PseudoColor, &xVisual) == True)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: Unsupported TIFF/X configuration\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
colors = (XColor *) malloc(colormapSize * sizeof(XColor));
|
|
roentgen |
b75cab |
MCHECK(colors);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < colormapSize; i++) {
|
|
roentgen |
b75cab |
colors[i].pixel = i;
|
|
roentgen |
b75cab |
colors[i].red = redMap[i];
|
|
roentgen |
b75cab |
colors[i].green = greenMap[i];
|
|
roentgen |
b75cab |
colors[i].blue = blueMap[i];
|
|
roentgen |
b75cab |
colors[i].flags = DoRed | DoGreen | DoBlue;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* xtiff's colormap allocation is private. It does not attempt
|
|
roentgen |
b75cab |
* to detect whether any existing colormap entries are suitable
|
|
roentgen |
b75cab |
* for its use. This will cause colormap flashing. Furthermore,
|
|
roentgen |
b75cab |
* background and foreground are taken from the environment.
|
|
roentgen |
b75cab |
* For example, the foreground color may be red when the visual
|
|
roentgen |
b75cab |
* is GrayScale. If the colormap is completely populated,
|
|
roentgen |
b75cab |
* Xt will not be able to allocate fg and bg.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (tfImageDepth == 8)
|
|
roentgen |
b75cab |
xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
|
|
roentgen |
b75cab |
xVisual, AllocAll);
|
|
roentgen |
b75cab |
else {
|
|
roentgen |
b75cab |
xColormap = XCreateColormap(xDisplay, RootWindow(xDisplay, xScreen),
|
|
roentgen |
b75cab |
xVisual, AllocNone);
|
|
roentgen |
b75cab |
pixels = (unsigned long *)
|
|
roentgen |
b75cab |
malloc(colormapSize * sizeof(unsigned long));
|
|
roentgen |
b75cab |
MCHECK(pixels);
|
|
roentgen |
b75cab |
(void) XAllocColorCells(xDisplay, xColormap, True,
|
|
roentgen |
b75cab |
NULL, 0, pixels, colormapSize);
|
|
roentgen |
b75cab |
basePixel = (unsigned char) pixels[0];
|
|
roentgen |
b75cab |
free(pixels);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
XStoreColors(xDisplay, xColormap, colors, colormapSize);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case 1:
|
|
roentgen |
b75cab |
xImageDepth = 1;
|
|
roentgen |
b75cab |
xVisual = DefaultVisual(xDisplay, xScreen);
|
|
roentgen |
b75cab |
xColormap = DefaultColormap(xDisplay, xScreen);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: unsupported image depth %d\n", tfImageDepth);
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (appData.verbose == True)
|
|
roentgen |
b75cab |
fprintf(stderr, "%s: Using %d-bit %s visual.\n",
|
|
roentgen |
b75cab |
fileName, xImageDepth, classNames[xVisual->class]);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (colors != NULL)
|
|
roentgen |
b75cab |
free(colors);
|
|
roentgen |
b75cab |
if (grayMap != NULL)
|
|
roentgen |
b75cab |
free(grayMap);
|
|
roentgen |
b75cab |
if (redMap != NULL)
|
|
roentgen |
b75cab |
free(redMap);
|
|
roentgen |
b75cab |
if (greenMap != NULL)
|
|
roentgen |
b75cab |
free(greenMap);
|
|
roentgen |
b75cab |
if (blueMap != NULL)
|
|
roentgen |
b75cab |
free(blueMap);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
colors = NULL; grayMap = redMap = greenMap = blueMap = NULL;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Search for an appropriate visual. Promote where necessary.
|
|
roentgen |
b75cab |
* Check to make sure that ENOUGH colormap entries are writeable.
|
|
roentgen |
b75cab |
* basePixel was determined when XAllocColorCells() contiguously
|
|
roentgen |
b75cab |
* allocated enough entries. basePixel is used below in GetTIFFImage.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
Boolean
|
|
roentgen |
b75cab |
SearchVisualList(image_depth, visual_class, visual)
|
|
roentgen |
b75cab |
int image_depth, visual_class;
|
|
roentgen |
b75cab |
Visual **visual;
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XVisualInfo template_visual, *visual_list, *vl;
|
|
roentgen |
b75cab |
int i, n_visuals;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
template_visual.screen = xScreen;
|
|
roentgen |
b75cab |
vl = visual_list = XGetVisualInfo(xDisplay, VisualScreenMask,
|
|
roentgen |
b75cab |
&template_visual, &n_visuals);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (n_visuals == 0) {
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: visual list not available\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < n_visuals; vl++, i++) {
|
|
roentgen |
b75cab |
if ((vl->class == visual_class) && (vl->depth >= image_depth)
|
|
roentgen |
b75cab |
&& (vl->visual->map_entries >= (1 << vl->depth))) {
|
|
roentgen |
b75cab |
*visual = vl->visual;
|
|
roentgen |
b75cab |
xImageDepth = vl->depth;
|
|
roentgen |
b75cab |
xRedMask = vl->red_mask;
|
|
roentgen |
b75cab |
xGreenMask = vl->green_mask;
|
|
roentgen |
b75cab |
xBlueMask = vl->blue_mask;
|
|
roentgen |
b75cab |
XFree((char *) visual_list);
|
|
roentgen |
b75cab |
return True;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XFree((char *) visual_list);
|
|
roentgen |
b75cab |
return False;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
GetTIFFImage()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
int pixel_map[3], red_shift, green_shift, blue_shift;
|
|
roentgen |
b75cab |
char *scan_line, *output_p, *input_p;
|
|
roentgen |
b75cab |
uint32 i, j;
|
|
roentgen |
b75cab |
uint16 s;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
scan_line = (char *) malloc(tfBytesPerRow = TIFFScanlineSize(tfFile));
|
|
roentgen |
b75cab |
MCHECK(scan_line);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((tfImageDepth == 32) || (tfImageDepth == 24)) {
|
|
roentgen |
b75cab |
output_p = imageMemory = (char *)
|
|
roentgen |
b75cab |
malloc(tfImageWidth * tfImageHeight * 4);
|
|
roentgen |
b75cab |
MCHECK(imageMemory);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Handle different color masks for different frame buffers.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (ImageByteOrder(xDisplay) == LSBFirst) { /* DECstation 5000 */
|
|
roentgen |
b75cab |
red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 3
|
|
roentgen |
b75cab |
: (xRedMask == 0xFF0000 ? 2 : (xRedMask == 0xFF00 ? 1 : 0));
|
|
roentgen |
b75cab |
green_shift = pixel_map[1] = xGreenMask == 0xFF000000 ? 3
|
|
roentgen |
b75cab |
: (xGreenMask == 0xFF0000 ? 2 : (xGreenMask == 0xFF00 ? 1 : 0));
|
|
roentgen |
b75cab |
blue_shift = pixel_map[2] = xBlueMask == 0xFF000000 ? 3
|
|
roentgen |
b75cab |
: (xBlueMask == 0xFF0000 ? 2 : (xBlueMask == 0xFF00 ? 1 : 0));
|
|
roentgen |
b75cab |
} else { /* Ardent */
|
|
roentgen |
b75cab |
red_shift = pixel_map[0] = xRedMask == 0xFF000000 ? 0
|
|
roentgen |
b75cab |
: (xRedMask == 0xFF0000 ? 1 : (xRedMask == 0xFF00 ? 2 : 3));
|
|
roentgen |
b75cab |
green_shift = pixel_map[0] = xGreenMask == 0xFF000000 ? 0
|
|
roentgen |
b75cab |
: (xGreenMask == 0xFF0000 ? 1 : (xGreenMask == 0xFF00 ? 2 : 3));
|
|
roentgen |
b75cab |
blue_shift = pixel_map[0] = xBlueMask == 0xFF000000 ? 0
|
|
roentgen |
b75cab |
: (xBlueMask == 0xFF0000 ? 1 : (xBlueMask == 0xFF00 ? 2 : 3));
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (tfPlanarConfiguration == PLANARCONFIG_CONTIG) {
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++) {
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
for (input_p = scan_line, j = 0; j < tfImageWidth; j++) {
|
|
roentgen |
b75cab |
*(output_p + red_shift) = *input_p++;
|
|
roentgen |
b75cab |
*(output_p + green_shift) = *input_p++;
|
|
roentgen |
b75cab |
*(output_p + blue_shift) = *input_p++;
|
|
roentgen |
b75cab |
output_p += 4;
|
|
roentgen |
b75cab |
if (tfSamplesPerPixel == 4) /* skip the fourth channel */
|
|
roentgen |
b75cab |
input_p++;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
for (s = 0; s < tfSamplesPerPixel; s++) {
|
|
roentgen |
b75cab |
if (s == 3) /* skip the fourth channel */
|
|
roentgen |
b75cab |
continue;
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++) {
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, scan_line, i, s) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
input_p = scan_line;
|
|
roentgen |
b75cab |
output_p = imageMemory + (i*tfImageWidth*4) + pixel_map[s];
|
|
roentgen |
b75cab |
for (j = 0; j < tfImageWidth; j++, output_p += 4)
|
|
roentgen |
b75cab |
*output_p = *input_p++;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
if (xImageDepth == tfImageDepth) {
|
|
roentgen |
b75cab |
output_p = imageMemory = (char *)
|
|
roentgen |
b75cab |
malloc(tfBytesPerRow * tfImageHeight);
|
|
roentgen |
b75cab |
MCHECK(imageMemory);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++, output_p += tfBytesPerRow)
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, output_p, i, 0) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
} else if ((xImageDepth == 8) && (tfImageDepth == 4)) {
|
|
roentgen |
b75cab |
output_p = imageMemory = (char *)
|
|
roentgen |
b75cab |
malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
|
|
roentgen |
b75cab |
MCHECK(imageMemory);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* If a scanline is of odd size the inner loop below will overshoot.
|
|
roentgen |
b75cab |
* This is handled very simply by recalculating the start point at
|
|
roentgen |
b75cab |
* each scanline and padding imageMemory a little at the end.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++) {
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
output_p = &imageMemory[i * tfImageWidth];
|
|
roentgen |
b75cab |
input_p = scan_line;
|
|
roentgen |
b75cab |
for (j = 0; j < tfImageWidth; j += 2, input_p++) {
|
|
roentgen |
b75cab |
*output_p++ = (*input_p >> 4) + basePixel;
|
|
roentgen |
b75cab |
*output_p++ = (*input_p & 0xf) + basePixel;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
} else if ((xImageDepth == 8) && (tfImageDepth == 2)) {
|
|
roentgen |
b75cab |
output_p = imageMemory = (char *)
|
|
roentgen |
b75cab |
malloc(tfBytesPerRow * 4 * tfImageHeight + 4);
|
|
roentgen |
b75cab |
MCHECK(imageMemory);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++) {
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
output_p = &imageMemory[i * tfImageWidth];
|
|
roentgen |
b75cab |
input_p = scan_line;
|
|
roentgen |
b75cab |
for (j = 0; j < tfImageWidth; j += 4, input_p++) {
|
|
roentgen |
b75cab |
*output_p++ = (*input_p >> 6) + basePixel;
|
|
roentgen |
b75cab |
*output_p++ = ((*input_p >> 4) & 3) + basePixel;
|
|
roentgen |
b75cab |
*output_p++ = ((*input_p >> 2) & 3) + basePixel;
|
|
roentgen |
b75cab |
*output_p++ = (*input_p & 3) + basePixel;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
} else if ((xImageDepth == 4) && (tfImageDepth == 2)) {
|
|
roentgen |
b75cab |
output_p = imageMemory = (char *)
|
|
roentgen |
b75cab |
malloc(tfBytesPerRow * 2 * tfImageHeight + 2);
|
|
roentgen |
b75cab |
MCHECK(imageMemory);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
for (i = 0; i < tfImageHeight; i++) {
|
|
roentgen |
b75cab |
if (TIFFReadScanline(tfFile, scan_line, i, 0) < 0)
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
output_p = &imageMemory[i * tfBytesPerRow * 2];
|
|
roentgen |
b75cab |
input_p = scan_line;
|
|
roentgen |
b75cab |
for (j = 0; j < tfImageWidth; j += 4, input_p++) {
|
|
roentgen |
b75cab |
*output_p++ = (((*input_p>>6) << 4)
|
|
roentgen |
b75cab |
| ((*input_p >> 4) & 3)) + basePixel;
|
|
roentgen |
b75cab |
*output_p++ = ((((*input_p>>2) & 3) << 4)
|
|
roentgen |
b75cab |
| (*input_p & 3)) + basePixel;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
fprintf(stderr,
|
|
roentgen |
b75cab |
"xtiff: can't handle %d-bit TIFF file on an %d-bit display\n",
|
|
roentgen |
b75cab |
tfImageDepth, xImageDepth);
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
free(scan_line);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
CreateXImage()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XGCValues gc_values;
|
|
roentgen |
b75cab |
GC bitmap_gc;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xOffset = yOffset = 0;
|
|
roentgen |
b75cab |
grabX = grabY = -1;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xImage = XCreateImage(xDisplay, xVisual, xImageDepth,
|
|
roentgen |
b75cab |
xImageDepth == 1 ? XYBitmap : ZPixmap, /* offset */ 0,
|
|
roentgen |
b75cab |
(char *) imageMemory, tfImageWidth, tfImageHeight,
|
|
roentgen |
b75cab |
/* bitmap_pad */ 8, /* bytes_per_line */ 0);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* libtiff converts LSB data into MSB but doesn't change the FillOrder tag.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (xImageDepth == 1)
|
|
roentgen |
b75cab |
xImage->bitmap_bit_order = MSBFirst;
|
|
roentgen |
b75cab |
if (xImageDepth <= 8)
|
|
roentgen |
b75cab |
xImage->byte_order = MSBFirst;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* create an appropriate GC
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
gc_values.function = GXcopy;
|
|
roentgen |
b75cab |
gc_values.plane_mask = AllPlanes;
|
|
roentgen |
b75cab |
if (tfPhotometricInterpretation == PHOTOMETRIC_MINISBLACK) {
|
|
roentgen |
b75cab |
gc_values.foreground = XWhitePixel(xDisplay, xScreen);
|
|
roentgen |
b75cab |
gc_values.background = XBlackPixel(xDisplay, xScreen);
|
|
roentgen |
b75cab |
} else {
|
|
roentgen |
b75cab |
gc_values.foreground = XBlackPixel(xDisplay, xScreen);
|
|
roentgen |
b75cab |
gc_values.background = XWhitePixel(xDisplay, xScreen);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
xWinGc = XCreateGC(xDisplay, XtWindow(shellWidget),
|
|
roentgen |
b75cab |
GCFunction | GCPlaneMask | GCForeground | GCBackground, &gc_values);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* create the pixmap and load the image
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (appData.usePixmap == True) {
|
|
roentgen |
b75cab |
xImagePixmap = XCreatePixmap(xDisplay, RootWindow(xDisplay, xScreen),
|
|
roentgen |
b75cab |
xImage->width, xImage->height, xImageDepth);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* According to the O'Reilly X Protocol Reference Manual, page 53,
|
|
roentgen |
b75cab |
* "A pixmap depth of one is always supported and listed, but windows
|
|
roentgen |
b75cab |
* of depth one might not be supported." Therefore we create a pixmap
|
|
roentgen |
b75cab |
* of depth one and use XCopyPlane(). This is idiomatic.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (xImageDepth == 1) { /* just pass the bits through */
|
|
roentgen |
b75cab |
gc_values.foreground = 1; /* foreground describes set bits */
|
|
roentgen |
b75cab |
gc_values.background = 0; /* background describes clear bits */
|
|
roentgen |
b75cab |
bitmap_gc = XCreateGC(xDisplay, xImagePixmap,
|
|
roentgen |
b75cab |
GCForeground | GCBackground, &gc_values);
|
|
roentgen |
b75cab |
XPutImage(xDisplay, xImagePixmap, bitmap_gc, xImage,
|
|
roentgen |
b75cab |
0, 0, 0, 0, xImage->width, xImage->height);
|
|
roentgen |
b75cab |
} else
|
|
roentgen |
b75cab |
XPutImage(xDisplay, xImagePixmap, xWinGc, xImage,
|
|
roentgen |
b75cab |
0, 0, 0, 0, xImage->width, xImage->height);
|
|
roentgen |
b75cab |
XDestroyImage(xImage);
|
|
roentgen |
b75cab |
free(imageMemory);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtCallbackProc
|
|
roentgen |
b75cab |
SelectProc(w, unused_1, unused_2)
|
|
roentgen |
b75cab |
Widget w;
|
|
roentgen |
b75cab |
caddr_t unused_1;
|
|
roentgen |
b75cab |
caddr_t unused_2;
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XawListReturnStruct *list_return;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
list_return = XawListShowCurrent(w);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
switch (list_return->list_index) {
|
|
roentgen |
b75cab |
case ButtonQuit:
|
|
roentgen |
b75cab |
QuitProc();
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case ButtonPreviousPage:
|
|
roentgen |
b75cab |
PreviousProc();
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case ButtonNextPage:
|
|
roentgen |
b75cab |
NextProc();
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
fprintf(stderr, "error in SelectProc\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
XawListUnhighlight(w);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
QuitProc(void)
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
NextProc()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
PageProc(ButtonNextPage);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
PreviousProc()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
PageProc(ButtonPreviousPage);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
PageProc(direction)
|
|
roentgen |
b75cab |
int direction;
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
XEvent fake_event;
|
|
roentgen |
b75cab |
Arg args[4];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
switch (direction) {
|
|
roentgen |
b75cab |
case ButtonPreviousPage:
|
|
roentgen |
b75cab |
if (tfDirectory > 0)
|
|
roentgen |
b75cab |
TIFFSetDirectory(tfFile, --tfDirectory);
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case ButtonNextPage:
|
|
roentgen |
b75cab |
if (TIFFReadDirectory(tfFile) == True)
|
|
roentgen |
b75cab |
tfDirectory++;
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
fprintf(stderr, "error in PageProc\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xOffset = yOffset = 0;
|
|
roentgen |
b75cab |
grabX = grabY = -1;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
GetTIFFHeader();
|
|
roentgen |
b75cab |
SetNameLabel();
|
|
roentgen |
b75cab |
GetTIFFImage();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (appData.usePixmap == True)
|
|
roentgen |
b75cab |
XFreePixmap(xDisplay, xImagePixmap);
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
XDestroyImage(xImage);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
CreateXImage();
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Using XtSetValues() to set the widget size causes a resize.
|
|
roentgen |
b75cab |
* This resize gets propagated up to the parent shell.
|
|
roentgen |
b75cab |
* In order to disable this visually disconcerting effect,
|
|
roentgen |
b75cab |
* shell resizing is temporarily disabled.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNallowShellResize, False);
|
|
roentgen |
b75cab |
XtSetValues(shellWidget, args, 1);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNwidth, tfImageWidth);
|
|
roentgen |
b75cab |
XtSetArg(args[1], XtNheight, tfImageHeight);
|
|
roentgen |
b75cab |
XtSetValues(imageWidget, args, 2);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNallowShellResize, True);
|
|
roentgen |
b75cab |
XtSetValues(shellWidget, args, 1);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XClearWindow(xDisplay, XtWindow(imageWidget));
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
fake_event.type = Expose;
|
|
roentgen |
b75cab |
fake_event.xexpose.x = fake_event.xexpose.y = 0;
|
|
roentgen |
b75cab |
fake_event.xexpose.width = tfImageWidth; /* the window will clip */
|
|
roentgen |
b75cab |
fake_event.xexpose.height = tfImageHeight;
|
|
roentgen |
b75cab |
EventProc(imageWidget, NULL, &fake_event);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
EventProc(widget, unused, event)
|
|
roentgen |
b75cab |
Widget widget;
|
|
roentgen |
b75cab |
caddr_t unused;
|
|
roentgen |
b75cab |
XEvent *event;
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
int ih, iw, ww, wh, sx, sy, w, h, dx, dy;
|
|
roentgen |
b75cab |
Dimension w_width, w_height;
|
|
roentgen |
b75cab |
XEvent next_event;
|
|
roentgen |
b75cab |
Arg args[2];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (event->type == MappingNotify) {
|
|
roentgen |
b75cab |
XRefreshKeyboardMapping((XMappingEvent *) event);
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (!XtIsRealized(widget))
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((event->type == ButtonPress) || (event->type == ButtonRelease))
|
|
roentgen |
b75cab |
if (event->xbutton.button != Button1)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
iw = tfImageWidth; /* avoid sign problems */
|
|
roentgen |
b75cab |
ih = tfImageHeight;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* The grabX and grabY variables record where the user grabbed the image.
|
|
roentgen |
b75cab |
* They also record whether the mouse button is down or not.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (event->type == ButtonPress) {
|
|
roentgen |
b75cab |
grabX = event->xbutton.x;
|
|
roentgen |
b75cab |
grabY = event->xbutton.y;
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* imageWidget is a Core widget and doesn't get resized.
|
|
roentgen |
b75cab |
* So we calculate the size of its viewport here.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNwidth, &w_width);
|
|
roentgen |
b75cab |
XtSetArg(args[1], XtNheight, &w_height);
|
|
roentgen |
b75cab |
XtGetValues(shellWidget, args, 2);
|
|
roentgen |
b75cab |
ww = w_width;
|
|
roentgen |
b75cab |
wh = w_height;
|
|
roentgen |
b75cab |
XtGetValues(listWidget, args, 2);
|
|
roentgen |
b75cab |
wh -= w_height;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
switch (event->type) {
|
|
roentgen |
b75cab |
case Expose:
|
|
roentgen |
b75cab |
dx = event->xexpose.x;
|
|
roentgen |
b75cab |
dy = event->xexpose.y;
|
|
roentgen |
b75cab |
sx = dx + xOffset;
|
|
roentgen |
b75cab |
sy = dy + yOffset;
|
|
roentgen |
b75cab |
w = MIN(event->xexpose.width, iw);
|
|
roentgen |
b75cab |
h = MIN(event->xexpose.height, ih);
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case KeyPress:
|
|
roentgen |
b75cab |
if ((grabX >= 0) || (grabY >= 0)) /* Mouse button is still down */
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
switch (XLookupKeysym((XKeyEvent *) event, /* KeySyms index */ 0)) {
|
|
roentgen |
b75cab |
case XK_Up:
|
|
roentgen |
b75cab |
if (ih < wh) /* Don't scroll if the window fits the image. */
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
sy = yOffset + appData.translate;
|
|
roentgen |
b75cab |
sy = MIN(ih - wh, sy);
|
|
roentgen |
b75cab |
if (sy == yOffset) /* Filter redundant stationary refreshes. */
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
yOffset = sy;
|
|
roentgen |
b75cab |
sx = xOffset;
|
|
roentgen |
b75cab |
dx = dy = 0;
|
|
roentgen |
b75cab |
w = ww; h = wh;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case XK_Down:
|
|
roentgen |
b75cab |
if (ih < wh)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
sy = yOffset - appData.translate;
|
|
roentgen |
b75cab |
sy = MAX(sy, 0);
|
|
roentgen |
b75cab |
if (sy == yOffset)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
yOffset = sy;
|
|
roentgen |
b75cab |
sx = xOffset;
|
|
roentgen |
b75cab |
dx = dy = 0;
|
|
roentgen |
b75cab |
w = ww; h = wh;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case XK_Left:
|
|
roentgen |
b75cab |
if (iw < ww)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
sx = xOffset + appData.translate;
|
|
roentgen |
b75cab |
sx = MIN(iw - ww, sx);
|
|
roentgen |
b75cab |
if (sx == xOffset)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
xOffset = sx;
|
|
roentgen |
b75cab |
sy = yOffset;
|
|
roentgen |
b75cab |
dx = dy = 0;
|
|
roentgen |
b75cab |
w = ww; h = wh;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case XK_Right:
|
|
roentgen |
b75cab |
if (iw < ww)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
sx = xOffset - appData.translate;
|
|
roentgen |
b75cab |
sx = MAX(sx, 0);
|
|
roentgen |
b75cab |
if (sx == xOffset)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
xOffset = sx;
|
|
roentgen |
b75cab |
sy = yOffset;
|
|
roentgen |
b75cab |
dx = dy = 0;
|
|
roentgen |
b75cab |
w = ww; h = wh;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case MotionNotify:
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* MotionEvent compression. Ignore multiple motion events.
|
|
roentgen |
b75cab |
* Ignore motion events if the mouse button is up.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if (XPending(xDisplay)) /* Xlib doesn't flush the output buffer */
|
|
roentgen |
b75cab |
if (XtPeekEvent(&next_event))
|
|
roentgen |
b75cab |
if (next_event.type == MotionNotify)
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
if ((grabX < 0) || (grabY < 0))
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
sx = xOffset + grabX - (int) event->xmotion.x;
|
|
roentgen |
b75cab |
if (sx >= (iw - ww)) /* clamp x motion but allow y motion */
|
|
roentgen |
b75cab |
sx = iw - ww;
|
|
roentgen |
b75cab |
sx = MAX(sx, 0);
|
|
roentgen |
b75cab |
sy = yOffset + grabY - (int) event->xmotion.y;
|
|
roentgen |
b75cab |
if (sy >= (ih - wh)) /* clamp y motion but allow x motion */
|
|
roentgen |
b75cab |
sy = ih - wh;
|
|
roentgen |
b75cab |
sy = MAX(sy, 0);
|
|
roentgen |
b75cab |
if ((sx == xOffset) && (sy == yOffset))
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
dx = dy = 0;
|
|
roentgen |
b75cab |
w = ww; h = wh;
|
|
roentgen |
b75cab |
break;
|
|
roentgen |
b75cab |
case ButtonRelease:
|
|
roentgen |
b75cab |
xOffset = xOffset + grabX - (int) event->xbutton.x;
|
|
roentgen |
b75cab |
xOffset = MIN(iw - ww, xOffset);
|
|
roentgen |
b75cab |
xOffset = MAX(xOffset, 0);
|
|
roentgen |
b75cab |
yOffset = yOffset + grabY - (int) event->xbutton.y;
|
|
roentgen |
b75cab |
yOffset = MIN(ih - wh, yOffset);
|
|
roentgen |
b75cab |
yOffset = MAX(yOffset, 0);
|
|
roentgen |
b75cab |
grabX = grabY = -1;
|
|
roentgen |
b75cab |
default:
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if (appData.usePixmap == True) {
|
|
roentgen |
b75cab |
if (xImageDepth == 1)
|
|
roentgen |
b75cab |
XCopyPlane(xDisplay, xImagePixmap, XtWindow(widget),
|
|
roentgen |
b75cab |
xWinGc, sx, sy, w, h, dx, dy, 1);
|
|
roentgen |
b75cab |
else
|
|
roentgen |
b75cab |
XCopyArea(xDisplay, xImagePixmap, XtWindow(widget),
|
|
roentgen |
b75cab |
xWinGc, sx, sy, w, h, dx, dy);
|
|
roentgen |
b75cab |
} else
|
|
roentgen |
b75cab |
XPutImage(xDisplay, XtWindow(widget), xWinGc, xImage,
|
|
roentgen |
b75cab |
sx, sy, dx, dy, w, h);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
ResizeProc()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
Dimension w_width, w_height;
|
|
roentgen |
b75cab |
int xo, yo, ww, wh;
|
|
roentgen |
b75cab |
XEvent fake_event;
|
|
roentgen |
b75cab |
Arg args[2];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((xOffset == 0) && (yOffset == 0))
|
|
roentgen |
b75cab |
return;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
XtSetArg(args[0], XtNwidth, &w_width);
|
|
roentgen |
b75cab |
XtSetArg(args[1], XtNheight, &w_height);
|
|
roentgen |
b75cab |
XtGetValues(shellWidget, args, 2);
|
|
roentgen |
b75cab |
ww = w_width;
|
|
roentgen |
b75cab |
wh = w_height;
|
|
roentgen |
b75cab |
XtGetValues(listWidget, args, 2);
|
|
roentgen |
b75cab |
wh -= w_height;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
xo = xOffset; yo = yOffset;
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
if ((xOffset + ww) >= tfImageWidth)
|
|
roentgen |
b75cab |
xOffset = MAX((int) tfImageWidth - ww, 0);
|
|
roentgen |
b75cab |
if ((yOffset + wh) >= tfImageHeight)
|
|
roentgen |
b75cab |
yOffset = MAX((int) tfImageHeight - wh, 0);
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Send an ExposeEvent if the origin changed.
|
|
roentgen |
b75cab |
* We have to do this because of the use and semantics of bit gravity.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if ((xo != xOffset) || (yo != yOffset)) {
|
|
roentgen |
b75cab |
fake_event.type = Expose;
|
|
roentgen |
b75cab |
fake_event.xexpose.x = fake_event.xexpose.y = 0;
|
|
roentgen |
b75cab |
fake_event.xexpose.width = tfImageWidth;
|
|
roentgen |
b75cab |
fake_event.xexpose.height = tfImageHeight;
|
|
roentgen |
b75cab |
EventProc(imageWidget, NULL, &fake_event);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
int
|
|
roentgen |
b75cab |
XTiffErrorHandler(display, error_event)
|
|
roentgen |
b75cab |
Display *display;
|
|
roentgen |
b75cab |
XErrorEvent *error_event;
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
char message[80];
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Some X servers limit the size of pixmaps.
|
|
roentgen |
b75cab |
*/
|
|
roentgen |
b75cab |
if ((error_event->error_code == BadAlloc)
|
|
roentgen |
b75cab |
&& (error_event->request_code == X_CreatePixmap))
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: requested pixmap too big for display\n");
|
|
roentgen |
b75cab |
else {
|
|
roentgen |
b75cab |
XGetErrorText(display, error_event->error_code, message, 80);
|
|
roentgen |
b75cab |
fprintf(stderr, "xtiff: error code %s\n", message);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
void
|
|
roentgen |
b75cab |
Usage()
|
|
roentgen |
b75cab |
{
|
|
roentgen |
b75cab |
fprintf(stderr, "Usage xtiff: [options] tiff-file\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\tstandard Xt options\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-help]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-gamma gamma]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-usePixmap (True | False)]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-viewportWidth pixels]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-viewportHeight pixels]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-translate pixels]\n");
|
|
roentgen |
b75cab |
fprintf(stderr, "\t[-verbose (True | False)]\n");
|
|
roentgen |
b75cab |
exit(0);
|
|
roentgen |
b75cab |
}
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/* vim: set ts=8 sts=8 sw=8 noet: */
|
|
roentgen |
b75cab |
|
|
roentgen |
b75cab |
/*
|
|
roentgen |
b75cab |
* Local Variables:
|
|
roentgen |
b75cab |
* mode: c
|
|
roentgen |
b75cab |
* c-basic-offset: 8
|
|
roentgen |
b75cab |
* fill-column: 78
|
|
roentgen |
b75cab |
* End:
|
|
roentgen |
b75cab |
*/
|