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