#--------------------------------------------------------------------------------
#  パターン塗りつぶしプログラム
#
#
#  引数１：入力ファイル名
#  引数２：出力ファイル名
#  引数３：塗りつぶすパターンの半径
#  引数４："NOPAT" -->  塗りつぶすパターンのみ出力
#
#--------------------------------------------------------------------------------
open( IN,  $ARGV[0]       ) || die "Can't open INPUT file";
open( OUT, ">" . $ARGV[1] ) || die "Can't open OUTPUT file";

binmode(IN);
binmode(OUT);

print "Input  FileName : " . $ARGV[0] . "\n";
print "Output FileName : " . $ARGV[1] . "\n";

#------------------------------------------------------------------------
#  ＢＭＰヘッダ部分読み込み
#------------------------------------------------------------------------
sysread( IN, $bfType,      2 );
sysread( IN, $bfSize,      4 );
sysread( IN, $bfRes1,      2 );
sysread( IN, $bfRes2,      2 );
sysread( IN, $bfOffs,      4 );
sysread( IN, $biSize,      4 );
sysread( IN, $biWidth,     4 );
sysread( IN, $biHight,     4 );
sysread( IN, $biPlane,     2 );
sysread( IN, $biBits,      2 );
sysread( IN, $biCompres,   4 );
sysread( IN, $biSizeImage, 4 );
sysread( IN, $biXpix,      4 );
sysread( IN, $biYpix,      4 );
sysread( IN, $biPal1,      4 );
sysread( IN, $biPal2,      4 );
sysread( IN, $biPalWhite,  4 );
sysread( IN, $biPalBlack,  4 );

$radius = $ARGV[2];
print "Radius --> " . $radius . "\n";

$no_pat = $ARGV[3];
print "Option --> " . $no_pat . "\n";

$bmFileSize		= unpack( "L", $bfSize      );
$bmWidth		= unpack( "L", $biWidth     );
$bmHight		= unpack( "L", $biHight     );
$bmSizeImage	= unpack( "L", $biSizeImage );
$one_line_byte	= int( ($bmWidth + 31) / 32) * 4;

print "--- Source file Information -------------\n";
print "  FileSize : " . $bmFileSize . " Bytes \n";
print "  Width    : " . $bmWidth    . " Pixcel\n";
print "  Hight    : " . $bmHight    . " Pixcel\n";
print "-----------------------------------------\n";


#------------------------------------------------------------------------
#  マスクパターン作成
#------------------------------------------------------------------------
$mask_size = $radius * 2 + 1;
$pack_fmt  = "B" . $mask_size;
$mask_buf  = "";
$idx = 0;
for( $x = -$radius ; $x <= $radius ; $x++ ) {
	for( $y = -$radius ; $y <= $radius ; $y++ ) {
		if( $y**2 + $x**2 <= $radius**2 ) {
			$mask_buf[$idx] = $mask_buf[$idx] . "1";
		} else {
			$mask_buf[$idx] = $mask_buf[$idx] . "0";
		}
	}

	$mask_pat[$idx] = pack( $pack_fmt, $mask_buf[$idx] );
	$idx++;
}

#------------------------------------------------------------------------
#  ＢＭＰイメージ部分読み込み
#------------------------------------------------------------------------

print "****** Image Read START *****\n";

$str = "";
for( $i = 1 ; $i <= $radius ; $i++ ) {
	$str_head = $str_head . "1";
}

for( $i = 1 ; $i <= $bmWidth ; $i++ ) {
	$str_mid = $str_mid . "1";
}

$line = 0;
for( $h = 1 ; $h <= $radius ; $h++ ) {
	$s_image[$line] = $str_head . $str_mid . $str_head;
	$line++;
}

$format = "B" . ($one_line_byte * 8);

for( $h = 0 ; $h < $bmHight ; $h++ ) {
	sysread( IN, $image, $one_line_byte );
	$img = unpack( $format, $image );
	$img = substr( $img, 0, $bmWidth );
	$s_image[$line] = $str_head . $img . $str_head;
	$line++;
}

for( $h = 1 ; $h <= $radius ; $h++ ) {
	$s_image[$line] = $str_head . $str_mid . $str_head;
	$line++;
}

print "****** Image Read END *******\n";

#------------------------------------------------------------------------
#　塗りつぶし処理
#------------------------------------------------------------------------
for( $x = 0 ; $x < $bmWidth ; $x++ ) {
	#-----------------------------
	#  非マスクパターン作成
	#-----------------------------
	for( $y = 0 ; $y < $bmHight + $mask_size ; $y++ ) {
		$sorc_buf[$y] = substr( $s_image[$y], $x, $mask_size );
		$sorc_pat[$y] = pack( $pack_fmt, $sorc_buf[$y] );
	}
	#-----------------------------
	#  非マスクパターンとの比較
	#-----------------------------
	for( $y = 0 ; $y < $bmHight ; $y++ ) {
		$match = 0;
		for( $m = 0 ; $m < $mask_size ; $m++ ) {
			if( ( $sorc_pat[$y+$m] & $mask_pat[$m] ) ne $mask_pat[$m] ) {
				$match = 1;
				last;
			}
		}
		if( $match == 1 ) {
			$dest_buf[$y] = $dest_buf[$y] . "1";
		} else {
			$dest_buf[$y] = $dest_buf[$y] . "0";
		}
	}
	print "Column " . $x . " Processd\n";
}

print "***** end *****\n";

#------------------------------------------------------------------------
#　ＢＭＰ書き込み
#------------------------------------------------------------------------

syswrite( OUT, $bfType,      2 );
syswrite( OUT, $bfSize,	     4 );
syswrite( OUT, $bfRes1,      2 );
syswrite( OUT, $bfRes2,      2 );
syswrite( OUT, $bfOffs,      4 );
syswrite( OUT, $biSize,      4 );
syswrite( OUT, $biWidth,     4 );
syswrite( OUT, $biHight,     4 );
syswrite( OUT, $biPlane,     2 );
syswrite( OUT, $biBits,      2 );
syswrite( OUT, $biCompres,   4 );
syswrite( OUT, $biSizeImage, 4 );
syswrite( OUT, $biXpix,      4 );
syswrite( OUT, $biYpix,      4 );
syswrite( OUT, $biPal1,      4 );
syswrite( OUT, $biPal2,      4 );
syswrite( OUT, $biPalWhite,  4 );
syswrite( OUT, $biPalBlack,  4 );

#--- １行分書き出し ---
$pack_fmt2 = "B" . ($one_line_byte * 8);
for( $h = 0 ; $h < $bmHight ; $h++ ) {
	if( $no_pat eq "NOPAT" ) {
		$out_buf = $dest_buf[$h] . "00000000000000000000000000000000";
	} else {
		$out_buf = ( $dest_buf[$h] & substr( $s_image[$h+$radius], $radius, $bmWidth ) ) . "00000000000000000000000000000000";
	}
	$out_buf = substr( $out_buf, 0, $one_line_byte * 8 );
	$out_buf = pack( $pack_fmt2, $out_buf );
	syswrite( OUT, $out_buf, $one_line_byte );
}

close( IN );
close( OUT );
