2005.03.15 17:56 "[Tiff] Need to write CCITT T.6 encoded TIFF file data directly to memory buffer", by Roger Watkins

2005.03.17 23:57 "Re: [Tiff] Need to write CCITT T.6 encoded TIFF file datadirectlytomemory buffer", by Roger Watkins

Joris and everyone else;

Success!!! I can now use libTIFF 3.7.1 with BCB5 TMemoryStream. This allows me to read in TIFFs using normal file libTIFF features, merge the files, and put the result directly into a stream that can be used to load a database without having to use an imtermediate temporary file for the result. In response to Joris Van Damme, who so graciously provided much needed assistance, patience, kindness (not to mention the VERY useful Pascal source), and stated:

I know for a fact that the TStream IO procedures in LibTiffDelphi.pas work, and you've identified them, so the easiest way is probably to translate these short routines to C. If you do, posting your translation here is a) a good way to have second opinions on it, and b) a nice gift to an archive user that has the same requirement.

The following two files are provided as text without strings (except of couse that I will dissavow any responsibility should someone be upset with them):

// BCBlibTIFF_ext.h
// This code is translated from Delphi (Pascal) code received from Joris Van
//  Damme.  Although Author has taken pains to translate this properly and
//  to ensure the resulting code meets C, C++ and libTIFF 3.7.1 standards, this
//  code is "use at your own risk" and carries no warranty of any kind, nor will
//  Author or his company accept any responsibility for use or misuse of this
//  code.
// This is a set of functions written to extend libTIFF features to work in
//  Borland C++ Builder 5.  Specifically, it addresses reading/writing a
//  TIFF file to/from a memory buffer or a TMemoryStream.  File streams and
//  blob streams are not addressed here.  File streams are not needed for use
//  of libTIFF, which handles file I/O just fine using a C-style file
//  interface.  Blob streams are a special case not addressed here but for
//  which these functions could easily be adapted merely by changing each
//  occurrence of "TMemoryStream" to "TBlobStream".
#ifndef BCBLIBTIFFEXT
#define BCBLIBTIFFEXT 1
// ================================ INCLUDES ================================
#include <vcl.h>
#include <windows.h>
#include "tiffconf.h"
#include "tiffio.h"

// ============================== DEFINITIONS ===============================

// ============================== DECLARATIONS ==============================
TIFF *TIFFOpenTStream(const TMemoryStream *Stream, const char *Mode);
tsize_t TIFFTStreamRead(thandle_t Stream,tdata_t Buffer,tsize_t Size);
tsize_t TIFFTStreamWrite(thandle_t Stream,tdata_t Buffer,tsize_t Size);
toff_t TIFFTStreamSeek(thandle_t Stream,toff_t Off,int Whence);
int TIFFTStreamClose(thandle_t Stream);
toff_t TIFFTStreamSize(thandle_t Stream);
int TIFFTStreamMap(thandle_t Stream, tdata_t *Base, toff_t *Size);
void TIFFTStreamUnmap(thandle_t Stream, tdata_t Base, toff_t Size);

#endif // BCBLIBTIFFEXT



// BCBlibTIFF_ext.cpp
// This code is translated from Delphi (Pascal) code received from Joris Van
//  Damme.  Although Author has taken pains to translate this properly and
//  to ensure the resulting code meets C, C++ and libTIFF 3.7.1 standards, this
//  code is "use at your own risk" and carries no warranty of any kind, nor will
//  Author or his company accept any responsibility for use or misuse of this
//  code.
// This is a set of functions written to extend libTIFF features to work in
//  Borland C++ Builder 5.  Specifically, it addresses reading/writing a
//  TIFF file to/from a memory buffer or a TMemoryStream.  File streams and
//  blob streams are not addressed here.  File streams are not needed for use
//  of libTIFF, which handles file I/O just fine using a C-style file
//  interface.  Blob streams are a special case not addressed here but for
//  which these functions could easily be adapted merely by changing each
//  occurrence of "TMemoryStream" to "TBlobStream".
// ================================ INCLUDES ================================
#include "BCBlibTIFF_ext.h"

