Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ LibTiff - Read and Save file from and to Memory

Is there a way in LibTiff how I can read a file from Memory and save it to Memory?

I don't want to save the image to the disc first, before opening it with an other library...

Thanks so much!

like image 835
Van Coding Avatar asked Jan 07 '11 09:01

Van Coding


3 Answers

I know this is an old question, but I am going to post an easier, more up-to-date answer for those like myself who need this information for more recent versions of libtiff. In the newest version of libtiff (4.0.2), and even the past few versions I believe (check for your specific version number), there is an include file called tiffio.hxx. It has two extern functions for reading/writing to streams in memory:

extern TIFF* TIFFStreamOpen(const char*, std::ostream *);
extern TIFF* TIFFStreamOpen(const char*, std::istream *);

You can just include this file and read or write to memory.

Writing example:

#include <tiffio.h>
#include <tiffio.hxx>
#include <sstream>    

std::ostringstream output_TIFF_stream;

//Note: because this is an in memory TIFF, just use whatever you want for the name - we 
//aren't using it to read from a file
TIFF* mem_TIFF = TIFFStreamOpen("MemTIFF", &output_TIFF_stream);

//perform normal operations on mem_TIFF here like setting fields
//...

//Write image data to the TIFF 
//..

TIFFClose(mem_TIFF);   

//Now output_TIFF_stream has all of my image data. I can do whatever I need to with it.

Reading is very similar:

#include <tiffio.h>
#include <tiffio.hxx>
#include <sstream>

std::istringstream input_TIFF_stream;
//Populate input_TIFF_stream with TIFF image data
//...

TIFF* mem_TIFF = TIFFStreamOpen("MemTIFF", &input_TIFF_stream);

//perform normal operations on mem_TIFF here reading fields
//...

TIFFClose(mem_TIFF);

These are very simple examples, but you can see that by using TIFFStreamOpen you don't have to override those functions and pass them to TIFFClientOpen.

like image 127
KSletmoe Avatar answered Sep 22 '22 09:09

KSletmoe


You should create your own read/write/etc. functions and pass them to TIFFClientOpen (not TIFFOpen) function when creating your TIFF.

Example:

TIFF* tif = TIFFClientOpen(
    "Memory", "w", (thandle_t)something_you_will_use_later,
    tiff_Read, tiff_Write, tiff_Seek, tiff_Close, tiff_Size,
    tiff_Map, tiff_Unmap);

And you should also implement following functions (st passed to these functions is the something_you_will_use_later passed to TIFFClientOpen :

tsize_t tiff_Read(thandle_t st,tdata_t buffer,tsize_t size)
{
    ...
};

tsize_t tiff_Write(thandle_t st,tdata_t buffer,tsize_t size)
{
    ...
};

int tiff_Close(thandle_t)
{
    return 0;
};

toff_t tiff_Seek(thandle_t st,toff_t pos, int whence)
{
    if (pos == 0xFFFFFFFF)
       return 0xFFFFFFFF;
    ...
};

toff_t tiff_Size(thandle_t st)
{
    ...
};

int tiff_Map(thandle_t, tdata_t*, toff_t*)
{
    return 0;
};

void tiff_Unmap(thandle_t, tdata_t, toff_t)
{
    return;
};
like image 7
Bobrovsky Avatar answered Sep 20 '22 09:09

Bobrovsky


What I'm using...:

#define MALLOC(ptr,type,number,action) {\
if (((ptr) = (type*) malloc ((number)*sizeof(type))) == NULL) {\
    (void) fprintf (stderr, "[%s: #%04d] ERROR : malloc of %lu bytes failed !\n", __FILE__, __LINE__, number*sizeof(type));\
    perror ("Operating system message");\
    action;}}

#define REALLOC(ptr,type,number,action) {\
if (((ptr) = (type*) realloc ((ptr), (number)*sizeof(type))) == NULL) {\
    (void) fprintf (stderr, "[%s: #%04d] ERROR : realloc of %lu bytes failed!\n", __FILE__, __LINE__, number*sizeof(type));\
    perror ("Operating system message");\
    action;}}

#define FREE(ptr) { if (ptr != NULL) free (ptr); ptr = NULL; }


