📄 xtiff.c
字号:
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 = (u_short *) malloc(colormapSize * sizeof(u_short)); greenMap = (u_short *) malloc(colormapSize * sizeof(u_short)); blueMap = (u_short *) malloc(colormapSize * sizeof(u_short)); 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 = (u_short *) malloc(colormapSize * sizeof(u_short)); greenMap = (u_short *) malloc(colormapSize * sizeof(u_short)); blueMap = (u_short *) malloc(colormapSize * sizeof(u_short)); 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 = (u_short *) malloc(colormapSize * sizeof(u_short)); greenMap = (u_short *) malloc(colormapSize * sizeof(u_short)); blueMap = (u_short *) malloc(colormapSize * sizeof(u_short)); 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 = (u_short *) malloc(colormapSize * sizeof(u_short)); greenMap = (u_short *) malloc(colormapSize * sizeof(u_short)); blueMap = (u_short *) malloc(colormapSize * sizeof(u_short)); 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); }}voidSetNameLabel(){ char buffer[BUFSIZ]; Arg args[1]; if (tfMultiPage) sprintf(buffer, "%s - page %d", fileName, tfDirectory); else strcpy(buffer, 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. */voidCheckAndCorrectColormap(){ 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");}voidSimpleGammaCorrection(){ 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. */voidGetVisual(){ register XColor *colors = NULL; register u_long *pixels = NULL; register int 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 = (u_long) (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 = (u_long) 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 = (u_long *) malloc(colormapSize * sizeof(u_long)); MCHECK(pixels); (void) XAllocColorCells(xDisplay, xColormap, True, NULL, 0, pixels, colormapSize); basePixel = (u_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. */BooleanSearchVisualList(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;}voidGetTIFFImage(){ int pixel_map[3], red_shift, green_shift, blue_shift; register u_char *scan_line, *output_p, *input_p; register int i, j, s; scan_line = (u_char *) malloc(tfBytesPerRow = TIFFScanlineSize(tfFile)); MCHECK(scan_line); if ((tfImageDepth == 32) || (tfImageDepth == 24)) { output_p = imageMemory = (u_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 = (u_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 = (u_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 = (u_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 = (u_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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -