File Coverage

blib/lib/Image/Xbm2bmp.pm
Criterion Covered Total %
statement 12 147 8.1
branch 0 48 0.0
condition 0 3 0.0
subroutine 4 14 28.5
pod 0 4 0.0
total 16 216 7.4


line stmt bran cond sub pod time code
1             package Image::Xbm2bmp;
2              
3 1     1   25607 use 5.006;
  1         4  
  1         39  
4 1     1   6 use strict;
  1         2  
  1         33  
5 1     1   5 use warnings;
  1         6  
  1         34  
6 1     1   5 use Carp;
  1         2  
  1         3689  
7              
8             our $VERSION = '0.02';
9              
10             sub new {
11 0     0 0   my $class = shift;
12 0           my $xbmfilepath = shift;
13 0           my($width,$height,@data);
14 0           eval{
15 0 0         if(defined($xbmfilepath)){
16 0           ($width,$height,@data) = _LoadXbmFile($xbmfilepath);
17             }
18             else{
19 0           $width = 0;
20 0           $height = 0;
21 0           @data = ();
22             }
23             };
24 0 0         if($@){
25 0           die "$@";
26             }
27 0           my $self = bless { _WIDTH=>$width,
28             _HEIGHT=>$height,
29             _DATA=>[@data]
30             }, $class;
31 0           return $self;
32             }
33              
34             sub load_xbm_data($$$){
35 0     0 0   my($self,$data_ref,$width,$height) = @_;
36 0           eval{
37 0           $self->{_WIDTH} = $width;
38 0           $self->{_HEIGHT} = $height;
39 0           $self->{_DATA} = [@$data_ref];
40             };
41 0 0         if($@){
42 0           die "load_xbm_data failed!:$@";
43             }
44             }
45              
46             sub to_bmp_file($$){
47 0     0 0   my($self,$bmpfilepath) = @_;
48 0           my $BMP_PACK = to_bmp_pack($self);
49 0 0         open(OUT,">$bmpfilepath") or die "save failed!$!";
50 0           binmode(OUT);
51 0           print OUT $BMP_PACK;
52 0           close(OUT);
53             }
54              
55             sub to_bmp_pack($){
56 0     0 0   my($self) = shift;
57 0           my($data_ref,$width,$height,@xbm_data,@source_xbm_data);
58 0           $width = $self->{_WIDTH};
59 0           $height = $self->{_HEIGHT};
60 0           $data_ref = $self->{_DATA};
61 0           @source_xbm_data = @$data_ref;
62              
63 0           my($old_row_bytes,$row_bytes);
64 0 0         if(($width%32)>0){
65 0           $row_bytes = ($width/32)*4+4;
66             }
67             else{
68 0           $row_bytes = $width/8;
69             }
70 0           $old_row_bytes = $width/8;
71 0 0         if($old_row_bytes==$row_bytes){
72 0           @xbm_data = @source_xbm_data;
73             }
74             else{
75 0           @xbm_data = _init_array($row_bytes,0x00);
76 0           for(my $c1=0; $c1<$height; $c1++){
77 0           for(my $c2=0; $c2<$old_row_bytes; $c2++){
78 0           $xbm_data[$c1*$old_row_bytes+$c2] = $source_xbm_data[$c1*$old_row_bytes+$c2];
79             }
80             }
81             }
82            
83 0           my @Bitmap_File_size = unpack("C4",pack("C4",(0x3e+$row_bytes*$height)));
84 0           my @Bitmap_Data_Offset = (0x3e,0x00,0x00,0x00);
85 0           my @Bitmap_Header_Size = (0x28,0x00,0x00,0x00);
86 0           my @Bitmap_Width = unpack("C4",pack("C4",$width));
87 0           my @Bitmap_Height = unpack("C4",pack("C4",$height));;
88 0           my @Planes = (0x01,0x00);
89 0           my @Bits_Per_Pixel = (0x01,0x00);
90 0           my @Bitmap_Data_Size = unpack("C4",pack("C4",($row_bytes*$height)));
91 0           my @data = ();
92            
93             #xbm数据的每个字节需要进行反序和NOT处理
94 0           foreach my $d(@xbm_data){
95 0           my $rd = _reverse_byte($d);
96 0           $rd = _NOT_byte($rd);
97 0           push @data,$rd;
98             }
99             #xbm数据行需要进行反序处理
100 0           @data = _reverse_ex(\@data,$row_bytes);
101              
102 0           my @BITMAPFILE = (
103             0x42,0x4d,
104             (@Bitmap_File_size),
105             0x00,0x00,0x00,0x00,
106             (@Bitmap_Data_Offset),
107             (@Bitmap_Header_Size),
108             (@Bitmap_Width),
109             (@Bitmap_Height),
110             (@Planes),
111             (@Bits_Per_Pixel),
112             0x00,0x00,0x00,0x00,
113             (@Bitmap_Data_Size),
114             0xc4,0x0e,0x00,0x00,
115             0xc4,0x0e,0x00,0x00,
116             0x00,0x00,0x00,0x00,
117             0x00,0x00,0x00,0x00,
118             0x00,0x00,0x00,0x00,
119             0xff,0xff,0xff,0x00,
120             (@data)
121             );
122 0           return pack('C*',@BITMAPFILE);
123             }
124              
125             sub _reverse_byte($){
126 0     0     my $in = shift;
127 0           my $out = 0x00;
128 0 0         if($in & 0b10000000){
129 0           $out = $out | 0b00000001;
130             }
131 0 0         if($in & 0b01000000){
132 0           $out = $out | 0b00000010;
133             }
134 0 0         if($in & 0b00100000){
135 0           $out = $out | 0b00000100;
136             }
137 0 0         if($in & 0b00010000){
138 0           $out = $out | 0b00001000;
139             }
140 0 0         if($in & 0b00001000){
141 0           $out = $out | 0b00010000;
142             }
143 0 0         if($in & 0b00000100){
144 0           $out = $out | 0b00100000;
145             }
146 0 0         if($in & 0b00000010){
147 0           $out = $out | 0b01000000;
148             }
149 0 0         if($in & 0b00000001){
150 0           $out = $out | 0b10000000;
151             }
152 0           return $out;
153             }
154              
155             sub _NOT_byte($){
156 0     0     my $in = shift;
157 0           my $out = ~$in;
158 0           $out = $out & 0b11111111;
159 0           return $out;
160             }
161              
162             sub _reverse_ex($$){
163 0     0     my($data_ref,$m) = @_;
164 0 0 0       if(!defined($data_ref)||!defined $m){
165 0           die "method[_reverse_ex] died!";
166             }
167 0           my @sdata = @$data_ref;
168 0           my $len = scalar(@sdata);
169 0           my @tdata= ();
170 0           for(my $n = 0; $n<$len/$m; $n++){
171 0           my $k = $len-$n*$m-$m;
172 0           $tdata[$k] = $sdata[$n*$m];
173 0           $tdata[$k+1] = $sdata[$n*$m+1];
174 0           $tdata[$k+2] = $sdata[$n*$m+2];
175 0           $tdata[$k+3] = $sdata[$n*$m+3];
176             }
177 0           return @tdata;
178             }
179              
180             sub _hex_value($){
181 0     0     my($list) = @_;
182 0           my $value;
183 0           my $h = substr($list,0,1);
184 0           my $l = substr($list,1,1);
185 0           my($h_value,$l_value);
186 0           $h = lc($h);
187 0           $l = lc($l);
188 0 0         if($h=~/[abcdef]/){
189 0           $h_value = ord($h)-ord('a')+10;
190             }
191 0 0         if($h=~/[0123456789]/){
192 0           $h_value = ord($h)-ord('0');
193             }
194 0 0         if($l=~/[abcdef]/){
195 0           $l_value = ord($l)-ord('a')+10;
196             }
197 0 0         if($l=~/[0123456789]/){
198 0           $l_value = ord($l)-ord('0');
199             }
200 0           $value = $h_value*16+$l_value;
201 0           return $value;
202             }
203              
204             sub _LoadXbmFile($){
205 0     0     my $file = shift;
206 0 0         open(INPUT,$file) or die "Can't load xbm file: $!\n";
207 0           my $buf;
208 0           while(){
209 0           $buf.= $_;
210             }
211 0           close(INPUT);
212 0           my @data = ();
213 0           my($height,$width);
214 0 0         if($buf=~/#define .*width (\d*)/){
215 0           $width=$1;
216             }
217 0 0         if($buf=~/#define .*height (\d*)/){
218 0           $height=$1;
219             }
220 0 0         if($buf=~/{\s*(.*)\s*}/s){
221 0           my $eval_str = qq~\@data=($1);~;
222 0           eval $eval_str;
223             }
224 0           return $width,$height,@data;
225             }
226              
227             sub _init_array($$){
228 0     0     my($length,$value) = @_;
229 0           my @array;
230 0 0         if($length=~/\d/){
231 0           for(my $count=0;$count<$length;$count++){
232 0           $array[$count] = $value;
233             }
234             }
235             else{
236 0           @array = undef;
237             }
238 0           return @array;
239             }
240              
241              
242             1;
243             __END__