TIF.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #if SUPPORT_TIF
  4. #include "../../../../ThirdPartyLibs/begin.h"
  5. #include "../../../../ThirdPartyLibs/Tiff/libtiff/tiffio.h"
  6. #include "../../../../ThirdPartyLibs/end.h"
  7. #endif
  8. namespace EE{
  9. /******************************************************************************/
  10. #if SUPPORT_TIF
  11. struct TIFFile
  12. {
  13. File &f;
  14. Long begin, // allows reading of TIF images from current file position and not from the file start
  15. end ; // allows detection of actual TIF file size, useful if we have data before/after the TIF image in the file
  16. TIFFile(File &f) : f(f) {begin=f.pos(); end=0;}
  17. };
  18. static tmsize_t TIFRead(thandle_t file, void *data, tmsize_t size)
  19. {
  20. if(TIFFile *f=(TIFFile*)file)
  21. {
  22. Int read=f->f.getReturnSize(data, size); MAX(f->end, f->f.pos());
  23. return read;
  24. }
  25. return 0;
  26. }
  27. static tmsize_t TIFWrite(thandle_t file, void *data, tmsize_t size)
  28. {
  29. if(TIFFile *f=(TIFFile*)file)
  30. {
  31. Int written=f->f.putReturnSize(data, size); MAX(f->end, f->f.pos());
  32. return written;
  33. }
  34. return 0;
  35. }
  36. static toff_t TIFSeek(thandle_t file, toff_t offset, int mode)
  37. {
  38. if(TIFFile *f=(TIFFile*)file)
  39. {
  40. switch(mode)
  41. {
  42. case SEEK_SET: offset+=f->begin ; break;
  43. case SEEK_CUR: offset+=f->f.pos (); break;
  44. case SEEK_END: offset+=f->f.size(); break;
  45. }
  46. f->f.pos(offset);
  47. return f->f.pos()-f->begin;
  48. }
  49. return 0;
  50. }
  51. static int TIFClose(thandle_t file)
  52. {
  53. return 0;
  54. }
  55. static toff_t TIFSize(thandle_t file)
  56. {
  57. if(TIFFile *f=(TIFFile*)file)return f->f.size()-f->begin;
  58. return 0;
  59. }
  60. #endif
  61. /******************************************************************************/
  62. Bool Image::ImportTIF(File &f)
  63. {
  64. #if SUPPORT_TIF
  65. Bool ok=false;
  66. TIFFile tf(f);
  67. TIFFSetErrorHandler (null); // disable error handlers, otherwise TIF library will create system message boxes
  68. TIFFSetErrorHandlerExt (null);
  69. TIFFSetWarningHandler (null);
  70. TIFFSetWarningHandlerExt(null);
  71. if(TIFF *tif=TIFFClientOpen("", "r", &tf, TIFRead, TIFWrite, TIFSeek, TIFClose, TIFSize, null, null)) // can't use null because crash will occur
  72. {
  73. uint32 w=0, h=0, samples=0, bits=0, photometric=0, compression=0;
  74. TIFFGetField(tif, TIFFTAG_IMAGEWIDTH , &w );
  75. TIFFGetField(tif, TIFFTAG_IMAGELENGTH , &h );
  76. TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples );
  77. TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE , &bits );
  78. TIFFGetField(tif, TIFFTAG_PHOTOMETRIC , &photometric);
  79. TIFFGetField(tif, TIFFTAG_COMPRESSION , &compression);
  80. Int scanline_size=TIFFScanlineSize(tif);
  81. if( scanline_size*8==samples*w*bits)
  82. {
  83. IMAGE_TYPE type=IMAGE_NONE;
  84. switch(samples)
  85. {
  86. case 1: if(photometric==PHOTOMETRIC_MINISBLACK)if(bits==8)type=IMAGE_L8;else if(bits==16)type=IMAGE_I16;else if(bits==24)type=IMAGE_I24;else if(bits==32)type=IMAGE_I32; break;
  87. case 3: if(photometric==PHOTOMETRIC_RGB)if(bits==8)type=IMAGE_R8G8B8 ; break;
  88. case 4: if(photometric==PHOTOMETRIC_RGB)if(bits==8)type=IMAGE_R8G8B8A8; break;
  89. }
  90. if(type && createSoftTry(w, h, 1, type))
  91. {
  92. if(compression==COMPRESSION_NONE)
  93. {
  94. ok=true; FREPD(y, h)if(!TIFFReadScanline(tif, data()+y*pitch(), y)){ok=false; break;} // read in forward order to avoid file seeking going back
  95. }else
  96. if(!TIFFIsTiled(tif))
  97. {
  98. ok=true;
  99. uint32 rows_per_strip=0, subsampling_x=0, subsampling_y=0;
  100. TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP , &rows_per_strip);
  101. TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsampling_x, &subsampling_y);
  102. Memt<Byte> buf; buf.setNum(TIFFStripSize(tif));
  103. for(UInt row=0; row<h; )
  104. {
  105. UInt rowstoread=rows_per_strip-row%rows_per_strip,
  106. nrow=(row+rowstoread>h ? h-row : rowstoread),
  107. nrowsub=nrow;
  108. if((nrowsub%subsampling_y)!=0)nrowsub+=subsampling_y-nrowsub%subsampling_y;
  109. tmsize_t read=TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf.data(), (row%rows_per_strip+nrowsub)*scanline_size);
  110. if(read!=nrow*scanline_size){ok=false; break;}
  111. Byte *dest=data()+row*pitch(), *src=buf.data()+(row%rows_per_strip)*scanline_size;
  112. REP(nrow)CopyFast(dest+i*pitch(), src+i*scanline_size, scanline_size);
  113. row+=nrow;
  114. }
  115. }
  116. }
  117. }
  118. if(!ok)
  119. if(createSoftTry(w, h, 1, IMAGE_R8G8B8A8))
  120. if(TIFFReadRGBAImageOriented(tif, w, h, (uint32*)data(), ORIENTATION_TOPLEFT, 0))
  121. {
  122. ok=true;
  123. if(photometric!=PHOTOMETRIC_PALETTE) // keep palette as RGBA
  124. if(samples==1 || samples==3)ok=copyTry(T, -1, -1, -1, (samples==1) ? IMAGE_L8 : IMAGE_R8G8B8);
  125. }
  126. TIFFClose(tif);
  127. f.pos(tf.end); // set position at the end of the read data, we have to do this because file pointer may not necessary be at the end, also don't use just 'f.size' in case there is some data after TIFF
  128. if(ok && f.ok())return true;
  129. }
  130. #endif
  131. del(); return false;
  132. }
  133. /******************************************************************************/
  134. Bool Image::ExportTIF(File &f, Flt compression_level)C
  135. {
  136. #if SUPPORT_TIF
  137. Image temp;
  138. C Image *src=this;
  139. IMAGE_TYPE uncompressed_type=src->type(); if(ImageTI[uncompressed_type].compressed)uncompressed_type=IMAGE_R8G8B8A8;
  140. if(src->cube ()){ temp.fromCube(*src , uncompressed_type, IMAGE_SOFT ); src=&temp;}
  141. if(src->compressed()){if(src->copyTry ( temp, -1, -1, -1, uncompressed_type, IMAGE_SOFT, 1)) src=&temp;else return false;}
  142. Bool ok=false;
  143. if(src->lockRead())
  144. {
  145. TIFFile tf(f);
  146. TIFFSetErrorHandler (null); // disable error handlers, otherwise TIF library will create system message boxes
  147. TIFFSetErrorHandlerExt (null);
  148. TIFFSetWarningHandler (null);
  149. TIFFSetWarningHandlerExt(null);
  150. if(TIFF *tif=TIFFClientOpen("", "w", &tf, TIFRead, TIFWrite, TIFSeek, TIFClose, TIFSize, null, null)) // can't use null because crash will occur
  151. {
  152. ok=true;
  153. C ImageTypeInfo &image_ti=ImageTI[src->type()];
  154. Bool alpha =(image_ti.a>0), bit16=(src->type()==IMAGE_I16);
  155. Byte channels= image_ti.channels; if(channels==2)channels=3;
  156. TIFFSetField(tif, TIFFTAG_IMAGEWIDTH , src->w());
  157. TIFFSetField(tif, TIFFTAG_IMAGELENGTH , src->h());
  158. TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels);
  159. TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE , bit16 ? 16 : 8);
  160. TIFFSetField(tif, TIFFTAG_ORIENTATION , ORIENTATION_TOPLEFT);
  161. TIFFSetField(tif, TIFFTAG_PLANARCONFIG , PLANARCONFIG_CONTIG);
  162. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC , (channels==1) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
  163. TIFFSetField(tif, TIFFTAG_COMPRESSION , (compression_level<0) ? COMPRESSION_NONE : (compression_level>0.5f) ? COMPRESSION_LZW : COMPRESSION_NONE);
  164. TIFFSetField(tif, TIFFTAG_PREDICTOR , PREDICTOR_HORIZONTAL);
  165. Memt<Byte> buf; buf.setNum(src->w()*channels*(bit16 ? 2 : 1));
  166. FREPD(y, src->h())
  167. {
  168. Byte *b=buf.data();
  169. if(bit16)CopyFast(b, src->data()+src->pitch()*y, buf.elms());else
  170. FREPD(x, src->w())
  171. {
  172. Color c=src->color(x, y);
  173. switch(channels)
  174. {
  175. case 1:
  176. {
  177. b[0]=(alpha ? c.a : c.r);
  178. b++;
  179. }break;
  180. case 3:
  181. {
  182. b[0]=c.r;
  183. b[1]=c.g;
  184. b[2]=c.b;
  185. b+=3;
  186. }break;
  187. case 4:
  188. {
  189. b[0]=c.r;
  190. b[1]=c.g;
  191. b[2]=c.b;
  192. b[3]=c.a;
  193. b+=4;
  194. }break;
  195. }
  196. }
  197. if(TIFFWriteScanline(tif, buf.data(), y)<0){ok=false; break;}
  198. }
  199. TIFFClose(tif);
  200. f.pos(tf.end); // set position at the end of the written data, we have to do this because 'TIFFClose' may perform seeking to write some data, also don't use just 'f.size' in case it had already some data before exporting
  201. ok&=f.ok();
  202. }
  203. src->unlock();
  204. }
  205. return ok;
  206. #endif
  207. return false;
  208. }
  209. /******************************************************************************/
  210. Bool Image::ExportTIF(C Str &name, Flt compression_level)C
  211. {
  212. File f; if(f.writeTry(name)){if(ExportTIF(f, compression_level) && f.flush())return true; f.del(); FDelFile(name);}
  213. return false;
  214. }
  215. Bool Image::ImportTIF(C Str &name)
  216. {
  217. File f; if(f.readTry(name))return ImportTIF(f);
  218. del(); return false;
  219. }
  220. /******************************************************************************/
  221. }
  222. /******************************************************************************/