Merge pull request #1026 from schrorg/blacken-zones

Add new zone type - privacy zones
This commit is contained in:
Isaac Connor 2015-08-27 09:14:16 -04:00
commit 1cf54d2e38
13 changed files with 149 additions and 14 deletions

View File

@ -4,7 +4,7 @@
# #
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
project (zoneminder) project (zoneminder)
set(zoneminder_VERSION "1.28.104") set(zoneminder_VERSION "1.28.105")
# make API version a minor of ZM version # make API version a minor of ZM version
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1") set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")

View File

@ -3,7 +3,7 @@
# For instructions on building with cmake, please see INSTALL # For instructions on building with cmake, please see INSTALL
# #
AC_PREREQ(2.59) AC_PREREQ(2.59)
AC_INIT(zm,1.28.104,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html) AC_INIT(zm,1.28.105,[http://www.zoneminder.com/forums/ - Please check FAQ first],zoneminder,http://www.zoneminder.com/downloads.html)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR(src/zm.h) AC_CONFIG_SRCDIR(src/zm.h)
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)

View File

@ -485,7 +485,7 @@ DROP TABLE IF EXISTS `ZonePresets`;
CREATE TABLE `ZonePresets` ( CREATE TABLE `ZonePresets` (
`Id` int(10) unsigned NOT NULL auto_increment, `Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL default 'Active',
`Units` enum('Pixels','Percent') NOT NULL default 'Pixels', `Units` enum('Pixels','Percent') NOT NULL default 'Pixels',
`CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs',
`MinPixelThreshold` smallint(5) unsigned default NULL, `MinPixelThreshold` smallint(5) unsigned default NULL,
@ -514,7 +514,7 @@ CREATE TABLE `Zones` (
`Id` int(10) unsigned NOT NULL auto_increment, `Id` int(10) unsigned NOT NULL auto_increment,
`MonitorId` int(10) unsigned NOT NULL default '0', `MonitorId` int(10) unsigned NOT NULL default '0',
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL default 'Active',
`Units` enum('Pixels','Percent') NOT NULL default 'Pixels', `Units` enum('Pixels','Percent') NOT NULL default 'Pixels',
`NumCoords` tinyint(3) unsigned NOT NULL default '0', `NumCoords` tinyint(3) unsigned NOT NULL default '0',
`Coords` tinytext NOT NULL, `Coords` tinytext NOT NULL,

10
db/zm_update-1.28.105.sql Normal file
View File

@ -0,0 +1,10 @@
--
-- This updates a 1.28.104 database to 1.28.105
--
--
-- Add Privacy type to Zone Types
--
alter table Zones modify Type enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL DEFAULT 'Active';
alter table ZonePresets modify Type enum('Active','Inclusive','Exclusive','Preclusive','Inactive','Privacy') NOT NULL DEFAULT 'Active';

View File

@ -1735,6 +1735,59 @@ const Coord Image::centreCoord( const char *text ) const
return( Coord( x, y ) ); return( Coord( x, y ) );
} }
/* RGB32 compatible: complete */
void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour )
{
const uint8_t pixel_r_col = RED_VAL_RGBA(pixel_colour);
const uint8_t pixel_g_col = GREEN_VAL_RGBA(pixel_colour);
const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour);
const uint8_t pixel_bw_col = pixel_colour & 0xff;
const Rgb pixel_rgb_col = rgb_convert(pixel_colour,subpixelorder);
unsigned char *ptr = &buffer[0];
unsigned int i = 0;
for ( unsigned int y = 0; y < height; y++ )
{
if ( colours == ZM_COLOUR_GRAY8 )
{
for ( unsigned int x = 0; x < width; x++, ptr++ )
{
if ( p_bitmask[i] )
*ptr = pixel_bw_col;
i++;
}
}
else if ( colours == ZM_COLOUR_RGB24 )
{
for ( unsigned int x = 0; x < width; x++, ptr += colours )
{
if ( p_bitmask[i] )
{
RED_PTR_RGBA(ptr) = pixel_r_col;
GREEN_PTR_RGBA(ptr) = pixel_g_col;
BLUE_PTR_RGBA(ptr) = pixel_b_col;
}
i++;
}
}
else if ( colours == ZM_COLOUR_RGB32 )
{
for ( unsigned int x = 0; x < width; x++, ptr += colours )
{
Rgb *temp_ptr = (Rgb*)ptr;
if ( p_bitmask[i] )
*temp_ptr = pixel_rgb_col;
i++;
}
} else {
Panic("MaskPrivacy called with unexpected colours: %d", colours);
return;
}
}
}
/* RGB32 compatible: complete */ /* RGB32 compatible: complete */
void Image::Annotate( const char *p_text, const Coord &coord, const int size, const Rgb fg_colour, const Rgb bg_colour ) void Image::Annotate( const char *p_text, const Coord &coord, const int size, const Rgb fg_colour, const Rgb bg_colour )
{ {

View File

@ -231,6 +231,7 @@ public:
void Delta( const Image &image, Image* targetimage) const; void Delta( const Image &image, Image* targetimage) const;
const Coord centreCoord( const char *text ) const; const Coord centreCoord( const char *text ) const;
void MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour=0x00222222 );
void Annotate( const char *p_text, const Coord &coord, const int size=1, const Rgb fg_colour=RGB_WHITE, const Rgb bg_colour=RGB_BLACK ); void Annotate( const char *p_text, const Coord &coord, const int size=1, const Rgb fg_colour=RGB_WHITE, const Rgb bg_colour=RGB_BLACK );
Image *HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits=0 ); Image *HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits=0 );
//Image *HighlightEdges( Rgb colour, const Polygon &polygon ); //Image *HighlightEdges( Rgb colour, const Polygon &polygon );

