);
}
-sub _ie_ems_animation {
- my ($self, %args) = @_;
- my $bitmaps = $args{"bitmaps"}; # list of GSM::SMS::Bitmap instances
+# @$bitmaps
+sub ems_animation_maxsize
+{
+my($bitmaps)=@_;
if (4 != @$bitmaps) {
carp "Invalid length of EMS animation (4 required)"; return ();
my $bitmap = $$bitmaps[0];
my ($width, $height) = ($bitmap->{"width"}, $bitmap->{"height"});
for my $testbitmap (@$bitmaps) {
- if ($width != $testbitmap->{"width"} || $height != $testbitmap->{"height"}) {
- carp "Non-matching sizes in EMS animation";
+ $width =max($width ,$testbitmap->{"width" });
+ $height=max($height,$testbitmap->{"height"});
}
- }
+ return ($width,$height);
+}
+
+sub _ie_ems_animation {
+ my ($self, %args) = @_;
+ my $bitmaps = $args{"bitmaps"}; # list of GSM::SMS::Bitmap instances
+
+ my ($width, $height) = ems_animation_maxsize($bitmaps);
my $iei;
- if ($width == 8 && $height == 8) { $iei = IEI_ANIMATION_SMALL ; }
- elsif ($width == 16 && $height == 16) { $iei = IEI_ANIMATION_LARGE ; }
+ if ($width <= 8 && $height <= 8) { $iei = IEI_ANIMATION_SMALL ; }
+ elsif ($width <= 16 && $height <= 16) { $iei = IEI_ANIMATION_LARGE ; }
else {
$iei = IEI_ANIMATION_LARGE;
- carp "Invalid frame size of EMS animation (8x8 or 16x16 required)";
+ carp "Invalid frame size of EMS animation (<=16x<=16 required)";
}
return $self->_iebuilder($iei,
$args{TEXT_POSITION}, # position in the SMS
&{sub {
my @r=();
- for $bitmap (@$bitmaps) {
+ for my $bitmap (@$bitmaps) {
push @r,$bitmap->pixlist_horiz();
}
return @r;
my @list=map { &{"_ie_".$$_{"type"}}($self,%$_); } @srcs;
use strict 'refs';
return "" if !@list;
- return pack "C*",scalar(@list),@list;
+ # if it is too long it will be recalculated anyway
+ return pack "C*",(@list<=0xFF ? scalar(@list) : 0xFF),@list;
+}
+
+sub udh_prepare_ems_picture
+{
+my($udh)=@_;
+
+ my $bitmap=$udh->{"bitmap"}; # GSM::SMS::Bitmap instance
+ $bitmap->crop(0xFF*8,0xFF);
+ my ($width, $height) = ($bitmap->{"width"}, $bitmap->{"height"});
+
+ # pixel-payload of concat8 SMS w/one IEI_PICTURE_VARIABLE is 129 bytes
+ my $stripe=int(129/int(($width+7)/8));
+ carp "Image width too big to fit in one SMS part" if $stripe<=0; # ==0
+ return $udh if $stripe>=$height;
+ my @r=();
+ for (my $y=0;$y<$height;$y+=$stripe) {
+ push @r,{
+ %$udh,
+ "bitmap"=>GSM::SMS::Bitmap->new($bitmap,0,$y,$width,min($stripe,$height-$y)),
+ };
+ }
+ return @r;
+}
+
+sub udh_prepare_ems_animation
+{
+my($udh)=@_;
+
+ my $bitmaps = $udh->{"bitmaps"}; # list of GSM::SMS::Bitmap instances
+ my ($width, $height) = ems_animation_maxsize($bitmaps);
+ return $udh if $width<=16 && $height<=16;
+
+ my @r=();
+ my $height_now;
+ # Here we can't touch the text and thus we do split to lines without
+ # giving there a newline! For proper way see &gsmcmd::ems_animation_send
+ for (my $y=0;$y<$height;$y+=$height_now) {
+ $height_now=($y+8>=$height ? 8 : 16);
+ my $width_now;
+ for (my $x=0;$x<$width;$x+=$width_now) {
+ # Never risk undeterministic wrapping if some rows yet to follow
+ # And we must be a square, not much other possibilies exist
+ $width_now=$height_now;
+ push @r,{
+ %$udh,
+ "bitmaps"=>[ map({
+ GSM::SMS::Bitmap->new($_,$x,$y,$width_now,$height_now);
+ } @$bitmaps) ],
+ };
+ }
+ }
+ return @r;
+}
+
+sub udh_prepare
+{
+my($udh)=@_;
+
+ return udh_prepare_ems_picture($udh) if $udh->{"type"} eq "ems_picture";
+ return udh_prepare_ems_animation($udh) if $udh->{"type"} eq "ems_animation";
+ return $udh;
}
# Create a message from a payload
my $PDU = GSM::SMS::PDU->new();
my @udhs=($args{"udh"} ? @{$args{"udh"}} : ());
+ @udhs=map({ udh_prepare($_); } @udhs);
# We put ME-specific default if ANY element of UDH was specified
# Autodetect $dcs BEFORE possible concatenation UDH IEs get inserted!
if (@udhpositioned && $udhpositioned[0]{TEXT_POSITION} <= $position) { # "<=" should be "=="
if (USERDATA_LENGTH < length($self->_udh_build(@udhstatic,@udhpositioned_now,$udhpositioned[0]))
+nail_payload_len($dcs,length($payload_now))) {
+ return (DECONCAT_TOTAL, undef) if !$deconcat_ieref;
return "UDH IE (User Data Header Information Element) too long to fit in one SMS fragment"
- if $payload_now eq "";
+ if $payload_now eq "" && !@udhpositioned_now;
last;
}