extern "C" {

    typedef struct _memtiff {
        unsigned char *data;
        tsize_t size;
        tsize_t incsiz;
        tsize_t flen;
        toff_t fptr;
    } MEMTIFF;

    static MEMTIFF *memTiffOpen(tsize_t incsiz = 10240, tsize_t initsiz = 10240)
    {
        MEMTIFF *memtif;
        MALLOC(memtif, MEMTIFF, 1, exit(-1));
        memtif->incsiz = incsiz;
        if (initsiz == 0) initsiz = incsiz;
        MALLOC(memtif->data, unsigned char, initsiz, exit(-1));
        memtif->size = initsiz;
        memtif->flen = 0;
        memtif->fptr = 0;
        return memtif;
    }
    /*===========================================================================*/

    static tsize_t memTiffReadProc(thandle_t handle, tdata_t buf, tsize_t size)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        tsize_t n;
        if (((tsize_t) memtif->fptr + size) <= memtif->flen) {
            n = size;
        }
        else {
            n = memtif->flen - memtif->fptr;
        }
        memcpy(buf, memtif->data + memtif->fptr, n);
        memtif->fptr += n;

        return n;
    }
    /*===========================================================================*/

    static tsize_t memTiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        if (((tsize_t) memtif->fptr + size) > memtif->size) {
            memtif->data = (unsigned char *) realloc(memtif->data, memtif->fptr + memtif->incsiz + size);
            memtif->size = memtif->fptr + memtif->incsiz + size;
        }
        memcpy (memtif->data + memtif->fptr, buf, size);
        memtif->fptr += size;
        if (memtif->fptr > memtif->flen) memtif->flen = memtif->fptr;

        return size;
    }
    /*===========================================================================*/

    static toff_t memTiffSeekProc(thandle_t handle, toff_t off, int whence)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        switch (whence) {
            case SEEK_SET: {
                if ((tsize_t) off > memtif->size) {
                    memtif->data = (unsigned char *) realloc(memtif->data, memtif->size + memtif->incsiz + off);
                    memtif->size = memtif->size + memtif->incsiz + off;
                }
                memtif->fptr = off;
                break;
            }
            case SEEK_CUR: {
                if ((tsize_t)(memtif->fptr + off) > memtif->size) {
                    memtif->data = (unsigned char *) realloc(memtif->data, memtif->fptr + memtif->incsiz + off);
                    memtif->size = memtif->fptr + memtif->incsiz + off;
                }
                memtif->fptr += off;
                break;
            }
            case SEEK_END: {
                if ((tsize_t) (memtif->size + off) > memtif->size) {
                    memtif->data = (unsigned char *) realloc(memtif->data, memtif->size + memtif->incsiz + off);
                    memtif->size = memtif->size + memtif->incsiz + off;
                }
                memtif->fptr = memtif->size + off;
                break;
            }
        }
        if (memtif->fptr > memtif->flen) memtif->flen = memtif->fptr;
        return memtif->fptr;
    }
    /*===========================================================================*/

    static int memTiffCloseProc(thandle_t handle)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        memtif->fptr = 0;
        return 0;
    }
    /*===========================================================================*/


    static toff_t memTiffSizeProc(thandle_t handle)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        return memtif->flen;
    }
    /*===========================================================================*/


    static int memTiffMapProc(thandle_t handle, tdata_t* base, toff_t* psize)
    {
        MEMTIFF *memtif = (MEMTIFF *) handle;
        *base = memtif->data;
        *psize = memtif->flen;
        return (1);
    }
    /*===========================================================================*/

    static void memTiffUnmapProc(thandle_t handle, tdata_t base, toff_t size)
    {
        return;
    }
    /*===========================================================================*/

    static void memTiffFree(MEMTIFF *memtif)
    {
        FREE(memtif->data);
        FREE(memtif);
        return;
    }
    /*===========================================================================*/

}

And then:

if ((filepath == "-") || (filepath == "HTTP")) {
    memtif = memTiffOpen();
    tif = TIFFClientOpen("MEMTIFF", "wb", (thandle_t) memtif,
        memTiffReadProc,
        memTiffWriteProc,
        memTiffSeekProc,
        memTiffCloseProc,
        memTiffSizeProc,
        memTiffMapProc,
        memTiffUnmapProc
    );
}
else {
    if ((tif = TIFFOpen (filepath.c_str(), "wb")) == NULL) {
        if (memtif != NULL) memTiffFree(memtif);
        string msg = "TIFFopen of \"" + filepath + "\" failed!";
        throw SipiError(__file__, __LINE__, msg);
    }
}

In order to use the in-memry buffer:

    if (filepath == "-") {
        size_t n = 0;
        while (n < memtif->flen) {
            n += fwrite (&(memtif->data[n]), 1, memtif->flen - n > 10240 ? 10240 : memtif->flen - n, stdout);
        }
        fflush(stdout);
        memTiffFree(memtif);
    }
like image 5
Lukas Rosenthaler Avatar answered Sep 23 '22 09:09

Lukas Rosenthaler