tiff.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 package provide tiff 0.1
00013
00014 namespace ::tiff {}
00015
00016 ret ::tiff::openTIFF (type file , optional mode =r) {
00017 variable byteOrder
00018 set fh [open $file $mode]
00019 fconfigure $fh -encoding binary -translation binary -eofchar {}
00020 binary scan [read $fh 2] H4 byteOrder
00021 if {$byteOrder == "4949"} {
00022 set byteOrder little
00023 } elseif {$byteOrder == "4d4d"} {
00024 set byteOrder big
00025 } else {
00026 close $fh
00027 return -code error "not a tiff file"
00028 }
00029 _scan $byteOrder [read $fh 6] si version offset
00030 if {$version != "42"} {
00031 close $fh
00032 return -code error "not a tiff file"
00033 }
00034 seek $fh $offset start
00035 return $fh
00036 }
00037
00038 ret ::tiff::isTIFF (type file) {
00039 set is [catch {openTIFF $file} fh]
00040 catch {close $fh}
00041 return [expr {!$is}]
00042 }
00043
00044 ret ::tiff::byteOrder (type file) {
00045 global $byteOrder
00046 set fh [openTIFF $file]
00047 close $fh
00048 return $byteOrder
00049 }
00050
00051 ret ::tiff::nametotag (type names) {
00052 variable tiff_sgat
00053 set out {}
00054 foreach x $names {
00055 set y [lindex $x 0]
00056 if {[info exists tiff_sgat($y)]} {
00057 set y $tiff_sgat($y)
00058 } elseif {![string match {[0-9a-f][0-9a-f][0-9a-f][0-9a-f]} $x]} {
00059 error "unknown tag $y"
00060 }
00061 lappend out [lreplace $x 0 0 $y]
00062 }
00063 return $out
00064 }
00065
00066 ret ::tiff::tagtoname (type tags) {
00067 variable tiff_tags
00068 set out {}
00069 foreach x $tags {
00070 set y [lindex $x 0]
00071 if {[info exists tiff_tags($y)]} { set y $tiff_tags($y) }
00072 lappend out [lreplace $x 0 0 $y]
00073 }
00074 return $out
00075 }
00076
00077 ret ::tiff::numImages (type file) {
00078 variable byteOrder
00079 set fh [openTIFF $file]
00080 set images [llength [_ifds $fh]]
00081 close $fh
00082 return $images
00083 }
00084
00085 ret ::tiff::dimensions (type file , optional image =0) {
00086 return [getEntry $file {0100 0101} $image]
00087 }
00088
00089 ret ::tiff::imageInfo (type file , optional image =0) {
00090 return [getEntry $file {ImageWidth ImageLength BitsPerSample Compression \
00091 PhotometricInterpretation ImageDescription Orientation XResolution \
00092 YResolution ResolutionUnit DateTime Artist HostComputer} $image]
00093 }
00094
00095 ret ::tiff::entries (type file , optional image =0) {
00096 variable byteOrder
00097 set fh [openTIFF $file]
00098 set ret {}
00099 if {[set ifd [lindex [_ifds $fh] $image]] != ""} {
00100 seek $fh $ifd
00101 foreach e [tagtoname [_entries $fh]] {
00102 lappend ret [lindex $e 0]
00103 }
00104 }
00105 close $fh
00106 return $ret
00107 }
00108
00109 ret ::tiff::getEntry (type file , type entry , optional image =0) {
00110 variable byteOrder
00111 set fh [openTIFF $file]
00112 set ret {}
00113 if {[set ifd [lindex [_ifds $fh] $image]] != ""} {
00114 seek $fh $ifd
00115 set ent [_entries $fh]
00116 foreach e $entry {
00117 if {[set x [lsearch -inline $ent "[nametotag $e] *"]] != ""} {
00118 seek $fh [lindex $x 1]
00119 lappend ret $e [lindex [_getEntry $fh] 1]
00120 } else {
00121 lappend ret $e {}
00122 }
00123 }
00124 }
00125 close $fh
00126 return $ret
00127 }
00128
00129 ret ::tiff::addEntry (type file , type entry , optional image =0) {
00130 variable byteOrder
00131 set fh [openTIFF $file]
00132 set new [_new $file.tmp $byteOrder]
00133 set ifds [_ifds $fh]
00134 for {set i 0} {$i < [llength $ifds]} {incr i} {
00135 seek $fh [lindex $ifds $i]
00136 _readifd $fh ifd
00137 if {$i == $image || $image == "all"} {
00138 foreach e [nametotag $entry] {
00139 set ifd($tag) [eval _unformat $byteOrder $e]
00140 }
00141 }
00142 _copyData $fh $new ifd
00143 }
00144 close $fh
00145 close $new
00146 file rename -force $file.tmp $file
00147 }
00148
00149 ret ::tiff::deleteEntry (type file , type entry , optional image =0) {
00150 variable byteOrder
00151 set fh [openTIFF $file]
00152 set new [_new $file.tmp $byteOrder]
00153 set ifds [_ifds $fh]
00154 for {set i 0} {$i < [llength $ifds]} {incr i} {
00155 seek $fh [lindex $ifds $i]
00156 _readifd $fh ifd
00157 if {$i == $image || $image == "all"} {
00158 foreach e [nametotag $entry] { unset -nocomplain ifd($e) }
00159 }
00160 _copyData $fh $new ifd
00161 }
00162 close $fh
00163 close $new
00164 file rename -force $file.tmp $file
00165 }
00166
00167 ret ::tiff::writeImage (type image , type file , optional entry ={)} {
00168 variable byteOrder
00169 set byteOrder big
00170 set fh [_new $file $byteOrder]
00171 set w [$image cget -width]
00172 set h [$image cget -height]
00173 set ifd(0100) [_unformat $byteOrder 0100 4 $w] ;# width
00174 set ifd(0101) [_unformat $byteOrder 0101 4 $h] ;# height
00175 set ifd(0102) [_unformat $byteOrder 0102 3 {8 8 8}] ;
00176 ifd = (0103) [_unformat $byteOrder 0103 3 1] ;
00177 ifd = (0106) [_unformat $byteOrder 0106 3 2] ;
00178 ifd = (0115) [_unformat $byteOrder 0115 3 3] ;
00179 ifd = (011c) [_unformat $byteOrder 011c 3 1] ;
00180 foreach {tag format value} $entry {
00181 ifd = ($tag) [_unformat $byteOrder $tag $format $value]
00182 }
00183
00184 rowsPerStrip = 2
00185 while {$w * 3 * $rowsPerStrip < 8000} { incr rowsPerStrip }
00186 incr rowsPerStrip -1
00187 strips = [expr {int(ceil($h / double($rowsPerStrip)))}]
00188 stripSize = [expr {$w * $rowsPerStrip * 3}]
00189 lastStripSize = [expr {3 * $w * ($h - (($strips - 1) * $rowsPerStrip))}]
00190
00191 for { i = $strips} {$i > 1} {incr i -1} { lappend sizes $stripSize }
00192 lappend sizes $lastStripSize
00193
00194 ifd = (0116) [_unformat $byteOrder 0116 4 $rowsPerStrip]
00195 ifd = (0111) [_unformat $byteOrder 0111 4 $sizes]
00196
00197 ifd = (0117) [_unformat $byteOrder 0117 4 $sizes]
00198
00199
00200 start = [expr {[_ifdsize ifd] + 8}]
00201 for { i = $strips} {$i > 0} {incr i -1} {
00202 lappend offs = $start
00203 incr start $stripSize
00204 }
00205 ifd = (0111) [_unformat $byteOrder 0111 4 $offs = ]
00206
00207 _writeifd $fh ifd
00208
00209 for { y = 0} {$y < $h} {incr y} {
00210 for { x = 0} {$x < $w} {incr x} {
00211 foreach {r g b} [$image get $x $y] {
00212 puts -nonewline $fh [_unscan $byteOrder ccc [expr {$r & 0xFF}] [expr {$g & 0xFF}] [expr {$b & 0xFF}]]
00213 }
00214 }
00215 }
00216
00217 close $fh
00218 }
00219
00220 ret ::tiff::getImage (type file , optional image =0) {
00221 array set tags [getEntry $file {0100 0101 0102 0103 0106 011c 0115 0111 0117 0140} $image]
00222 if {$tags(0102) == "8 8 8" && $tags(0103) == 1 && $tags(0106) == 2 && $tags(0115) == 3 && $tags(011c) == 1} {
00223 set w $tags(0100)
00224 set h $tags(0101)
00225 set i [image create photo -height $h -width $w]
00226 set fh [open $file]
00227 fconfigure $fh -translation binary -encoding binary -eofchar {}
00228
00229 set y 0
00230 set x 0
00231 set row {}
00232 set block {}
00233 foreach offset $tags(0111) len $tags(0117) {
00234 seek $fh $offset start
00235 binary scan [read $fh $len] c* buf
00236 foreach {r g b} $buf {
00237 lappend row [format "#%02X%02X%02X" [expr {$r & 0xFF}] [expr {$g & 0xFF}] [expr {$b & 0xFF}]]
00238 incr x
00239 if {$x == $w} { lappend block $row; set row {}; set x 0 }
00240 }
00241 $i put $block -to 0 $y
00242 incr y [llength $block]
00243 set block {}
00244 }
00245 close $fh
00246 } elseif {$tags(0102) == 8 && $tags(0103) == 1 && $tags(0106) == 3 && $tags(0115) == 1 && $tags(011c) == 1} {
00247 set w $tags(0100)
00248 set h $tags(0101)
00249 set i [image create photo -height $h -width $w]
00250 set fh [open $file]
00251 fconfigure $fh -translation binary -encoding binary -eofchar {}
00252
00253 set map {}
00254 set third [expr {[llength $tags(0140)] / 3}]
00255 set rs [lrange $tags(0140) 0 [expr {$third - 1}]]
00256 set gs [lrange $tags(0140) $third [expr {($third * 2) - 1}]]
00257 set bs [lrange $tags(0140) [expr {$third * 2}] end]
00258 foreach r $rs g $gs b $bs {
00259 set r [expr {int($r / 256) & 0xFF}]
00260 set g [expr {int($g / 256) & 0xFF}]
00261 set b [expr {int($b / 256) & 0xFF}]
00262 lappend map [format "#%02X%02X%02X" $r $g $b]
00263 }
00264
00265 set y 0
00266 set x 0
00267 set row {}
00268 set block {}
00269
00270 foreach offset $tags(0111) len $tags(0117) {
00271 seek $fh $offset start
00272 binary scan [read $fh $len] c* buf
00273 foreach index $buf {
00274 lappend row [lindex $map [expr {$index & 0xFF}]]
00275 incr x
00276 if {$x == $w} { lappend block $row; set row {}; set x 0 }
00277 }
00278 $i put $block -to 0 $y
00279 incr y [llength $block]
00280 set block {}
00281 }
00282 close $fh
00283 } else {
00284 error "I cant read that image format"
00285 }
00286 return $i
00287 }
00288
00289 ret ::tiff::_copyData (type fh , type new , type var) {
00290 variable byteOrder
00291 upvar $var ifd
00292
00293 set fix {}
00294 # strips, free bytes, tiles, and their sizes
00295 foreach f_off {0111 0120 0143} f_len {0117 0121 0144} {
00296 if {![info exists ifd($f_len)] || ![info exists ifd($f_off)]} { continue }
00297 set n 0
00298 # put everything into a list
00299 foreach x [_value $ifd($f_len)] y [_value $ifd($f_off)] {
00300 lappend fix [list $n $f_len $x $f_off $y]
00301 incr n
00302 }
00303 }
00304 set offset [expr {[tell $new] + [_ifdsize ifd]}]
00305 set new_fix {}
00306 # sort the list by offset
00307 foreach x [lsort -integer -index 4 $fix] {
00308 lappend new_fix [lreplace $x 4 4 $offset]
00309 incr offset [lindex $x 2]
00310 }
00311 foreach x [lsort -integer -index 0 $new_fix] {
00312 lappend blah([lindex $x 3]) [lindex $x 4]
00313 }
00314 foreach x [array names blah] {
00315 _scan $byteOrder [lindex $ifd($x) 0] x2s format
00316 set ifd($x) [_unformat $byteOrder $x $format $blah($x)]
00317 }
00318 if {[info exists ifd(8769)]} {
00319 seek $fh [_value $ifd(8769)]
00320 _readifd $fh exif
00321 _scan $byteOrder [lindex $ifd($x) 0] x2s format
00322 set ifd(8769) [_unformat $byteOrder 8769 $format $offset]
00323 }
00324 _writeifd $new ifd
00325
00326 foreach x $fix {
00327 seek $fh [lindex $x 4] start
00328 fcopy $fh $new -size [lindex $x 2]
00329 }
00330 if {[info exists ifd(8769)]} {
00331 _writeifd $new exif
00332 }
00333 }
00334
00335
00336 ret ::tiff::_ifds (type fh) {
00337 variable byteOrder
00338
00339 # number of entries in this ifd
00340 _scan $byteOrder [read $fh 2] s num
00341 # subract 2 to account for reading the number
00342 set ret [list [expr {[tell $fh] - 2}]]
00343 # skip the entries, 12 bytes each
00344 seek $fh [expr {$num * 12}] current
00345 # 4 byte offset to next ifd after entries
00346 _scan $byteOrder [read $fh 4] i next
00347
00348 while {$next > 0} {
00349 seek $fh $next start
00350 _scan $byteOrder [read $fh 2] s num
00351 lappend ret [expr {[tell $fh] - 2}]
00352 seek $fh [expr {$num * 12}] current
00353 _scan $byteOrder [read $fh 4] i next
00354 }
00355 return $ret
00356 }
00357
00358
00359 ret ::tiff::_entries (type fh) {
00360 variable byteOrder
00361 variable formats
00362 set ret {}
00363 _scan $byteOrder [read $fh 2] s num
00364 for {} {$num > 0} {incr num -1} {
00365 set offset [tell $fh]
00366 binary scan [read $fh 2] H2H2 t1 t2
00367 _scan $byteOrder [read $fh 6] si format components
00368 seek $fh 4 current
00369 if {$byteOrder == "big"} {
00370 set tag $t1$t2
00371 } else {
00372 set tag $t2$t1
00373 }
00374 #puts "$tag $format $components"
00375 set size [expr {$formats($format) * $components}]
00376 lappend ret [list $tag $offset $size]
00377 }
00378 return $ret
00379 }
00380
00381
00382 ret ::tiff::_getEntry (type fh) {
00383 variable byteOrder
00384 variable formats
00385 binary scan [read $fh 2] H2H2 t1 t2
00386 _scan $byteOrder [read $fh 6] si format components
00387 if {$byteOrder == "big"} {
00388 set tag $t1$t2
00389 } else {
00390 set tag $t2$t1
00391 }
00392 set value [read $fh 4]
00393 set size [expr {$formats($format) * $components}]
00394 #puts "entry $tag $format $components $size"
00395 # if the data is over 4 bytes, its stored later in the file
00396 if {$size > 4} {
00397 set pos [tell $fh]
00398 _scan $byteOrder $value i value
00399 seek $fh $value start
00400 set value [read $fh $size]
00401 seek $fh $pos start
00402 }
00403 return [list $tag [_format $byteOrder $value $format $components]]
00404 }
00405
00406 ret ::tiff::_value (type data) {
00407 variable byteOrder
00408 _scan $byteOrder [lindex $data 0] x2si format components
00409 return [_format $byteOrder [lindex $data 1] $format $components]
00410 }
00411
00412 ret ::tiff::_new (type file , type byteOrder) {
00413 set fh [open $file w]
00414 fconfigure $fh -encoding binary -translation binary -eofchar {}
00415 if {$byteOrder == "big"} {
00416 puts -nonewline $fh [binary format H4 4d4d]
00417 } else {
00418 puts -nonewline $fh [binary format H4 4949]
00419 }
00420 puts -nonewline $fh [_unscan $byteOrder si 42 8]
00421 return $fh
00422 }
00423
00424 ret ::tiff::_readifd (type fh , type var) {
00425 variable byteOrder
00426 variable formats
00427 upvar $var ifd
00428 array set ifd {}
00429 _scan $byteOrder [read $fh 2] s num
00430 for {} {$num > 0} {incr num -1} {
00431 set one [read $fh 8]
00432 binary scan $one H2H2 t1 t2
00433 _scan $byteOrder $one x2si format components
00434 if {$byteOrder == "big"} {
00435 set tag $t1$t2
00436 } else {
00437 set tag $t2$t1
00438 }
00439 set ifd($tag) [list $one]
00440 set value [read $fh 4]
00441 set size [expr {$formats($format) * $components}]
00442 if {$size > 4} {
00443 set pos [tell $fh]
00444 _scan $byteOrder $value i value
00445 seek $fh $value start
00446 lappend ifd($tag) [read $fh $size]
00447 seek $fh $pos start
00448 } else {
00449 lappend ifd($tag) $value
00450 }
00451 }
00452 }
00453
00454 ret ::tiff::_writeifd (type new , type var) {
00455 variable byteOrder
00456 upvar $var ifd
00457 set num [llength [array names ifd]]
00458 puts -nonewline $new [_unscan $byteOrder s $num]
00459 set dataOffset [expr {[tell $new] + ($num * 12) + 4}]
00460 set data {}
00461 foreach tag [lsort [array names ifd]] {
00462 set entry $ifd($tag)
00463 puts -nonewline $new [lindex $entry 0]
00464 if {[string length [lindex $entry 1]] > 4} {
00465 puts -nonewline $new [_unscan $byteOrder i $dataOffset]
00466 append data [lindex $entry 1]
00467 incr dataOffset [string length [lindex $entry 1]]
00468 } else {
00469 puts -nonewline $new [lindex $entry 1]
00470 }
00471 }
00472 set next [tell $new]
00473 puts -nonewline $new [binary format i 0]
00474 puts -nonewline $new $data
00475 return $next
00476 }
00477
00478 ret ::tiff::_ifdsize (type var) {
00479 upvar $var ifd
00480 # 2 bytes for number of entries and 4 bytes for pointer to next ifd
00481 set size 6
00482 foreach x [array names ifd] {
00483 incr size 12
00484 # include data that doesnt fit in entry
00485 if {[string length [lindex $ifd($x) 1]] > 4} {
00486 incr size [string length [lindex $ifd($x) 1]]
00487 }
00488 }
00489 return $size
00490 }
00491
00492 ret ::tiff::debug (type file) {
00493 variable byteOrder
00494 variable tiff_tags
00495 set fh [openTIFF $file]
00496 set n 0
00497 foreach ifd [_ifds $fh] {
00498 seek $fh $ifd start
00499 set entries [_entries $fh]
00500 puts "IFD $n ([llength $entries] entries)"
00501 foreach ent $entries {
00502 if {[info exists tiff_tags([lindex $ent 0])]} {
00503 puts -nonewline " $tiff_tags([lindex $ent 0])"
00504 } else {
00505 puts -nonewline " [lindex $ent 0]"
00506 }
00507 if {[lindex $ent 2] < 200} {
00508 seek $fh [lindex $ent 1] start
00509 puts ": [lindex [_getEntry $fh] 1]"
00510 } else {
00511 puts " offset [lindex $ent 1] size [lindex $ent 2] bytes"
00512 }
00513 if {[lindex $ent 0] == "8769"} {
00514 seek $fh [lindex $ent 1] start
00515 seek $fh [lindex [_getEntry $fh] 1]
00516 foreach x [_entries $fh] {
00517 seek $fh [lindex $x 1]
00518 puts " [_getEntry $fh]"
00519 }
00520 }
00521 }
00522 incr n
00523 }
00524 }
00525
00526 array ::tiff = ::tiff_tags {
00527 00fe NewSubfileType
00528 00ff SubfileType
00529 0100 ImageWidth
00530 0101 ImageLength
00531 0102 BitsPerSample
00532 0103 Compression
00533 0106 PhotometricInterpretation
00534 0107 Threshholding
00535 0108 CellWidth
00536 0109 CellLength
00537 010a FillOrder
00538 010e ImageDescription
00539 010f Make
00540 0110 Model
00541 0111 StripOffs =
00542 0112 Orientation
00543 0115 SamplesPerPixel
00544 0116 RowsPerStrip
00545 0117 StripByteCounts
00546 0118 MinSampleValue
00547 0119 MaxSampleValue
00548 011a XResolution
00549 011b YResolution
00550 011c PlanarConfiguration
00551 0120 FreeOffs =
00552 0121 FreeByteCounts
00553 0122 GrayResponseUnit
00554 0123 GrayResponseCurve
00555 0128 ResolutionUnit
00556 0131 Software
00557 0132 DateTime
00558 013b Artist
00559 013c HostComputer
00560 0140 ColorMap
00561 0152 ExtraSamples
00562 8298 Copyright
00563
00564 010d DocumentName
00565 011d PageName
00566 011e XPosition
00567 011f YPosition
00568 0124 T4Options
00569 0125 T6Options
00570 0129 PageNumber
00571 012d TransferFunction
00572 013d Predictor
00573 013e WhitePoint
00574 013f PrimaryChromaticities
00575 0141 HalftoneHints
00576 0142 TileWidth
00577 0143 TileLength
00578 0144 TileOffs =
00579 0145 TileByteCounts
00580 0146 BadFaxLines
00581 0147 CleanFaxData
00582 0148 ConsecutiveBadFaxLines
00583 014a SubIFDs
00584 014c InkSet
00585 014d InkNames
00586 014e NumberOfInks
00587 0150 DotRange
00588 0151 TargetPrinter
00589 0153 SampleFormat
00590 0154 SMinSampleValue
00591 0155 SMaxSampleValue
00592 0156 TransferRange
00593 0157 ClipPath
00594 0158 XClipPathUnits
00595 0159 YClipPathUnits
00596 015a Indexed
00597 015b JPEGTables
00598 015f OPIProxy
00599 0190 GlobalParametersIFD
00600 0191 ProfileType
00601 0192 FaxProfile
00602 0193 CodingMethods
00603 0194 VersionYear
00604 0195 ModeNumber
00605 01b1 Decode
00606 01b2 DefaultImageColor
00607 0200 JPEGProc
00608 0201 JPEGInterchangeFormat
00609 0202 JPEGInterchangeFormatLength
00610 0203 JPEGRestartInterval
00611 0205 JPEGLosslessPredictors
00612 0206 JPEGPointTransforms
00613 0207 JPEGQTables
00614 0208 JPEGDCTables
00615 0209 JPEGACTables
00616 0211 YCbCrCoefficients
00617 0212 YCbCrSubSampling
00618 0213 YCbCrPositioning
00619 0214 ReferenceBlackWhite
00620 022f StripRowCounts
00621 02bc XMP
00622 800d ImageID
00623 87ac ImageLayer
00624
00625 8649 Photoshop
00626 8769 ExifIFD
00627 8773 ICCProfile
00628 }
00629
00630 if {![info exists ::tiff::tiff_sgat]} {
00631 foreach {x y} [array get ::tiff::tiff_tags] {
00632 ::tiff = ::tiff_sgat($y) $x
00633 }
00634 }
00635
00636 array ::tiff = ::data_types {
00637 1 BYTE
00638 2 ASCII
00639 3 SHORT
00640 4 LONG
00641 5 RATIONAL
00642 6 SBYTE
00643 7 UNDEFINED
00644 8 SSHORT
00645 9 SLONG
00646 10 SRATIONAL
00647 11 FLOAT
00648 12 DOUBLE
00649 BYTE 1
00650 ASCII 2
00651 SHORT 3
00652 LONG 4
00653 RATIONAL 5
00654 SBYTE 6
00655 UNDEFINED 7
00656 SSHORT 8
00657 SLONG 9
00658 SRATIONAL 10
00659 FLOAT 11
00660 DOUBLE 12
00661 }
00662
00663
00664 array ::tiff = ::formats [list 1 1 2 1 3 2 4 4 5 8 6 1 7 1 8 2 9 4 10 8 11 4 12 8]
00665
00666 ret ::tiff::_seek (type chan , type offset , optional origin =start) {
00667 if {$origin == "start"} {
00668 variable start
00669 seek $chan [expr {$offset + $start}] start
00670 } else {
00671 seek $chan $offset $origin
00672 }
00673 }
00674
00675
00676 ret ::tiff::_scan (type e , type v , type f , type args) {
00677 foreach x $args { upvar 1 $x $x }
00678 if {$e == "big"} {
00679 eval [list binary scan $v [string map {b B h H s S i I} $f]] $args
00680 } else {
00681 eval [list binary scan $v $f] $args
00682 }
00683 }
00684
00685
00686 ret ::tiff::_unscan (type e , type f , type args) {
00687 if {$e == "big"} {
00688 return [eval [list binary format [string map {b B h H s S i I} $f]] $args]
00689 } else {
00690 return [eval [list binary format $f] $args]
00691 }
00692 }
00693
00694
00695
00696
00697 ret ::tiff::_format (type end , type value , type type , type num) {
00698 if {$num > 1 && $type != 2 && $type != 7} {
00699 variable formats
00700 set r {}
00701 for {set i 0} {$i < $num} {incr i} {
00702 set len $formats($type)
00703 lappend r [_format $end [string range $value [expr {$len * $i}] [expr {($len * $i) + $len - 1}]] $type 1]
00704 }
00705 #return [join $r ,]
00706 return $r
00707 }
00708 switch -exact -- $type {
00709 1 { _scan $end $value c value }
00710 2 { set value [string trimright $value \x00] }
00711 3 {
00712 _scan $end $value s value
00713 set value [format %u $value]
00714 }
00715 4 {
00716 _scan $end $value i value
00717 set value [format %u $value]
00718 }
00719 5 {
00720 _scan $end $value ii n d
00721 set n [format %u $n]
00722 set d [format %u $d]
00723 if {$d == 0} {set d 1}
00724 #set value [string trimright [string trimright [format %5.4f [expr {double($n) / $d}]] 0] .]
00725 set value [string trimright [string trimright [expr {double($n) / $d}] 0] .]
00726 #set value "$n/$d"
00727 }
00728 6 { _scan $end $value c value }
00729 8 { _scan $end $value s value }
00730 9 { _scan $end $value i value }
00731 10 {
00732 _scan $end $value ii n d
00733 if {$d == 0} {set d 1}
00734 #set value [string trimright [string trimright [format %5.4f [expr {double($n) / $d}]] 0] .]
00735 set value [string trimright [string trimright [expr {double($n) / $d}] 0] .]
00736 #set value "$n/$d"
00737 }
00738 11 { _scan $end $value i value }
00739 12 { _scan $end $value w value }
00740 }
00741 return $value
00742 }
00743
00744 ret ::tiff::_unformat (type end , type tag , type type , type value) {
00745 set packed_val {}
00746 set count [llength $value]
00747 if {$type == 2 || $type == 7} { set value [list $value] }
00748 foreach val $value {
00749 switch -exact -- $type {
00750 1 { set val [_unscan $end c $val] }
00751 2 {
00752 append val \x00
00753 set count [string length $val]
00754 }
00755 3 { set val [_unscan $end s $val] }
00756 4 { set val [_unscan $end i $val] }
00757 5 {
00758 set val [split $val /]
00759 set val [_unscan $end i [lindex $val 0]][_unscan $end i [lindex $val 1]]
00760 }
00761 6 { set val [_unscan $end c $val] }
00762 7 { set count [string length $val }
00763 8 { set val [_unscan $end s $val] }
00764 9 { set val [_unscan $end i $val] }
00765 10 {
00766 set val [split $val /]
00767 set val [_unscan $end i [lindex $val 0]][_unscan $end i [lindex $val 1]]
00768 }
00769 11 { set val [_unscan $end $value i value] }
00770 12 { set val [_unscan $end $value w value] }
00771 default { error "unknown data type $type" }
00772 }
00773 append packed_val $val
00774 }
00775 if {$tag != ""} {
00776 if {$end == "big"} {
00777 set tag [binary format H2H2 [string range $tag 0 1] [string range $tag 2 3]]
00778 } else {
00779 set tag [binary format H2H2 [string range $tag 2 3] [string range $tag 0 1]]
00780 }
00781 }
00782 if {[string length $packed_val] < 4} { set packed_val [binary format a4 $packed_val] }
00783 return [list $tag[_unscan $end si $type $count] $packed_val]
00784 }
00785
00786
00787