View File

@ -607,6 +607,10 @@ Monitor::~Monitor()
delete[] images; delete[] images;
images = 0; images = 0;
} }
if ( privacy_bitmask ) {
delete[] privacy_bitmask;
privacy_bitmask = NULL;
}
if ( mem_ptr ) { if ( mem_ptr ) {
if ( event ) if ( event )
Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() );
@ -686,6 +690,27 @@ void Monitor::AddZones( int p_n_zones, Zone *p_zones[] )
zones = p_zones; zones = p_zones;
} }
void Monitor::AddPrivacyBitmask( Zone *p_zones[] )
{
delete[] privacy_bitmask;
privacy_bitmask = NULL;
Image *privacy_image = NULL;
for ( int i = 0; i < n_zones; i++ )
if ( p_zones[i]->IsPrivacy() )
{
if ( !privacy_image )
{
privacy_image = new Image( width, height, 1, ZM_SUBPIX_ORDER_NONE);
privacy_image->Clear();
}
privacy_image->Fill( 0xff, p_zones[i]->GetPolygon() );
privacy_image->Outline( 0xff, p_zones[i]->GetPolygon() );
}
if ( privacy_image )
privacy_bitmask = privacy_image->Buffer();
}
Monitor::State Monitor::GetState() const Monitor::State Monitor::GetState() const
{ {
return( (State)shared_data->state ); return( (State)shared_data->state );
@ -2179,6 +2204,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
Zone **zones = 0; Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones ); int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones ); monitors[i]->AddZones( n_zones, zones );
monitors[i]->AddPrivacyBitmask( zones );
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -2360,6 +2386,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
Zone **zones = 0; Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones ); int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones ); monitors[i]->AddZones( n_zones, zones );
monitors[i]->AddPrivacyBitmask( zones );
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones );
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -2504,6 +2531,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
Zone **zones = 0; Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones ); int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones ); monitors[i]->AddZones( n_zones, zones );
monitors[i]->AddPrivacyBitmask( zones );
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -2653,6 +2681,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
Zone **zones = 0; Zone **zones = 0;
int n_zones = Zone::Load( monitors[i], zones ); int n_zones = Zone::Load( monitors[i], zones );
monitors[i]->AddZones( n_zones, zones ); monitors[i]->AddZones( n_zones, zones );
monitors[i]->AddPrivacyBitmask( zones );
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
} }
if ( mysql_errno( &dbconn ) ) if ( mysql_errno( &dbconn ) )
@ -2980,6 +3009,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
Zone **zones = 0; Zone **zones = 0;
n_zones = Zone::Load( monitor, zones ); n_zones = Zone::Load( monitor, zones );
monitor->AddZones( n_zones, zones ); monitor->AddZones( n_zones, zones );
monitor->AddPrivacyBitmask( zones );
} }
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones );
} }
@ -3097,6 +3127,9 @@ int Monitor::Capture()
} }
} }
if ( privacy_bitmask )
capture_image->MaskPrivacy( privacy_bitmask );
gettimeofday( image_buffer[index].timestamp, NULL ); gettimeofday( image_buffer[index].timestamp, NULL );
if ( config.timestamp_on_capture ) if ( config.timestamp_on_capture )
{ {

View File

@ -294,6 +294,7 @@ protected:
int n_zones; int n_zones;
Zone **zones; Zone **zones;
const unsigned char *privacy_bitmask;
struct timeval **timestamps; struct timeval **timestamps;
Image **images; Image **images;
@ -310,6 +311,7 @@ public:
~Monitor(); ~Monitor();
void AddZones( int p_n_zones, Zone *p_zones[] ); void AddZones( int p_n_zones, Zone *p_zones[] );
void AddPrivacyBitmask( Zone *p_zones[] );
bool connect(); bool connect();
inline int ShmValid() const inline int ShmValid() const

View File

@ -1013,7 +1013,10 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
{ {
zones[i] = new Zone( monitor, Id, Name, polygon ); zones[i] = new Zone( monitor, Id, Name, polygon );
} }
else else if ( atoi(dbrow[2]) == Zone::PRIVACY )
{
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon );
}
{ {
zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames ); zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames );
} }
@ -1039,8 +1042,9 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ )
type==INCLUSIVE?"Inclusive":( type==INCLUSIVE?"Inclusive":(
type==EXCLUSIVE?"Exclusive":( type==EXCLUSIVE?"Exclusive":(
type==PRECLUSIVE?"Preclusive":( type==PRECLUSIVE?"Preclusive":(
type==INACTIVE?"Inactive":"Unknown" type==INACTIVE?"Inactive":(
))))); type==PRIVACY?"Privacy":"Unknown"
))))));
sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() );
for ( int i = 0; i < polygon.getNumCoords(); i++ ) for ( int i = 0; i < polygon.getNumCoords(); i++ )
{ {

View File

@ -43,7 +43,7 @@ protected:
}; };
public: public:
typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType; typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE, PRIVACY } ZoneType;
typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod; typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod;
protected: protected:
@ -111,6 +111,10 @@ public:
{ {
Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 ); Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 );
} }
Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon )
{
Setup( p_monitor, p_id, p_label, p_type, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 );
}
public: public:
~Zone(); ~Zone();
@ -123,6 +127,7 @@ public:
inline bool IsExclusive() const { return( type == EXCLUSIVE ); } inline bool IsExclusive() const { return( type == EXCLUSIVE ); }
inline bool IsPreclusive() const { return( type == PRECLUSIVE ); } inline bool IsPreclusive() const { return( type == PRECLUSIVE ); }
inline bool IsInactive() const { return( type == INACTIVE ); } inline bool IsInactive() const { return( type == INACTIVE ); }
inline bool IsPrivacy() const { return( type == PRIVACY ); }
inline const Image *AlarmImage() const { return( image ); } inline const Image *AlarmImage() const { return( image ); }
inline const Polygon &GetPolygon() const { return( polygon ); } inline const Polygon &GetPolygon() const { return( polygon ); }
inline bool Alarmed() const { return( alarmed ); } inline bool Alarmed() const { return( alarmed ); }