// ============================== DEFINITIONS ===============================

// ============================== DECLARATIONS ==============================

// =============================== FUNCTIONS ================================

// --------------------------- TIFFOpenTStream() ----------------------------
// This function sets up a Borland TStream for handling I/O for a TIFF
//  structure.  To use this function, Stream must already be created and
//  allocated using:
//   TMemoryStream* Stream = new TMemoryStream();
// The calling application must also call:
//   delete(Stream);
//  when done.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Mode           This is one of the standard modes as described in
//                       TIFFClientOpen() documentation, generally it will be
//                       "r" (read), "w" (write), or "a" (append), possibly with
//                       modifiers l, L, b, B, H, m, M, c, or C.
// Return Value:
//        A pointer to the TIFF opened is returned.  A NULL value indicates
//        failure.
// Author:  Roger Watkins
// Date:  16MAR05
TIFF *TIFFOpenTStream(const TMemoryStream *Stream, const char *Mode)
{
     TIFF *returnval;

     // use TIFFClientOpen() to configure libTIFF to use these functions for I/O
     returnval = TIFFClientOpen("Stream",Mode,(thandle_t)Stream,
                                TIFFTStreamRead,TIFFTStreamWrite,
                                TIFFTStreamSeek,TIFFTStreamClose,
                                TIFFTStreamSize, TIFFTStreamMap,
                                TIFFTStreamUnmap);
     if (returnval != (TIFF *)NULL)
       TIFFSetFileno(returnval,(int)Stream);  // assign stream handle as Fd
     return returnval;
} // end TIFFOpenTStream()

// --------------------------- TIFFTStreamRead() ----------------------------
// This function reads Size bytes of data from Stream into Buffer.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Buffer         This is a pointer to the base address of the byte
//                       buffer to read data into.
//        Size           This is the number of bytes to read into Buffer.
// Return Value:
//        The number of bytes read into Buffer.  On an error interrupt durng
//        read, the returned value will be zero.
// Author:  Roger Watkins
// Date:  16MAR05
tsize_t TIFFTStreamRead(thandle_t Stream,tdata_t Buffer,tsize_t Size)
{
     tsize_t returnval;

     try
     { // attempt a standard read
       returnval = ((TMemoryStream *)Stream)->Read((void *)Buffer,(int)Size);
     } // end try
     catch (...)
     { // read failed for whatever reason, so no characters were read properly
       returnval = 0;
     } // end catch
     return returnval;
} // end TIFFTStreamRead()

// --------------------------- TIFFTStreamWrite() ---------------------------
// This function writes Size bytes of data from Stream to Buffer.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Buffer         This is a pointer to the base address of the byte
//                       buffer to write data to.
//        Size           This is the number of bytes to write to Buffer.
// Return Value:
//        The number of bytes written to Buffer.  On an error interrupt durng
//        write, the returned value will be zero.
// Author:  Roger Watkins
// Date:  16MAR05
tsize_t TIFFTStreamWrite(thandle_t Stream,tdata_t Buffer,tsize_t Size)
{
     tsize_t returnval;

     try
     { // attempt a standard write
       returnval = ((TMemoryStream *)Stream)->Write((void *)Buffer,(int)Size);
     } // end try
     catch (...)
     { // write failed for whatever reason, no characters were written properly
       returnval = 0;
     } // end catch
     return returnval;
} // end TIFFTStreamWrite()

