С++ LibTiff - чтение и сохранение файла из памяти и в память
Есть ли способ в LibTiff, как я могу читать файл из памяти и сохранять его в памяти?
Я не хочу сначала сохранять изображение на диск, прежде чем открывать его другой библиотекой...
Большое спасибо!
Ответы
Ответ 1
Я знаю, что это старый вопрос, но я собираюсь опубликовать более простой и актуальный ответ для тех, кто, как я, нуждается в этой информации для более поздних версий libtiff. В самой последней версии libtiff (4.0.2) и даже в нескольких последних версиях, которые я считаю (проверьте ваш конкретный номер версии), есть включаемый файл с именем tiffio.hxx. Он имеет две внешние функции для чтения/записи в потоки в памяти:
extern TIFF* TIFFStreamOpen(const char*, std::ostream *);
extern TIFF* TIFFStreamOpen(const char*, std::istream *);
Вы можете просто включить этот файл и читать или записывать в память.
Написание примера:
#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.
Чтение очень похоже:
#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);
Это очень простые примеры, но вы можете видеть, что при использовании TIFFStreamOpen вам не нужно переопределять эти функции и передавать их в TIFFClientOpen.
Ответ 2
Вы должны создать собственное чтение/запись/и т.д. функции и передать их функции TIFFClientOpen
(not TIFFOpen
) при создании TIFF
.
Пример:
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);
И вы также должны реализовать следующие функции (st
, переданный этим функциям, - это something_you_will_use_later
, переданный в 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;
};
Ответ 3
Что я использую...:
#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;
}
/*===========================================================================*/
}
И затем:
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-memry:
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);
}