#!/usr/bin/perl # # camtoppm $Revision: 1.0 $ programmed by SENDA Shuji # # Convert cam-file to ppm (or jpeg) file # require 'getopts.pl'; &Getopts("hctjp"); if ($opt_h || $#ARGV > 0) { print STDERR "Usage : $0 [-c|-t|-j|-p] [cam_file]\n"; print STDERR "-c : print comments\n"; print STDERR "-t : output thumbnail image 52x36 (ppm)\n"; print STDERR "-j : output full image 480x240 (jpeg)\n"; print STDERR "-p : output full image 480x240 (ppm) [default]\n"; exit 0; } $area_comment = 1; $area_thumbnail = 2; $area_jfif = 3; &setconst; # set JFIF constant tables if ($opt_c) { $pickid = $area_comment; } elsif ($opt_t) { $pickid = $area_thumbnail; } else { $pickid = $area_jfif; } if ($#ARGV) { open(FILE, "-"); $ARGV[0] = "stdin"; } else { open(FILE, $ARGV[0]) || die "$ARGV[0] can not be opened"; } $narea = &camopen(FILE) || die "$ARGV[0] is not cam file"; $off = 0; foreach (1..$narea) { ($id, $len) = &camarea(FILE); if ($id == $pickid) { $pickoff = $off; } $off += $len; } die "can not find ID:$pickid" if (!defined($pickoff)); if ($pickoff) { read(FILE, $buf, $pickoff) || die "read error"; # dummy read } if ($pickid == $area_comment) { while (1) { read(FILE, $cid, 1); last if ($cid eq "\x00"); $cid = unpack("C", $cid); $comment = ""; while (1) { read(FILE, $buf, 1); last if ($buf eq "\x00"); $comment .= $buf; } print "($cid)$comment\n"; } } elsif ($pickid == $area_thumbnail) { read(FILE, $data, $len); print "P6\n52 36\n255\n$data"; } elsif ($pickid == $area_jfif) { if (!$opt_j || $opt_p) { open(PPMOUT, "|djpeg"); select(PPMOUT); } read(FILE, $buf, 8) || die "read error"; ($narea, $ysize, $usize, $vsize) = unpack("nnnn", $buf); die "JFIF area number != 3" if ($narea != 3); print "$soi"; print "$app0"; print "$dqt0"; read(FILE, $buf, 64); print "$buf"; print "$dqt1"; read(FILE, $buf, 64); print "$buf"; print "$sof"; print "$dht"; print "$sos_y"; read(FILE, $buf, $ysize); print "$buf"; print "$sos_u"; read(FILE, $buf, $usize); print "$buf"; print "$sos_v"; read(FILE, $buf, $vsize); print "$buf"; print "$eoi"; } exit 0; sub camopen { # return (narea) local($fd) = @_; local($buf); read($fd, $buf, 4) || die "read error"; return undef if ($buf ne "\x07\x20\x4d\x4d"); read($fd, $buf, 2) || die "read error"; return unpack("n", $buf); } sub camarea { # return (ID, length) local($fd) = @_; local($buf); read($fd, $buf, 16) || die "read error"; return unpack("nN", $buf); } sub setconst { $soi = pack("H*", "ffd8"); $app0 = pack("H*", "ffe000104a46494600010101012c012c0000"); $dqt0 = pack("H*", "ffdb004300"); $dqt1 = pack("H*", "ffdb004301"); $sof = pack("H*", "ffc000110800f001e003013200021101031101"); $dht = pack("H*", "ffc4001f00" . "00010501010101010100000000000000" . "000102030405060708090a0b" . "ffc400b510" . "0002010303020403050504040000017d" . "01020300041105122131410613516107" . "227114328191a1082342b1c11552d1f0" . "2433627282090a161718191a25262728" . "292a3435363738393a43444546474849" . "4a535455565758595a63646566676869" . "6a737475767778797a83848586878889" . "8a92939495969798999aa2a3a4a5a6a7" . "a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5" . "c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2" . "e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8" . "f9fa" . "ffc4001f01" . "00030101010101010101010000000000" . "000102030405060708090a0b" . "ffc400b511" . "00020102040403040705040400010277" . "00010203110405213106124151076171" . "1322328108144291a1b1c109233352f0" . "156272d10a162434e125f11718191a26" . "2728292a35363738393a434445464748" . "494a535455565758595a636465666768" . "696a737475767778797a828384858687" . "88898a92939495969798999aa2a3a4a5" . "a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3" . "c4c5c6c7c8c9cad2d3d4d5d6d7d8d9da" . "e2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8" . "f9fa"); $sos_y = pack("H*", "ffda0008010100003f00"); $sos_u = pack("H*", "ffda0008010211003f00"); $sos_v = pack("H*", "ffda0008010311003f00"); $eoi = pack("H*", "ffd9"); }