// --------------------------- TIFFTStreamSeek() ----------------------------
// This function moves the location for reading or writing within the stream.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Off            This is the offset location to move to.
//        Whence         This is reference point for the offset location.
//             SEEK_SET  (0)  offset from beginning of stream
//             SEEK_CUR  (1)  offset from current position in stream
//             SEEK_END  (2)  offset from end of stream
//
// Return Value:
//        The new value of the stream position.  On an error interrupt durng
//        write, the returned value will be zero.  If Off is 0xFFFFFFFF,
//        no seek will be performed and 0xFFFFFFFF will be returned.
// Note:  This code is translated and Author does not understand why 0xFFFFFFFF
//   should be a problem.
// Author:  Roger Watkins
// Date:  17MAR05
toff_t TIFFTStreamSeek(thandle_t Stream,toff_t Off,int Whence)
{
     toff_t returnval;
     Word MoveMethod;

     if (Off == 0xFFFFFFFF)
     { // bad value, don't do it (??????)
       returnval = (toff_t)0xFFFFFFFF;
       return returnval;
     } // end if (Off == 0xFFFFFFFF)
     switch (Whence)
     { // translate choices from libTIFF to BCB alternatives
       case 0:  // libTIFF SEEK_SET
         MoveMethod = soFromBeginning;
         break;
       case 1:  // libTIFF SEEK_CUR
         MoveMethod = soFromCurrent;
         break;
       case 2:  // libTIFF SEEK_END
         MoveMethod = soFromEnd;
         break;
       default:
         MoveMethod = soFromBeginning;
         break;
     } // end switch (Whence)
     try
     {
       returnval = ((TMemoryStream *)Stream)->Seek(Off,MoveMethod);
     } // end try
     catch (...)
     { // failed, so return zero (start of stream)
       returnval = (toff_t)0;
     } // end catch
     return returnval;
} // end TIFFTStreamSeek()

// --------------------------- TIFFTStreamClose() ---------------------------
// This function is called to release resources associated with the previously
//  open TIFF.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
// Return Value:
//        Zero.
// Author:  Roger Watkins
// Date:  17MAR05
int TIFFTStreamClose(thandle_t Stream)
{
//  following line eliminated because this would cause the stream contents to be
//   elminated when the TIFF is closed
//     ((TMemoryStream *)Stream)->Clear();  // free stream associated memory
     return 0;
} // end TIFFTStreamClose()

// --------------------------- TIFFTStreamSize() ---------------------------
// This function is called to obtain the length of Stream.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
// Return Value:
//        Length in bytes, with 0 on a failure.
// Author:  Roger Watkins
// Date:  17MAR05
toff_t TIFFTStreamSize(thandle_t Stream)
{
     toff_t returnval;
     try
     {
       returnval = ((TMemoryStream *)Stream)->Size;  // read length of Stream
     } // end try
     catch (...)
     {
       returnval = 0;
     }
     return returnval;
} // end TIFFTStreamSize()

// ---------------------------- TIFFTStreamMap() ----------------------------
// This function is called to map Stream onto memory, a process that has no
//  meaning here so is basically ignored.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Base           This is a base address (I think)
//        Size           This is the size in bytes to map (I think)
// Return Value:
//        Zero.
// Author:  Roger Watkins
// Date:  17MAR05
#pragma argsused      // (prevent compiler from complaining about unused args)
int TIFFTStreamMap(thandle_t Stream, tdata_t *Base, toff_t *Size)
{
     return 0;  // successful map by definition
} // end TIFFTStreamMap()

// --------------------------- TIFFTStreamUnmap() ---------------------------
// This function is called to unmap Stream from memory, a process that has no
//  meaning here so is basically ignored.
// Arguments:
//        Stream         This is the handle of a TStream previously created.
//        Base           This is a base address (I think)
//        Size           This is the size in bytes to map (I think)
// Return Value:
//        Zero.
// Author:  Roger Watkins
// Date:  17MAR05
#pragma argsused      // (prevent compiler from complaining about unused args)
void TIFFTStreamUnmap(thandle_t Stream, tdata_t Base, toff_t Size)
{
     return;  // (do nothing)
} // end TIFFTStreamUnmap()