#!/usr/bin/perl # Try to parse jpeg file, possibly corrupted require 'jpeg_marker.perl' ; $/ = undef ; # read whole file # Read it all and convert to array of ASCII codes @data = unpack('C*',<>) ; $length = scalar @data ; $s_length = sprintf("%x",$length) ; print "$s_length (hex), $length (decimal) characters\n" ; $l_chars = length($s_length) ; $last_type = -1 ; #$first_loc = -1 ; #$last_loc = -1 ; #$count = 0 ; # Some common tokens $APP0 = ord("\xe0") ; $SOI = ord("\xd8") ; $ff = ord("\xff") ; $i = 0 ; # Check for JFIF file header if ($data[0] != $ff) { print "ERROR: No marker at beginning of file!\n" ; } elsif ($data[1] != $SOI) { print "ERROR: Non-SOI marker at beginning of file!\n" ; } else { &do_marker(0,$data[1]) ; $i = 2 ; if ($data[2] != $ff) { print "WARNING: No marker after initial SOI (not JFIF standard)!\n" ; } elsif ($data[3] < $APP0 && $data[3] > $APP0+7) { print "WARNING: Non-APPn marker after initial SOI (not JFIF standard)!\n" ; } else { &do_marker(2,$data[3]) ; if ($data[3] != $APP0) { print "WARNING: Non-APP0 marker after initial SOI (not JFIF standard)!\n" ; print " Trying to parse anyway ...\n" ; } $i = 4 ; # length field $length1 = $data[4] + 256*$data[5] ; $length2 = $data[5] + 256*$data[4] ; # look for next marker, check consistency #for ($j=6;$j<$length;$j++) #{ # last if ($data[$j] == $ff && # $data[$j+1] != 0) ; # #$data[$j+1] != $ff) ; #} #$length3 = $j - 4 ; #print "\tlength: $length1 $length2 $length3\n" ; print "\tlength: $length2\n" ; #if ($length1 != $length3 && $length2 != $length3) #{ # print "\tWARNING: inconsistent lengths\n" ; #} if ($data[$length1+2] == $ff and $data[$length1+3] != $ff and $data[$length1+3] != "\0") { print "Length1 ($length1) points to a marker.\n" ; &do_marker($length1+4,$data[$length1+5]) ; } if ($data[$length2+2] == $ff and $data[$length2+3] != $ff and $data[$length2+3] != "\0") { #print "Length2 ($length2) points to a marker:" ; print "Skipping to next marker:\n" ; $i = $length2+2 ; #&do_marker($i,$data[$i+1]) ; } else { print "No marker after length, parsing intermediate data:\n" ; } } } for (; $i < (scalar @data); $i++) { if ($data[$i] == $ff) { $j = $i + 1 ; next if ($data[$j] == 0) ; # skip "stuffed zero" next if ($data[$j] == $ff) ; # skip filler &do_marker($i,$data[$j]) ; } } sub do_marker() { my($loc,$type) = @_ ; print sprintf("%${l_chars}x %4s %s\n",$loc,$mark_code[$type],$mark_text[$type]) ; }