分类:
2009-03-29 12:48:57
#!/usr/bin/perl -w # --------------------------------------------------------- # parse bmp file to get RGB information # by Tao Yuliang # 28/03/2009 # --------------------------------------------------------- # #use strict; # prepare my @bmp_tag = qw( bfType bfSize bfReserved1 bfReserved2 bfOffBits biSize biWidth biHeight biPlanes biBitCount biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant ); binmode STDIN; binmode STDOUT; my $data_format = "H"; #------------------------------------------# # read the bmp file and parse the data # #------------------------------------------# # get the file name die "No input file!\n" if not $filename = shift @ARGV; # open the file open RGBFILE, $filename or die "Can't open $filename: $!"; binmode RGBFILE; # read the bmp file my $data = # convert the data into a certain format # to get the information of bmp file #my @hdr_dat = unpack "SLSSLLLLSSLLLLLLC*", $data; my @hdr_dat = unpack "SLSSLLLLSSLLLLLL$data_format*", $data; $hdr_dat[0] = join '', unpack "aa", $data; #print "@hdr_dat\n"; # get the image data form $hdr_dat[-1] my @rgb_data; for ( 1..($#hdr_dat-$#bmp_tag) ) { unshift @rgb_data, pop @hdr_dat; } #print "@hdr_dat\n"; #print "@rgb_data\n"; # if there is '0A' data in image data, perl will treate it as a '\n' # so we must read the remaining data while ( # don't chomp, else it will discards '0A' #chomp ; push @rgb_data, unpack "$data_format*", $_; } close RGBFILE; # store the info of file structure into a hash my %header; @header{@bmp_tag}=@hdr_dat; print "$_\t$header{$_}\n" for @bmp_tag; #------------------------------------------# # get the RGB info and write into txt file # #------------------------------------------# my @table_R; my @table_G; my @table_B; if ( $data_format eq 'H' ) { &process_H_format ; } else { &process_C_format ; } open INFOTXT, "> $filename.txt" or die "Can't open $filename.txt: $!"; print INFOTXT "R\n"; print INFOTXT "@table_R\n"; print INFOTXT "G\n"; print INFOTXT "@table_G\n"; print INFOTXT "B\n"; print INFOTXT "@table_B\n"; #------------------------------------------# # convert RGB to YCbCr # #------------------------------------------# my ( @YR_LUT, @CbR_LUT, @CrR_LUT ); my ( @YG_LUT, @CbG_LUT, @CrG_LUT ); my ( @YB_LUT, @CbB_LUT, @CrB_LUT ); # call subroutine &prepare_Y_LUT ; &prepare_Cb_LUT ; &prepare_Cr_LUT ; # get the YCbCr data according to LUT my ( @table_Y, @table_Cb, @table_Cr ); for ( 0..$#table_R ) { my $R = ( $data_format eq "H" ) ? hex( $table_R[$_] ) : $table_R[$_]; my $G = ( $data_format eq "H" ) ? hex( $table_G[$_] ) : $table_G[$_]; my $B = ( $data_format eq "H" ) ? hex( $table_B[$_] ) : $table_B[$_]; push @table_Y, int( ($YR_LUT[$R]+$YG_LUT[$G]+$YB_LUT[$B]) / 2**16 ); push @table_Cb, ( int(($CbR_LUT[$R]+$CbG_LUT[$G]+$CbB_LUT[$B]) / 2**16) + 128 ); push @table_Cr, ( int(($CrR_LUT[$R]+$CrG_LUT[$G]+$CrB_LUT[$B]) / 2**16) + 128 ); } # write into file print INFOTXT "Y\n"; print INFOTXT "@table_Y\n"; print INFOTXT "Cb\n"; print INFOTXT "@table_Cb\n"; print INFOTXT "Cr\n"; print INFOTXT "@table_Cr\n"; close INFOTXT; ############################################################################ #-----------------------------------------# # subrountine definition # #-----------------------------------------# sub process_H_format { my $data = join '', @rgb_data; # reorder the image data my $offset = $header{ 'biWidth' } * 3 * 2; my @lines = reverse ($data =~ /([\w\d]{$offset})/ig ); #print "@lines\n"; my $reorder_data = join '', @lines; # while ( $reorder_data =~ /([\w\d]{2})([\w\d]{2})([\w\d]{2})/ig ) { push @table_R, $3; push @table_G, $2; push @table_B, $1; #print "R=>$3 : G=>$2 : B=>$1\n"; } } sub process_C_format { # reorder the image data my @reorder_data; for( my $y=0; $y < $header{ 'biHeight' }; $y++ ) { my @lines; my $x_count = $header{ 'biWidth' } * 3; while( $x_count-- ) { push @lines, pop @rgb_data; } #print "@lines\n"; unshift @reorder_data, @lines; } #print "@reorder_data\n"; my $size = $header{ 'biWidth' } * $header{ 'biHeight' }; while ( $size-- ) { #print $size, "\n"; push @table_B, pop @reorder_data; push @table_G, pop @reorder_data; push @table_R, pop @reorder_data; } } # prepare the YCbCr data sub prepare_Y_LUT { for ( 0..255 ) { $YR_LUT[$_] = int(65536*0.299+0.5) * $_; $YG_LUT[$_] = int(65536*0.587+0.5) * $_; $YB_LUT[$_] = int(65536*0.114+0.5) * $_; } } sub prepare_Cb_LUT { for ( 0..255 ) { $CbR_LUT[$_] = int(65536*-0.16874+0.5) * $_; $CbG_LUT[$_] = int(65536*-0.33126+0.5) * $_; $CbB_LUT[$_] = 32768 * $_; } } sub prepare_Cr_LUT { for ( 0..255 ) { $CrR_LUT[$_] = 32768 * $_; $CrG_LUT[$_] = int(65536*-0.41869+0.5) * $_; $CrB_LUT[$_] = int(65536*-0.08131+0.5) * $_; } } |