From 15d83eea1ad61ae76946f364eefb9ee305a2e435 Mon Sep 17 00:00:00 2001 From: stan Date: Sun, 15 Feb 2004 19:47:23 +0000 Subject: [PATCH] Merged in montage sizing and scaling improvements. git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@853 e3e1d417-86f3-4887-817a-d78f3d33393f --- configure | 2 +- configure.in | 2 +- scripts/zmvideo.pl.z | 48 ++++++------------ src/zm_config.h.z | 3 ++ src/zm_event.cpp | 5 +- src/zm_image.cpp | 84 ++++++++++++++++++++++---------- src/zm_image.h | 2 +- src/zms.cpp | 4 +- web/zm_config.php.z | 2 + web/zm_funcs.php | 15 ++---- web/zm_html.php | 28 ++++++----- web/zm_html_view_console.php | 4 +- web/zm_html_view_cycle.php | 8 +-- web/zm_html_view_event.php | 4 +- web/zm_html_view_montage.php | 7 +-- web/zm_html_view_montagefeed.php | 16 ++++-- web/zm_html_view_video.php | 6 +-- web/zm_html_view_watch.php | 12 ++--- web/zm_html_view_watchfeed.php | 2 +- zmconfig.pl.in | 18 ++++++- 20 files changed, 157 insertions(+), 115 deletions(-) diff --git a/configure b/configure index 6dd10e074..f04f3e726 100755 --- a/configure +++ b/configure @@ -1508,7 +1508,7 @@ fi # Define the identity of the package. PACKAGE=zm - VERSION=1.17.2 + VERSION=1.17.2-ms cat >>confdefs.h <<_ACEOF diff --git a/configure.in b/configure.in index 39c4b1270..cb471ef14 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT(src/zm.h) -AM_INIT_AUTOMAKE(zm,1.17.2) +AM_INIT_AUTOMAKE(zm,1.17.2-ms) AM_CONFIG_HEADER(config.h) AC_ARG_WITH(mysql, diff --git a/scripts/zmvideo.pl.z b/scripts/zmvideo.pl.z index 517c510b9..803cb3f96 100644 --- a/scripts/zmvideo.pl.z +++ b/scripts/zmvideo.pl.z @@ -77,8 +77,8 @@ $ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $event_id; -my $rate = 1; -my $scale = 1; +my $rate = 0.0; +my $scale = 1.0; my $overwrite = 0; sub Usage @@ -87,14 +87,14 @@ sub Usage Usage: zmvideo.pl -e ,--event= [-r ,--rate=] [-s ,--scale=] [-o,--overwrite] Parameters are :- -e, --event= - What event to create the video for --r, --rate= - Relative rate to use, 1 = realtime, 2 = double speed , -2 = half speed etc --s, --scale= - Scale to use, 1 = normal, 2 = double size, -2 = half size etc +-r, --rate= - Relative rate to use, 1 = realtime, 2 = double speed , 0.5 = half speed etc +-s, --scale= - Scale to use, 1 = normal, 2 = double size, 0.5 = half size etc -o, --overwrite - Whether to overwrite an existing file, off by default. "); exit( -1 ); } -if ( !GetOptions( 'event=i'=>\$event_id, 'rate=i'=>\$rate, 'scale=i'=>\$scale, 'overwrite'=>\$overwrite ) ) +if ( !GetOptions( 'event=i'=>\$event_id, 'rate=f'=>\$rate, 'scale=f'=>\$scale, 'overwrite'=>\$overwrite ) ) { Usage(); } @@ -111,21 +111,21 @@ if ( ZM_OPT_MPEG eq "no" ) exit(-1); } -if ( ZM_OPT_MPEG eq "mpeg_encode" && $rate != 1 ) +if ( ZM_OPT_MPEG eq "mpeg_encode" && $rate != 1.0 ) { print( STDERR "Variable rate not supported with mpeg_encode\n" ); exit(-1); } -if ( $rate < -4 || $rate > 10 ) +if ( $rate < 0.25 || $rate > 10 ) { - print( STDERR "Rate is out of range, -4 >= rate <= 10\n" ); + print( STDERR "Rate is out of range, 0.25 >= rate <= 10\n" ); Usage(); } -if ( !$scale || $scale < -4 || $scale > 4 ) +if ( !$scale || $scale < 0.25 || $scale > 4 ) { - print( STDERR "Scale is out of range, -4 >= scale <= 4\n" ); + print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" ); Usage(); } @@ -232,19 +232,9 @@ if ( $overwrite || !-s $video_file ) elsif ( ZM_OPT_MPEG eq "ffmpeg" ) { my $frame_rate = sprintf( "%.2f", $event->{Frames}/$event->{FullLength} ); - if ( $rate ) + if ( $rate != 0.0 ) { - if ( $rate != 1 ) - { - if ( $rate > 1 ) - { - $frame_rate *= $rate; - } - else - { - $frame_rate /= $rate; - } - } + $frame_rate *= $rate; } else { @@ -252,18 +242,10 @@ if ( $overwrite || !-s $video_file ) } my $width = $event->{MonitorWidth}; my $height = $event->{MonitorHeight}; - if ( $scale != 1 ) + if ( $scale != 1.0 ) { - if ( $scale > 1 ) - { - $width = int($width*$scale); - $height = int($height*$scale); - } - else - { - $width = int($width/$scale); - $height = int($height/$scale); - } + $width = int($width*$scale); + $height = int($height*$scale); } my $command = ZM_PATH_FFMPEG." -y ".ZM_FFMPEG_OPTIONS." -r $frame_rate -s ${width}x${height} -i %03d-capture.jpg $video_file > mpeg.log"; print( LOG $command."\n" ); diff --git a/src/zm_config.h.z b/src/zm_config.h.z index 5a2bdc7ca..445bfdb74 100644 --- a/src/zm_config.h.z +++ b/src/zm_config.h.z @@ -37,6 +37,9 @@ #define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT) #define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS) +#define ZM_SCALE_SCALE 100 // The factor by which we bump up 'scale' to simulate FP +#define ZM_RATE_SCALE 100 // The factor by which we bump up 'rate' to simulate FP + class ConfigItem { private: diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 4ae2b34b6..2bec95171 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -404,10 +404,7 @@ void Event::StreamEvent( int event_id, int rate, int scale, FILE *fd ) int delay = (int)((DT_GRAN_1000000*frame_delta))-delta_time.delta; - if ( rate < 0 ) - delay *= abs(rate); - else - delay /= rate; + delay = (delay * ZM_RATE_SCALE) / rate; //Info(( "FD:%lf, DDT:%d, D:%d, N:%d.%d, LN:%d.%d", frame_delta, delta_time.delta, delay, now.tv_sec, now.tv_usec, last_now.tv_sec, last_now.tv_usec )); if ( delay > 0 ) diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 4bb2773a1..21a871508 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -834,29 +834,40 @@ void Image::Rotate( int angle ) memcpy( buffer, rotate_buffer, size ); } -void Image::Scale( int factor ) +void Image::Scale( unsigned int factor ) { if ( !factor ) { + Error(( "Bogus scale factor %d found", factor )); return; } - if ( factor == 1 ) + if ( factor == ZM_SCALE_SCALE ) { return; } static unsigned char scale_buffer[ZM_MAX_IMAGE_SIZE]; - if ( factor > 1 ) + unsigned int new_width = (width*factor)/ZM_SCALE_SCALE; + unsigned int new_height = (height*factor)/ZM_SCALE_SCALE; + if ( factor > ZM_SCALE_SCALE ) { unsigned char *pd = scale_buffer; unsigned int wc = width*colours; - unsigned int wcf = wc*factor; + unsigned int nwc = new_width*colours; + unsigned int h_count = ZM_SCALE_SCALE/2; + unsigned int last_h_index = 0; + unsigned int h_index; for ( int y = 0; y < height; y++ ) { unsigned char *ps = &buffer[y*wc]; + unsigned int w_count = ZM_SCALE_SCALE/2; + unsigned int last_w_index = 0; + unsigned int w_index; for ( int x = 0; x < width; x++ ) { - for ( int f = 0; f < factor; f++ ) + w_count += factor; + w_index = w_count/ZM_SCALE_SCALE; + for ( int f = last_w_index; f < w_index; f++ ) { for ( int c = 0; c < colours; c++ ) { @@ -864,43 +875,64 @@ void Image::Scale( int factor ) } } ps += colours; + last_w_index = w_index; } - for ( int f = 1; f < factor; f++ ) + h_count += factor; + h_index = h_count/ZM_SCALE_SCALE; + for ( int f = last_h_index+1; f < h_index; f++ ) { - memcpy( pd, pd-wcf, wcf ); - pd += wcf; + memcpy( pd, pd-nwc, nwc ); + pd += nwc; } + last_h_index = h_index; } - width *= factor; - height *= factor; - size = width*height*colours; } else { - factor = abs(factor); + unsigned int inv_factor = (ZM_SCALE_SCALE*ZM_SCALE_SCALE)/factor; unsigned char *pd = scale_buffer; unsigned int wc = width*colours; - unsigned int cf = factor*colours; - unsigned int xrem = width%factor; - unsigned int yrem = height%factor; - unsigned int xstart = xrem/2; - unsigned int ystart = yrem/2; - for ( int y = xstart; y < height; y += factor ) + unsigned int xstart = factor/2; + unsigned int ystart = factor/2; + unsigned int h_count = ystart; + unsigned int last_h_index = 0; + unsigned int h_index; + for ( unsigned int y = 0; y < height; y++ ) { - unsigned char *ps = &buffer[y*wc]; - for ( int x = ystart; x < width; x += factor ) + h_count += factor; + h_index = h_count/ZM_SCALE_SCALE; + if ( h_index > last_h_index ) { - for ( int c = 0; c < colours; c++ ) + unsigned int w_count = xstart; + unsigned int last_w_index = 0; + unsigned int w_index; + + unsigned char *ps = &buffer[y*wc]; + for ( unsigned int x = 0; x < width; x++ ) { - *pd++ = *(ps+c); + w_count += factor; + w_index = w_count/ZM_SCALE_SCALE; + + if ( w_index > last_w_index ) + { + for ( int c = 0; c < colours; c++ ) + { + *pd++ = *ps++; + } + } + else + { + ps += colours; + } + last_w_index = w_index; } - ps += cf; } + last_h_index = h_index; } - width = 1+int((width-1)/factor); - height = 1+int((height-1)/factor); - size = width*height*colours; } + width = new_width; + height = new_height; + size = width*height*colours; delete[] buffer; buffer = new JSAMPLE[size]; memcpy( buffer, scale_buffer, size ); diff --git a/src/zm_image.h b/src/zm_image.h index 18d9c3303..1c6e76ce6 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -168,7 +168,7 @@ public: void Rotate( int angle ); - void Scale( int factor ); + void Scale( unsigned int factor ); }; #endif // ZM_IMAGE_H diff --git a/src/zms.cpp b/src/zms.cpp index ffc2c8798..89212cc8c 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -26,8 +26,8 @@ int main(void ) int id = 1; unsigned long idle = 5000; unsigned long refresh = 50; - unsigned int rate = 1; - unsigned int scale = 1; + unsigned int rate = 100; + unsigned int scale = 100; int event = 0; unsigned int ttl = 0; diff --git a/web/zm_config.php.z b/web/zm_config.php.z index 1d7f4cf12..6c3f32270 100644 --- a/web/zm_config.php.z +++ b/web/zm_config.php.z @@ -41,6 +41,8 @@ define( "MAX_EVENTS", 10 ); // The maximum number of events to show in th define( "EVENT_HEADER_LINES", 25 ); // How many events are listed in the event window before a new header is inserted define( "EVENT_FRAMES_PER_LINE", 4 ); // How many images per line in the event image view define( "EVENT_FRAME_LINES", 4 ); // How many lines of images to show in paged mode +define( "RATE_SCALE", 100 ); // The additional scaling factor used to help get fractional rates in integer format +define( "SCALE_SCALE", 100 ); // The additional scaling factor used to help get fractional scales in integer format define( "LEARN_MODE", false ); // Currently unimplemented, do not change require_once( 'zm_db.php' ); diff --git a/web/zm_funcs.php b/web/zm_funcs.php index e52bfc385..98b06384d 100644 --- a/web/zm_funcs.php +++ b/web/zm_funcs.php @@ -377,26 +377,19 @@ function zmaCheck( $monitor ) function createVideo( $event, $rate, $scale, $overwrite=0 ) { - $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event['Id']." -r $rate -s $scale"; + $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event['Id']." -r ".sprintf( "%.2f", ($rate/SCALE_SCALE) )." -s ".sprintf( "%.2f", ($scale/SCALE_SCALE) ); if ( $overwrite ) $command .= " -o"; $result = exec( $command, $output, $status ); return( $status?"":rtrim($result) ); } -function reScale( $dimension, $scale=1 ) +function reScale( $dimension, $scale=SCALE_SCALE ) { - if ( $scale == 1 ) + if ( $scale == SCALE_SCALE ) return( $dimension ); - if ( $scale > 0 ) - { - return( (int)($dimension*$scale) ); - } - else - { - return( (int)(1+(($dimension-1)/-$scale)) ); - } + return( (int)(($dimension*$scale)/SCALE_SCALE) ); } ?> diff --git a/web/zm_html.php b/web/zm_html.php index bda79a889..b46ddae15 100644 --- a/web/zm_html.php +++ b/web/zm_html.php @@ -69,22 +69,24 @@ $bw_array = array( $rates = array( "0" => $zmSlangMax, - "10" => "10x", - "4" => "4x", - "2" => "2x", - "1" => $zmSlangReal, - "-2" => "1/2x", - "-4" => "1/4x", + "1000" => "10x", + "400" => "4x", + "200" => "2x", + "100" => $zmSlangReal, + "50" => "1/2x", + "25" => "1/4x", ); $scales = array( - "4" => "4x", - "3" => "3x", - "2" => "2x", - "1" => $zmSlangActual, - "-2" => "1/2x", - "-3" => "1/3x", - "-4" => "1/4x", + "400" => "4x", + "300" => "3x", + "200" => "2x", + "150" => "1.5x", + "100" => $zmSlangActual, + "75" => "3/4x", + "50" => "1/2x", + "33" => "1/3x", + "25" => "1/4x", ); if ( !isset($user) ) diff --git a/web/zm_html_view_console.php b/web/zm_html_view_console.php index 073d87328..d664fbc7e 100644 --- a/web/zm_html_view_console.php +++ b/web/zm_html_view_console.php @@ -61,6 +61,8 @@ while( $row = mysql_fetch_assoc( $result ) ) } $montage_rows = intval(ceil($cycle_count/ZM_WEB_MONTAGE_MAX_COLS)); $montage_cols = $cycle_count>=ZM_WEB_MONTAGE_MAX_COLS?ZM_WEB_MONTAGE_MAX_COLS:$cycle_count; +$montage_width = ZM_WEB_MONTAGE_WIDTH?ZM_WEB_MONTAGE_WIDTH:$max_width; +$montage_height = ZM_WEB_MONTAGE_HEIGHT?ZM_WEB_MONTAGE_HEIGHT:$max_height; ?> @@ -135,7 +137,7 @@ preg_match( '/load average: ([\d.]+)/', $uptime, $matches ); if ( canView( 'Stream' ) && $cycle_count > 1 ) { ?> - () + () - + - + - + diff --git a/web/zm_html_view_event.php b/web/zm_html_view_event.php index 3cdc6f137..133fe2819 100644 --- a/web/zm_html_view_event.php +++ b/web/zm_html_view_event.php @@ -56,9 +56,9 @@ if ( !$result ) $next_event = mysql_fetch_assoc( $result ); if ( !isset( $rate ) ) - $rate = 1; + $rate = RATE_SCALE; if ( !isset( $scale ) ) - $scale = 1; + $scale = SCALE_SCALE; $frames_per_page = EVENT_FRAMES_PER_LINE * EVENT_FRAME_LINES; diff --git a/web/zm_html_view_montage.php b/web/zm_html_view_montage.php index 565e3ad3b..f91c5c159 100644 --- a/web/zm_html_view_montage.php +++ b/web/zm_html_view_montage.php @@ -40,13 +40,14 @@ $heights = array(); for ( $i = 0; $i < count($monitors); $i++ ) { $monitor = $monitors[$i]; - $frame_height = $monitor['Height']+16; + $frame_height = (ZM_WEB_MONTAGE_HEIGHT?ZM_WEB_MONTAGE_HEIGHT:$monitor['Height'])+16; + $frame_width = (ZM_WEB_MONTAGE_WIDTH?ZM_WEB_MONTAGE_WIDTH:$monitor['Width']); $row = $i/ZM_WEB_MONTAGE_MAX_COLS; $col = $i%ZM_WEB_MONTAGE_MAX_COLS; if ( empty( $heights[$row] ) || $frame_height > $heights[$row] ) $heights[$row] = $frame_height; - if ( empty( $widths[$col] ) || $monitor['Width'] > $widths[$col] ) - $widths[$col] = $monitor['Width']; + if ( empty( $widths[$col] ) || $frame_width > $widths[$col] ) + $widths[$col] = $frame_width; } $row_spec = join( ',', $heights ); $col_spec = join( ',', $widths ); diff --git a/web/zm_html_view_montagefeed.php b/web/zm_html_view_montagefeed.php index f09ffd495..c35543e34 100644 --- a/web/zm_html_view_montagefeed.php +++ b/web/zm_html_view_montagefeed.php @@ -36,6 +36,9 @@ if ( !$result ) die( mysql_error() ); $monitor = mysql_fetch_assoc( $result ); +$montage_width = ZM_WEB_MONTAGE_WIDTH?ZM_WEB_MONTAGE_WIDTH:$monitor['Width']; +$montage_height = ZM_WEB_MONTAGE_HEIGHT?ZM_WEB_MONTAGE_HEIGHT:$monitor['Height']; + if ( $mode != "stream" ) { // Prompt an image to be generated @@ -86,20 +89,27 @@ if ( $mode == "stream" ) if ( canStreamNative() ) { ?> - + - + - + diff --git a/web/zm_html_view_video.php b/web/zm_html_view_video.php index f672c51e4..7f8081caf 100644 --- a/web/zm_html_view_video.php +++ b/web/zm_html_view_video.php @@ -28,10 +28,10 @@ if ( !$result ) die( mysql_error() ); $event = mysql_fetch_assoc( $result ); -if ( !isset( $scale ) ) - $scale = 1; if ( !isset( $rate ) ) - $rate = 1; + $rate = RATE_SCALE; +if ( !isset( $scale ) ) + $scale = SCALE_SCALE; ob_start(); diff --git a/web/zm_html_view_watch.php b/web/zm_html_view_watch.php index 065c5b7b7..db7bfb06e 100644 --- a/web/zm_html_view_watch.php +++ b/web/zm_html_view_watch.php @@ -28,23 +28,23 @@ if ( !$result ) die( mysql_error() ); $monitor = mysql_fetch_assoc( $result ); -if ( empty($scale) ) - $scale = 1; +if ( !isset($scale) ) + $scale = SCALE_SCALE; -$width_scale = ($scale<1)?1:$scale; -$height_scale = ($scale<1)?(1/abs($scale)):$scale; +$width_scale = ($scale ZM - <?= $monitor['Name'] ?> - <?= $zmSlangWatch ?> - + diff --git a/web/zm_html_view_watchfeed.php b/web/zm_html_view_watchfeed.php index aade902e1..983ccc1f2 100644 --- a/web/zm_html_view_watchfeed.php +++ b/web/zm_html_view_watchfeed.php @@ -52,7 +52,7 @@ header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); // HTTP/1.0 if ( !isset( $scale ) ) - $scale = 1; + $scale = SCALE_SCALE; ?> diff --git a/zmconfig.pl.in b/zmconfig.pl.in index 3e18a3b12..372195756 100755 --- a/zmconfig.pl.in +++ b/zmconfig.pl.in @@ -513,6 +513,22 @@ my @options = type => $types{integer}, category => 'web', }, + { + name => "ZM_WEB_MONTAGE_WIDTH", + default => "0", + description => "What width should each monitor in the montage view be", + help => "In the montage view it is possible to view all of your monitors at once. If they are all different sizes this can be fairly untidy. Setting this option allows you to constrain the width of each of the monitor views to a fixed value to make the window tidier overall. Leaving it at the default of zero lets each monitor be displayed at it's normal native size.", + type => $types{integer}, + category => 'web', + }, + { + name => "ZM_WEB_MONTAGE_HEIGHT", + default => "0", + description => "What height should each monitor in the montage view be", + help => "In the montage view it is possible to view all of your monitors at once. If they are all different sizes this can be fairly untidy. Setting this option allows you to constrain the height of each of the monitor views to a fixed value to make the window tidier overall. Leaving it at the default of zero lets each monitor be displayed at it's normal native size.", + type => $types{integer}, + category => 'web', + }, { name => "ZM_OPT_FAST_DELETE", default => "yes", @@ -1076,7 +1092,7 @@ my %options_hash = map { ( $_->{name}, $_ ) } @options; foreach my $option ( @options ) { - if ( $option->{default} ) + if ( defined($option->{default}) ) { $option->{value} = $option->{default} }