home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0040 - 0049 / ibm0040-0049 / ibm0040.tar / ibm0040 / IMGPROC.ZIP / C6TIFF.ZIP / TIFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-11  |  15.7 KB  |  538 lines

  1. /*
  2. Copyright 1990 by John Wiley & Sons, Inc.
  3.           All Rights Reserved.
  4. */
  5. /****************************************/
  6. /*        TIFF Function Library         */
  7. /*       written in Turbo C 2.0         */
  8. /*                by                    */
  9. /*         Craig A. Lindley             */
  10. /*                                      */
  11. /*   Vers: 1.0  Last Update: 12/29/89   */
  12. /****************************************/
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <process.h>
  17. #include <mem.h>
  18. #include <conio.h>
  19. #include <string.h>
  20. #include <graphics.h>
  21. #include "misc.h"
  22. #include "vga.h"
  23. #include "pcx.h"
  24. #include "tiffintf.h"
  25.  
  26.  
  27. /*
  28. Create a TIFF file from the image currently
  29. being displayed on the VGA adapter.
  30. */
  31.  
  32. CompletionCode WriteTIFFFile(char *FileName,
  33.                  unsigned BitsPerSample,
  34.                  unsigned SamplesPerPixel,
  35.                  unsigned ImageWidth, unsigned ImageLength)
  36. {
  37.    TIFF *tif;
  38.    char *RowBuffer  = NULL;
  39.    char *Message = "";
  40.    register unsigned Col, Row;
  41.    unsigned *RedColorMap   = NULL;
  42.    unsigned *GreenColorMap = NULL;
  43.    unsigned *BlueColorMap  = NULL;
  44.    unsigned Index, ColorReg, BytesPerRow, Sample;
  45.    unsigned RedColor, GreenColor, BlueColor;
  46.    unsigned BitPlane, Mask;
  47.    long     RowsPerStrip;
  48.    struct palettetype Palette;
  49.  
  50.    /*
  51.    Allocate colormaps arrays. Calloc clears them to zero.
  52.    */
  53.    if((RedColorMap = (unsigned *) calloc(MAX256PALETTECOLORS,sizeof(unsigned))) == NULL)
  54.    {
  55.       Message = "No memory for RedColorMap";
  56.       goto NoMem;
  57.    }
  58.  
  59.    if((GreenColorMap = (unsigned *) calloc(MAX256PALETTECOLORS,sizeof(unsigned))) == NULL)
  60.    {
  61.       Message = "No memory for GreenColorMap";
  62.       goto NoMem;
  63.    }
  64.  
  65.    if((BlueColorMap = (unsigned *) calloc(MAX256PALETTECOLORS,sizeof(unsigned))) == NULL)
  66.    {
  67.       Message = "No memory for BlueColorMap";
  68.       goto NoMem;
  69.    }
  70.  
  71.    tif = TIFFOpen(FileName,"w");
  72.    if (!tif)
  73.    {
  74.       restorecrtmode();
  75.       printf("Error opening output file: %s\n",FileName);
  76.       return(EFileIOError);
  77.    }
  78.  
  79.    /* set constant tags */
  80.    TIFFSetField(tif,TIFFTAG_SUBFILETYPE,0L);
  81.    TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,(long)ImageWidth);
  82.    TIFFSetField(tif,TIFFTAG_IMAGELENGTH,(long)ImageLength);
  83.    TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,BitsPerSample);
  84.    TIFFSetField(tif,TIFFTAG_COMPRESSION,COMPRESSION_LZW);
  85.    TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_PALETTE);
  86.    TIFFSetField(tif,TIFFTAG_MAKE,"Craig's Video Digitizer");
  87.    TIFFSetField(tif,TIFFTAG_ARTIST,"Craig A. Lindley");
  88.    TIFFSetField(tif,TIFFTAG_HOSTCOMPUTER,"IBM PC with VGA graphics adapter");
  89.    TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,SamplesPerPixel);
  90.    TIFFSetField(tif,TIFFTAG_XRESOLUTION,72.0);
  91.    TIFFSetField(tif,TIFFTAG_YRESOLUTION,72.0);
  92.    if (SamplesPerPixel == 1)
  93.       TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
  94.    else
  95.       TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
  96.  
  97.    TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_INCH);
  98.  
  99.    BytesPerRow = (unsigned) TIFFScanlineSize(tif);
  100.    /* allocate memory for single scan line from display */
  101.    if ((RowBuffer = malloc(BytesPerRow)) == NULL)
  102.    {
  103.       Message = "No memory for RowBuffer";
  104.       goto NoMem;
  105.    }
  106.    /* make strips approximately 8K in length */
  107.    RowsPerStrip = 8; /* (8L*1024L)/(long) BytesPerRow; */
  108.  
  109.    TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,RowsPerStrip);
  110.  
  111.    if ((BitsPerSample == 1) || (BitsPerSample == 4))
  112.    {
  113.       /* read palette from VGA adapter */
  114.       getpalette(&Palette);
  115.       for (Index=0; Index < 16; Index++)
  116.       {
  117.      /*
  118.      Even 16 color 320x200 images use VGA mode 13H
  119.      without a palette.
  120.      */
  121.      if (ImageWidth == LRMAXCOLS)
  122.         ColorReg = Index;
  123.      else
  124.         ColorReg = Palette.colors[Index];
  125.      /* read color register components from VGA */
  126.      GetAColorReg(ColorReg,&RedColor,&GreenColor,&BlueColor);
  127.      /*
  128.      Scale color components to range 0..255 as
  129.      required by the TIFF spec. Normal range is
  130.      from 0..63.
  131.      */
  132.      RedColorMap[Index]   = RedColor<<2;
  133.      GreenColorMap[Index] = GreenColor<<2;
  134.      BlueColorMap[Index]  = BlueColor<<2;
  135.       }
  136.    }
  137.    else
  138.    {
  139.       for (Index=0; Index < MAX256PALETTECOLORS; Index++)
  140.       {
  141.      /* read color register components from VGA */
  142.      GetAColorReg(Index,&RedColor,&GreenColor,&BlueColor);
  143.      /*
  144.      Scale color components to range 0..255 as
  145.      required by the TIFF spec. Normal range is
  146.      from 0..63.
  147.      */
  148.      RedColorMap[Index]   = RedColor<<2;
  149.      GreenColorMap[Index] = GreenColor<<2;
  150.      BlueColorMap[Index]  = BlueColor<<2;
  151.       }
  152.    }
  153.  
  154.    TIFFSetField(tif,TIFFTAG_COLORMAP,RedColorMap,GreenColorMap,BlueColorMap);
  155.  
  156.    if (ImageWidth == HRMAXCOLS)    /* a 640x200 or 640x480 image */
  157.    {
  158.       if (SamplesPerPixel == 1)
  159.       {
  160.      for (Row = 0; Row < ImageLength; Row++)
  161.      {
  162.         for (Col=0; Col < HRMAXCOLS; Col+=2)
  163.         {
  164.            Sample = getpixel(Col,Row) << 4;
  165.            RowBuffer[Col>>1] = Sample + getpixel(Col+1,Row);
  166.         }
  167.         if (!TIFFWriteScanline(tif,RowBuffer,Row,0))
  168.            return(EWrtScanLine);
  169.      }
  170.       }
  171.       else
  172.       {
  173.      /* Four samples per pixel */
  174.      for (BitPlane = 0; BitPlane < SamplesPerPixel; BitPlane++)
  175.      {
  176.         Mask = 1 << BitPlane;
  177.         for (Row = 0; Row < ImageLength; Row++)
  178.         {
  179.            memset(RowBuffer,0,BytesPerRow);
  180.            for (Col=0; Col < HRMAXCOLS; Col++)
  181.           if (getpixel(Col,Row) & Mask)
  182.              RowBuffer[Col>>3] |= 1 << (7 - (Col % BITSPERBYTE));
  183.            if (!TIFFWriteScanline(tif,RowBuffer,Row,BitPlane))
  184.           return(EWrtScanLine);
  185.         }
  186.      }
  187.       }
  188.    }
  189.    else
  190.    /*
  191.    320x200 pixel image. All 320x200 images are assumed to use
  192.    VGA mode 13H. For this reason, the GetPixel256() function
  193.    must be used to read the pixels from the image currently
  194.    displayed on the screen.
  195.    */
  196.    {
  197.       if (BitsPerSample == 4)
  198.       {
  199.      for (Row = 0; Row < ImageLength; Row++)
  200.      {
  201.         for (Col=0; Col < LRMAXCOLS; Col+=2)
  202.         {
  203.            Sample = GetPixel256(Col,Row) << 4;
  204.            RowBuffer[Col>>1] = Sample + GetPixel256(Col+1,Row);
  205.         }
  206.         if (!TIFFWriteScanline(tif,RowBuffer,Row,0))
  207.            return(EWrtScanLine);
  208.      }
  209.       }
  210.       else /* 320x200 8 bits/sample image */
  211.       {
  212.      for (Row = 0; Row < ImageLength; Row++)
  213.      {
  214.         for (Col=0; Col < LRMAXCOLS; Col++)
  215.            RowBuffer[Col] = GetPixel256(Col,Row);
  216.  
  217.         if (!TIFFWriteScanline(tif,RowBuffer,Row,0))
  218.            return(EWrtScanLine);
  219.      }
  220.       }
  221.    }
  222.    TIFFClose(tif);
  223.    free((char *) RowBuffer);
  224.    free((char *) RedColorMap);
  225.    free((char *) GreenColorMap);
  226.    free((char *) BlueColorMap);
  227.    return(NoError);
  228.  
  229. NoMem:
  230.    restorecrtmode();
  231.    printf("Error: %s\n",Message);
  232.    if (RowBuffer)
  233.       free((char *) RowBuffer);
  234.    if (RedColorMap)
  235.       free((char *) RedColorMap);
  236.    if (GreenColorMap)
  237.       free((char *) GreenColorMap);
  238.    if (BlueColorMap)
  239.       free((char *) BlueColorMap);
  240.    TIFFClose(tif);
  241.    return(ENoMemory);
  242. }
  243.  
  244. /*
  245. This function will display a TIFF file on the VGA
  246. graphics adapter. It will complain about TIFF files
  247. it doesn't understand. This code only supports a small
  248. portion of possible TIFF images. Constraints mainly a
  249. result of VGA limitations.
  250. */
  251.  
  252. CompletionCode DisplayTIFFFile(char *FileName, unsigned Verbose)
  253. {
  254.    TIFF *tif;
  255.    unsigned long ImageWidth, ImageLength;
  256.    unsigned PhotometricIntrp, Index;
  257.    unsigned *RedColorMap, *GreenColorMap, *BlueColorMap;
  258.    register short PixelNum;
  259.    register unsigned Col, Row;
  260.    unsigned MaxColors, LoadColorMap, RowByte, RowByteCnt;
  261.    unsigned BitColor, BitPlane, LowResImage;
  262.    unsigned long ScanlineBytes;
  263.    BYTE *RowBuffer;
  264.    register BYTE *RowBufferPtr;
  265.    char *Message = "";
  266.    BYTE *Map = NULL;
  267.    struct palettetype Palette;
  268.  
  269.    unsigned BitsPerSample = 1;         /* install TIFF defaults */
  270.    unsigned SamplesPerPixel = 1;
  271.    unsigned PlanarConfig = PLANARCONFIG_CONTIG;
  272.  
  273.    /* Attemp to open the specified TIFF file */
  274.    tif = TIFFOpen(FileName,"r");
  275.    if (!tif)
  276.    {
  277.       restorecrtmode();
  278.       printf("TIFF error: File %s not found or directory format error",FileName);
  279.       return(EFileNotFound);
  280.    }
  281.  
  282.    if (Verbose)
  283.    {
  284.       printf("\nTIFF file: %s\n\n",FileName);
  285.       TIFFPrintDirectory(tif, stdout, TRUE, TRUE, TRUE);
  286.       getch();
  287.    }
  288.    if ((RowBuffer = malloc((unsigned) TIFFScanlineSize(tif))) == NULL)
  289.    {
  290.       Message = "No memory for RowBuffer";
  291.       goto bad;
  292.    }
  293.  
  294.    /* check for the presence of the proper tag compliment */
  295.    if (!TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&ImageWidth))
  296.    {
  297.       Message = "ImageWidth tag missing";
  298.       goto bad;
  299.    }
  300.    ImageWidth = MIN(ImageWidth,HRMAXCOLS);
  301.  
  302.    if (!TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ImageLength))
  303.    {
  304.       Message = "ImageLength tag missing";
  305.       goto bad;
  306.    }
  307.    ImageLength = MIN(ImageLength,HRMAXROWS);
  308.  
  309.    if (!TIFFGetField(tif,TIFFTAG_BITSPERSAMPLE,&BitsPerSample))
  310.       printf("Warning BitsPerSample tag missing\n");
  311.  
  312.    /* check for proper values */
  313.    if ((BitsPerSample != 1) && (BitsPerSample != 4) && (BitsPerSample != 8))
  314.    {
  315.       Message = "BitsPerSample not 1,4 or 8";
  316.       goto bad;
  317.    }
  318.  
  319.    if (!TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&SamplesPerPixel))
  320.       printf("Warning SamplesPerPixel tag missing\n");
  321.    /* check for proper value */
  322.  
  323.    if ((SamplesPerPixel != 1) && (SamplesPerPixel != 4))
  324.    {
  325.       Message = "SamplesPerPixel not 1 or 4";
  326.       goto bad;
  327.    }
  328.  
  329.    if(!TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&PlanarConfig))
  330.       printf("Warning PlanarConfig tag missing\n");
  331.  
  332.  
  333.    if (!TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&PhotometricIntrp))
  334.    {
  335.       Message = "PhotometricInterpretation tag missing";
  336.       goto bad;
  337.    }
  338.    /* check for proper value */
  339.    if ((PhotometricIntrp != PHOTOMETRIC_MINISWHITE) &&
  340.        (PhotometricIntrp != PHOTOMETRIC_MINISBLACK) &&
  341.        (PhotometricIntrp != PHOTOMETRIC_PALETTE))
  342.    {
  343.       Message = "Cannot handle this PhotometricInterpretation";
  344.       goto bad;
  345.    }
  346.    /*
  347.    Figure out the max number of colors necessary for this
  348.    image. Create a mapping function, only required for
  349.    black and white images, to convert images which have
  350.    the color white as the minimum value to minimum black.
  351.    as required by the VGA adapter. The variable LoadColorMap
  352.    will be set true if this image contains a COLORMAP tag.
  353.    It will cause the palette to be loaded later.
  354.    */
  355.    MaxColors = 1 << (BitsPerSample * SamplesPerPixel);
  356.    Map = (char *)malloc((MaxColors) * sizeof (BYTE));
  357.    LoadColorMap = FALSE;
  358.    LowResImage  = FALSE;
  359.    switch(PhotometricIntrp)
  360.    {
  361.       case PHOTOMETRIC_MINISBLACK:
  362.      for (Index=0; Index < MaxColors ; Index++)
  363.         Map[Index] = Index;
  364.      break;
  365.       case PHOTOMETRIC_MINISWHITE:
  366.      for (Index=0; Index < MaxColors; Index++)
  367.         Map[Index] = MaxColors - Index - 1;
  368.      break;
  369.       case PHOTOMETRIC_PALETTE:
  370.      /*
  371.      Check to see if file has COLORMAP tag. If so, load
  372.      the three pointers to the colormap data.
  373.      */
  374.      if (!TIFFGetField(tif,TIFFTAG_COLORMAP,&RedColorMap,
  375.                         &GreenColorMap,
  376.                                             &BlueColorMap))
  377.          {
  378.         Message = "ColorMap tag missing";
  379.         goto bad;
  380.      }
  381.      LoadColorMap = TRUE;
  382.      break;
  383.       default:
  384.      Message = "Unsupported PhotometricInterpretation";
  385.      goto bad;
  386.    }
  387.  
  388.    InitGraphics();
  389.  
  390.    /* Determine VGA mode to use for display of image */
  391.    if (ImageWidth <= LRMAXCOLS)        /* less than 320 pixels */
  392.    {
  393.       ImageLength = MIN(ImageLength,LRMAXROWS); /* truncate to 200 */
  394.       Set256ColorMode();               /* VGA mode 13H */
  395.       LoadGray64Palette();             /* default 64 levels of gray */
  396.       LowResImage = TRUE;
  397.    }
  398.    else
  399.    {
  400.       ImageWidth = MIN(ImageWidth,HRMAXCOLS); /* truncate to 640 pixels */
  401.       if (ImageWidth <= LRMAXROWS)     /* 640x200 image ? */
  402.      setgraphmode(VGALO);
  403.       else if (ImageWidth <= MRMAXROWS)/* 640x350 image ? */
  404.      setgraphmode(VGAMED);
  405.       else                             /* 640x480 image */
  406.      setgraphmode(VGAHI);
  407.  
  408.       LoadGray16Palette();             /* 16 levels of gray palette */
  409.    }
  410.    if (LoadColorMap)
  411.    {
  412.       /*
  413.       Load the color registers with this palette after
  414.       scaling the color data by 4. Scaling is necessary
  415.       because data ranges from 0..255 and VGA accepts
  416.       0..63.
  417.       */
  418.       if (!LowResImage)
  419.      Palette.size = MaxColors;
  420.       for (Index=0; Index < MaxColors; Index++)
  421.       {
  422.     if (!LowResImage)
  423.        Palette.colors[Index] = Index;
  424.     SetAColorReg(Index,RedColorMap[Index]  >>2,
  425.                GreenColorMap[Index]>>2,
  426.                BlueColorMap[Index] >>2);
  427.       }
  428.       if (!LowResImage)
  429.      setallpalette(&Palette);
  430.    }
  431.    switch(BitsPerSample)
  432.    {
  433.       case 1:
  434.      if (SamplesPerPixel == 1)
  435.      {
  436.         ScanlineBytes =
  437.           MIN(TIFFScanlineSize(tif),ImageWidth/(long)BITSPERBYTE);
  438.         for (Row=0; Row < ImageLength; Row++)
  439.         {
  440.            if (!TIFFReadScanline(tif, RowBuffer, Row, 0))
  441.           break;
  442.            RowBufferPtr = RowBuffer;
  443.            for (RowByteCnt=0; RowByteCnt < ScanlineBytes; RowByteCnt++)
  444.            {
  445.           RowByte = *RowBufferPtr++;
  446.           for (PixelNum=7; PixelNum >= 0; PixelNum--)
  447.           {
  448.              BitColor = (Map[((RowByte & (1 << PixelNum)) != 0)])? 15:0;
  449.              putpixel(RowByteCnt*8+(7-PixelNum),Row,BitColor);
  450.           }
  451.            }
  452.         }
  453.      }
  454.      else /* Samples per Pixel = 4 */
  455.      {
  456.         for (Row=0; Row < ImageLength; Row++)
  457.         {
  458.            if (!TIFFReadScanline(tif, RowBuffer, Row, 0))
  459.           break;
  460.            for (Col = 0; Col < ImageWidth; Col++)
  461.           if (LoadColorMap && (ImageWidth == LRMAXCOLS))
  462.             PutPixel256(Col,Row,
  463.               (RowBuffer[Col>>3] & (1 << (7 - Col % BITSPERBYTE)))? 1:0);
  464.           else
  465.             putpixel(Col,Row,
  466.               (RowBuffer[Col>>3] & (1 << (7 - Col % BITSPERBYTE)))? 1:0);
  467.  
  468.         }
  469.         for (BitPlane = 1; BitPlane < SamplesPerPixel; BitPlane++)
  470.            for (Row=0; Row < ImageLength; Row++)
  471.            {
  472.           if (!TIFFReadScanline(tif, RowBuffer, Row, BitPlane))
  473.              break;
  474.           for (Col = 0; Col < ImageWidth; Col++)
  475.              if (RowBuffer[Col>>3] & (1 << (7 - Col % BITSPERBYTE)))
  476.             if (LoadColorMap && (ImageWidth == LRMAXCOLS))
  477.                PutPixel256(Col,Row, GetPixel256(Col,Row) | (1 << BitPlane));
  478.             else
  479.                putpixel(Col,Row, getpixel(Col,Row) | (1 << BitPlane));
  480.  
  481.            }
  482.      }
  483.          break;
  484.       case 4:
  485.      ScanlineBytes = MIN(TIFFScanlineSize(tif),ImageWidth/2L);
  486.          for (Row=0; Row < ImageLength; Row++)
  487.          {
  488.             if (!TIFFReadScanline(tif, RowBuffer, Row, 0))
  489.                break;
  490.             RowBufferPtr = RowBuffer;
  491.         for (RowByteCnt=0; RowByteCnt < ScanlineBytes; RowByteCnt++)
  492.             {
  493.            RowByte = *RowBufferPtr++;
  494.                if (LoadColorMap && (ImageWidth == LRMAXCOLS))
  495.                {
  496.                   PutPixel256(RowByteCnt*2,Row,((RowByte>>4) & 0xFF));
  497.                   PutPixel256(RowByteCnt*2+1,Row,(RowByte & 0xFF));
  498.                }
  499.                else
  500.                {
  501.                   putpixel(RowByteCnt*2,Row,((RowByte>>4) & 0xFF));
  502.                   putpixel(RowByteCnt*2+1,Row,(RowByte & 0xFF));
  503.                }
  504.             }
  505.          }
  506.      break;
  507.       case 8:
  508.      ScanlineBytes = MIN(TIFFScanlineSize(tif),ImageWidth);
  509.          for (Row=0; Row < ImageLength; Row++)
  510.          {
  511.             if (!TIFFReadScanline(tif, RowBuffer, Row, 0))
  512.                break;
  513.             RowBufferPtr = RowBuffer;
  514.         for (RowByteCnt=0; RowByteCnt < ScanlineBytes; RowByteCnt++)
  515.            PutPixel256(RowByteCnt,Row,(unsigned) *RowBufferPtr++);
  516.          }
  517.          break;
  518.    }
  519.    if (Map)
  520.       free((char *) Map);
  521.    if (RowBuffer)
  522.       free((char *) RowBuffer);
  523.    TIFFClose(tif);
  524.    return(TRUE);
  525.  
  526. bad:
  527.    restorecrtmode();
  528.    printf("Error: %s\n",Message);
  529.    if (Map)
  530.       free((char *) Map);
  531.    if (RowBuffer)
  532.       free((char *) RowBuffer);
  533.    TIFFClose(tif);
  534.    return(FALSE);
  535. }
  536.  
  537.  
  538.