Merge pull request #1026 from schrorg/blacken-zones
Add new zone type - privacy zones
This commit is contained in:
commit
1cf54d2e38
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (zoneminder)
|
||||
set(zoneminder_VERSION "1.28.104")
|
||||
set(zoneminder_VERSION "1.28.105")
|
||||
# make API version a minor of ZM version
|
||||
set(zoneminder_API_VERSION "${zoneminder_VERSION}.1")
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# For instructions on building with cmake, please see INSTALL
|
||||
#
|
||||
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
|
||||
AC_CONFIG_SRCDIR(src/zm.h)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
|
|
@ -485,7 +485,7 @@ DROP TABLE IF EXISTS `ZonePresets`;
|
|||
CREATE TABLE `ZonePresets` (
|
||||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`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',
|
||||
`CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs',
|
||||
`MinPixelThreshold` smallint(5) unsigned default NULL,
|
||||
|
@ -514,7 +514,7 @@ CREATE TABLE `Zones` (
|
|||
`Id` int(10) unsigned NOT NULL auto_increment,
|
||||
`MonitorId` int(10) unsigned NOT NULL default '0',
|
||||
`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',
|
||||
`NumCoords` tinyint(3) unsigned NOT NULL default '0',
|
||||
`Coords` tinytext NOT NULL,
|
||||
|
|
|
@ -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';
|
|
@ -1735,6 +1735,59 @@ const Coord Image::centreCoord( const char *text ) const
|
|||
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 */
|
||||
void Image::Annotate( const char *p_text, const Coord &coord, const int size, const Rgb fg_colour, const Rgb bg_colour )
|
||||
{
|
||||
|
|
|
@ -231,6 +231,7 @@ public:
|
|||
void Delta( const Image &image, Image* targetimage) 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 );
|
||||
Image *HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits=0 );
|
||||
//Image *HighlightEdges( Rgb colour, const Polygon &polygon );
|
||||
|
|
|
@ -607,6 +607,10 @@ Monitor::~Monitor()
|
|||
delete[] images;
|
||||
images = 0;
|
||||
}
|
||||
if ( privacy_bitmask ) {
|
||||
delete[] privacy_bitmask;
|
||||
privacy_bitmask = NULL;
|
||||
}
|
||||
if ( mem_ptr ) {
|
||||
if ( event )
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
monitors[i]->AddZones( n_zones, zones );
|
||||
monitors[i]->AddPrivacyBitmask( zones );
|
||||
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) )
|
||||
|
@ -2360,6 +2386,7 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c
|
|||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], 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 );
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) )
|
||||
|
@ -2504,6 +2531,7 @@ int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose pu
|
|||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
monitors[i]->AddZones( n_zones, zones );
|
||||
monitors[i]->AddPrivacyBitmask( zones );
|
||||
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) )
|
||||
|
@ -2653,6 +2681,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose
|
|||
Zone **zones = 0;
|
||||
int n_zones = Zone::Load( monitors[i], zones );
|
||||
monitors[i]->AddZones( n_zones, zones );
|
||||
monitors[i]->AddPrivacyBitmask( zones );
|
||||
Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones );
|
||||
}
|
||||
if ( mysql_errno( &dbconn ) )
|
||||
|
@ -2980,6 +3009,7 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
|
|||
Zone **zones = 0;
|
||||
n_zones = Zone::Load( monitor, zones );
|
||||
monitor->AddZones( n_zones, zones );
|
||||
monitor->AddPrivacyBitmask( 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 );
|
||||
if ( config.timestamp_on_capture )
|
||||
{
|
||||
|
|
|
@ -294,6 +294,7 @@ protected:
|
|||
|
||||
int n_zones;
|
||||
Zone **zones;
|
||||
const unsigned char *privacy_bitmask;
|
||||
|
||||
struct timeval **timestamps;
|
||||
Image **images;
|
||||
|
@ -310,6 +311,7 @@ public:
|
|||
~Monitor();
|
||||
|
||||
void AddZones( int p_n_zones, Zone *p_zones[] );
|
||||
void AddPrivacyBitmask( Zone *p_zones[] );
|
||||
|
||||
bool connect();
|
||||
inline int ShmValid() const
|
||||
|
|
|
@ -1013,7 +1013,10 @@ int Zone::Load( Monitor *monitor, Zone **&zones )
|
|||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -1039,8 +1042,9 @@ bool Zone::DumpSettings( char *output, bool /*verbose*/ )
|
|||
type==INCLUSIVE?"Inclusive":(
|
||||
type==EXCLUSIVE?"Exclusive":(
|
||||
type==PRECLUSIVE?"Preclusive":(
|
||||
type==INACTIVE?"Inactive":"Unknown"
|
||||
)))));
|
||||
type==INACTIVE?"Inactive":(
|
||||
type==PRIVACY?"Privacy":"Unknown"
|
||||
))))));
|
||||
sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() );
|
||||
for ( int i = 0; i < polygon.getNumCoords(); i++ )
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ protected:
|
|||
};
|
||||
|
||||
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;
|
||||
|
||||
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 );
|
||||
}
|
||||
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:
|
||||
~Zone();
|
||||
|
@ -123,6 +127,7 @@ public:
|
|||
inline bool IsExclusive() const { return( type == EXCLUSIVE ); }
|
||||
inline bool IsPreclusive() const { return( type == PRECLUSIVE ); }
|
||||
inline bool IsInactive() const { return( type == INACTIVE ); }
|
||||
inline bool IsPrivacy() const { return( type == PRIVACY ); }
|
||||
inline const Image *AlarmImage() const { return( image ); }
|
||||
inline const Polygon &GetPolygon() const { return( polygon ); }
|
||||
inline bool Alarmed() const { return( alarmed ); }
|
||||
|
|
|
@ -325,8 +325,21 @@ if ( !empty($action) )
|
|||
//if ( $cookies ) session_write_close();
|
||||
if ( daemonCheck() )
|
||||
{
|
||||
zmaControl( $mid, "restart" );
|
||||
}
|
||||
if ( $_REQUEST['newZone']['Type'] == 'Privacy' )
|
||||
{
|
||||
zmaControl( $monitor, "stop" );
|
||||
zmcControl( $monitor, "restart" );
|
||||
zmaControl( $monitor, "start" );
|
||||
}
|
||||
else
|
||||
{
|
||||
zmaControl( $mid, "restart" );
|
||||
}
|
||||
}
|
||||
if ( $_REQUEST['newZone']['Type'] == 'Privacy' && $monitor['Controllable'] ) {
|
||||
require_once( 'control_functions.php' );
|
||||
sendControlCommand( $mid, 'quit' );
|
||||
}
|
||||
$refreshParent = true;
|
||||
}
|
||||
$view = 'none';
|
||||
|
@ -374,6 +387,7 @@ if ( !empty($action) )
|
|||
$deletedZid = 0;
|
||||
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) );
|
||||
$deletedZid = 1;
|
||||
}
|
||||
|
@ -382,7 +396,16 @@ if ( !empty($action) )
|
|||
//if ( $cookies )
|
||||
//session_write_close();
|
||||
if ( daemonCheck() )
|
||||
zmaControl( $mid, "restart" );
|
||||
if ( $zone['Type'] == 'Privacy' )
|
||||
{
|
||||
zmaControl( $mid, "stop" );
|
||||
zmcControl( $mid, "restart" );
|
||||
zmaControl( $mid, "start" );
|
||||
}
|
||||
else
|
||||
{
|
||||
zmaControl( $mid, "restart" );
|
||||
}
|
||||
$refreshParent = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ function validateForm( form )
|
|||
{
|
||||
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 )
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ function submitForm( form )
|
|||
function applyZoneType()
|
||||
{
|
||||
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.newAlarmRgbR.disabled = true;
|
||||
|
@ -420,6 +420,10 @@ function saveChanges( element )
|
|||
if ( validateForm( 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( false );
|
||||
|
|
Loading…
Reference in New Issue