tiff/0000755000176000001440000000000012211542311011222 5ustar ripleyuserstiff/inst/0000755000176000001440000000000012211457633012213 5ustar ripleyuserstiff/inst/img/0000755000176000001440000000000012211457633012767 5ustar ripleyuserstiff/inst/img/Rlogo.tiff0000644000176000001440000003314012211457633014724 0ustar ripleyusersMM*5n P8$ BaPd6D`fCiBOw<ߒ0LAg =P^#Gt!'(D%t$GJWVkUv_CIgN"Y3 SRG~ovzޯA|@.g@ h0$ɍp\v[=mX`0Y+z^a_@zPn>$o,_@_.L 1 _|!a+ʪLa^U!rg,(9BS #CΌ>ƺN/s-`>njSGqLHok⪸<`H [?Yf j8 L Įf ~0›~NDAđ3nŠD 3ŻLT1=d%6F SNDGY@HPB^ @Lum%!>ǁ/NaR Q$l sDv} ?:t:7FI6e !T,SJ])u&97Y#J/FG@l2Bs;&X)LLyx]:{OL~6Hk)faB1KBB|iXQg޲Ro4%${rV&l 6;׸ ÇN $XHM hW $| S$h;D3` PRc3Q&3նO 6әS;}mc6]AIֈ mjg @,a0 >G(*mZ*a\ZľDʾ0D FTV@A潇} ڞ-<`+ޏ.DX\_"@& K 'oi/ 0\Add@@ZpPql*hqd;)J̵P Jg+/@2 cJ>'ԫNAPUU##l  G Ѥ 1tnN/ !ALt6AFB.$A.`Qtw !JvJ@`P5]<́,!~mlG#&PNNaR}B\24VvF!n&@ <`*N`8bD"&ܽ<U(` 䙌؂|@K8`^!*.+.a*l2rR`p0LjA8 Ę>w\ B* )R`-0(K؏@HF nu ,a*z CG}ACt |B 6t PLRA#8lA`h`+f`^a\G"qfx OaiY֜`^@PHjS#kWsjF @ 2+ad,"`Q4ֈLS+IKWtyc⭪f&DD 2ʎ*{pH8 qV~l+@AG/AI-!w \ЩuP!?J]4TIFg!xy?, `TbV}K1Mk*:VQU++mAwH,@, Aa;4oT၏Sy+/B6r"k`: @7A!}A*̠L @ @ *A:pE\q2g!. = "!6y `Zrz /,FYa_]=$  >NjW;ݙc۝;z!xɡ~{Ȥ(A* N `F*fyˠ%!|赌aal@rnfsb*zvᢔ`]S&|TX ^s~:& ]+|^1A 4 G7-Ә CN)CVIWcj Q@`b7" @.Ӑi6} `d6dLL< I}/7޴ P. B9pJ/V@{?lz oQhT0Q4rIsyяP[zM[WtD`Ic1U(C8OG_@{p4s:wbQ~`m "h22i*N%)ZZB K"ojᰟg B)>>@qMP^cfLyTNF(%A @P˞gmq@8 Z81O$Ls)*PS~ J;T}0 *#ePiJ0"Nc NL: ,i{<yG a t/ԁ1ǹ+ FD{!6j #@$2P%ra)02np?q,Oql_fYe1X]i`4?]FNr.@FPt&йbEouICj Yc{[FFG}=F0 z5MjWO@NhVxz>m\xGacuW2nY=Zpm0nPDrTYnaF!vB( f:H(@ d\sL@iR@I&fda^@yUzcIODmz~m̆k5NҘ\Ԡ~zw!{)GY@A5r47PZAAl!2bÄ\.!r"g|F4M P80 T l AbtIy= ; Qv o 4{h#q0"!+Q$`X'8ضDE>ȅcvJsđ4V{Q A)"{>62Hb5r:\X Gl5d$A-$PzBKj -Ds):!;Q%`98%P|@0& 7<!~%aDu "6&N =ЪQL00 @dY4f MJ X $@,5 0񴶱;q #ThpA.)Yʘ++BmoWTq  'Er2!A8 PuF;DpR@d4AD@ 2<3nG ĕ{A,.&Ĩ%#m(L m0# A VUഒ:N~xxq8GZ}#~@puAu)oL? ZjTk A x."@Q T19#h p7F7EN@>Tk0M 0jbY 17lp$"p y!gc :|7{ToQ-Q T@ܬ2(U18?ZAެ@2`He{n:on6ʥ@Hl D>P@|xպɰoq BJE¤T ]z NDWv1P#hJ 6jDpKz!}Ѐ oS QE0s"E=k]1pQу+$e$jj!Ězp AX)XWf73*) >mA(B sYX + ՛ [hT]70ԁ#אȈ !଩Npg\0⧫Ճ`6p"HD0^`ONehXpXhVHWB>;8|8@;1{Qp8[S`,C"12+yY5a#; hjp&p8}A"ⲚH)`iੌ$v'J!q( }"IхPR'#'+1(@Vdc:pvT!X^i\LLQ oHF(#ʼn5,pJJdٞsď"xhn:? P@hK{(A wb;jod콥$w)Օ8#H'h,&kԌB}=[e;pj"@uMc nv+$,w0!>hPhysԇmn9)d@nxi$#y;Aׇ#iE\!E!pADO{oxMONPd % @Ǐ]F<E7Yp!T* HpY:@b}@q2(vtci^hu vMG04x'9eQQX` :pYhxhYX@ >g^`N8a;{:X}EX|™g^xK0sł}0f# @0mNDpzX#sŕHaE#'(HGˆJg2,2-H(\H8a$HʕՖܹP6Հ X y\j!{{jJl _Ԍn( |YUZ0y A0X% <:ҙuS|S0XvO `"@*IRS@K%^R~ 2WM̑ zt2ȀӲ(|ޖ 8ˇ(rUW'mhMON4lP{ΐ)Aqm=M+Ő_xh¢lH`dDH/wVYiI1PyZxcͰ&`%`+)8U( VW}}ӳT(U& D t1?H\ £|YYMROADJ'c,<ŇT#JUˎAШiՁ !X=Xhk-ey)9 ѫxLKl@}Ehr;PsQЂ$H%H A~K[&R!Eh{  ɘ}2ӇvHKh<۸܈cI`~Y7N벧&3cyE-JQܞ(Z5=]{y6PUCEΕ~Cj$݃@i+xY4YjF (8o hP  ~}ґ8<;mw QUfn<2,VUh04+8N 8|GxavPe(=7`YZv"`><PX#H|~#q`kX+XNSwPX&$_R]Hl0inG'N@zlbj奊ť S`[`er8v 9TXfFжk*0ht厫 HV0n~ȇr[a,b8lp]^pFxD8n XH3Y+)5!!y5fQ}n?0hX.Lj_g*h~P]NkRx,-rdHYa4p)$LQωI( @rt2ȁ, ~s $-Ɇ_ g !H/pUH{{/`8H,K`81p d8~?|r]%?M2AP|A9`b7" Z[VHngnD!!TT{V u|f_/4  P_pP3jv:#u9@ N +?`8"fZGc~APPc1I/}w{r;ïBm{l)FcQ BB: #<n&\gbFX (j*jjj6kIJ,BԶ-˂.;9"SFp@6hnL CʲbLwmqq,-8txX|ts``6 v` B;VP]вzgL( @(A'`d˦Hߧ}g ʌ)Jb*J,*±:ҵz#*"xgHP Հ2fq~x F&y=gAZOhvQ1HBfw$x&< ġ"K'Fi٩Cqp{5sEV?T6>Uh赥aZk {HǑ#($CcĖTOfV[iflA;VժWN^p| 8k vpr SXErY P*~%h3%&@7"sC(vyfC9G1rǘ3AN>4 !R06N"ñY-AoiEel88@E!L" @. эA iY,pNuCw cyuˏQE 7Қ5q@n A",?'=;>P.9G( ,3dPCR$DH^U eMxHy`,&[RD2,X1Z)0p/()sUVr X$mJM h0ظ @V(NpjFmM I8!P>¸T 24?a]q ĺ>^cDbtQTp=H~oJ#ϵ?֋kt~D) VjŭnKq]#2D<$0Rjp  A17KnG1a<\}qRJ#SFA @ܿAc,IHhԊn%)&`Ϣr|jZ3Th .Hu Ut sWQ(ZNk$A<1&0x l+| FVq2vуn6m2D9ӈ%v B[u/xs tXGAf9rl03["ƜϱƓkCR*RiV58QM&h:>ڰ&v%C` 4.8@> B9: UÕv2R&LxFۦxRa:P.F %2p]A_ FzQsHƎ9X%|CZ`%i{K%EzSuIm&\˩w/:dNQn#h`( h&^IiPV EF>)ŴǨC& 0":L=Dp> O Y"tf'r4ߋ صu!׍3*lr1%]`bյ By$)]n:.KrőΛb]1Fx^p H7ɒp0 <bX3N6F&_ /pHsB ATVT  II!&|mZ_c*` Dc Fޓ G "Vc~a @ REJzd~Q8,+  4nApJO`bsZAF1`eP.@jAV-AjpN~a~0A"&PIJPP\+$U#.!iJk@  .0M7A硲 QYNc.@>,>r M.Ah+)yTD NaxšELP A $z&w>5b."j6A|A@ȕdpd,1A @ `g|"*-%TVI|TC|.`F=oAAn> To Pr4q$ǂ* n  y&@bA:! Un!dAb*\~&[  dL6@L5e6H6P(=RS6X% % tiff/src/0000755000176000001440000000000012211457633012025 5ustar ripleyuserstiff/src/Makevars0000644000176000001440000000004512211457633013520 0ustar ripleyusersPKG_LIBS=-ltiff -ljpeg # PKG_CFLAGS= tiff/src/common.h0000644000176000001440000000041612211457634013470 0ustar ripleyusers#ifndef PKG_TIFF_COMMON_H__ #define PKG_TIFF_COMMON_H__ #include #include #include typedef struct tiff_job { FILE *f; long ptr, len, alloc; char *data; } tiff_job_t; TIFF *TIFF_Open(const char *mode, tiff_job_t *rj); #endif tiff/src/common.c0000644000176000001440000001167312211457634013472 0ustar ripleyusers#include "common.h" #include #include #include static int need_init = 1; static char txtbuf[2048]; static TIFF *last_tiff; /* this to avoid leaks */ static void TIFFWarningHandler_(const char* module, const char* fmt, va_list ap) { /* we can't pass it directly since R has no vprintf entry point */ vsnprintf(txtbuf, sizeof(txtbuf), fmt, ap); Rf_warning("%s: %s", module, txtbuf); } static int err_reenter = 0; static void TIFFErrorHandler_(const char* module, const char* fmt, va_list ap) { if (err_reenter) return; /* prevent re-entrance which can happen as TIFF is happy to call another error from Close */ err_reenter = 1; /* FIXME: if TIFFClose below fails we may get stuck without errors!! */ /* we can't pass it directly since R has no vprintf entry point */ vsnprintf(txtbuf, sizeof(txtbuf), fmt, ap); /* we have to close the TIFF that caused it as it will not come back -- recursive calls won't work under errors but that is hopefully unlikely/impossible */ if (last_tiff) TIFFClose(last_tiff); /* this will also reset last_tiff */ err_reenter = 0; Rf_error("%s: %s", module, txtbuf); } static void init_tiff() { if (need_init) { TIFFSetWarningHandler(TIFFWarningHandler_); TIFFSetErrorHandler(TIFFErrorHandler_); need_init = 0; } } static tsize_t TIFFReadProc_(thandle_t usr, tdata_t buf, tsize_t length) { tiff_job_t *rj = (tiff_job_t*) usr; tsize_t to_read = length; if (rj->f) return fread(buf, 1, to_read, rj->f); #if TIFF_DEBUG Rprintf("read [@%d %d/%d] -> %d\n", rj->ptr, rj->len, rj->alloc, length); #endif if (to_read > (rj->len - rj->ptr)) to_read = (rj->len - rj->ptr); if (to_read > 0) { memcpy(buf, rj->data + rj->ptr, to_read); rj->ptr += to_read; } return to_read; } static int guarantee_write_buffer(tiff_job_t *rj, long where) { if (where > rj->alloc) { /* need to resize buffer? */ void *new_data; unsigned long new_alloc = rj->alloc; while (new_alloc <= where) new_alloc <<= 1; new_data = realloc(rj->data, new_alloc); if (!new_data) /* FAILED */ return 0; rj->data = new_data; rj->alloc = new_alloc; } return 1; } static tsize_t TIFFWriteProc_(thandle_t usr, tdata_t buf, tsize_t length) { tiff_job_t *rj = (tiff_job_t*) usr; if (rj->f) return (tsize_t) fwrite(buf, 1, length, rj->f); #if TIFF_DEBUG Rprintf("write [@%d %d/%d] <- %d\n", rj->ptr, rj->len, rj->alloc, length); #endif if (!guarantee_write_buffer(rj, rj->ptr + length)) return 0; memcpy(rj->data + rj->ptr, buf, length); rj->ptr += length; if (rj->ptr > rj->len) rj->len = rj->ptr; return length; } static toff_t TIFFSeekProc_(thandle_t usr, toff_t offset, int whence) { tiff_job_t *rj = (tiff_job_t*) usr; if (rj->f) { int e = fseeko(rj->f, offset, whence); if (e != 0) { Rf_warning("fseek failed on a file in TIFFSeekProc"); return -1; } return ftello(rj->f); } #if TIFF_DEBUG Rprintf("seek [@%d %d/%d] %d (%d)\n", rj->ptr, rj->len, rj->alloc, offset, whence); #endif if (whence == SEEK_CUR) offset += rj->ptr; else if (whence == SEEK_END) offset += rj->len; else if (whence != SEEK_SET) { Rf_warning("invalid `whence' argument to TIFFSeekProc callback called by libtiff"); return -1; } if (rj->alloc && rj->len < offset) { if (offset >= rj->alloc) { /* need more space? */ if (!guarantee_write_buffer(rj, offset)) return -1; } else /* enough space but need to zero out */ memset(rj->data + rj->len, 0, offset - rj->len); rj->len = offset; } if (offset < 0 || offset > rj->len) { Rf_warning("libtiff attempted to seek beyond the data end"); return -1; } return (toff_t) (rj->ptr = offset); } static int TIFFCloseProc_(thandle_t usr) { tiff_job_t *rj = (tiff_job_t*) usr; if (rj->f) fclose(rj->f); else if (rj->alloc) { free(rj->data); rj->data = 0; rj->alloc = 0; } last_tiff = 0; return 0; } static toff_t TIFFSizeProc_(thandle_t usr) { tiff_job_t *rj = (tiff_job_t*) usr; if (rj->f) { off_t cur = ftello(rj->f), end; fseek(rj->f, 0, SEEK_END); end = ftello(rj->f); fseeko(rj->f, cur, SEEK_SET); return end; } return (toff_t) rj->len; } static int TIFFMapFileProc_(thandle_t usr, tdata_t* map, toff_t* off) { Rf_warning("libtiff attempted to use TIFFMapFileProc on non-file which is unsupported"); return -1; } static void TIFFUnmapFileProc_(thandle_t usr, tdata_t map, toff_t off) { Rf_warning("libtiff attempted to use TIFFUnmapFileProc on non-file which is unsupported"); } /* actual interface */ TIFF *TIFF_Open(const char *mode, tiff_job_t *rj) { if (need_init) init_tiff(); #if AGGRESSIVE_CLEANUP if (last_tiff) TIFFClose(last_tiff); #endif return (last_tiff = TIFFClientOpen("pkg:tiff", mode, (thandle_t) rj, TIFFReadProc_, TIFFWriteProc_, TIFFSeekProc_, TIFFCloseProc_, TIFFSizeProc_, TIFFMapFileProc_, TIFFUnmapFileProc_) ); } tiff/src/read.c0000644000176000001440000004301612211457634013111 0ustar ripleyusers#include #include #include #include "common.h" #include /* avoid protection issues with setAttrib where new symbols may trigger GC probelms */ static void setAttr(SEXP x, const char *name, SEXP val) { PROTECT(val); setAttrib(x, Rf_install(name), val); UNPROTECT(1); } /* add information attributes accorsing to the TIGG tags. Only a somewhat randome set (albeit mostly baseline) is supported */ static void TIFF_add_info(TIFF *tiff, SEXP res) { uint32 i32; uint16 i16; float f; char *c = 0; if (TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &i32)) setAttr(res, "depth", ScalarInteger(i32)); if (TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &i16)) setAttr(res, "bits.per.sample", ScalarInteger(i16)); if (TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &i16)) setAttr(res, "samples.per.pixel", ScalarInteger(i16)); if (TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &i16)) { char uv[24]; const char *name = 0; switch (i16) { case 1: name = "uint"; break; case 2: name = "int"; break; case 3: name = "float"; break; case 4: name = "undefined"; break; case 5: name = "complex int"; break; case 6: name = "complex float"; break; default: snprintf(uv, sizeof(uv), "unknown (%d)", i16); name = uv; } setAttr(res, "sample.format", mkString(name)); } if (TIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &i16)) { if (i16 == PLANARCONFIG_CONTIG) setAttr(res, "planar.config", mkString("contiguous")); else if (i16 == PLANARCONFIG_SEPARATE) setAttr(res, "planar.config", mkString("separate")); else { char uv[24]; snprintf(uv, sizeof(uv), "unknown (%d)", i16); setAttr(res, "planar.config", mkString(uv)); } } if (TIFFGetField(tiff, TIFFTAG_COMPRESSION, &i16)) { char uv[24]; const char *name = 0; switch (i16) { case 1: name = "none"; break; case 2: name = "CCITT RLE"; break; case 32773: name = "PackBits"; break; case 3: name = "CCITT Group 3 fax"; break; case 4: name = "CCITT Group 4 fax"; break; case 5: name = "LZW"; break; case 6: name = "old JPEG"; break; case 7: name = "JPEG"; break; case 8: name = "deflate"; break; case 9: name = "JBIG b/w"; break; case 10: name = "JBIG color"; break; default: snprintf(uv, sizeof(uv), "unknown (%d)", i16); name = uv; } setAttr(res, "compression", mkString(name)); } if (TIFFGetField(tiff, TIFFTAG_THRESHHOLDING, &i16)) setAttr(res, "threshholding", ScalarInteger(i16)); if (TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &f)) setAttr(res, "x.resolution", ScalarReal(f)); if (TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &f)) setAttr(res, "y.resolution", ScalarReal(f)); if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &i16)) { const char *name = "unknown"; switch (i16) { case 1: name = "none"; break; case 2: name = "inch"; break; case 3: name = "cm"; break; } setAttr(res, "resolution.unit", mkString(name)); } #ifdef TIFFTAG_INDEXED /* very recent in libtiff even though it's an old tag */ if (TIFFGetField(tiff, TIFFTAG_INDEXED, &i16)) setAttr(res, "indexed", ScalarLogical(i16)); #endif if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &i16)) { const char *name = ""; switch (i16) { case 1: name = "top.left"; break; case 2: name = "top.right"; break; case 3: name = "bottom.right"; break; case 4: name = "bottom.left"; break; case 5: name = "left.top"; break; case 6: name = "right.top"; break; case 7: name = "right.bottom"; break; case 8: name = "left.bottom"; break; } setAttr(res, "orientation", mkString(name)); } if (TIFFGetField(tiff, TIFFTAG_COPYRIGHT, &c) && c) setAttr(res, "copyright", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_ARTIST, &c) && c) setAttr(res, "artist", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_DOCUMENTNAME, &c) && c) setAttr(res, "document.name", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_DATETIME, &c) && c) setAttr(res, "date.time", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &c) && c) setAttr(res, "description", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_SOFTWARE, &c) && c) setAttr(res, "software", mkString(c)); if (TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &i16)) { char uv[24]; const char *name = 0; switch (i16) { case 0: name = "white is zero"; break; case 1: name = "black is zero"; break; case 2: name = "RGB"; break; case 3: name = "palette"; break; case 4: name = "mask"; break; case 5: name = "separated"; break; case 6: name = "YCbCr"; break; case 8: name = "CIELAB"; break; case 9: name = "ICCLab"; break; case 10: name = "ITULab"; break; default: snprintf(uv, sizeof(uv), "unknown (%d)", i16); name = uv; } setAttr(res, "color.space", mkString(name)); } } SEXP read_tiff(SEXP sFn, SEXP sNative, SEXP sAll, SEXP sConvert, SEXP sInfo, SEXP sIndexed, SEXP sOriginal) { SEXP res = R_NilValue, multi_res = R_NilValue, multi_tail = R_NilValue, dim; const char *fn; int native = asInteger(sNative), all = (asInteger(sAll) == 1), n_img = 0, convert = (asInteger(sConvert) == 1), add_info = (asInteger(sInfo) == 1), indexed = (asInteger(sIndexed) == 1), original = (asInteger(sOriginal) == 1); tiff_job_t rj; TIFF *tiff; FILE *f; if (indexed && (convert || native)) Rf_error("indexed and native/convert cannot both be TRUE as they are mutually exclusive"); if (TYPEOF(sFn) == RAWSXP) { rj.data = (char*) RAW(sFn); rj.len = LENGTH(sFn); rj.alloc = rj.ptr = 0; rj.f = f = 0; } else { if (TYPEOF(sFn) != STRSXP || LENGTH(sFn) < 1) Rf_error("invalid filename"); fn = CHAR(STRING_ELT(sFn, 0)); f = fopen(fn, "rb"); if (!f) Rf_error("unable to open %s", fn); rj.f = f; } tiff = TIFF_Open("rmc", &rj); /* no mmap, no chopping */ if (!tiff) Rf_error("Unable to open TIFF"); while (1) { /* loop over separate image in a directory if desired */ uint32 imageWidth = 0, imageLength = 0, imageDepth; uint32 tileWidth, tileLength; uint32 x, y; uint16 config, bps = 8, spp = 1, sformat = 1, out_spp; tdata_t buf; double *ra; uint16 *colormap[3] = {0, 0, 0}; int is_float = 0; TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &imageWidth); TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imageLength); if (!TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &imageDepth)) imageDepth = 0; if (TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth)) TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); else /* no tiles */ tileWidth = tileLength = 0; TIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &config); TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps); TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &spp); out_spp = spp; TIFFGetField(tiff, TIFFTAG_COLORMAP, colormap, colormap + 1, colormap + 2); if (TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sformat) && sformat == SAMPLEFORMAT_IEEEFP) is_float = 1; if (spp == 1 && !indexed) { /* modify out_spp for colormaps */ if (colormap[2]) out_spp = 3; else if (colormap[1]) out_spp = 2; } #if TIFF_DEBUG Rprintf("image %d x %d x %d, tiles %d x %d, bps = %d, spp = %d (output %d), config = %d, colormap = %s\n", imageWidth, imageLength, imageDepth, tileWidth, tileLength, bps, spp, out_spp, config, colormap[0] ? "yes" : "no"); #endif if (native || convert) { /* use built-in RGBA conversion - fortunately, libtiff uses exactly the same RGBA representation as R ... *but* flipped y coordinate :( */ SEXP tmp = R_NilValue; /* FIXME: TIFF handle leak in case this fails */ if (convert) PROTECT(tmp = allocVector(REALSXP, imageWidth * imageLength * out_spp)); res = allocVector(INTSXP, imageWidth * imageLength); TIFFReadRGBAImage(tiff, imageWidth, imageLength, (uint32*) INTEGER(res), 0); PROTECT(res); /* TIFF uses flipped y-axis, so we need to invert it .. argh ... */ if (imageLength > 1) { int *line = INTEGER(allocVector(INTSXP, imageWidth)); int *src = INTEGER(res), *dst = INTEGER(res) + imageWidth * (imageLength - 1), ls = imageWidth * sizeof(int); int *el = src + imageWidth * (imageLength / 2); while (src < el) { memcpy(line, src, ls); memcpy(src, dst, ls); memcpy(dst, line, ls); src += imageWidth; dst -= imageWidth; } } if (convert) { uint16 s; uint32 *data = (uint32*) INTEGER(res); ra = REAL(tmp); for (x = 0; x < imageWidth; x++) for (y = 0; y < imageLength; y++) { if (out_spp == 1) { /* single plane (gray) just take R */ ra[imageLength * x + y] = ((double)(data[x + y * imageWidth] & 255)) / 255.0; } else if (out_spp == 2 /* G+A */) { /* this is a bit odd as we need to copy R and A */ ra[imageLength * x + y] = ((double)(data[x + y * imageWidth] & 255)) / 255.0; ra[imageWidth * imageLength + imageLength * x + y] = ((double)((data[x + y * imageWidth] >> 16) & 255)) / 255.0; } else /* 3-4 are simply sequential copies */ for (s = 0; s < out_spp; s++) ra[(imageLength * imageWidth * s) + imageLength * x + y] = ((double) ((data[x + y * imageWidth] >> (s * 8)) & 255)) / 255.0; } UNPROTECT(1); /* res */ res = tmp; dim = allocVector(INTSXP, (out_spp > 1) ? 3 : 2); INTEGER(dim)[0] = imageLength; INTEGER(dim)[1] = imageWidth; if (out_spp > 1) INTEGER(dim)[2] = out_spp; setAttrib(res, R_DimSymbol, dim); if (add_info) TIFF_add_info(tiff, res); UNPROTECT(1); } else { dim = allocVector(INTSXP, 2); INTEGER(dim)[0] = imageLength; INTEGER(dim)[1] = imageWidth; setAttrib(res, R_DimSymbol, dim); setAttrib(res, R_ClassSymbol, mkString("nativeRaster")); setAttrib(res, install("channels"), ScalarInteger(out_spp)); if (add_info) TIFF_add_info(tiff, res); UNPROTECT(1); } if (!all) { TIFFClose(tiff); return res; } n_img++; if (multi_res == R_NilValue) { multi_tail = multi_res = CONS(res, R_NilValue); PROTECT(multi_res); } else { SEXP q = CONS(res, R_NilValue); SETCDR(multi_tail, q); multi_tail = q; } if (!TIFFReadDirectory(tiff)) break; continue; } if (bps != 8 && bps != 16 && bps != 32 && ( bps != 12 || spp != 1 )) { TIFFClose(tiff); Rf_error("image has %d bits/sample which is unsupported in direct mode - use native=TRUE or convert=TRUE", bps); } if (sformat == SAMPLEFORMAT_INT && !original) Rf_warning("tiff package currently only supports unsigned integer or float sample formats in direct mode, but the image contains signed integer format - it will be treated as unsigned (use as.is=TRUE, native=TRUE or convert=TRUE depending on your intent)"); /* FIXME: TIFF handle leak in case this fails */ res = allocVector((spp == 1 && (original || (indexed && colormap[0]))) ? INTSXP : REALSXP, imageWidth * imageLength * out_spp); if (!(spp == 1 && (original || (indexed && colormap[0])))) ra = REAL(res); #define DE12A(v) ((((unsigned int) v[0]) << 4) | (((unsigned int) v[1]) >> 4)) #define DE12B(v) (((((unsigned int) v[1]) & 0x0f) << 8) | ((unsigned int) v[2])) if (tileWidth == 0) { tstrip_t strip; tsize_t plane_offset = 0; x = 0; y = 0; buf = _TIFFmalloc(TIFFStripSize(tiff)); #if TIFF_DEBUG Rprintf(" - %d x %d strips\n", TIFFNumberOfStrips(tiff), TIFFStripSize(tiff)); #endif for (strip = 0; strip < TIFFNumberOfStrips(tiff); strip++) { tsize_t n = TIFFReadEncodedStrip(tiff, strip, buf, (tsize_t) -1); if (spp == 1) { /* config doesn't matter for spp == 1 */ if (colormap[0] && !indexed) { tsize_t i, step = bps / 8; int *ia = original ? INTEGER(res) : 0; if (bps == 12) step += 2; for (i = 0; i < n; i += step) { unsigned int ci = 0, ci2; const unsigned char *v = (const unsigned char*) buf + i; if (bps == 8) ci = v[0]; else if (bps == 16) ci = ((const unsigned short int*)v)[0]; else if (bps == 32) ci = ((const unsigned int*)v)[0]; else if (bps == 12) { ci = DE12A(v); ci2 = DE12B(v); } if (original) { ia[imageLength * x + y] = colormap[0][ci]; /* color maps are always 16-bit */ /* FIXME: bps==12 is broken with color map lookup !!! */ if (bps == 12) ia[imageLength * ++x + y] = colormap[0][ci2]; if (colormap[1]) { ia[(imageLength * imageWidth) + imageLength * x + y] = colormap[1][ci]; if (colormap[2]) ia[(2 * imageLength * imageWidth) + imageLength * x + y] = colormap[2][ci]; } } else { ra[imageLength * x + y] = ((double)colormap[0][ci]) / 65535.0; /* color maps are always 16-bit */ if (bps == 12) ra[imageLength * ++x + y] = ((double)colormap[0][ci2]) / 65535.0; if (colormap[1]) { ra[(imageLength * imageWidth) + imageLength * x + y] = ((double)colormap[1][ci]) / 65535.0; if (colormap[2]) ra[(2 * imageLength * imageWidth) + imageLength * x + y] = ((double)colormap[2][ci]) / 65535.0; } } x++; if (x >= imageWidth) { x -= imageWidth; y++; } } } else if (colormap[0] || original) { /* indexed requested */ tsize_t i, step = bps / 8; int *ia = INTEGER(res), ix_base = original ? 0 : 1; if (bps == 12) step = 3; for (i = 0; i < n; i += step) { int val = NA_INTEGER; const unsigned char *v = (const unsigned char*) buf + i; if (bps == 8) val = ix_base + v[0]; else if (bps == 16) val = ix_base + ((const unsigned short int*)v)[0]; else if (bps == 32) val = ix_base + ((const unsigned int*)v)[0]; else if (bps == 12) { ia[imageLength * x++ + y] = ix_base + DE12A(v); val = ix_base + DE12B(v); } ia[imageLength * x++ + y] = val; if (x >= imageWidth) { x -= imageWidth; y++; } } } else { /* direct gray */ tsize_t i, step = bps / 8; if (bps == 12) step = 3; for (i = 0; i < n; i += step) { double val = NA_REAL; const unsigned char *v = (const unsigned char*) buf + i; if (bps == 8) val = ((double) v[0]) / 255.0; else if (bps == 16) val = ((double) ((const unsigned short int*)v)[0]) / 65535.0; else if (bps == 32) { if (is_float) val = (double) ((const float*)v)[0]; else val = ((double) ((const unsigned int*)v)[0]) / 4294967296.0; } if (bps == 12) { ra[imageLength * x++ + y] = ((double) DE12A(v)) / 4096.0; val = ((double) DE12B(v)) / 4096.0; } ra[imageLength * x + y] = val; x++; if (x >= imageWidth) { x -= imageWidth; y++; } } } } else if (config == PLANARCONFIG_CONTIG) { /* interlaced */ tsize_t i, j, step = spp * bps / 8; for (i = 0; i < n; i += step) { const unsigned char *v = (const unsigned char*) buf + i; if (bps == 8) { for (j = 0; j < spp; j++) ra[(imageLength * imageWidth * j) + imageLength * x + y] = ((double) v[j]) / 255.0; } else if (bps == 16) { for (j = 0; j < spp; j++) ra[(imageLength * imageWidth * j) + imageLength * x + y] = ((double) ((const unsigned short int*)v)[j]) / 65535.0; } else if (bps == 32 && !is_float) { for (j = 0; j < spp; j++) ra[(imageLength * imageWidth * j) + imageLength * x + y] = ((double) ((const unsigned int*)v)[j]) / 4294967296.0; } else if (bps == 32 && is_float) { for (j = 0; j < spp; j++) ra[(imageLength * imageWidth * j) + imageLength * x + y] = (double) ((const float*)v)[j]; } x++; if (x >= imageWidth) { x -= imageWidth; y++; } } } else { /* separate */ tsize_t step = bps / 8, i; for (i = 0; i < n; i += step) { const unsigned char *v = (const unsigned char*) buf + i; if (bps == 8) ra[plane_offset + imageLength * x + y] = ((double) v[0]) / 255.0; else if (bps == 16) ra[plane_offset + imageLength * x + y] = ((double) ((const unsigned short int*)v)[0]) / 65535.0; else if (bps == 32 && !is_float) ra[plane_offset + imageLength * x + y] = ((double) ((const unsigned int*)v)[0]) / 4294967296.0; else if (bps == 32 && is_float) ra[plane_offset + imageLength * x + y] = (double) ((const float*)v)[0]; } x++; if (x >= imageWidth) { x -= imageWidth; y++; if (y >= imageLength) { y -= imageLength; plane_offset += imageWidth * imageLength; } } } } } else { Rf_error("tile-based images are currently supported only with native=TRUE or convert=TRUE"); buf = _TIFFmalloc(TIFFTileSize(tiff)); for (y = 0; y < imageLength; y += tileLength) for (x = 0; x < imageWidth; x += tileWidth) TIFFReadTile(tiff, buf, x, y, 0 /*depth*/, 0 /*plane*/); } _TIFFfree(buf); PROTECT(res); dim = allocVector(INTSXP, (out_spp > 1) ? 3 : 2); INTEGER(dim)[0] = imageLength; INTEGER(dim)[1] = imageWidth; if (out_spp > 1) INTEGER(dim)[2] = out_spp; setAttrib(res, R_DimSymbol, dim); if (colormap[0] && TYPEOF(res) == INTSXP && indexed) { int nc = 1 << bps, i; SEXP cm = allocMatrix(REALSXP, 3, nc); double *d = REAL(cm); for (i = 0; i < nc; i++) { d[3 * i] = ((double) colormap[0][i]) / 65535.0; d[3 * i + 1] = ((double) colormap[1][i]) / 65535.0; d[3 * i + 2] = ((double) colormap[2][i]) / 65535.0; } setAttr(res, "color.map", cm); } if (add_info) TIFF_add_info(tiff, res); UNPROTECT(1); if (!all) { TIFFClose(tiff); return res; } n_img++; if (multi_res == R_NilValue) { multi_tail = multi_res = CONS(res, R_NilValue); PROTECT(multi_res); } else { SEXP q = CONS(res, R_NilValue); SETCDR(multi_tail, q); multi_tail = q; } if (!TIFFReadDirectory(tiff)) break; } TIFFClose(tiff); /* convert LISTSXP into VECSXP */ PROTECT(res = allocVector(VECSXP, n_img)); { int i = 0; while (multi_res != R_NilValue) { SET_VECTOR_ELT(res, i, CAR(multi_res)); i++; multi_res = CDR(multi_res); } } UNPROTECT(2); return res; } tiff/src/Makevars.win0000644000176000001440000000035612211457633014321 0ustar ripleyusers## detect 64-bit Windows ifeq ($(strip $(shell $(R_HOME)/bin/R --slave -e 'cat(.Machine$$sizeof.pointer)')),8) PKG_CFLAGS=-Iwin64 PKG_LIBS=-Lwin64 -ltiff -ljpeg -lz else PKG_CFLAGS=-Iwin32 PKG_LIBS=-Lwin32 -ltiff -ljpeg -lz endif tiff/src/write.c0000644000176000001440000001762312211457634013335 0ustar ripleyusers#include #include #include #include "common.h" #include #include #define INIT_SIZE (256 * 1024) #define HAS_ALPHA 0x01 #define IS_GRAY 0x02 #define IS_RGB 0x04 /* if neither GRAY/RGB is set then it's B/W */ int analyze_native(const unsigned int *what, int length) { int alpha = 0, ac = 0, i; for (i = 0; i < length; i++) { if (!alpha && (what[i] & 0xff000000) != 0xff000000) alpha = 1; if (ac < 2 && ((what[i] & 0xff) != ((what[i] >> 8) & 0xff) || (what[i] & 0xff) != ((what[i] >> 16) & 0xff))) ac = 2; if (ac == 0 && (what[i] & 0xffffff) != 0xffffff && (what[i] & 0xffffff)) ac = 1; if (ac == 2 && alpha) break; /* no need to continue */ } return alpha | (ac << 1); } SEXP write_tiff(SEXP image, SEXP where, SEXP sBPS, SEXP sCompr, SEXP sReduce) { SEXP dims, img_list = 0; tiff_job_t rj; TIFF *tiff; FILE *f; int native = 0, raw_array = 0, bps = asInteger(sBPS), compression = asInteger(sCompr), reduce = asInteger(sReduce), img_index = 0, n_img = 1; uint32 width, height, planes = 1; if (TYPEOF(image) == VECSXP) { if ((n_img = LENGTH(image)) == 0) { Rf_warning("empty image list, nothing to do"); return R_NilValue; } img_list = image; } if (bps != 8 && bps != 16 && bps != 32) Rf_error("currently bits.per.sample must be 8, 16 or 32"); if (TYPEOF(where) == RAWSXP) { rj.alloc = INIT_SIZE; if (!(rj.data = malloc(rj.alloc))) Rf_error("unable to allocate memory for the in-memory output buffer"); rj.len = 0; rj.ptr = 0; rj.f = f = 0; } else { const char *fn; if (TYPEOF(where) != STRSXP || LENGTH(where) < 1) Rf_error("invalid filename"); fn = CHAR(STRING_ELT(where, 0)); f = fopen(fn, "w+b"); if (!f) Rf_error("unable to create %s", fn); rj.f = f; } tiff = TIFF_Open("wm", &rj); if (!tiff) { if (!rj.f) free(rj.data); Rf_error("cannot create TIFF structure"); } while (1) { if (img_list) image = VECTOR_ELT(img_list, img_index++); if (inherits(image, "nativeRaster") && TYPEOF(image) == INTSXP) native = 1; if (TYPEOF(image) == RAWSXP) raw_array = 1; if (!native && !raw_array && TYPEOF(image) != REALSXP) Rf_error("image must be a matrix or array of raw or real numbers"); dims = Rf_getAttrib(image, R_DimSymbol); if (dims == R_NilValue || TYPEOF(dims) != INTSXP || LENGTH(dims) < 2 || LENGTH(dims) > 3) Rf_error("image must be a matrix or an array of two or three dimensions"); if (raw_array && LENGTH(dims) == 3) { /* raw arrays have either bpp, width, height or width, height dimensions */ planes = INTEGER(dims)[0]; width = INTEGER(dims)[1]; height = INTEGER(dims)[2]; } else { /* others have width, height[, bpp] */ width = INTEGER(dims)[1]; height = INTEGER(dims)[0]; if (LENGTH(dims) == 3) planes = INTEGER(dims)[2]; } if (planes < 1 || planes > 4) Rf_error("image must have either 1 (grayscale), 2 (GA), 3 (RGB) or 4 (RGBA) planes"); if (native) { /* nativeRaster should have a "channels" attribute if it has anything else than 4 channels */ SEXP cha = getAttrib(image, install("channels")); if (cha != R_NilValue) { planes = asInteger(cha); if (planes < 1 || planes > 4) planes = 4; } else planes = 4; } if (raw_array) { if (planes != 4) Rf_error("Only RGBA format is supported as raw data"); native = 1; /* from now on we treat raw arrays like native */ } TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height); TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, 1); TIFFSetField(tiff, TIFFTAG_SOFTWARE, "tiff package, R " R_MAJOR "." R_MINOR); if (native) { TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8); if (reduce) { int an = analyze_native((const unsigned int*) INTEGER(image), width * height); if (an == (HAS_ALPHA | IS_RGB)) reduce = 0; else { /* we only reduce to RGB, GA or G */ int out_spp = ((an & HAS_ALPHA) ? 1 : 0 ) + ((an & IS_RGB) ? 3 : 1); uint32 i = 1, n = width * height; tdata_t buf; unsigned char *data8; const unsigned int *nd = (const unsigned int*) INTEGER(image); TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, out_spp); TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, height); TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression); TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, (out_spp > 2) ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK); buf = _TIFFmalloc(width * height * out_spp); data8 = (unsigned char*) buf; if (out_spp == 1) for (i = 0; i < n; i++) /* G */ data8[i] = nd[i] & 255; else if (out_spp == 2) { if (((const char*)&i)[0] == 1) /* little-endian */ for (i = 0; i < n; i++) { /* GA */ *(data8++) = nd[i] & 255; *(data8++) = (nd[i] >> 24) & 255; } else /* big-endian */ for (i = 0; i < n; i++) { /* GA */ *(data8++) = (nd[i] >> 24) & 255; *(data8++) = nd[i] & 255; } } else if (out_spp == 3) { if (((const char*)&i)[0] == 1) /* little-endian */ for (i = 0; i < n; i++) { /* RGB */ *(data8++) = nd[i] & 255; *(data8++) = (nd[i] >> 8) & 255; *(data8++) = (nd[i] >> 16) & 255; } else /* big-endian */ for (i = 0; i < n; i++) { /* RGB */ *(data8++) = (nd[i] >> 16) & 255; *(data8++) = (nd[i] >> 8) & 255; *(data8++) = nd[i] & 255; } } TIFFWriteEncodedStrip(tiff, 0, buf, width * height * out_spp); _TIFFfree(buf); } } if (!reduce) { TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4); TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, height); TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression); TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFWriteEncodedStrip(tiff, 0, INTEGER(image), width * height * 4); } } else { uint32 x, y, pl; tdata_t buf; unsigned char *data8; unsigned short *data16; unsigned int *data32; double *ra = REAL(image); uint32 i, N = LENGTH(image); for (i = 0; i < N; i++) /* do a pre-flight check */ if (ra[i] < 0.0 || ra[i] > 1.0) { Rf_warning("The input contains values outside the [0, 1] range - storage of such values is undefined"); break; } TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, bps); TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, planes); TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, height); TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression); TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, (planes > 2) ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK); buf = _TIFFmalloc(width * height * planes * (bps / 8)); data8 = (unsigned char*) buf; data16 = (unsigned short*) buf; data32 = (unsigned int*) buf; if (!buf) Rf_error("cannot allocate output image buffer"); if (bps == 8) for (y = 0; y < height; y++) for (x = 0; x < width; x++) for (pl = 0; pl < planes; pl++) data8[(x + y * width) * planes + pl] = (unsigned char) (ra[y + x * height + pl * width * height] * 255.0); else if (bps == 16) for (y = 0; y < height; y++) for (x = 0; x < width; x++) for (pl = 0; pl < planes; pl++) data16[(x + y * width) * planes + pl] = (unsigned short) (ra[y + x * height + pl * width * height] * 65535.0); else if (bps == 32) for (y = 0; y < height; y++) for (x = 0; x < width; x++) for (pl = 0; pl < planes; pl++) data32[(x + y * width) * planes + pl] = (unsigned int) (ra[y + x * height + pl * width * height] * 4294967295.0); TIFFWriteEncodedStrip(tiff, 0, buf, width * height * planes * (bps / 8)); _TIFFfree(buf); } if (img_list && img_index < n_img) TIFFWriteDirectory(tiff); else break; } if (!rj.f) { SEXP res; TIFFFlush(tiff); res = allocVector(RAWSXP, rj.len); #if TIFF_DEBUG Rprintf("convert to raw %d bytes (ptr=%d, alloc=%d)\n", rj.len, rj.ptr, rj.alloc); #endif memcpy(RAW(res), rj.data, rj.len); TIFFClose(tiff); return res; } TIFFClose(tiff); return ScalarInteger(n_img); } tiff/NAMESPACE0000644000176000001440000000005012211457633012450 0ustar ripleyusersuseDynLib(tiff) exportPattern(".*TIFF") tiff/NEWS0000644000176000001440000000212512211457633011735 0ustar ripleyusersNEWS/Changelog 0.1-5 2013-09-03 o bugfix: output of readTIFF(..., as.is=TRUE) with integer values was shifted by one (i.e., stored integer value x was returned as x + 1) o writeTIFF() now supports 32-bit (integer) output o writeTIFF() issues a warning if the input data range is outside [0, 1] 0.1-4 2013-02-19 o remove debugging output (it is now only shown if tiff is compiled with -DTIFF_DEBUG=1) 0.1-3 2012-11-05 o add support for 12-bit grayscale TIFF images in readTIFF() (Note that 12-bit TIFFs are outside of the standard, so we assume big-endian packing order) o add readTIFF(..., as.is=TRUE) which preserves the integer values used in the TIFF as they are (if applicable) instead of rescaling to reals 0.1-2 2012-08-30 o fixed a bug in writeTIFF() for 16-bit images 0.1-1 2012-08-24 o add readTIFF(..., indexed=TRUE) which return indexed images as color map and an index matrix. o fixed a bug in writing a TIFF file consisting of multiple subimages o prevent TIFF from re-entering error calls 0.1-0 2012-08-04 o first CRAN release tiff/R/0000755000176000001440000000000012211457633011437 5ustar ripleyuserstiff/R/write.R0000644000176000001440000000106412211457633012715 0ustar ripleyuserswriteTIFF <- function(what, where, bits.per.sample = 8L, compression = c("LZW", "none", "PackBits", "RLE", "JPEG", "deflate"), reduce = TRUE) { if (!is.numeric(compression) || length(compression) != 1L) { compressions <- c(none=1L, RLE=2L, PackBits=32773L, fax3=3L, fax4=4L, LZW=5L, JPEG=7L, deflate=8L) compression <- match.arg(compression) compression <- compressions[match(compression, names(compressions))] } .Call("write_tiff", what, where, bits.per.sample, compression, reduce, PACKAGE="tiff") } tiff/R/read.R0000644000176000001440000000036312211457633012477 0ustar ripleyusersreadTIFF <- function(source, native=FALSE, all=FALSE, convert=FALSE, info=FALSE, indexed=FALSE, as.is=FALSE) .Call("read_tiff", if (is.raw(source)) source else path.expand(source), native, all, convert, info, indexed, as.is, PACKAGE="tiff") tiff/MD50000644000176000001440000000127612211542311011540 0ustar ripleyusersd7ee614fe7880ad0b2e48e78b99ec36e *DESCRIPTION c5cd9fade03f932b1269addafcb3331e *NAMESPACE 3d76a6333b4a5ec8eb6d20efd3eb89e6 *NEWS ec9fcd3f410b2bcfead19d9bf76278fb *R/read.R cb8492a3c34c2d383a0dda887727d108 *R/write.R e81a493d145e1be54feea75761f97022 *configure.win 39ab4d2a0fc38ce4f556b2f4ce71104e *inst/img/Rlogo.tiff 4d32df92bb0a20d27c99faeeef6b5ea7 *man/readTIFF.Rd 1246a701cce89e0856ecfa18ad76a273 *man/writeTIFF.Rd bf85e1d4645fb00fa2db4da1f284a34d *src/Makevars 31ef274798e4f16419457f854954b702 *src/Makevars.win 11d9a3f6675a230bcc0d336003c89a55 *src/common.c ca1d1edf6d0f3392afcb3d6ec20c43cc *src/common.h 77717b344bf33cba155fa573b2049638 *src/read.c 78102102456cae933741f2b1d02c137f *src/write.c tiff/DESCRIPTION0000644000176000001440000000112712211542311012731 0ustar ripleyusersPackage: tiff Version: 0.1-5 Title: Read and write TIFF images Author: Simon Urbanek Maintainer: Simon Urbanek Depends: R (>= 2.9.0) Description: This package provides an easy and simple way to read, write and display bitmap images stored in the TIFF format. It can read and write both files and in-memory raw vectors. License: GPL-2 | GPL-3 SystemRequirements: tiff and jpeg libraries URL: http://www.rforge.net/tiff/ Packaged: 2013-09-03 22:15:56 UTC; svnuser NeedsCompilation: yes Repository: CRAN Date/Publication: 2013-09-04 07:27:36 tiff/man/0000755000176000001440000000000012211457633012011 5ustar ripleyuserstiff/man/readTIFF.Rd0000644000176000001440000001107512211457633013670 0ustar ripleyusers\name{readTIFF} \alias{readTIFF} \title{ Read a bitmap image stored in the TIFF format } \description{ Reads an image from a TIFF file/content into a raster array. } \usage{ readTIFF(source, native = FALSE, all = FALSE, convert = FALSE, info = FALSE, indexed = FALSE, as.is = FALSE) } \arguments{ \item{source}{Either name of the file to read from or a raw vector representing the TIFF file content.} \item{native}{determines the image representation - if \code{FALSE} (the default) then the result is an array, if \code{TRUE} then the result is a native raster representation (suitable for plotting).} \item{all}{TIFF files can contain more than one image, if \code{all = TRUE} then all images are returenin a list, otherwsie only the first image is returned.} \item{convert}{first convert the image into 8-bit RGBA samples and then to an array, see below for details.} \item{info}{if set to \code{TRUE} then the resulting image(s) will also contain information from TIFF tags as attributes} \item{indexed}{if set to \code{TRUE} then indexed images will be returned in the indexed form, i.e., as a matrix of integer indices referencing into a color map which is returned in the \code{"color.map"} attribute. This flag cannot be combined with \code{convert} or \code{native} and has no effect on images that are not indexed.} \item{as.is}{attempt to return original values without re-scaling where possible} } \value{ If \code{native} is \code{FALSE} then an array of the dimensions height x width x channels. If there is only one channel the result is a matrix. The values are reals between 0 and 1 (except for 32-bit floating point sample storage which are unscaled reals, and for indexed and \code{as.is=TRUE} which are integers). If \code{native} is \code{TRUE} then an object of the class \code{nativeRaster} is returned instead. The latter cannot be easily computed on but is the most efficient way to draw using \code{rasterImage}. If \code{all} is \code{TRUE} then the result is a list of the above with one or more elements.. } \details{ Most common files decompress into RGB (3 channels), RGBA (4 channels), Grayscale (1 channel) or GA (2 channels). Note that G and GA images cannot be directly used in \code{\link{rasterImage}} unless \code{native} is set to \code{TRUE} because \code{rasterImage} requires RGB or RGBA format (\code{nativeRaster} is always 8-bit RGBA). TIFF images can have a wide range of internal representations, but only the most common in image processing are directly supported (8-bit, 16-bit integer and 32-bit float samples). Other formats (color maps, sub-8-bit images, etc.) are only supported via \code{convert=TRUE} which uses the built-in facilities of the TIFF library to convert the image into RGBA format with 8-bit samples (i.e. total of 32-bit per pixel) and then store the relevant components from there into real arrays. This is the same path as used by \code{native=TRUE} and so differs only in the output value. Note that conversion may result in different values than direct acccess as it is intended mainly for viewing and not computation. } %\references{ %} %\author{ %} \note{ Some non-standard formats such as 12-bit TIFFs are partially supported (there is no standard for packing order for TIFFs beoynd 8-bit so we assume big-endian packing similar to the default fill order and only support single channel or indexed). The \code{as.is=TRUE} option is experimental, cannot be used with \code{native} or \code{convert} and only works for integer storage TIFFs. } \seealso{ \code{\link{rasterImage}}, \code{\link{writeTIFF}} } \examples{ # read a sample file (R logo) img <- readTIFF(system.file("img", "Rlogo.tiff", package="tiff")) # read it also in native format img.n <- readTIFF(system.file("img", "Rlogo.tiff", package="tiff"), native=TRUE) # and also in converted img.c <- readTIFF(system.file("img", "Rlogo.tiff", package="tiff"), convert=TRUE) # if your R supports it, we'll plot it if (exists("rasterImage")) { # can plot only in R 2.11.0 and higher plot(1:2, type='n') if (names(dev.cur()) == "windows") { # windows device doesn't support semi-transparency so we'll need # to flatten the image transparent <- img[,,4] == 0 img <- as.raster(img[,,1:3]) img[transparent] <- NA # interpolate must be FALSE on Windows, otherwise R will # try to interpolate transparency and fail rasterImage(img, 1.2, 1.27, 1.8, 1.73, interpolate=FALSE) } else { # any reasonable device will be fine using alpha rasterImage(img, 1.2, 1.27, 1.8, 1.73) rasterImage(img.n, 1.5, 1.5, 1.9, 1.8) } } } \keyword{IO} tiff/man/writeTIFF.Rd0000644000176000001440000000452512211457633014111 0ustar ripleyusers\name{writeTIFF} \alias{writeTIFF} \title{ Write one or more bitmap images in TIFF format } \description{ Writes images into a TIFF file or a raw vector representing such. } \usage{ writeTIFF(what, where, bits.per.sample = 8L, compression = c("LZW", "none", "PackBits", "RLE", "JPEG", "deflate"), reduce = TRUE) } \arguments{ \item{what}{either an image or a list of images. An image is a real matrix or array of three dimensions, or an object of the class \code{"nativeRaster"}.} \item{where}{file name or a raw vector} \item{bits.per.sample}{number of bits per sample (numeric scalar). Supported values in this version are 8, 16, and 32.} \item{compression}{desired compression algorithm (string). Optionally, it can be specified as a numeric value corresponding to the compression TIFF tag, but it needs to be also supported by the underlying TIFF library} \item{reduce}{if \code{TRUE} then \code{writeTIFF} will attempt to reduce the number of planes in native rasters by analyzing the image to choose one of RGBA, RGB, GA or G formats, whichever uses the least planes without any loss. Otherwise the image is always saved with four planes (RGBA).} } \value{ If \code{where} is a raw vector then the value is the raw vector containg the TIFF contents, otherwise a scalar integer specifying the number of images written in the file. } %\references{ %} \author{ Simon Urbanek } \details{ By default \code{writeTIFF} uses the same number of planes as there are planes in the input image. For native images it is always four unless \code{reduce = TRUE} is set (see above). Consequently, color maps are not used. The output always uses contiguous planar configuration (baseline TIFF). The output is tagged with a photometric tag of either RGB (3 or 4 planes) or zero-is-black (1 or 2 planes). If \code{what} is a list then the TIFF output will be a directory of the corresponding number of images (in TIFF speak - not to be confused with file directories). } \seealso{ \code{\link{readTIFF}} } \examples{ img <- readTIFF(system.file("img", "Rlogo.tiff", package="tiff")) # write without the alpha channel tiff <- writeTIFF(img[,,-4], raw(0)) # read as native i2 <- readTIFF(tiff, native=TRUE) # write reduced - should be the same as tiff t2 <- writeTIFF(i2, raw(0), reduce=TRUE) } \keyword{IO} tiff/configure.win0000644000176000001440000000206512211457633013741 0ustar ripleyusers#!/bin/sh echo " checking TIFF headers and libraries" allok=yes if [ ! -e src/win32/libz.a ]; then if [ ! -e src/libtiff-current-win.tar.gz ]; then echo " cannot find current TIFF files" echo " attempting to download them" echo 'download.file("http://www.rforge.net/tiff/files/libtiff-current-win.tar.gz","src/libtiff-current-win.tar.gz",mode="wb",quiet=TRUE)'|${R_HOME}/bin/R --vanilla --slave fi if [ ! -e src/libtiff-current-win.tar.gz ]; then allok=no else echo " unpacking current TIFF" tar fxz src/libtiff-current-win.tar.gz -C src if [ ! -e src/win32/libz.a ]; then allok=no fi fi fi if [ ! -e src/win32/libz.a ]; then allok=no fi if [ ${allok} != yes ]; then echo "" echo " *** ERROR: unable to find TIFF files" echo "" echo " They must be either in src/win32 or in a tar-ball" echo " src/libtiff-current-win.tar.gz" echo "" echo " You can get the latest binary tar ball from" echo " http://www.rforge.net/tiff/files/" echo "" exit 1 fi echo " seems ok, ready to go" exit 0