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

前端 未结 3 411
情书的邮戳
情书的邮戳 2021-01-01 19:48

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

相关标签:
3条回答
  • 2021-01-01 20:11

    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);
        }
    
    0 讨论(0)
  • 2021-01-01 20:20

    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.

    0 讨论(0)
  • 2021-01-01 20:25

    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;
    };
    
    0 讨论(0)
提交回复
热议问题