home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / libtiff / tools / sgigt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  23.0 KB  |  979 lines

  1. /* $Header: /usr/people/sam/tiff/tools/RCS/sgigt.c,v 1.66 1996/01/10 19:35:32 sam Rel $ */
  2.  
  3. /*
  4.  * Copyright (c) 1988-1996 Sam Leffler
  5.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31.  
  32. #include <gl.h>
  33. #include <device.h>
  34.  
  35. #include "tiffio.h"
  36.  
  37. #ifndef TRUE
  38. #define    TRUE    1
  39. #define    FALSE    0
  40. #endif
  41.  
  42. /* XXX fudge adjustment for window borders */
  43. #define    YFUDGE    20
  44. #define    XFUDGE    20
  45.  
  46. static    tileContigRoutine putContig;
  47. static    tileSeparateRoutine putSeparate;
  48. static    uint32 width, height;        /* window width & height */
  49. static    uint32* raster = NULL;        /* displayable image */
  50.  
  51. extern    Colorindex greyi(int);
  52. static    void setupColormapSupport(TIFFRGBAImage*);
  53. static    void putContigAndDraw(TIFFRGBAImage*, uint32*,
  54.     uint32, uint32, uint32, uint32, int32, int32, unsigned char*);
  55. static    void putSeparateAndDraw(TIFFRGBAImage*, uint32*,
  56.     uint32, uint32, uint32, uint32, int32, int32,
  57.     unsigned char*, unsigned char*, unsigned char*, unsigned char*);
  58.  
  59. static    int prevImage(char* argv[], int ix, int b, int e, int wrap);
  60. static    int nextImage(char* argv[], int ix, int b, int e, int wrap);
  61. static    void usage(void);
  62. static    uint16 photoArg(const char*);
  63. static    void beep(void);
  64.  
  65. extern    char* optarg;
  66. extern    int optind;
  67.  
  68. int
  69. main(int argc, char* argv[])
  70. {
  71.     static Cursor hourglass = {
  72.     0x1ff0, 0x1ff0, 0x0820, 0x0820,
  73.     0x0820, 0x0c60, 0x06c0, 0x0100,
  74.     0x0100, 0x06c0, 0x0c60, 0x0820,
  75.     0x0820, 0x0820, 0x1ff0, 0x1ff0
  76.     };
  77.     int isRGB0 = -1, isRGB;
  78.     int verbose = 0;
  79.     int stoponerr = 0;            /* stop on read error */
  80.     char* filename;
  81.     TIFF* tif = NULL;
  82.     int fg = 0;
  83.     int c;
  84.     int dirnum = -1;
  85.     int order0 = 0, order;
  86.     uint32 diroff = 0;
  87.     uint16 photo0 = (uint16) -1, photo;
  88.     long x, y, xmax, ymax;
  89.     int ix, nix;
  90.     TIFFErrorHandler oerror = TIFFSetErrorHandler(NULL);
  91.     TIFFErrorHandler owarning = TIFFSetWarningHandler(NULL);
  92.     uint32 w, h;
  93.     long wid = -1;
  94.  
  95.     while ((c = getopt(argc, argv, "d:o:p:cerflmsvw")) != -1)
  96.     switch (c) {
  97.     case 'c':
  98.         isRGB0 = 0;
  99.         break;
  100.     case 'd':
  101.         dirnum = atoi(optarg);
  102.         break;
  103.     case 'e':
  104.         oerror = TIFFSetErrorHandler(oerror);
  105.         break;
  106.     case 'f':
  107.         fg = 1;
  108.         break;
  109.     case 'l':
  110.         order0 = FILLORDER_LSB2MSB;
  111.         break;
  112.     case 'm':
  113.         order0 = FILLORDER_MSB2LSB;
  114.         break;
  115.     case 'o':
  116.         diroff = strtoul(optarg, NULL, 0);
  117.         break;
  118.     case 'p':
  119.         photo0 = photoArg(optarg);
  120.         break;
  121.     case 'r':
  122.         isRGB0 = 1;
  123.         break;
  124.     case 's':
  125.         stoponerr = 1;
  126.         break;
  127.     case 'w':
  128.         owarning = TIFFSetWarningHandler(owarning);
  129.         break;
  130.     case 'v':
  131.         verbose = 1;
  132.         break;
  133.     case '?':
  134.         usage();
  135.         /*NOTREACHED*/
  136.     }
  137.     if (argc - optind < 1)
  138.     usage();
  139.     xmax = getgdesc(GD_XPMAX) - XFUDGE;
  140.     ymax = getgdesc(GD_YPMAX) - YFUDGE;
  141.     ix = optind;
  142.     do {
  143.     tif = TIFFOpen(argv[ix], "r");
  144.     } while (tif == NULL && (ix = nextImage(argv, ix, optind, argc, FALSE)));
  145.     if (tif == NULL)
  146.     exit(0);
  147.     if (ix == optind) {
  148.     /*
  149.      * Set initial directory if user-specified
  150.      * file was opened successfully.
  151.      */
  152.     if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
  153.         TIFFError(argv[ix], "Error, seeking to directory %d", dirnum);
  154.     if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff))
  155.         TIFFError(argv[ix], "Error, setting subdirectory at %#x", diroff);
  156.     }
  157.     isRGB = isRGB0;
  158.     order = order0;
  159.     photo = photo0;
  160.     goto newfile0;
  161.     for (;;) {
  162.     TIFFRGBAImage img;
  163.     char title[1024];            /* window title line */
  164.     const char* cp;
  165.     int isrgb;
  166.  
  167.     if (order)
  168.         TIFFSetField(tif, TIFFTAG_FILLORDER, order);
  169.     if (photo != (uint16) -1)
  170.         TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo);
  171.     if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) {
  172.         TIFFError(filename, title);
  173.         goto bad2;
  174.     }
  175.     /*
  176.      * Use a full-color window if the image is
  177.      * full color or a palette image and the
  178.      * hardware support is present.
  179.      */
  180.     isrgb = isRGB;
  181.     if (isrgb == -1)
  182.         isrgb = (img.bitspersample >= 8 &&
  183.         (img.photometric == PHOTOMETRIC_RGB ||
  184.          img.photometric == PHOTOMETRIC_YCBCR ||
  185.          img.photometric == PHOTOMETRIC_SEPARATED ||
  186.          img.photometric == PHOTOMETRIC_PALETTE));
  187.     /*
  188.      * Check to see if the hardware can display 24-bit RGB.
  189.      */
  190.     if (isrgb && getgdesc(GD_BITS_NORM_SNG_RED) < img.bitspersample &&
  191.       !getgdesc(GD_DITHER)) {
  192.         if (verbose)
  193.         printf("Warning, display is incapable of full RGB,%s\n",
  194.              " using dithered colormap");
  195.         isrgb = 0;
  196.     }
  197.     /*
  198.      * Colormap-based display is done by overriding the put
  199.      * routine to install a private method that understands
  200.      * how to convert RGBA values to suitable colormap indices.
  201.      */
  202.     if (!isrgb)
  203.         setupColormapSupport(&img);
  204.     /*
  205.      * Override default ``put routine'' with private
  206.      * routine that also draws the raster on the display.
  207.      */
  208.     if (img.put.any == 0) {
  209.         TIFFError(filename,
  210.         "No \"put\" routine; must not handle image format");
  211.         goto bad3;
  212.     }
  213.     if (img.isContig) {
  214.         putContig = img.put.contig;
  215.         img.put.contig = putContigAndDraw;
  216.     } else {
  217.         putSeparate = img.put.separate;
  218.         img.put.separate = putSeparateAndDraw;
  219.     }
  220.     /*
  221.      * Setup the image raster as required.
  222.      */
  223.     if ((w = img.width) > xmax)
  224.         w = xmax;
  225.     if ((h = img.height) > ymax)
  226.         h = ymax;
  227.     if (w != width || h != height) {
  228.         if (raster != NULL)
  229.         _TIFFfree(raster), raster = NULL;
  230.         raster = (uint32*) _TIFFmalloc(w * h * sizeof (uint32));
  231.         if (raster == 0) {
  232.         width = height = 0;
  233.         TIFFError(filename, "No space for raster buffer");
  234.         goto bad3;
  235.         }
  236.         width = w;
  237.         height = h;
  238.     }
  239.     /*
  240.      * Create a new window or reconfigure an existing
  241.      * one to suit the image to be displayed.
  242.      */
  243.     if (wid < 0) {
  244.         x = (xmax+XFUDGE-width)/2;
  245.         y = (ymax+YFUDGE-height)/2;
  246.         prefposition(x, x+width-1, y, y+height-1);
  247.         cp = strrchr(filename, '/');
  248.         sprintf(title, "%s [%u] %s",
  249.         cp == NULL ? filename : cp+1,
  250.         (unsigned int) TIFFCurrentDirectory(tif),
  251.         isrgb ? " rgb" : " cmap");
  252.         if (fg)
  253.         foreground();
  254.         wid = winopen(title);
  255.         if (wid < 0) {
  256.         TIFFError(filename, "Can not create window");
  257.         TIFFRGBAImageEnd(&img);
  258.         break;
  259.         }
  260.         curstype(C16X1);
  261.         defcursor(1, hourglass);
  262.         qdevice(LEFTMOUSE);
  263.         qdevice(MIDDLEMOUSE);
  264.         qdevice(RIGHTMOUSE);
  265.         qdevice(KEYBD);
  266.         qdevice(PAGEUPKEY);
  267.         qdevice(PAGEDOWNKEY);
  268.         qdevice(HOMEKEY);
  269.         qdevice(ENDKEY);
  270.     } else {
  271.         x = (xmax+XFUDGE-width)/2;
  272.         y = (ymax+YFUDGE-height)/2;
  273.         winposition(x, x+width-1, y, y+height-1);
  274.         viewport(0, width-1, 0, height-1);
  275.         cp = strrchr(filename, '/');
  276.         sprintf(title, "%s [%u] %s",
  277.         cp == NULL ? filename : cp+1,
  278.         (unsigned int) TIFFCurrentDirectory(tif),
  279.         isrgb ? " rgb" : " cmap");
  280.         wintitle(title);
  281.     }
  282.     singlebuffer();
  283.     if (isrgb) {
  284.         RGBmode();
  285.         gconfig();
  286.     } else {
  287.         cmode();
  288.         gconfig();
  289.     }
  290.     /*
  291.      * Fetch the image.
  292.      */
  293.     setcursor(1, 0, 0);
  294.     greyi(225);
  295.     clear();
  296.     (void) TIFFRGBAImageGet(&img, raster, width, height);
  297.     setcursor(0, 0, 0);
  298.     /*
  299.      * Process input.
  300.      */
  301.     for (;;) {
  302.         short val;
  303.         switch (qread(&val)) {
  304.         case KEYBD:
  305.         switch (val) {
  306.         case 'b':            /* photometric MinIsBlack */
  307.             photo = PHOTOMETRIC_MINISBLACK;
  308.             goto newpage;
  309.         case 'l':            /* lsb-to-msb FillOrder */
  310.             order = FILLORDER_LSB2MSB;
  311.             goto newpage;
  312.         case 'm':            /* msb-to-lsb FillOrder */
  313.             order = FILLORDER_MSB2LSB;
  314.             goto newpage;
  315.         case 'c':            /* colormap visual */
  316.             isRGB = 0;
  317.             goto newpage;
  318.         case 'r':            /* RGB visual */
  319.             isRGB = 1;
  320.             goto newpage;
  321.         case 'w':            /* photometric MinIsWhite */
  322.             photo = PHOTOMETRIC_MINISWHITE;
  323.             goto newpage;
  324.         case 'W':            /* toggle warnings */
  325.             owarning = TIFFSetWarningHandler(owarning);
  326.             goto newpage;
  327.         case 'E':            /* toggle errors */
  328.             oerror = TIFFSetErrorHandler(oerror);
  329.             goto newpage;
  330.         case 'z':            /* reset to defaults */
  331.         case 'Z':
  332.             order = order0;
  333.             photo = photo0;
  334.             isRGB = isRGB0;
  335.             if (owarning == NULL)
  336.             owarning = TIFFSetWarningHandler(NULL);
  337.             if (oerror == NULL)
  338.             oerror = TIFFSetErrorHandler(NULL);
  339.             goto newpage;
  340.         case 'q':            /* exit */
  341.         case '\033':
  342.             TIFFRGBAImageEnd(&img);
  343.             goto done;
  344.         }
  345.         break;
  346.         case PAGEUPKEY:            /* previous logical image */
  347.         if (val) {
  348.             if (TIFFCurrentDirectory(tif) > 0) {
  349.             if (TIFFSetDirectory(tif, TIFFCurrentDirectory(tif)-1))
  350.                 goto newpage;
  351.             beep();        /* XXX */
  352.             } else {
  353.             ix = prevImage(argv, ix, optind, argc, TRUE);
  354.             /* XXX set directory to last image in new file */
  355.             goto newfile;
  356.             }
  357.         }
  358.         break;
  359.         case PAGEDOWNKEY:            /* next logical image */
  360.         if (val) {
  361.             if (!TIFFLastDirectory(tif)) {
  362.             if (TIFFReadDirectory(tif))
  363.                 goto newpage;
  364.             beep();        /* XXX */
  365.             } else {
  366.             ix = nextImage(argv, ix, optind, argc, TRUE);
  367.             goto newfile;
  368.             }
  369.         }
  370.         break;
  371.         case HOMEKEY:            /* 1st image in current file */
  372.         if (val) {
  373.             if (TIFFSetDirectory(tif, 0))
  374.             goto newpage;
  375.             beep();
  376.         }
  377.         break;
  378.         case ENDKEY:            /* last image in current file */
  379.         if (val) {
  380.             /* XXX */
  381.             beep();
  382.         }
  383.         break;
  384.         case RIGHTMOUSE:            /* previous file */
  385.         if (val) {
  386.             if (nix = prevImage(argv, ix, optind, argc, FALSE)) {
  387.             ix = nix;
  388.             goto newfile;
  389.             }
  390.             beep();
  391.         }
  392.         break;
  393.         case LEFTMOUSE:            /* next file */
  394.         if (val) {
  395.             if (nix = nextImage(argv, ix, optind, argc, FALSE)) {
  396.             ix = nix;
  397.             goto newfile;
  398.             }
  399.             beep();
  400.         }
  401.         break;
  402.         case MIDDLEMOUSE:            /* first file */
  403.         if (val) {
  404.             if (nix = nextImage(argv, optind-1, optind, argc, FALSE)) {
  405.             ix = nix;
  406.             goto newfile;
  407.             }
  408.             beep();
  409.         }
  410.         break;
  411.         case REDRAW:
  412.         lrectwrite(0, 0, width-1, height-1, raster);
  413.         break;
  414.         }
  415.     }
  416.     newfile:
  417.     TIFFRGBAImageEnd(&img);
  418.     if (tif != NULL && argv[ix] != filename)
  419.         TIFFClose(tif), tif = NULL;
  420.     /* fall thru... */
  421.     newfile0:
  422.     if (argv[ix] == NULL)
  423.         break;
  424.     filename = argv[ix];
  425.     if (tif == NULL) {
  426.         tif = TIFFOpen(filename, "r");
  427.         if (tif == NULL)
  428.         goto bad1;
  429.         isRGB = isRGB0;
  430.         order = order0;
  431.         photo = photo0;
  432.     }
  433.     continue;
  434.     newpage:
  435.     TIFFRGBAImageEnd(&img);
  436.     continue;
  437.     bad3:
  438.     TIFFRGBAImageEnd(&img);
  439.     bad2:
  440.     TIFFClose(tif), tif = NULL;
  441.     bad1:
  442.     argv[ix] = NULL;            /* don't revisit file */
  443.     ix = nextImage(argv, ix, optind, argc, TRUE);
  444.     goto newfile0;
  445.     }
  446. done:
  447.     if (wid >= 0)
  448.     winclose(wid);
  449.     if (raster != NULL)
  450.     _TIFFfree(raster);
  451.     if (tif != NULL)
  452.     TIFFClose(tif);
  453.     return (0);
  454. }
  455.  
  456. static int
  457. prevImage(char* argv[], int ix, int b, int e, int wrap)
  458. {
  459.     int i;
  460.  
  461.     for (i = ix-1; i >= b && argv[i] == NULL; i--)
  462.     ;
  463.     if (i < b) {
  464.     if (wrap) {
  465.         for (i = e-1; i > ix && argv[i] == NULL; i--)
  466.         ;
  467.     } else
  468.         i = 0;
  469.     }
  470.     return (i);
  471. }
  472.  
  473. static int
  474. nextImage(char* argv[], int ix, int b, int e, int wrap)
  475. {
  476.     int i;
  477.  
  478.     for (i = ix+1; i < e && argv[i] == NULL; i++)
  479.     ;
  480.     if (i >= e) {
  481.     if (wrap) {
  482.         for (i = b; i < ix && argv[i] == NULL; i++)
  483.         ;
  484.     } else
  485.         i = 0;
  486.     }
  487.     return (i);
  488. }
  489.  
  490. static void
  491. beep(void)
  492. {
  493.     greyi(0);
  494.     clear();
  495.     sginap(5);
  496.     lrectwrite(0, 0, width-1, height-1, raster);
  497. }
  498.  
  499. char* stuff[] = {
  500. "usage: tiffgt [options] file.tif",
  501. "where options are:",
  502. " -c        use colormap visual",
  503. " -d dirnum    set initial directory (default is 0)",
  504. " -e        enable display of TIFF error messages",
  505. " -f          run program in the foreground",
  506. " -l          force lsb-to-msb FillOrder",
  507. " -m          force msb-to-lsb FillOrder",
  508. " -o offset    set initial directory offset",
  509. " -p photo    override photometric interpretation",
  510. " -r        use fullcolor visual",
  511. " -s          stop decoding on first error (default is ignore errors)",
  512. " -v        enable verbose mode",
  513. " -w        enable display of TIFF warning messages",
  514. NULL
  515. };
  516.  
  517. static void
  518. usage(void)
  519. {
  520.     char buf[BUFSIZ];
  521.     int i;
  522.  
  523.     setbuf(stderr, buf);
  524.     for (i = 0; stuff[i] != NULL; i++)
  525.     fprintf(stderr, "%s\n", stuff[i]);
  526.     exit(-1);
  527. }
  528.  
  529. static uint16
  530. photoArg(const char* arg)
  531. {
  532.     if (strcmp(arg, "miniswhite") == 0)
  533.     return (PHOTOMETRIC_MINISWHITE);
  534.     else if (strcmp(arg, "minisblack") == 0)
  535.     return (PHOTOMETRIC_MINISBLACK);
  536.     else if (strcmp(arg, "rgb") == 0)
  537.     return (PHOTOMETRIC_RGB);
  538.     else if (strcmp(arg, "palette") == 0)
  539.     return (PHOTOMETRIC_PALETTE);
  540.     else if (strcmp(arg, "mask") == 0)
  541.     return (PHOTOMETRIC_MASK);
  542.     else if (strcmp(arg, "separated") == 0)
  543.     return (PHOTOMETRIC_SEPARATED);
  544.     else if (strcmp(arg, "ycbcr") == 0)
  545.     return (PHOTOMETRIC_YCBCR);
  546.     else if (strcmp(arg, "cielab") == 0)
  547.     return (PHOTOMETRIC_CIELAB);
  548.     else
  549.     return ((uint16) -1);
  550. }
  551.  
  552. static void
  553. putContigAndDraw(TIFFRGBAImage* img, uint32* raster,
  554.     uint32 x, uint32 y, uint32 w, uint32 h,
  555.     int32 fromskew, int32 toskew,
  556.     unsigned char* cp)
  557. {
  558.     (*putContig)(img, raster, x, y, w, h, fromskew, toskew, cp);
  559.     if (x+w == width) {
  560.     w = width;
  561.     if (img->orientation == ORIENTATION_TOPLEFT)
  562.         lrectwrite(0, y-(h-1), w-1, y, raster-x-(h-1)*w);
  563.     else
  564.         lrectwrite(0, y, w-1, y+h-1, raster);
  565.     }
  566. }
  567.  
  568. static void
  569. putSeparateAndDraw(TIFFRGBAImage* img, uint32* raster,
  570.     uint32 x, uint32 y, uint32 w, uint32 h,
  571.     int32 fromskew, int32 toskew,
  572.     unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a)
  573. {
  574.     (*putSeparate)(img, raster, x, y, w, h, fromskew, toskew, r, g, b, a);
  575.     if (x+w == width) {
  576.     w = width;
  577.     if (img->orientation == ORIENTATION_TOPLEFT)
  578.         lrectwrite(x, y-(h-1), w-1, y, raster-x-(h-1)*w);
  579.     else
  580.         lrectwrite(x, y, w-1, y+h-1, raster);
  581.     }
  582. }
  583.  
  584. /*
  585.  * {red,green,blue}_inverse are tables in libgutil.a that
  586.  * do an inverse map from (r,g,b) to the closest colormap
  587.  * index in the "standard" GL colormap.  grey_inverse is
  588.  * the equivalent map for mapping greyscale values to
  589.  * colormap indices.  We access these maps directly instead
  590.  * of through the rgbi and greyi functions to avoid the
  591.  * additional overhead of the color calls that they make.
  592.  */
  593. extern    u_char red_inverse[256];
  594. extern    u_char green_inverse[256];
  595. extern    u_char blue_inverse[256];
  596. extern    u_char grey_inverse[256];
  597. #define    greyi(g)    grey_inverse[g]
  598.  
  599. static u_char
  600. rgbi(u_char r, u_char g, u_char b)
  601. {
  602.     return (r == g && g == b ? grey_inverse[r] :
  603.     red_inverse[r] + green_inverse[g] + blue_inverse[b]);
  604. }
  605.  
  606. /*
  607.  * The following routines move decoded data returned
  608.  * from the TIFF library into rasters that are suitable
  609.  * for passing to lrecwrite.  They do the necessary
  610.  * conversions for when a colormap drawing mode is used.
  611.  */
  612. #define    REPEAT8(op)    REPEAT4(op); REPEAT4(op)
  613. #define    REPEAT4(op)    REPEAT2(op); REPEAT2(op)
  614. #define    REPEAT2(op)    op; op
  615. #define    CASE8(x,op)            \
  616.     switch (x) {            \
  617.     case 7: op; case 6: op; case 5: op;    \
  618.     case 4: op; case 3: op; case 2: op;    \
  619.     case 1: op;                \
  620.     }
  621. #define    CASE4(x,op)    switch (x) { case 3: op; case 2: op; case 1: op; }
  622. #define    NOP
  623.  
  624. #define    UNROLL8(w, op1, op2) {        \
  625.     uint32 _x;                \
  626.     for (_x = w; _x >= 8; _x -= 8) {    \
  627.     op1;                \
  628.     REPEAT8(op2);            \
  629.     }                    \
  630.     if (_x > 0) {            \
  631.     op1;                \
  632.     CASE8(_x,op2);            \
  633.     }                    \
  634. }
  635. #define    UNROLL4(w, op1, op2) {        \
  636.     uint32 _x;                \
  637.     for (_x = w; _x >= 4; _x -= 4) {    \
  638.     op1;                \
  639.     REPEAT4(op2);            \
  640.     }                    \
  641.     if (_x > 0) {            \
  642.     op1;                \
  643.     CASE4(_x,op2);            \
  644.     }                    \
  645. }
  646. #define    UNROLL2(w, op1, op2) {        \
  647.     uint32 _x;                \
  648.     for (_x = w; _x >= 2; _x -= 2) {    \
  649.     op1;                \
  650.     REPEAT2(op2);            \
  651.     }                    \
  652.     if (_x) {                \
  653.     op1;                \
  654.     op2;                \
  655.     }                    \
  656. }
  657.  
  658. #define    SKEW(r,g,b,skew)    { r += skew; g += skew; b += skew; }
  659.  
  660. #define    DECLAREContigPutFunc(name) \
  661. static void name(\
  662.     TIFFRGBAImage* img, \
  663.     uint32* cp, \
  664.     uint32 x, uint32 y, \
  665.     uint32 w, uint32 h, \
  666.     int32 fromskew, int32 toskew, \
  667.     u_char* pp \
  668. )
  669.  
  670. #define    DECLARESepPutFunc(name) \
  671. static void name(\
  672.     TIFFRGBAImage* img,\
  673.     uint32* cp,\
  674.     uint32 x, uint32 y, \
  675.     uint32 w, uint32 h,\
  676.     int32 fromskew, int32 toskew,\
  677.     u_char* r, u_char* g, u_char* b, u_char* a\
  678. )
  679.  
  680. static    tileContigRoutine libput;
  681.  
  682. /*
  683.  * 8-bit packed samples => colormap
  684.  */
  685. DECLAREContigPutFunc(putcontig8bittile)
  686. {
  687.     int samplesperpixel = img->samplesperpixel;
  688.     TIFFRGBValue* Map = img->Map;
  689.  
  690.     (void) y;
  691.     fromskew *= samplesperpixel;
  692.     if (Map) {
  693.     while (h-- > 0) {
  694.         for (x = w; x-- > 0;) {
  695.         *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  696.         pp += samplesperpixel;
  697.         }
  698.         cp += toskew;
  699.         pp += fromskew;
  700.     }
  701.     } else {
  702.     while (h-- > 0) {
  703.         for (x = w; x-- > 0;) {
  704.         *cp++ = rgbi(pp[0], pp[1], pp[2]);
  705.         pp += samplesperpixel;
  706.         }
  707.         cp += toskew;
  708.         pp += fromskew;
  709.     }
  710.     }
  711. }
  712.  
  713. /*
  714.  * Convert 8-bit packed samples => colormap
  715.  */
  716. DECLAREContigPutFunc(cvtcontig8bittile)
  717. {
  718.     (*libput)(img, cp, x, y, w, h, fromskew, toskew, pp);
  719.     while (h-- > 0) {
  720.     UNROLL8(w, NOP,
  721.         cp[0] = rgbi(TIFFGetR(cp[0]),TIFFGetG(cp[0]),TIFFGetB(cp[0])); cp++
  722.     );
  723.     cp += toskew;
  724.     }
  725. }
  726.  
  727. /*
  728.  * 16-bit packed samples => colormap
  729.  */
  730. DECLAREContigPutFunc(putcontig16bittile)
  731. {
  732.     int samplesperpixel = img->samplesperpixel;
  733.     TIFFRGBValue* Map = img->Map;
  734.  
  735.     (void) y;
  736.     fromskew *= samplesperpixel;
  737.     if (Map) {
  738.     while (h-- > 0) {
  739.         for (x = w; x-- > 0;) {
  740.         *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
  741.         pp += samplesperpixel;
  742.         }
  743.         cp += toskew;
  744.         pp += fromskew;
  745.     }
  746.     } else {
  747.     while (h-- > 0) {
  748.         for (x = w; x-- > 0;) {
  749.         *cp++ = rgbi(pp[0], pp[1], pp[2]);
  750.         pp += samplesperpixel;
  751.         }
  752.         cp += toskew;
  753.         pp += fromskew;
  754.     }
  755.     }
  756. }
  757.  
  758. /*
  759.  * 8-bit unpacked samples => colormap
  760.  */
  761. DECLARESepPutFunc(putseparate8bittile)
  762. {
  763.     TIFFRGBValue* Map = img->Map;
  764.  
  765.     (void) y; (void) a;
  766.     if (Map) {
  767.     while (h-- > 0) {
  768.         for (x = w; x-- > 0;)
  769.         *cp++ = rgbi(Map[*r++], Map[*g++], Map[*b++]);
  770.         SKEW(r, g, b, fromskew);
  771.         cp += toskew;
  772.     }
  773.     } else {
  774.     while (h-- > 0) {
  775.         for (x = w; x-- > 0;)
  776.         *cp++ = rgbi(*r++, *g++, *b++);
  777.         SKEW(r, g, b, fromskew);
  778.         cp += toskew;
  779.     }
  780.     }
  781. }
  782.  
  783. /*
  784.  * 16-bit unpacked samples => colormap
  785.  */
  786. DECLARESepPutFunc(putseparate16bittile)
  787. {
  788.     TIFFRGBValue* Map = img->Map;
  789.  
  790.     (void) y; (void) a;
  791.     if (Map) {
  792.     while (h-- > 0) {
  793.         for (x = 0; x < w; x++)
  794.         *cp++ = rgbi(Map[*r++], Map[*g++], Map[*b++]);
  795.         SKEW(r, g, b, fromskew);
  796.         cp += toskew;
  797.     }
  798.     } else {
  799.     while (h-- > 0) {
  800.         for (x = 0; x < w; x++)
  801.         *cp++ = rgbi(*r++, *g++, *b++);
  802.         SKEW(r, g, b, fromskew);
  803.         cp += toskew;
  804.     }
  805.     }
  806. }
  807.  
  808. /*
  809.  * 8-bit packed CMYK samples => cmap
  810.  *
  811.  * NB: The conversion of CMYK->RGB is *very* crude.
  812.  */
  813. DECLAREContigPutFunc(putcontig8bitCMYKtile)
  814. {
  815.     int samplesperpixel = img->samplesperpixel;
  816.     TIFFRGBValue* Map = img->Map;
  817.     uint16 r, g, b, k;
  818.  
  819.     (void) y;
  820.     fromskew *= samplesperpixel;
  821.     if (Map) {
  822.     while (h-- > 0) {
  823.         for (x = w; x-- > 0;) {
  824.         k = 255 - pp[3];
  825.         r = (k*(255-pp[0]))/255;
  826.         g = (k*(255-pp[1]))/255;
  827.         b = (k*(255-pp[2]))/255;
  828.         *cp++ = rgbi(Map[r], Map[g], Map[b]);
  829.         pp += samplesperpixel;
  830.         }
  831.         pp += fromskew;
  832.         cp += toskew;
  833.     }
  834.     } else {
  835.     while (h-- > 0) {
  836.         UNROLL8(w, NOP,
  837.         k = 255 - pp[3];
  838.         r = (k*(255-pp[0]))/255;
  839.         g = (k*(255-pp[1]))/255;
  840.         b = (k*(255-pp[2]))/255;
  841.         *cp++ = rgbi(r, g, b);
  842.         pp += samplesperpixel);
  843.         cp += toskew;
  844.         pp += fromskew;
  845.     }
  846.     }
  847. }
  848.  
  849. #define    YCbCrtoRGB(dst, yc) {                        \
  850.     int Y = (yc);                            \
  851.     dst = rgbi(                                \
  852.     clamptab[Y+Crrtab[Cr]],                        \
  853.     clamptab[Y + (int)((Cbgtab[Cb]+Crgtab[Cr])>>16)],        \
  854.     clamptab[Y+Cbbtab[Cb]]);                    \
  855. }
  856. #define    YCbCrSetup                            \
  857.     TIFFYCbCrToRGB* ycbcr = img->ycbcr;                    \
  858.     int* Crrtab = ycbcr->Cr_r_tab;                    \
  859.     int* Cbbtab = ycbcr->Cb_b_tab;                    \
  860.     int32* Crgtab = ycbcr->Cr_g_tab;                    \
  861.     int32* Cbgtab = ycbcr->Cb_g_tab;                    \
  862.     TIFFRGBValue* clamptab = ycbcr->clamptab
  863.  
  864. /*
  865.  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
  866.  */
  867. DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
  868. {
  869.     YCbCrSetup;
  870.     uint32* cp1 = cp+w+toskew;
  871.     unsigned int incr = 2*toskew+w;
  872.  
  873.     (void) y;
  874.     /* XXX adjust fromskew */
  875.     for (; h >= 2; h -= 2) {
  876.     x = w>>1;
  877.     do {
  878.         int Cb = pp[4];
  879.         int Cr = pp[5];
  880.  
  881.         YCbCrtoRGB(cp [0], pp[0]);
  882.         YCbCrtoRGB(cp [1], pp[1]);
  883.         YCbCrtoRGB(cp1[0], pp[2]);
  884.         YCbCrtoRGB(cp1[1], pp[3]);
  885.  
  886.         cp += 2, cp1 += 2;
  887.         pp += 6;
  888.     } while (--x);
  889.     cp += incr, cp1 += incr;
  890.     pp += fromskew;
  891.     }
  892. }
  893. #undef    YCbCrSetup
  894. #undef    YCbCrtoRGB
  895.  
  896. /*
  897.  * Setup to handle conversion for display in a colormap
  898.  * window.  Many cases are handled by massaging the mapping
  899.  * tables used by the normal library code to convert 32-bit
  900.  * packed RGBA samples into colormap indices.  Other cases
  901.  * are handled with special-case routines that replace the
  902.  * normal ``put routine'' installed by the library.
  903.  */
  904. static void
  905. setupColormapSupport(TIFFRGBAImage* img)
  906. {
  907.     int bitspersample = img->bitspersample;
  908.     int i;
  909.  
  910.     if (img->BWmap) {
  911.     i = 255;
  912.     do {
  913.         uint32* p = img->BWmap[i];
  914.         switch (bitspersample) {
  915. #define    GREY(x)    p[x] = greyi(TIFFGetR(p[x]))
  916.         case 1: GREY(7); GREY(6); GREY(5); GREY(4);
  917.         case 2: GREY(3); GREY(2);
  918.         case 4: GREY(1);
  919.         case 8: GREY(0);
  920.         }
  921. #undef    GREY
  922.     } while (i--);
  923.     } else if (img->PALmap) {
  924.     i = 255;
  925.     do {
  926.         uint32 rgb;
  927.         uint32* p = img->PALmap[i];
  928. #define    CMAP(x) \
  929.     (rgb = p[x], p[x] = rgbi(TIFFGetR(rgb),TIFFGetG(rgb),TIFFGetB(rgb)))
  930.         switch (bitspersample) {
  931.         case 1: CMAP(7); CMAP(6); CMAP(5); CMAP(4);
  932.         case 2: CMAP(3); CMAP(2);
  933.         case 4: CMAP(1);
  934.         case 8: CMAP(0);
  935.         }
  936. #undef CMAP
  937.     } while (i--);
  938.     } else if (img->isContig) {
  939.     switch (img->photometric) {
  940.     case PHOTOMETRIC_RGB:
  941.         switch (bitspersample) {
  942.         case 8:  img->put.contig = putcontig8bittile; break;
  943.         case 16: img->put.contig = putcontig16bittile; break;
  944.         }
  945.         break;
  946.     case PHOTOMETRIC_SEPARATED:
  947.         switch (bitspersample) {
  948.         case 8:  img->put.contig = putcontig8bitCMYKtile; break;
  949.         }
  950.         break;
  951.     case PHOTOMETRIC_YCBCR:
  952.         if (img->bitspersample == 8) {
  953.             uint16 hs, vs;
  954.             TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
  955.             &hs, &vs);
  956.             switch ((hs<<4)|vs) {
  957.             case 0x22:            /* most common case */
  958.             img->put.contig = putcontig8bitYCbCr22tile;
  959.             break;
  960.             default:            /* all others cost more */
  961.             libput = img->put.contig;
  962.             img->put.contig = cvtcontig8bittile;
  963.             break;
  964.             }
  965.         }
  966.         break;
  967.     }
  968.     } else {
  969.     switch (img->photometric) {
  970.     case PHOTOMETRIC_RGB:
  971.         switch (img->bitspersample) {
  972.         case 8:  img->put.separate = putseparate8bittile; break;
  973.         case 16: img->put.separate = putseparate16bittile; break;
  974.         }
  975.         break;
  976.     }
  977.     }
  978. }
  979.