home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / imagtiff.cpp < prev    next >
C/C++ Source or Header  |  2002-05-23  |  9KB  |  385 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        imagtiff.cpp
  3. // Purpose:     wxImage TIFF handler
  4. // Author:      Robert Roebling
  5. // RCS-ID:      $Id: imagtiff.cpp,v 1.22 2002/05/22 23:14:47 VZ Exp $
  6. // Copyright:   (c) Robert Roebling
  7. // Licence:     wxWindows licence
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10. #ifdef __GNUG__
  11. #pragma implementation "imagtiff.h"
  12. #endif
  13.  
  14. // For compilers that support precompilation, includes "wx.h".
  15. #include "wx/wxprec.h"
  16.  
  17. #ifdef __BORLANDC__
  18. #pragma hdrstop
  19. #endif
  20.  
  21. #include "wx/defs.h"
  22.  
  23. #if wxUSE_IMAGE && wxUSE_LIBTIFF
  24.  
  25. #include "wx/imagtiff.h"
  26. #include "wx/bitmap.h"
  27. #include "wx/debug.h"
  28. #include "wx/log.h"
  29. #include "wx/app.h"
  30. extern "C"
  31. {
  32.     #include "tiff.h"
  33.     #include "tiffio.h"
  34. }
  35. #include "wx/filefn.h"
  36. #include "wx/wfstream.h"
  37. #include "wx/intl.h"
  38. #include "wx/module.h"
  39.  
  40. #ifndef TIFFLINKAGEMODE
  41.   #define TIFFLINKAGEMODE LINKAGEMODE
  42. #endif
  43.  
  44. //-----------------------------------------------------------------------------
  45. // wxTIFFHandler
  46. //-----------------------------------------------------------------------------
  47.  
  48. IMPLEMENT_DYNAMIC_CLASS(wxTIFFHandler,wxImageHandler)
  49.  
  50. extern "C"
  51. {
  52.  
  53. tsize_t TIFFLINKAGEMODE
  54. _tiffNullProc(thandle_t WXUNUSED(handle),
  55.           tdata_t WXUNUSED(buf),
  56.           tsize_t WXUNUSED(size))
  57. {
  58.     return (tsize_t) -1;
  59. }
  60.  
  61. tsize_t TIFFLINKAGEMODE
  62. _tiffReadProc(thandle_t handle, tdata_t buf, tsize_t size)
  63. {
  64.     wxInputStream *stream = (wxInputStream*) handle;
  65.     stream->Read( (void*) buf, (size_t) size );
  66.     return stream->LastRead();
  67. }
  68.  
  69. tsize_t TIFFLINKAGEMODE
  70. _tiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size)
  71. {
  72.     wxOutputStream *stream = (wxOutputStream*) handle;
  73.     stream->Write( (void*) buf, (size_t) size );
  74.     return stream->LastWrite();
  75. }
  76.  
  77. toff_t TIFFLINKAGEMODE
  78. _tiffSeekIProc(thandle_t handle, toff_t off, int whence)
  79. {
  80.     wxInputStream *stream = (wxInputStream*) handle;
  81.     wxSeekMode mode;
  82.     switch (whence)
  83.     {
  84.         case SEEK_SET: mode = wxFromStart; break;
  85.         case SEEK_CUR: mode = wxFromCurrent; break;
  86.         case SEEK_END: mode = wxFromEnd; break;
  87.         default:       mode = wxFromCurrent; break;
  88.     }
  89.  
  90.     return (toff_t)stream->SeekI( (off_t)off, mode );
  91. }
  92.  
  93. toff_t TIFFLINKAGEMODE
  94. _tiffSeekOProc(thandle_t handle, toff_t off, int whence)
  95. {
  96.     wxOutputStream *stream = (wxOutputStream*) handle;
  97.     wxSeekMode mode;
  98.     switch (whence)
  99.     {
  100.         case SEEK_SET: mode = wxFromStart; break;
  101.         case SEEK_CUR: mode = wxFromCurrent; break;
  102.         case SEEK_END: mode = wxFromEnd; break;
  103.         default:       mode = wxFromCurrent; break;
  104.     }
  105.  
  106.     return (toff_t)stream->SeekO( (off_t)off, mode );
  107. }
  108.  
  109. int TIFFLINKAGEMODE
  110. _tiffCloseProc(thandle_t WXUNUSED(handle))
  111. {
  112.     return 0;  // ?
  113. }
  114.  
  115. toff_t TIFFLINKAGEMODE
  116. _tiffSizeProc(thandle_t handle)
  117. {
  118.     wxStreamBase *stream = (wxStreamBase*) handle;
  119.     return (toff_t) stream->GetSize();
  120. }
  121.  
  122. int TIFFLINKAGEMODE
  123. _tiffMapProc(thandle_t WXUNUSED(handle),
  124.              tdata_t* WXUNUSED(pbase),
  125.              toff_t* WXUNUSED(psize))
  126. {
  127.     return 0;
  128. }
  129.  
  130. void TIFFLINKAGEMODE
  131. _tiffUnmapProc(thandle_t WXUNUSED(handle),
  132.                tdata_t WXUNUSED(base),
  133.                toff_t WXUNUSED(size))
  134. {
  135. }
  136.  
  137. } // extern "C"
  138.  
  139. TIFF*
  140. TIFFwxOpen(wxInputStream &stream, const char* name, const char* mode)
  141. {
  142.     TIFF* tif = TIFFClientOpen(name, mode,
  143.         (thandle_t) &stream,
  144.         _tiffReadProc, _tiffNullProc,
  145.         _tiffSeekIProc, _tiffCloseProc, _tiffSizeProc,
  146.         _tiffMapProc, _tiffUnmapProc);
  147.  
  148.     return tif;
  149. }
  150.  
  151. TIFF*
  152. TIFFwxOpen(wxOutputStream &stream, const char* name, const char* mode)
  153. {
  154.     TIFF* tif = TIFFClientOpen(name, mode,
  155.         (thandle_t) &stream,
  156.         _tiffNullProc, _tiffWriteProc,
  157.         _tiffSeekOProc, _tiffCloseProc, _tiffSizeProc,
  158.         _tiffMapProc, _tiffUnmapProc);
  159.  
  160.     return tif;
  161. }
  162.  
  163. bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
  164. {
  165.     if (index == -1)
  166.         index = 0;
  167.  
  168.     image->Destroy();
  169.  
  170.     TIFF *tif = TIFFwxOpen( stream, "image", "r" );
  171.  
  172.     if (!tif)
  173.     {
  174.         if (verbose)
  175.             wxLogError( _("TIFF: Error loading image.") );
  176.  
  177.         return FALSE;
  178.     }
  179.  
  180.     if (!TIFFSetDirectory( tif, (tdir_t)index ))
  181.     {
  182.         if (verbose)
  183.             wxLogError( _("Invalid TIFF image index.") );
  184.  
  185.         TIFFClose( tif );
  186.  
  187.         return FALSE;
  188.     }
  189.  
  190.     uint32 w, h;
  191.     uint32 npixels;
  192.     uint32 *raster;
  193.  
  194.     TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
  195.     TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );
  196.  
  197.     npixels = w * h;
  198.  
  199.     raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );
  200.  
  201.     if (!raster)
  202.     {
  203.         if (verbose)
  204.             wxLogError( _("TIFF: Couldn't allocate memory.") );
  205.  
  206.         TIFFClose( tif );
  207.  
  208.         return FALSE;
  209.     }
  210.  
  211.     image->Create( (int)w, (int)h );
  212.     if (!image->Ok())
  213.     {
  214.         if (verbose)
  215.             wxLogError( _("TIFF: Couldn't allocate memory.") );
  216.  
  217.         _TIFFfree( raster );
  218.         TIFFClose( tif );
  219.  
  220.         return FALSE;
  221.     }
  222.  
  223.     if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
  224.     {
  225.         if (verbose)
  226.             wxLogError( _("TIFF: Error reading image.") );
  227.  
  228.         _TIFFfree( raster );
  229.         image->Destroy();
  230.         TIFFClose( tif );
  231.  
  232.         return FALSE;
  233.     }
  234.  
  235.     bool hasmask = FALSE;
  236.  
  237.     unsigned char *ptr = image->GetData();
  238.     ptr += w*3*(h-1);
  239.     uint32 pos = 0;
  240.  
  241.     for (uint32 i = 0; i < h; i++)
  242.     {
  243.         for (uint32 j = 0; j < w; j++)
  244.         {
  245.             unsigned char alpha = (unsigned char)TIFFGetA(raster[pos]);
  246.             if (alpha < 127)
  247.             {
  248.                 hasmask = TRUE;
  249.                 ptr[0] = image->GetMaskRed();
  250.                 ptr++;
  251.                 ptr[0] = image->GetMaskGreen();
  252.                 ptr++;
  253.                 ptr[0] = image->GetMaskBlue();
  254.                 ptr++;
  255.             }
  256.             else
  257.             {
  258.                 ptr[0] = (unsigned char)TIFFGetR(raster[pos]);
  259.                 ptr++;
  260.                 ptr[0] = (unsigned char)TIFFGetG(raster[pos]);
  261.                 ptr++;
  262.                 ptr[0] = (unsigned char)TIFFGetB(raster[pos]);
  263.                 ptr++;
  264.             }
  265.             pos++;
  266.         }
  267.         ptr -= 2*w*3; // subtract line we just added plus one line
  268.     }
  269.  
  270.     _TIFFfree( raster );
  271.  
  272.     TIFFClose( tif );
  273.  
  274.     image->SetMask( hasmask );
  275.  
  276.     return TRUE;
  277. }
  278.  
  279. int wxTIFFHandler::GetImageCount( wxInputStream& stream )
  280. {
  281.     TIFF *tif = TIFFwxOpen( stream, "image", "r" );
  282.  
  283.     if (!tif)
  284.         return 0;
  285.  
  286.     int dircount = 0;  // according to the libtiff docs, dircount should be set to 1 here???
  287.     do {
  288.         dircount++;
  289.     } while (TIFFReadDirectory(tif));
  290.  
  291.     TIFFClose( tif );
  292.  
  293.     return dircount;
  294. }
  295.  
  296. bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
  297. {
  298.     TIFF *tif = TIFFwxOpen( stream, "image", "w" );
  299.  
  300.     if (!tif)
  301.     {
  302.         if (verbose)
  303.             wxLogError( _("TIFF: Error saving image.") );
  304.  
  305.         return FALSE;
  306.     }
  307.  
  308.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH,  (uint32)image->GetWidth());
  309.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32)image->GetHeight());
  310.     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  311.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
  312.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  313.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  314.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  315.     TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
  316.  
  317.     tsize_t linebytes = (tsize_t)image->GetWidth() * 3;
  318.     unsigned char *buf;
  319.  
  320.     if (TIFFScanlineSize(tif) > linebytes)
  321.     {
  322.         buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));
  323.         if (!buf)
  324.         {
  325.             if (verbose)
  326.                 wxLogError( _("TIFF: Couldn't allocate memory.") );
  327.  
  328.             TIFFClose( tif );
  329.  
  330.             return FALSE;
  331.         }
  332.     }
  333.     else
  334.     {
  335.         buf = NULL;
  336.     }
  337.  
  338.     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
  339.         TIFFDefaultStripSize(tif, (uint32) -1));
  340.  
  341.     unsigned char *ptr = image->GetData();
  342.     for (int row = 0; row < image->GetHeight(); row++)
  343.     {
  344.         if (buf)
  345.             memcpy(buf, ptr, image->GetWidth());
  346.  
  347.         if (TIFFWriteScanline(tif, buf ? buf : ptr, (uint32)row, 0) < 0)
  348.         {
  349.             if (verbose)
  350.                 wxLogError( _("TIFF: Error writing image.") );
  351.  
  352.             TIFFClose( tif );
  353.             if (buf)
  354.                 _TIFFfree(buf);
  355.  
  356.             return FALSE;
  357.         }
  358.         ptr += image->GetWidth()*3;
  359.     }
  360.  
  361.     (void) TIFFClose(tif);
  362.  
  363.     if (buf)
  364.     _TIFFfree(buf);
  365.  
  366.     return TRUE;
  367. }
  368.  
  369. bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
  370. {
  371.     unsigned char hdr[2];
  372.  
  373.     if ( !stream.Read(&hdr, WXSIZEOF(hdr)) )
  374.         return FALSE;
  375.  
  376.     return (hdr[0] == 'I' && hdr[1] == 'I') ||
  377.            (hdr[0] == 'M' && hdr[1] == 'M');
  378. }
  379.  
  380.  
  381. #endif
  382.    // wxUSE_LIBTIFF
  383.  
  384.  
  385.