View File

@ -1 +1 @@
1.28.104 1.28.105

View File

@ -324,9 +324,22 @@ if ( !empty($action) )
} }
//if ( $cookies ) session_write_close(); //if ( $cookies ) session_write_close();
if ( daemonCheck() ) if ( daemonCheck() )
{
if ( $_REQUEST['newZone']['Type'] == 'Privacy' )
{
zmaControl( $monitor, "stop" );
zmcControl( $monitor, "restart" );
zmaControl( $monitor, "start" );
}
else
{ {
zmaControl( $mid, "restart" ); zmaControl( $mid, "restart" );
} }
}
if ( $_REQUEST['newZone']['Type'] == 'Privacy' && $monitor['Controllable'] ) {
require_once( 'control_functions.php' );
sendControlCommand( $mid, 'quit' );
}
$refreshParent = true; $refreshParent = true;
} }
$view = 'none'; $view = 'none';
@ -374,6 +387,7 @@ if ( !empty($action) )
$deletedZid = 0; $deletedZid = 0;
foreach( $_REQUEST['markZids'] as $markZid ) foreach( $_REQUEST['markZids'] as $markZid )
{ {
$zone = dbFetchOne( "select * from Zones where Id=?", NULL, array($markZid) );
dbQuery( "delete from Zones WHERE MonitorId=? AND Id=?", array( $mid, $markZid) ); dbQuery( "delete from Zones WHERE MonitorId=? AND Id=?", array( $mid, $markZid) );
$deletedZid = 1; $deletedZid = 1;
} }
@ -382,7 +396,16 @@ if ( !empty($action) )
//if ( $cookies ) //if ( $cookies )
//session_write_close(); //session_write_close();
if ( daemonCheck() ) if ( daemonCheck() )
if ( $zone['Type'] == 'Privacy' )
{
zmaControl( $mid, "stop" );
zmcControl( $mid, "restart" );
zmaControl( $mid, "start" );
}
else
{
zmaControl( $mid, "restart" ); zmaControl( $mid, "restart" );
}
$refreshParent = true; $refreshParent = true;
} }
} }

