mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
6.6 KiB
295 lines
6.6 KiB
/* $Id: tif_stream.cxx,v 1.6.2.1 2009-01-01 00:10:43 bfriesen Exp $ */ |
|
|
|
/* |
|
* Copyright (c) 1988-1996 Sam Leffler |
|
* Copyright (c) 1991-1996 Silicon Graphics, Inc. |
|
* |
|
* Permission to use, copy, modify, distribute, and sell this software and |
|
* its documentation for any purpose is hereby granted without fee, provided |
|
* that (i) the above copyright notices and this permission notice appear in |
|
* all copies of the software and related documentation, and (ii) the names of |
|
* Sam Leffler and Silicon Graphics may not be used in any advertising or |
|
* publicity relating to the software without the specific, prior written |
|
* permission of Sam Leffler and Silicon Graphics. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, |
|
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
|
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
|
* |
|
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR |
|
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, |
|
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF |
|
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
|
* OF THIS SOFTWARE. |
|
*/ |
|
|
|
/* |
|
* TIFF Library UNIX-specific Routines. |
|
*/ |
|
#include "tiffiop.h" |
|
#include <iostream> |
|
|
|
#ifndef __VMS |
|
using namespace std; |
|
#endif |
|
|
|
class tiffis_data |
|
{ |
|
public: |
|
|
|
istream *myIS; |
|
long myStreamStartPos; |
|
}; |
|
|
|
class tiffos_data |
|
{ |
|
public: |
|
|
|
ostream *myOS; |
|
long myStreamStartPos; |
|
}; |
|
|
|
static tsize_t |
|
_tiffosReadProc(thandle_t, tdata_t, tsize_t) |
|
{ |
|
return 0; |
|
} |
|
|
|
static tsize_t |
|
_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size) |
|
{ |
|
tiffis_data *data = (tiffis_data *)fd; |
|
|
|
data->myIS->read((char *)buf, (int)size); |
|
|
|
return data->myIS->gcount(); |
|
} |
|
|
|
static tsize_t |
|
_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size) |
|
{ |
|
tiffos_data *data = (tiffos_data *)fd; |
|
ostream *os = data->myOS; |
|
int pos = os->tellp(); |
|
|
|
os->write((const char *)buf, size); |
|
|
|
return ((int)os->tellp()) - pos; |
|
} |
|
|
|
static tsize_t |
|
_tiffisWriteProc(thandle_t, tdata_t, tsize_t) |
|
{ |
|
return 0; |
|
} |
|
|
|
static toff_t |
|
_tiffosSeekProc(thandle_t fd, toff_t off, int whence) |
|
{ |
|
tiffos_data *data = (tiffos_data *)fd; |
|
ostream *os = data->myOS; |
|
|
|
// if the stream has already failed, don't do anything |
|
if( os->fail() ) |
|
return os->tellp(); |
|
|
|
switch(whence) { |
|
case SEEK_SET: |
|
os->seekp(data->myStreamStartPos + off, ios::beg); |
|
break; |
|
case SEEK_CUR: |
|
os->seekp(off, ios::cur); |
|
break; |
|
case SEEK_END: |
|
os->seekp(off, ios::end); |
|
break; |
|
} |
|
|
|
// Attempt to workaround problems with seeking past the end of the |
|
// stream. ofstream doesn't have a problem with this but |
|
// ostrstream/ostringstream does. In that situation, add intermediate |
|
// '\0' characters. |
|
if( os->fail() ) { |
|
#ifdef __VMS |
|
int old_state; |
|
#else |
|
ios::iostate old_state; |
|
#endif |
|
toff_t origin=0; |
|
|
|
old_state = os->rdstate(); |
|
// reset the fail bit or else tellp() won't work below |
|
os->clear(os->rdstate() & ~ios::failbit); |
|
switch( whence ) { |
|
case SEEK_SET: |
|
origin = data->myStreamStartPos; |
|
break; |
|
case SEEK_CUR: |
|
origin = os->tellp(); |
|
break; |
|
case SEEK_END: |
|
os->seekp(0, ios::end); |
|
origin = os->tellp(); |
|
break; |
|
} |
|
// restore original stream state |
|
os->clear(old_state); |
|
|
|
// only do something if desired seek position is valid |
|
if( origin + off > data->myStreamStartPos ) { |
|
toff_t num_fill; |
|
|
|
// clear the fail bit |
|
os->clear(os->rdstate() & ~ios::failbit); |
|
|
|
// extend the stream to the expected size |
|
os->seekp(0, ios::end); |
|
num_fill = origin + off - (toff_t)os->tellp(); |
|
for( toff_t i = 0; i < num_fill; i++ ) |
|
os->put('\0'); |
|
|
|
// retry the seek |
|
os->seekp(origin + off, ios::beg); |
|
} |
|
} |
|
|
|
return os->tellp(); |
|
} |
|
|
|
static toff_t |
|
_tiffisSeekProc(thandle_t fd, toff_t off, int whence) |
|
{ |
|
tiffis_data *data = (tiffis_data *)fd; |
|
|
|
switch(whence) { |
|
case SEEK_SET: |
|
data->myIS->seekg(data->myStreamStartPos + off, ios::beg); |
|
break; |
|
case SEEK_CUR: |
|
data->myIS->seekg(off, ios::cur); |
|
break; |
|
case SEEK_END: |
|
data->myIS->seekg(off, ios::end); |
|
break; |
|
} |
|
|
|
return ((long)data->myIS->tellg()) - data->myStreamStartPos; |
|
} |
|
|
|
static toff_t |
|
_tiffosSizeProc(thandle_t fd) |
|
{ |
|
tiffos_data *data = (tiffos_data *)fd; |
|
ostream *os = data->myOS; |
|
toff_t pos = os->tellp(); |
|
toff_t len; |
|
|
|
os->seekp(0, ios::end); |
|
len = os->tellp(); |
|
os->seekp(pos); |
|
|
|
return len; |
|
} |
|
|
|
static toff_t |
|
_tiffisSizeProc(thandle_t fd) |
|
{ |
|
tiffis_data *data = (tiffis_data *)fd; |
|
int pos = data->myIS->tellg(); |
|
int len; |
|
|
|
data->myIS->seekg(0, ios::end); |
|
len = data->myIS->tellg(); |
|
data->myIS->seekg(pos); |
|
|
|
return len; |
|
} |
|
|
|
static int |
|
_tiffosCloseProc(thandle_t fd) |
|
{ |
|
// Our stream was not allocated by us, so it shouldn't be closed by us. |
|
delete (tiffos_data *)fd; |
|
return 0; |
|
} |
|
|
|
static int |
|
_tiffisCloseProc(thandle_t fd) |
|
{ |
|
// Our stream was not allocated by us, so it shouldn't be closed by us. |
|
delete (tiffis_data *)fd; |
|
return 0; |
|
} |
|
|
|
static int |
|
_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* ) |
|
{ |
|
return (0); |
|
} |
|
|
|
static void |
|
_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t ) |
|
{ |
|
} |
|
|
|
/* |
|
* Open a TIFF file descriptor for read/writing. |
|
*/ |
|
static TIFF* |
|
_tiffStreamOpen(const char* name, const char* mode, void *fd) |
|
{ |
|
TIFF* tif; |
|
|
|
if( strchr(mode, 'w') ) { |
|
tiffos_data *data = new tiffos_data; |
|
data->myOS = (ostream *)fd; |
|
data->myStreamStartPos = data->myOS->tellp(); |
|
|
|
// Open for writing. |
|
tif = TIFFClientOpen(name, mode, |
|
(thandle_t) data, |
|
_tiffosReadProc, _tiffosWriteProc, |
|
_tiffosSeekProc, _tiffosCloseProc, |
|
_tiffosSizeProc, |
|
_tiffDummyMapProc, _tiffDummyUnmapProc); |
|
} else { |
|
tiffis_data *data = new tiffis_data; |
|
data->myIS = (istream *)fd; |
|
data->myStreamStartPos = data->myIS->tellg(); |
|
// Open for reading. |
|
tif = TIFFClientOpen(name, mode, |
|
(thandle_t) data, |
|
_tiffisReadProc, _tiffisWriteProc, |
|
_tiffisSeekProc, _tiffisCloseProc, |
|
_tiffisSizeProc, |
|
_tiffDummyMapProc, _tiffDummyUnmapProc); |
|
} |
|
|
|
return (tif); |
|
} |
|
|
|
TIFF* |
|
TIFFStreamOpen(const char* name, ostream *os) |
|
{ |
|
// If os is either a ostrstream or ostringstream, and has no data |
|
// written to it yet, then tellp() will return -1 which will break us. |
|
// We workaround this by writing out a dummy character and |
|
// then seek back to the beginning. |
|
if( !os->fail() && (int)os->tellp() < 0 ) { |
|
*os << '\0'; |
|
os->seekp(0); |
|
} |
|
|
|
// NB: We don't support mapped files with streams so add 'm' |
|
return _tiffStreamOpen(name, "wm", os); |
|
} |
|
|
|
TIFF* |
|
TIFFStreamOpen(const char* name, istream *is) |
|
{ |
|
// NB: We don't support mapped files with streams so add 'm' |
|
return _tiffStreamOpen(name, "rm", is); |
|
} |
|
|
|
/* vim: set ts=8 sts=8 sw=8 noet: */
|
|
|