|
JPGvivisect.pm
#!/usr/local/bin/perl
# (c)copyleft 2017-5-17 : Coded by shun kinoshita / knuhs
# $SGMsize = JPGvivisect( \$jpgSTR, $size, $directory, $jpgFile);
# $SGMsize : Segment部の長さを返す
# 解剖結果は %HashTBL と %DataTBL 上に保存される
use strict;
use vars qw/ %HashTBL %DataTBL /; # Global の扱いにする
sub JPGvivisect
{
my ( $jpgRef, $Fsize, $dirSTR, $fileSTR ) = @_;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$Size,$atime,$Mtime,
$ctime,$blksize,$blocks) = stat("$dirSTR/$fileSTR");
my ($sec,$Min,$Hour,$Mday,$Mon,$Year,$wday,$yday,$isdst)
= localtime($Mtime);
my $Date = sprintf("%04d-%02d-%02d",$Year+1900,$Mon+1,$Mday);
my $TimeHM = sprintf("%02d:%02d",$Hour,$Min);
# 基礎データを記録する
$DataTBL{'File Name'} = "$fileSTR\n";
$DataTBL{'File Path'} = "$dirSTR\n";
$DataTBL{'File Size'} = insCom($Size)." Bytes\n";
$DataTBL{'Time Stamp'} = "$Date $TimeHM\n";
# 数値に3桁ごとにコンマを挿入する関数
sub insCom
{ my $_ = shift @_; s/(\d{1,3})(?=(?:\d\d\d)+(?!\d))/$1,/g; return $_; }
# 数値を10進数と16進数で表現する関数
sub show
{ my $_ = shift @_; return ( insCom($_).sprintf(" [0x%X]", $_) ); }
# getByte(startpos, nbyte) 数バイトごとに取り出す関数
sub getByte
{ my ($p, $n) = @_;
return ( unpack(($n==1)?"C":"n", substr($$jpgRef, $p, $n)) ) ;
}
# Vivisection start here
my ($pos, $cc) = (0, 0);
my $i;
my $FF=0xFF; #
my $E0=0xE0; # APP0-15 (0xFFE0〜0xFFEF) その他のAPPセグメント
my $E1=0xE1; #
my $C0=0xC0; # SOF (0xFFC0〜FFCF) Frame Header
my $C4=0xC4; # DHT (0xFFC4) Huffman Table定義
my $DA=0xDA; # SOS (0xFFDA) Scan Header
my $DB=0xDB; # .. (0xFFDB) Scan Header
my $D9=0xD9; # EOI (0xFFD9) End Marker
my $SOI=0xFFD8; # SOI : Start Of Image ' FF D8'
my $SOS=0xFFDA; # SOS : Start Of Scan ' FF DA'
my $EOI=0xFFD9; # EOI : End Of Image
my $SOF=0xFFC0; # SOF : Segment Of Frame Header
if( getByte($pos, 2) != $SOI )
{ print "JPEGファイルではありません!\n"; return(-1); }
# Marker の位置を記録する
$i = ++$HashTBL{'FFD8'}[0]; $HashTBL{'FFD8'}[$i] = "$pos";
$pos = 2;
while(1)
{ next if( $cc=getByte($pos, 1) != $FF );
$cc = getByte($pos+1, 1);
if( $cc==$C0 || $cc==$C4 || $cc==$E0 || $cc==$E1 || $cc==$DB )
{ my $f = sprintf("FF%X",$cc);
$i = ++$HashTBL{$f}[0]; $HashTBL{$f}[$i] = "$pos";
$pos += getByte($pos+2, 2); next;
}
if( $cc == $DA )
{ $i = ++$HashTBL{'FFDA'}[0]; $HashTBL{'FFDA'}[$i] = "$pos";
$pos += getByte($pos+2, 2); last;
}
}continue{ $pos++; }
# データの先頭位置を記録する
$i = ++$HashTBL{'Data1'}[0]; $HashTBL{'Data1'}[$i] = "$pos"+2;
my $Ssize = $pos+2;
# Segment部の長さを記録する
$DataTBL{'SGMT Size'} = insCom($Ssize)." Bytes\n";
$pos = $Fsize-3; # 大幅にスキップして最後の EOI を確認する
while(1)
{ next if( getByte($pos, 1) != $FF );
last if( getByte($pos+1, 1) == $D9 );
print "データが壊れています!\n"; return(-1);
}continue{ $pos++; }
# データの終端位置を記録する
$i = ++$HashTBL{'Data2'}[0]; $HashTBL{'Data2'}[$i] = "$pos"-1;
$i = ++$HashTBL{'FFD9'}[0]; $HashTBL{'FFD9'}[$i] = "$pos";
return ( $Ssize );
}
1;
|
![](/cgi-bin/user/skinoshita/Count.cgi?df=cp02.count)
|
|
|