View File

@ -5,7 +5,7 @@ function validateForm( form )
{ {
errors[errors.length] = selfIntersectingString; errors[errors.length] = selfIntersectingString;
} }
if ( form.elements['newZone[Type]'].value != 'Inactive' ) if ( form.elements['newZone[Type]'].value != 'Inactive' && form.elements['newZone[Type]'].value != 'Privacy' )
{ {
if ( !form.newAlarmRgbR.value || !form.newAlarmRgbG.value || !form.newAlarmRgbB.value ) if ( !form.newAlarmRgbR.value || !form.newAlarmRgbG.value || !form.newAlarmRgbB.value )
{ {
@ -95,7 +95,7 @@ function submitForm( form )
function applyZoneType() function applyZoneType()
{ {
var form = document.zoneForm; var form = document.zoneForm;
if ( form.elements['newZone[Type]'].value == 'Inactive' ) if ( form.elements['newZone[Type]'].value == 'Inactive' || form.elements['newZone[Type]'].value == 'Privacy' )
{ {
form.presetSelector.disabled = true; form.presetSelector.disabled = true;
form.newAlarmRgbR.disabled = true; form.newAlarmRgbR.disabled = true;
@ -420,6 +420,10 @@ function saveChanges( element )
if ( validateForm( form ) ) if ( validateForm( form ) )
{ {
submitForm( form ); submitForm( form );
if ( form.elements['newZone[Type]'].value == 'Privacy' )
{
alert( 'Capture process for this monitor will be restarted for the Privacy zone changes to take effect.' );
}
return( true ); return( true );
} }
return( false ); return( false );