source: tol/tolsh/tolsh.vfs/lib/tcllib1.10/tiff/tiff.tcl @ 8597867d

1941-docker-image-to-testdevel
Last change on this file since 8597867d was 8597867d, checked in by Jorge Pérez <josp.jorge@…>, 16 years ago

closes #976, se incluye tcllib1.10, base64 debe eliminarse del raiz de lib ya que esta incluido en tcllib

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@2556 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 22.7 KB
Line 
1# tiff.tcl --
2#
3#       Querying and modifying TIFF image files.
4#
5# Copyright (c) 2004    Aaron Faupell <afaupell@users.sourceforge.net>
6#
7# See the file "license.terms" for information on usage and redistribution
8# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9#
10# RCS: @(#) $Id: tiff.tcl,v 1.3 2006/07/20 07:09:58 afaupell Exp $
11
12package provide tiff 0.1
13
14namespace eval ::tiff {}
15
16proc ::tiff::openTIFF {file {mode r}} {
17    variable byteOrder
18    set fh [open $file $mode]
19    fconfigure $fh -encoding binary -translation binary -eofchar {}
20    binary scan [read $fh 2] H4 byteOrder
21    if {$byteOrder == "4949"} {
22        set byteOrder little
23    } elseif {$byteOrder == "4d4d"} {
24        set byteOrder big
25    } else {
26        close $fh
27        return -code error "not a tiff file"
28    }
29    _scan $byteOrder [read $fh 6] si version offset
30    if {$version != "42"} {
31        close $fh
32        return -code error "not a tiff file"
33    }
34    seek $fh $offset start
35    return $fh
36}
37
38proc ::tiff::isTIFF {file} {
39    set is [catch {openTIFF $file} fh]
40    catch {close $fh}
41    return [expr {!$is}]
42}
43
44proc ::tiff::byteOrder {file} {
45    global $byteOrder
46    set fh [openTIFF $file]
47    close $fh
48    return $byteOrder
49}
50
51proc ::tiff::nametotag {names} {
52    variable tiff_sgat
53    set out {}
54    foreach x $names {
55        set y [lindex $x 0]
56        if {[info exists tiff_sgat($y)]} {
57            set y $tiff_sgat($y)
58        } elseif {![string match {[0-9a-f][0-9a-f][0-9a-f][0-9a-f]} $x]} {
59            error "unknown tag $y"
60        }
61        lappend out [lreplace $x 0 0 $y]
62    }
63    return $out
64}
65
66proc ::tiff::tagtoname {tags} {
67    variable tiff_tags
68    set out {}
69    foreach x $tags {
70        set y [lindex $x 0]
71        if {[info exists tiff_tags($y)]} { set y $tiff_tags($y) }
72        lappend out [lreplace $x 0 0 $y]
73    }
74    return $out
75}
76
77proc ::tiff::numImages {file} {
78    variable byteOrder
79    set fh [openTIFF $file]
80    set images [llength [_ifds $fh]]
81    close $fh
82    return $images
83}
84
85proc ::tiff::dimensions {file {image 0}} {
86    return [getEntry $file {0100 0101} $image]
87}
88
89proc ::tiff::imageInfo {file {image 0}} {
90    return [getEntry $file {ImageWidth ImageLength BitsPerSample Compression \
91          PhotometricInterpretation ImageDescription Orientation XResolution \
92          YResolution ResolutionUnit DateTime Artist HostComputer} $image]
93}
94
95proc ::tiff::entries {file {image 0}} {
96    variable byteOrder
97    set fh [openTIFF $file]
98    set ret {}
99    if {[set ifd [lindex [_ifds $fh] $image]] != ""} {
100        seek $fh $ifd
101        foreach e [tagtoname [_entries $fh]] {
102            lappend ret [lindex $e 0]
103        }
104    }
105    close $fh
106    return $ret
107}
108
109proc ::tiff::getEntry {file entry {image 0}} {
110    variable byteOrder
111    set fh [openTIFF $file]
112    set ret {}
113    if {[set ifd [lindex [_ifds $fh] $image]] != ""} {
114        seek $fh $ifd
115        set ent [_entries $fh]
116        foreach e $entry {
117            if {[set x [lsearch -inline $ent "[nametotag $e] *"]] != ""} {
118                seek $fh [lindex $x 1]
119                lappend ret $e [lindex [_getEntry $fh] 1]
120            } else {
121                lappend ret $e {}
122            }
123        }
124    }
125    close $fh
126    return $ret
127}
128
129proc ::tiff::addEntry {file entry {image 0}} {
130    variable byteOrder
131    set fh [openTIFF $file]
132    set new [_new $file.tmp $byteOrder]
133    set ifds [_ifds $fh]
134    for {set i 0} {$i < [llength $ifds]} {incr i} {
135        seek $fh [lindex $ifds $i]
136        _readifd $fh ifd
137        if {$i == $image || $image == "all"} {
138            foreach e [nametotag $entry] {
139                set ifd($tag) [eval _unformat $byteOrder $e]
140            }
141        }
142        _copyData $fh $new ifd
143    }
144    close $fh
145    close $new
146    file rename -force $file.tmp $file
147}
148
149proc ::tiff::deleteEntry {file entry {image 0}} {
150    variable byteOrder
151    set fh [openTIFF $file]
152    set new [_new $file.tmp $byteOrder]
153    set ifds [_ifds $fh]
154    for {set i 0} {$i < [llength $ifds]} {incr i} {
155        seek $fh [lindex $ifds $i]
156        _readifd $fh ifd
157        if {$i == $image || $image == "all"} {
158            foreach e [nametotag $entry] { unset -nocomplain ifd($e) }
159        }
160        _copyData $fh $new ifd
161    }
162    close $fh
163    close $new
164    file rename -force $file.tmp $file
165}
166
167proc ::tiff::writeImage {image file {entry {}}} {
168    variable byteOrder
169    set byteOrder big
170    set fh [_new $file $byteOrder]
171    set w [$image cget -width]
172    set h [$image cget -height]
173    set ifd(0100) [_unformat $byteOrder 0100 4 $w]      ;# width
174    set ifd(0101) [_unformat $byteOrder 0101 4 $h]      ;# height
175    set ifd(0102) [_unformat $byteOrder 0102 3 {8 8 8}] ;# color depth
176    set ifd(0103) [_unformat $byteOrder 0103 3 1]       ;# compression = none
177    set ifd(0106) [_unformat $byteOrder 0106 3 2]       ;# photometric interpretation = rgb
178    set ifd(0115) [_unformat $byteOrder 0115 3 3]       ;# 3 samples per pixel r, g, and b
179    set ifd(011c) [_unformat $byteOrder 011c 3 1]       ;# planar configuration = rgb
180    foreach {tag format value} $entry {
181        set ifd($tag) [_unformat $byteOrder $tag $format $value]
182    }
183
184    set rowsPerStrip 2
185    while {$w * 3 * $rowsPerStrip < 8000} { incr rowsPerStrip }
186    incr rowsPerStrip -1
187    set strips [expr {int(ceil($h / double($rowsPerStrip)))}]
188    set stripSize [expr {$w * $rowsPerStrip * 3}]
189    set lastStripSize [expr {3 * $w * ($h - (($strips - 1) * $rowsPerStrip))}]
190   
191    for {set i $strips} {$i > 1} {incr i -1} { lappend sizes $stripSize }
192    lappend sizes $lastStripSize
193   
194    set ifd(0116) [_unformat $byteOrder 0116 4 $rowsPerStrip]
195    set ifd(0111) [_unformat $byteOrder 0111 4 $sizes]
196    # dummy data, to get ifd size, real value inserted later
197    set ifd(0117) [_unformat $byteOrder 0117 4 $sizes]
198   
199    # add 8 bytes for file header
200    set start [expr {[_ifdsize ifd] + 8}]
201    for {set i $strips} {$i > 0} {incr i -1} {
202        lappend offsets $start
203        incr start $stripSize
204    }
205    set ifd(0111) [_unformat $byteOrder 0111 4 $offsets]
206   
207    _writeifd $fh ifd
208
209    for {set y 0} {$y < $h} {incr y} {
210        for {set x 0} {$x < $w} {incr x} {
211            foreach {r g b} [$image get $x $y] {
212                puts -nonewline $fh [_unscan $byteOrder ccc [expr {$r & 0xFF}] [expr {$g & 0xFF}] [expr {$b & 0xFF}]]
213            }
214        }
215    }
216   
217    close $fh
218}
219
220proc ::tiff::getImage {file {image 0}} {
221    array set tags [getEntry $file {0100 0101 0102 0103 0106 011c 0115 0111 0117 0140} $image]
222    if {$tags(0102) == "8 8 8" && $tags(0103) == 1 && $tags(0106) == 2 && $tags(0115) == 3 && $tags(011c) == 1} {
223        set w $tags(0100)
224        set h $tags(0101)
225        set i [image create photo -height $h -width $w]
226        set fh [open $file]
227        fconfigure $fh -translation binary -encoding binary -eofchar {}
228
229        set y 0
230        set x 0
231        set row {}
232        set block {}
233        foreach offset $tags(0111) len $tags(0117) {
234            seek $fh $offset start
235            binary scan [read $fh $len] c* buf
236            foreach {r g b} $buf {
237                lappend row [format "#%02X%02X%02X" [expr {$r & 0xFF}] [expr {$g & 0xFF}] [expr {$b & 0xFF}]]
238                incr x
239                if {$x == $w} { lappend block $row; set row {}; set x 0 }
240            }
241            $i put $block -to 0 $y
242            incr y [llength $block]
243            set block {}
244        }
245        close $fh
246    } elseif {$tags(0102) == 8 && $tags(0103) == 1 && $tags(0106) == 3 && $tags(0115) == 1 && $tags(011c) == 1} {
247        set w $tags(0100)
248        set h $tags(0101)
249        set i [image create photo -height $h -width $w]
250        set fh [open $file]
251        fconfigure $fh -translation binary -encoding binary -eofchar {}
252
253        set map {}
254        set third [expr {[llength $tags(0140)] / 3}]
255        set rs [lrange $tags(0140) 0 [expr {$third - 1}]]
256        set gs [lrange $tags(0140) $third [expr {($third * 2) - 1}]]
257        set bs [lrange $tags(0140) [expr {$third * 2}] end]
258        foreach r $rs g $gs b $bs {
259            set r [expr {int($r / 256) & 0xFF}]
260            set g [expr {int($g / 256) & 0xFF}]
261            set b [expr {int($b / 256) & 0xFF}]
262            lappend map [format "#%02X%02X%02X" $r $g $b]
263        }
264       
265        set y 0
266        set x 0
267        set row {}
268        set block {}
269       
270        foreach offset $tags(0111) len $tags(0117) {
271            seek $fh $offset start
272            binary scan [read $fh $len] c* buf
273            foreach index $buf {
274                lappend row [lindex $map [expr {$index & 0xFF}]]
275                incr x
276                if {$x == $w} { lappend block $row; set row {}; set x 0 }
277            }
278            $i put $block -to 0 $y
279            incr y [llength $block]
280            set block {}
281        }
282        close $fh
283    } else {
284        error "I cant read that image format"
285    }
286    return $i
287}
288
289proc ::tiff::_copyData {fh new var} {
290    variable byteOrder
291    upvar $var ifd
292
293    set fix {}
294    #       strips, free bytes, tiles,   and their sizes     
295    foreach f_off {0111 0120 0143} f_len {0117 0121 0144} {
296        if {![info exists ifd($f_len)] || ![info exists ifd($f_off)]} { continue }
297        set n 0
298        # put everything into a list
299        foreach x [_value $ifd($f_len)] y [_value $ifd($f_off)] {
300            lappend fix [list $n $f_len $x $f_off $y]
301            incr n
302        }
303    }
304    set offset [expr {[tell $new] + [_ifdsize ifd]}]
305    set new_fix {}
306    # sort the list by offset
307    foreach x [lsort -integer -index 4 $fix] {
308        lappend new_fix [lreplace $x 4 4 $offset]
309        incr offset [lindex $x 2]
310    }
311    foreach x [lsort -integer -index 0 $new_fix] {
312        lappend blah([lindex $x 3]) [lindex $x 4]
313    }
314    foreach x [array names blah] {
315        _scan $byteOrder [lindex $ifd($x) 0] x2s format
316        set ifd($x) [_unformat $byteOrder $x $format $blah($x)]
317    }
318    if {[info exists ifd(8769)]} {
319        seek $fh [_value $ifd(8769)]
320        _readifd $fh exif
321        _scan $byteOrder [lindex $ifd($x) 0] x2s format
322        set ifd(8769) [_unformat $byteOrder 8769 $format $offset]
323    }
324    _writeifd $new ifd
325       
326    foreach x $fix {
327        seek $fh [lindex $x 4] start
328        fcopy $fh $new -size [lindex $x 2]
329    }
330    if {[info exists ifd(8769)]} {
331        _writeifd $new exif
332    }
333}
334
335# returns a list of offsets of all the IFDs
336proc ::tiff::_ifds {fh} {
337    variable byteOrder
338
339    # number of entries in this ifd
340    _scan $byteOrder [read $fh 2] s num
341    # subract 2 to account for reading the number
342    set ret [list [expr {[tell $fh] - 2}]]
343    # skip the entries, 12 bytes each
344    seek $fh [expr {$num * 12}] current
345    # 4 byte offset to next ifd after entries
346    _scan $byteOrder [read $fh 4] i next
347
348    while {$next > 0} {
349        seek $fh $next start
350        _scan $byteOrder [read $fh 2] s num
351        lappend ret [expr {[tell $fh] - 2}]
352        seek $fh [expr {$num * 12}] current
353        _scan $byteOrder [read $fh 4] i next
354    }
355    return $ret
356}
357
358# takes fh at start of IFD and returns entries, offset, and size
359proc ::tiff::_entries {fh} {
360    variable byteOrder
361    variable formats
362    set ret {}
363    _scan $byteOrder [read $fh 2] s num
364    for {} {$num > 0} {incr num -1} {
365        set offset [tell $fh]
366        binary scan [read $fh 2] H2H2 t1 t2
367        _scan $byteOrder [read $fh 6] si format components
368        seek $fh 4 current
369        if {$byteOrder == "big"} {
370            set tag $t1$t2
371        } else {
372            set tag $t2$t1
373        }
374        #puts "$tag $format $components"
375        set size [expr {$formats($format) * $components}]
376        lappend ret [list $tag $offset $size]
377    }
378    return $ret
379}
380
381# takes fh at start of dir entry and returns tag and value(s)
382proc ::tiff::_getEntry {fh} {
383    variable byteOrder
384    variable formats
385    binary scan [read $fh 2] H2H2 t1 t2
386    _scan $byteOrder [read $fh 6] si format components
387    if {$byteOrder == "big"} {
388        set tag $t1$t2
389    } else {
390        set tag $t2$t1
391    }
392    set value [read $fh 4]
393    set size [expr {$formats($format) * $components}]
394    #puts "entry $tag $format $components $size"
395    # if the data is over 4 bytes, its stored later in the file
396    if {$size > 4} {
397        set pos [tell $fh]
398        _scan $byteOrder $value i value
399        seek $fh $value start
400        set value [read $fh $size]
401        seek $fh $pos start
402    }
403    return [list $tag [_format $byteOrder $value $format $components]]
404}
405
406proc ::tiff::_value {data} {
407    variable byteOrder
408    _scan $byteOrder [lindex $data 0] x2si format components
409    return [_format $byteOrder [lindex $data 1] $format $components]
410}
411
412proc ::tiff::_new {file byteOrder} {
413    set fh [open $file w]
414    fconfigure $fh -encoding binary -translation binary -eofchar {}
415    if {$byteOrder == "big"} {
416        puts -nonewline $fh [binary format H4 4d4d]
417    } else {
418        puts -nonewline $fh [binary format H4 4949]
419    }
420    puts -nonewline $fh [_unscan $byteOrder si 42 8]
421    return $fh
422}
423
424proc ::tiff::_readifd {fh var} {
425    variable byteOrder
426    variable formats
427    upvar $var ifd
428    array set ifd {}
429    _scan $byteOrder [read $fh 2] s num
430    for {} {$num > 0} {incr num -1} {
431        set one [read $fh 8]
432        binary scan $one H2H2 t1 t2
433        _scan $byteOrder $one x2si format components
434        if {$byteOrder == "big"} {
435            set tag $t1$t2
436        } else {
437            set tag $t2$t1
438        }
439        set ifd($tag) [list $one]
440        set value [read $fh 4]
441        set size [expr {$formats($format) * $components}]
442        if {$size > 4} {
443            set pos [tell $fh]
444            _scan $byteOrder $value i value
445            seek $fh $value start
446            lappend ifd($tag) [read $fh $size]
447            seek $fh $pos start
448        } else {
449            lappend ifd($tag) $value
450        }
451    }
452}
453
454proc ::tiff::_writeifd {new var} {
455    variable byteOrder
456    upvar $var ifd
457    set num [llength [array names ifd]]
458    puts -nonewline $new [_unscan $byteOrder s $num]
459    set dataOffset [expr {[tell $new] + ($num * 12) + 4}]
460    set data {}
461    foreach tag [lsort [array names ifd]] {
462        set entry $ifd($tag)
463        puts -nonewline $new [lindex $entry 0]
464        if {[string length [lindex $entry 1]] > 4} {
465            puts -nonewline $new [_unscan $byteOrder i $dataOffset]
466            append data [lindex $entry 1]
467            incr dataOffset [string length [lindex $entry 1]]
468        } else {
469            puts -nonewline $new [lindex $entry 1]
470        }
471    }
472    set next [tell $new]
473    puts -nonewline $new [binary format i 0]
474    puts -nonewline $new $data
475    return $next
476}
477
478proc ::tiff::_ifdsize {var} {
479    upvar $var ifd
480    # 2 bytes for number of entries and 4 bytes for pointer to next ifd
481    set size 6
482    foreach x [array names ifd] {
483        incr size 12
484        # include data that doesnt fit in entry
485        if {[string length [lindex $ifd($x) 1]] > 4} {
486            incr size [string length [lindex $ifd($x) 1]]
487        }
488    }
489    return $size
490}
491
492proc ::tiff::debug {file} {
493    variable byteOrder
494    variable tiff_tags
495    set fh [openTIFF $file]
496    set n 0
497    foreach ifd [_ifds $fh] {
498        seek $fh $ifd start
499        set entries [_entries $fh]
500        puts "IFD $n ([llength $entries] entries)"
501        foreach ent $entries {
502            if {[info exists tiff_tags([lindex $ent 0])]} {
503                puts -nonewline "  $tiff_tags([lindex $ent 0])"
504            } else {
505                puts -nonewline "  [lindex $ent 0]"
506            }
507            if {[lindex $ent 2] < 200} {
508                seek $fh [lindex $ent 1] start
509                puts ": [lindex [_getEntry $fh] 1]"
510            } else {
511                puts " offset [lindex $ent 1] size [lindex $ent 2] bytes"
512            }
513            if {[lindex $ent 0] == "8769"} {
514                seek $fh [lindex $ent 1] start
515                seek $fh [lindex [_getEntry $fh] 1]
516                foreach x [_entries $fh] {
517                    seek $fh [lindex $x 1]
518                    puts "    [_getEntry $fh]"
519                }
520            }
521        }
522        incr n
523    }
524}
525
526array set ::tiff::tiff_tags {
527    00fe NewSubfileType
528    00ff SubfileType
529    0100 ImageWidth
530    0101 ImageLength
531    0102 BitsPerSample
532    0103 Compression
533    0106 PhotometricInterpretation
534    0107 Threshholding
535    0108 CellWidth 
536    0109 CellLength
537    010a FillOrder
538    010e ImageDescription
539    010f Make
540    0110 Model
541    0111 StripOffsets
542    0112 Orientation   
543    0115 SamplesPerPixel
544    0116 RowsPerStrip
545    0117 StripByteCounts
546    0118 MinSampleValue
547    0119 MaxSampleValue
548    011a XResolution
549    011b YResolution
550    011c PlanarConfiguration
551    0120 FreeOffsets
552    0121 FreeByteCounts
553    0122 GrayResponseUnit
554    0123 GrayResponseCurve
555    0128 ResolutionUnit
556    0131 Software
557    0132 DateTime
558    013b Artist
559    013c HostComputer
560    0140 ColorMap
561    0152 ExtraSamples
562    8298 Copyright
563
564    010d DocumentName
565    011d PageName   
566    011e XPosition 
567    011f YPosition   
568    0124 T4Options
569    0125 T6Options
570    0129 PageNumber
571    012d TransferFunction
572    013d Predictor
573    013e WhitePoint
574    013f PrimaryChromaticities
575    0141 HalftoneHints
576    0142 TileWidth   
577    0143 TileLength 
578    0144 TileOffsets
579    0145 TileByteCounts 
580    0146 BadFaxLines
581    0147 CleanFaxData
582    0148 ConsecutiveBadFaxLines
583    014a SubIFDs
584    014c InkSet
585    014d InkNames
586    014e NumberOfInks
587    0150 DotRange
588    0151 TargetPrinter
589    0153 SampleFormat
590    0154 SMinSampleValue
591    0155 SMaxSampleValue
592    0156 TransferRange
593    0157 ClipPath
594    0158 XClipPathUnits
595    0159 YClipPathUnits
596    015a Indexed
597    015b JPEGTables
598    015f OPIProxy
599    0190 GlobalParametersIFD
600    0191 ProfileType
601    0192 FaxProfile
602    0193 CodingMethods
603    0194 VersionYear
604    0195 ModeNumber
605    01b1 Decode
606    01b2 DefaultImageColor
607    0200 JPEGProc
608    0201 JPEGInterchangeFormat
609    0202 JPEGInterchangeFormatLength
610    0203 JPEGRestartInterval
611    0205 JPEGLosslessPredictors
612    0206 JPEGPointTransforms
613    0207 JPEGQTables
614    0208 JPEGDCTables
615    0209 JPEGACTables
616    0211 YCbCrCoefficients
617    0212 YCbCrSubSampling
618    0213 YCbCrPositioning
619    0214 ReferenceBlackWhite
620    022f StripRowCounts
621    02bc XMP
622    800d ImageID
623    87ac ImageLayer
624
625    8649 Photoshop
626    8769 ExifIFD
627    8773 ICCProfile
628}
629
630if {![info exists ::tiff::tiff_sgat]} {
631    foreach {x y} [array get ::tiff::tiff_tags] {
632        set ::tiff::tiff_sgat($y) $x
633    }
634}
635
636array set ::tiff::data_types {
637    1 BYTE
638    2 ASCII
639    3 SHORT
640    4 LONG
641    5 RATIONAL
642    6 SBYTE
643    7 UNDEFINED
644    8 SSHORT
645    9 SLONG
646    10 SRATIONAL
647    11 FLOAT
648    12 DOUBLE
649    BYTE 1
650    ASCII 2
651    SHORT 3
652    LONG 4
653    RATIONAL 5
654    SBYTE 6
655    UNDEFINED 7
656    SSHORT 8
657    SLONG 9
658    SRATIONAL 10
659    FLOAT 11
660    DOUBLE 12
661}
662
663# for mapping the format types to byte lengths
664array set ::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]
665
666proc ::tiff::_seek {chan offset {origin start}} {
667    if {$origin == "start"} {
668        variable start
669        seek $chan [expr {$offset + $start}] start
670    } else {
671        seek $chan $offset $origin
672    }
673}
674
675# [binary scan], in the byte order indicated by $e
676proc ::tiff::_scan {e v f args} {
677     foreach x $args { upvar 1 $x $x }
678     if {$e == "big"} {
679          eval [list binary scan $v [string map {b B h H s S i I} $f]] $args
680     } else {
681         eval [list binary scan $v $f] $args
682     }
683}
684
685# [binary format], in the byte order indicated by $e
686proc ::tiff::_unscan {e f args} {
687     if {$e == "big"} {
688         return [eval [list binary format [string map {b B h H s S i I} $f]] $args]
689     } else {
690         return [eval [list binary format $f] $args]
691     }
692}
693
694# formats values, the numbers correspond to data types
695# values may be either byte order, as indicated by $end
696# see the tiff spec for more info
697proc ::tiff::_format {end value type num} {
698    if {$num > 1 && $type != 2 && $type != 7} {
699        variable formats
700        set r {}
701        for {set i 0} {$i < $num} {incr i} {
702            set len $formats($type)
703            lappend r [_format $end [string range $value [expr {$len * $i}] [expr {($len * $i) + $len - 1}]] $type 1]
704        }
705        #return [join $r ,]
706        return $r
707    }
708    switch -exact -- $type {
709        1 { _scan $end $value c value }
710        2 { set value [string trimright $value \x00] }
711        3 {
712            _scan $end $value s value
713            set value [format %u $value]
714        }
715        4 {
716            _scan $end $value i value
717            set value [format %u $value]
718        }
719        5 {
720            _scan $end $value ii n d
721            set n [format %u $n]
722            set d [format %u $d]
723            if {$d == 0} {set d 1}
724            #set value [string trimright [string trimright [format %5.4f [expr {double($n) / $d}]] 0] .]
725            set value [string trimright [string trimright [expr {double($n) / $d}] 0] .]
726            #set value "$n/$d"
727        }
728        6 { _scan $end $value c value }
729        8 { _scan $end $value s value }
730        9 { _scan $end $value i value }
731        10 {
732            _scan $end $value ii n d
733            if {$d == 0} {set d 1}
734            #set value [string trimright [string trimright [format %5.4f [expr {double($n) / $d}]] 0] .]
735            set value [string trimright [string trimright [expr {double($n) / $d}] 0] .]
736            #set value "$n/$d"
737        }
738        11 { _scan $end $value i value }
739        12 { _scan $end $value w value }
740    }
741    return $value
742}
743
744proc ::tiff::_unformat {end tag type value} {
745    set packed_val {}
746    set count [llength $value]
747    if {$type == 2 || $type == 7} { set value [list $value] }
748    foreach val $value {
749        switch -exact -- $type {
750            1 { set val [_unscan $end c $val] }
751            2 {
752                append val \x00
753                set count [string length $val]
754            }
755            3 { set val [_unscan $end s $val] }
756            4 { set val [_unscan $end i $val] }
757            5 {
758                set val [split $val /]
759                set val [_unscan $end i [lindex $val 0]][_unscan $end i [lindex $val 1]]
760            }
761            6 { set val [_unscan $end c $val] }
762            7 { set count [string length $val }
763            8 { set val [_unscan $end s $val] }
764            9 { set val [_unscan $end i $val] }
765            10 {
766                set val [split $val /]
767                set val [_unscan $end i [lindex $val 0]][_unscan $end i [lindex $val 1]]
768            }
769            11 { set val [_unscan $end $value i value] }
770            12 { set val [_unscan $end $value w value] }
771            default { error "unknown data type $type" }
772        }
773        append packed_val $val
774    }
775    if {$tag != ""} {
776        if {$end == "big"} {
777            set tag [binary format H2H2 [string range $tag 0 1] [string range $tag 2 3]]
778        } else {
779            set tag [binary format H2H2 [string range $tag 2 3] [string range $tag 0 1]]
780        }
781    }
782    if {[string length $packed_val] < 4} { set packed_val [binary format a4 $packed_val] }
783    return [list $tag[_unscan $end si $type $count] $packed_val]
784}
785       
786
Note: See TracBrowser for help on using the repository browser.