00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "ioTIFF.hpp"
00033 #include <vlCore/LoadWriterManager.hpp>
00034 #include <vlCore/VisualizationLibrary.hpp>
00035 #include <vlCore/FileSystem.hpp>
00036 #include <vlCore/VirtualFile.hpp>
00037 #include <vlCore/Image.hpp>
00038 #include <tiffio.h>
00039
00040
00041
00042 using namespace vl;
00043
00044 namespace
00045 {
00046 void tiff_error(const char*, const char*, va_list)
00047 {
00048 vl::Log::error("ioTIFF unspecified error.\n");
00049 }
00050 void tiff_warning(const char *, const char *, va_list)
00051 {
00052 }
00053 tsize_t tiff_io_read_func(thandle_t fd, tdata_t buf, tsize_t size)
00054 {
00055 VirtualFile *fin = (VirtualFile*)fd;
00056 long long c = fin->read(buf,size);
00057 return (tsize_t)c;
00058 }
00059 tsize_t tiff_io_write_func(thandle_t fd, tdata_t buf, tsize_t size)
00060 {
00061 VirtualFile *fin = (VirtualFile*)fd;
00062 long long c = fin->write(buf,size);
00063 return (tsize_t)c;
00064 }
00065 toff_t tiff_io_seek_func(thandle_t fd, toff_t off, int i)
00066 {
00067 VirtualFile*fin = (VirtualFile*)fd;
00068
00069 switch(i)
00070 {
00071 case SEEK_SET:
00072 fin->seekSet(off);
00073 return (tsize_t)fin->position();
00074
00075 case SEEK_CUR:
00076 fin->seekCur(off);
00077 return (tsize_t)fin->position();
00078
00079 case SEEK_END:
00080 fin->seekEnd(off);
00081 return (tsize_t)fin->position();
00082
00083 default:
00084 return 0;
00085 }
00086 }
00087 int tiff_io_close_func(thandle_t fd)
00088 {
00089 VirtualFile*fin = (VirtualFile*)fd;
00090 fin->close();
00091 return 0;
00092 }
00093 toff_t tiff_io_size_func(thandle_t fd)
00094 {
00095 VirtualFile *fin = (VirtualFile*)fd;
00096 return (tsize_t)fin->size();
00097 }
00098 int tiff_io_map_func(thandle_t, tdata_t*, toff_t*)
00099 {
00100 return 0;
00101 }
00102 void tiff_io_unmap_func(thandle_t, tdata_t, toff_t)
00103 {
00104 return;
00105 }
00106 }
00107
00108
00109 ref<Image> vl::loadTIFF(const String& path)
00110 {
00111 ref<VirtualFile> file = defFileSystem()->locateFile(path);
00112 if ( !file )
00113 {
00114 Log::error( Say("File '%s' not found.\n") << path );
00115 return NULL;
00116 }
00117 else
00118 return loadTIFF(file.get());
00119 }
00120
00121 ref<Image> vl::loadTIFF(VirtualFile* file)
00122 {
00123 file->open(OM_ReadOnly);
00124 ref<Image> img = new Image;
00125
00126 TIFFSetErrorHandler(tiff_error);
00127 TIFFSetWarningHandler(tiff_warning);
00128
00129 TIFF* tif = TIFFClientOpen("tiffread", "r", reinterpret_cast<thandle_t>(file),
00130 tiff_io_read_func,
00131 tiff_io_write_func,
00132 tiff_io_seek_func,
00133 tiff_io_close_func,
00134 tiff_io_size_func,
00135 tiff_io_map_func,
00136 tiff_io_unmap_func);
00137
00138 if (tif)
00139 {
00140 uint32 w, h;
00141 size_t npixels;
00142 uint32* raster;
00143
00144 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
00145 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
00146 npixels = w * h;
00147 raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
00148 if (raster != NULL)
00149 {
00150 if (TIFFReadRGBAImage(tif, w, h, raster, 0))
00151 {
00152 img->allocate2D(w,h,1,vl::IF_RGBA,vl::IT_UNSIGNED_BYTE);
00153 memcpy(img->pixels(), raster, img->requiredMemory());
00154 }
00155 _TIFFfree(raster);
00156 }
00157 uint16 orientation = ORIENTATION_TOPLEFT;
00158 TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation);
00159 if (orientation == ORIENTATION_LEFTBOT )
00160 img->flipVertically();
00161 TIFFClose(tif);
00162 }
00163
00164 file->close();
00165 return img;
00166 }
00167
00168 bool vl::isTIFF(VirtualFile* file)
00169 {
00170 if (!file->open(OM_ReadOnly))
00171 return false;
00172
00173 unsigned char byteorder[2];
00174 file->read(byteorder, 2);
00175 bool little_endian = byteorder[0] == 'I';
00176 unsigned short version = file->readUInt16(little_endian);
00177 file->close();
00178
00179 if (byteorder[0] != byteorder[1])
00180 return false;
00181
00182 if (byteorder[0] != 'M' && byteorder[0] != 'I')
00183 return false;
00184
00185 if (byteorder[1] != 'M' && byteorder[1] != 'I')
00186 return false;
00187
00188 if (version != 42)
00189 return false;
00190
00191 return true;
00192 }
00193
00194 bool vl::saveTIFF(const Image* image, const String& path)
00195 {
00196 ref<DiskFile> file = new DiskFile(path);
00197 return saveTIFF(image, file.get());
00198 }
00199
00200 bool vl::saveTIFF(const Image* src, VirtualFile* fout)
00201 {
00202
00203
00204 int w = src->width();
00205 int h = src->height();
00206 int d = src->depth();
00207 if (h == 0) h=1;
00208 if (d == 0) d=1;
00209 if (src->isCubemap()) d=6;
00210 h = h*d;
00211
00212
00213 ref<Image> cimg;
00214 if (src->type() != IT_UNSIGNED_BYTE)
00215 {
00216 cimg = src->convertType(IT_UNSIGNED_BYTE);
00217 src = cimg.get();
00218 if (!cimg)
00219 {
00220 Log::error( Say("saveTIFF('%s'): could not convert src to IT_UNSIGNED_BYTE.\n") << fout->path() );
00221 return false;
00222 }
00223 }
00224 if (src->format() != IF_RGBA)
00225 {
00226 cimg = src->convertFormat(IF_RGBA);
00227 src = cimg.get();
00228 if (!cimg)
00229 {
00230 Log::error( Say("saveTIFF('%s'): could not convert src to IF_RGBA.\n") << fout->path() );
00231 return false;
00232 }
00233 }
00234
00235 const int SHORT = 3;
00236 const int LONG = 4;
00237 const int RATIONAL = 5;
00238
00239 if (!fout->open(OM_WriteOnly))
00240 {
00241 Log::error( Say("TIFF: could not open '%s' for writing.\n") << fout->path() );
00242 return false;
00243 }
00244
00245
00246 unsigned char little_endian[] = { 'I', 'I' };
00247 fout->write(little_endian, 2);
00248
00249 unsigned short version = 42;
00250 fout->writeUInt16(version);
00251
00252 unsigned long ifd_offset = 8;
00253 fout->writeUInt32(ifd_offset);
00254
00255 unsigned short dir_count = 14;
00256 fout->writeUInt16(dir_count);
00257
00258 unsigned short tag, type;
00259 unsigned long count;
00260
00261
00262
00263 tag = 256; fout->writeUInt16(tag);
00264 type = SHORT; fout->writeUInt16(type);
00265 count = 1; fout->writeUInt32(count);
00266 fout->writeUInt16((unsigned short)w); fout->writeUInt16(0);
00267
00268
00269
00270 tag = 257; fout->writeUInt16(tag);
00271 type = SHORT; fout->writeUInt16(type);
00272 count = 1; fout->writeUInt32(count);
00273 fout->writeUInt16((unsigned short)h); fout->writeUInt16(0);
00274
00275
00276
00277 tag = 258; fout->writeUInt16(tag);
00278 type = SHORT; fout->writeUInt16(type);
00279 count = 4; fout->writeUInt32(count);
00280 fout->writeUInt32(10 + dir_count*12 + 4 + 16);
00281
00282
00283
00284 tag = 259; fout->writeUInt16(tag);
00285 type = SHORT; fout->writeUInt16(type);
00286 count = 1; fout->writeUInt32(count);
00287 fout->writeUInt16(1); fout->writeUInt16(0);
00288
00289
00290
00291 tag = 262; fout->writeUInt16(tag);
00292 type = SHORT; fout->writeUInt16(type);
00293 count = 1; fout->writeUInt32(count);
00294 fout->writeUInt16(2); fout->writeUInt16(0);
00295
00296
00297
00298 tag = 273; fout->writeUInt16(tag);
00299 type = LONG; fout->writeUInt16(type);
00300 count = 1; fout->writeUInt32(count);
00301 fout->writeUInt32(10 + dir_count*12 + 4 + 16 + 8);
00302
00303
00304
00305 tag = 277; fout->writeUInt16(tag);
00306 type = SHORT; fout->writeUInt16(type);
00307 count = 1; fout->writeUInt32(count);
00308 fout->writeUInt16(4); fout->writeUInt16(0);
00309
00310
00311
00312 tag = 278; fout->writeUInt16(tag);
00313 type = SHORT; fout->writeUInt16(type);
00314 count = 1; fout->writeUInt32(count);
00315 fout->writeUInt16((unsigned short)h); fout->writeUInt16(0);
00316
00317
00318
00319 tag = 279; fout->writeUInt16(tag);
00320 type = LONG; fout->writeUInt16(type);
00321 count = 1; fout->writeUInt32(count);
00322 fout->writeUInt32(src->requiredMemory());
00323
00324
00325
00326 tag = 282; fout->writeUInt16(tag);
00327 type = RATIONAL; fout->writeUInt16(type);
00328 count = 1; fout->writeUInt32(count);
00329 fout->writeUInt32(10 + dir_count*12 + 4 + 0);
00330
00331
00332
00333 tag = 283; fout->writeUInt16(tag);
00334 type = RATIONAL; fout->writeUInt16(type);
00335 count = 1; fout->writeUInt32(count);
00336 fout->writeUInt32(10 + dir_count*12 + 4 + 8);
00337
00338
00339
00340 tag = 284; fout->writeUInt16(tag);
00341 type = SHORT; fout->writeUInt16(type);
00342 count = 1; fout->writeUInt32(count);
00343 fout->writeUInt16(1); fout->writeUInt16(0);
00344
00345
00346
00347 tag = 296; fout->writeUInt16(tag);
00348 type = SHORT; fout->writeUInt16(type);
00349 count = 1; fout->writeUInt32(count);
00350 fout->writeUInt16(2); fout->writeUInt16(0);
00351
00352
00353
00354 tag = 338; fout->writeUInt16(tag);
00355 type = SHORT; fout->writeUInt16(type);
00356 count = 1; fout->writeUInt32(count);
00357 fout->writeUInt16(0); fout->writeUInt16(0);
00358
00359
00360 fout->writeUInt32(0);
00361
00362
00363 fout->writeUInt32(72);
00364 fout->writeUInt32(1);
00365
00366 fout->writeUInt32(72);
00367 fout->writeUInt32(1);
00368
00369
00370 fout->writeUInt16(8);
00371 fout->writeUInt16(8);
00372 fout->writeUInt16(8);
00373 fout->writeUInt16(8);
00374
00375
00376 int y = h;
00377 while( y-- )
00378 fout->write(src->pixels()+src->pitch()*y, w*src->bitsPerPixel()/8);
00379
00380 fout->close();
00381 return true;
00382 }
00383