Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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 // mic fixme: read and write 16 bits images. 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; // default 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'; // 'I' == LE, 'M' == BE 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 // mic fixme: handle somehow not supported image type, cubemaps, 3d textures, mimaps etc. 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 // convert src to IT_UNSIGNED_BYTE / IF_RGBA 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 // little endian 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 // WIDTH 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 // HEIGHT 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 // BITS PER SAMPLE 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 // COMPRESSION 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 // PHOTOMETRIC INTERPRETATION 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 // STRIP OFFSET 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 // SAMPLES PER PIXEL 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 // ROWS PER STRIP 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 // STRIP BYTE COUNT 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 // X RESOLUTION 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 // Y RESOLUTION 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 // PLANAR CONFIGURATION 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 // RESOLUTION UNIT 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 // EXTRA SAMPLES 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 // next ifd offset 00360 fout->writeUInt32(0); 00361 00362 // rational1 00363 fout->writeUInt32(72); 00364 fout->writeUInt32(1); 00365 // rational2 00366 fout->writeUInt32(72); 00367 fout->writeUInt32(1); 00368 00369 // bits per sample 00370 fout->writeUInt16(8); 00371 fout->writeUInt16(8); 00372 fout->writeUInt16(8); 00373 fout->writeUInt16(8); 00374 00375 // save the lines in reverse order 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 //-----------------------------------------------------------------------------