Image: Convert API to std::chrono
Utils: Remove TimespecDiff. It is not used anymore
This commit is contained in:
parent
1fe30c848d
commit
ff8c9f67c1
|
@ -294,17 +294,18 @@ bool Event::WriteFrameImage(
|
||||||
|
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
if ( !config.timestamp_on_capture ) {
|
SystemTimePoint jpeg_timestamp =
|
||||||
|
monitor->Exif() ? SystemTimePoint(zm::chrono::duration_cast<Microseconds>(timestamp)) : SystemTimePoint();
|
||||||
|
|
||||||
|
if (!config.timestamp_on_capture) {
|
||||||
// stash the image we plan to use in another pointer regardless if timestamped.
|
// stash the image we plan to use in another pointer regardless if timestamped.
|
||||||
// exif is only timestamp at present this switches on or off for write
|
// exif is only timestamp at present this switches on or off for write
|
||||||
Image *ts_image = new Image(*image);
|
Image *ts_image = new Image(*image);
|
||||||
monitor->TimestampImage(ts_image, timestamp);
|
monitor->TimestampImage(ts_image, timestamp);
|
||||||
rc = ts_image->WriteJpeg(event_file, thisquality,
|
rc = ts_image->WriteJpeg(event_file, thisquality, jpeg_timestamp);
|
||||||
(monitor->Exif() ? timestamp : (timeval){0,0}));
|
delete ts_image;
|
||||||
delete(ts_image);
|
|
||||||
} else {
|
} else {
|
||||||
rc = image->WriteJpeg(event_file, thisquality,
|
rc = image->WriteJpeg(event_file, thisquality, jpeg_timestamp);
|
||||||
(monitor->Exif() ? timestamp : (timeval){0,0}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -1061,23 +1061,26 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
// Note quality=zero means default
|
// Note quality=zero means default
|
||||||
|
|
||||||
bool Image::WriteJpeg(const char *filename, int quality_override) const {
|
bool Image::WriteJpeg(const char *filename, int quality_override) const {
|
||||||
return Image::WriteJpeg(filename, quality_override, (timeval){0,0}, false);
|
return Image::WriteJpeg(filename, quality_override, {}, false);
|
||||||
}
|
}
|
||||||
bool Image::WriteJpeg(const char *filename) const {
|
bool Image::WriteJpeg(const char *filename) const {
|
||||||
return Image::WriteJpeg(filename, 0, (timeval){0,0}, false);
|
return Image::WriteJpeg(filename, 0, {}, false);
|
||||||
}
|
}
|
||||||
bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const {
|
bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const {
|
||||||
return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort);
|
return Image::WriteJpeg(filename, 0, {}, on_blocking_abort);
|
||||||
}
|
}
|
||||||
bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
|
bool Image::WriteJpeg(const char *filename, SystemTimePoint timestamp) const {
|
||||||
return Image::WriteJpeg(filename, 0, timestamp, false);
|
return Image::WriteJpeg(filename, 0, timestamp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const {
|
bool Image::WriteJpeg(const char *filename, int quality_override, SystemTimePoint timestamp) const {
|
||||||
return Image::WriteJpeg(filename, quality_override, timestamp, false);
|
return Image::WriteJpeg(filename, quality_override, timestamp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp, bool on_blocking_abort) const {
|
bool Image::WriteJpeg(const char *filename,
|
||||||
|
int quality_override,
|
||||||
|
SystemTimePoint timestamp,
|
||||||
|
bool on_blocking_abort) const {
|
||||||
if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) {
|
if ( config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8) ) {
|
||||||
Image temp_image(*this);
|
Image temp_image(*this);
|
||||||
temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB);
|
temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB);
|
||||||
|
@ -1196,7 +1199,7 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
}
|
}
|
||||||
// If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal
|
// If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal
|
||||||
// No timestamp just leave off the exif section.
|
// No timestamp just leave off the exif section.
|
||||||
if ( timestamp.tv_sec ) {
|
if (timestamp.time_since_epoch() > Seconds(0)) {
|
||||||
#define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds
|
#define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds
|
||||||
#define EXIFTIMES_MS_LEN 0x03
|
#define EXIFTIMES_MS_LEN 0x03
|
||||||
#define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes
|
#define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes
|
||||||
|
@ -1205,9 +1208,15 @@ cinfo->out_color_space = JCS_RGB;
|
||||||
|
|
||||||
// This is a lot of stuff to allocate on the stack. Recommend char *timebuf[64];
|
// This is a lot of stuff to allocate on the stack. Recommend char *timebuf[64];
|
||||||
char timebuf[64], msbuf[64];
|
char timebuf[64], msbuf[64];
|
||||||
|
|
||||||
tm timestamp_tm = {};
|
tm timestamp_tm = {};
|
||||||
strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime_r(×tamp.tv_sec, ×tamp_tm));
|
time_t timestamp_t = std::chrono::system_clock::to_time_t(timestamp);
|
||||||
snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it
|
strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime_r(×tamp_t, ×tamp_tm));
|
||||||
|
Seconds ts_sec = std::chrono::duration_cast<Seconds>(timestamp.time_since_epoch());
|
||||||
|
Microseconds ts_usec = std::chrono::duration_cast<Microseconds>(timestamp.time_since_epoch() - ts_sec);
|
||||||
|
// we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it
|
||||||
|
snprintf(msbuf, sizeof msbuf, "%06d", static_cast<int32>(ts_usec.count()));
|
||||||
|
|
||||||
unsigned char exiftimes[82] = {
|
unsigned char exiftimes[82] = {
|
||||||
0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00,
|
0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||||
0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -1722,11 +1731,6 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) {
|
||||||
} // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y )
|
} // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y )
|
||||||
|
|
||||||
void Image::Blend( const Image &image, int transparency ) {
|
void Image::Blend( const Image &image, int transparency ) {
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
|
||||||
struct timespec start,end,diff;
|
|
||||||
unsigned long long executetime;
|
|
||||||
unsigned long milpixels;
|
|
||||||
#endif
|
|
||||||
uint8_t* new_buffer;
|
uint8_t* new_buffer;
|
||||||
|
|
||||||
if ( !(
|
if ( !(
|
||||||
|
@ -1744,19 +1748,21 @@ void Image::Blend( const Image &image, int transparency ) {
|
||||||
new_buffer = AllocBuffer(size);
|
new_buffer = AllocBuffer(size);
|
||||||
|
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start);
|
TimePoint start = std::chrono::steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Do the blending */
|
/* Do the blending */
|
||||||
(*blend)(buffer, image.buffer, new_buffer, size, transparency);
|
(*blend)(buffer, image.buffer, new_buffer, size, transparency);
|
||||||
|
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end);
|
TimePoint end = std::chrono::steady_clock::now();
|
||||||
TimespecDiff(&start,&end,&diff);
|
|
||||||
|
|
||||||
executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec;
|
std::chrono::nanoseconds diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
||||||
milpixels = (unsigned long)((long double)size)/((((long double)executetime)/1000));
|
uint64 mil_pixels = static_cast<uint64>(size / (static_cast<long double>(diff.count()) / 1000));
|
||||||
Debug(5, "Blend: %u colours blended in %llu nanoseconds, %lu million colours/s\n",size,executetime,milpixels);
|
Debug(5, "Blend: %u colours blended in %" PRIi64 " nanoseconds, % " PRIi64 " million colours/s\n",
|
||||||
|
size,
|
||||||
|
static_cast<int64>(diff.count()),
|
||||||
|
mil_pixels);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AssignDirect(width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM);
|
AssignDirect(width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM);
|
||||||
|
@ -1860,12 +1866,6 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres
|
||||||
|
|
||||||
/* New function to allow buffer re-using instead of allocationg memory for the delta image every time */
|
/* New function to allow buffer re-using instead of allocationg memory for the delta image every time */
|
||||||
void Image::Delta(const Image &image, Image* targetimage) const {
|
void Image::Delta(const Image &image, Image* targetimage) const {
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
|
||||||
struct timespec start,end,diff;
|
|
||||||
unsigned long long executetime;
|
|
||||||
unsigned long milpixels;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) {
|
if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) {
|
||||||
Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d",
|
Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d",
|
||||||
width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder);
|
width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder);
|
||||||
|
@ -1878,7 +1878,7 @@ void Image::Delta(const Image &image, Image* targetimage) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start);
|
TimePoint start = std::chrono::steady_clock::now();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch ( colours ) {
|
switch ( colours ) {
|
||||||
|
@ -1915,12 +1915,14 @@ void Image::Delta(const Image &image, Image* targetimage) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ZM_IMAGE_PROFILING
|
#ifdef ZM_IMAGE_PROFILING
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end);
|
TimePoint end = std::chrono::steady_clock::now();
|
||||||
TimespecDiff(&start,&end,&diff);
|
|
||||||
|
|
||||||
executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec;
|
std::chrono::nanoseconds diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
||||||
milpixels = (unsigned long)((long double)pixels)/((((long double)executetime)/1000));
|
uint64 mil_pixels = static_cast<uint64>(size / (static_cast<long double>(diff.count()) / 1000));
|
||||||
Debug(5, "Delta: %u delta pixels generated in %llu nanoseconds, %lu million pixels/s",pixels,executetime,milpixels);
|
Debug(5, "Delta: %u delta pixels generated in %" PRIi64 " nanoseconds, % " PRIi64 " million pixels/s",
|
||||||
|
size,
|
||||||
|
static_cast<int64>(diff.count()),
|
||||||
|
mil_pixels);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2119,17 +2121,18 @@ void Image::Annotate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Timestamp(const char *label, const time_t when, const Vector2 &coord, const int size) {
|
void Image::Timestamp(const char *label, SystemTimePoint when, const Vector2 &coord, int label_size) {
|
||||||
char time_text[64];
|
char time_text[64];
|
||||||
tm when_tm = {};
|
tm when_tm = {};
|
||||||
strftime(time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime_r(&when, &when_tm));
|
time_t when_t = std::chrono::system_clock::to_time_t(when);
|
||||||
if ( label ) {
|
strftime(time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime_r(&when_t, &when_tm));
|
||||||
|
if (label) {
|
||||||
// Assume label is max 64, + ' - ' + 64 chars of time_text
|
// Assume label is max 64, + ' - ' + 64 chars of time_text
|
||||||
char text[132];
|
char text[132];
|
||||||
snprintf(text, sizeof(text), "%s - %s", label, time_text);
|
snprintf(text, sizeof(text), "%s - %s", label, time_text);
|
||||||
Annotate(text, coord, size);
|
Annotate(text, coord, label_size);
|
||||||
} else {
|
} else {
|
||||||
Annotate(time_text, coord, size);
|
Annotate(time_text, coord, label_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "zm_logger.h"
|
#include "zm_logger.h"
|
||||||
#include "zm_mem_utils.h"
|
#include "zm_mem_utils.h"
|
||||||
#include "zm_rgb.h"
|
#include "zm_rgb.h"
|
||||||
|
#include "zm_time.h"
|
||||||
#include "zm_vector2.h"
|
#include "zm_vector2.h"
|
||||||
|
|
||||||
#if HAVE_ZLIB_H
|
#if HAVE_ZLIB_H
|
||||||
|
@ -237,9 +238,9 @@ class Image {
|
||||||
bool WriteJpeg(const char *filename) const;
|
bool WriteJpeg(const char *filename) const;
|
||||||
bool WriteJpeg(const char *filename, bool on_blocking_abort) const;
|
bool WriteJpeg(const char *filename, bool on_blocking_abort) const;
|
||||||
bool WriteJpeg(const char *filename, int quality_override) const;
|
bool WriteJpeg(const char *filename, int quality_override) const;
|
||||||
bool WriteJpeg(const char *filename, struct timeval timestamp) const;
|
bool WriteJpeg(const char *filename, SystemTimePoint timestamp) const;
|
||||||
bool WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const;
|
bool WriteJpeg(const char *filename, int quality_override, SystemTimePoint timestamp) const;
|
||||||
bool WriteJpeg(const char *filename, int quality_override, struct timeval timestamp, bool on_blocking_abort) const;
|
bool WriteJpeg(const char *filename, int quality_override, SystemTimePoint timestamp, bool on_blocking_abort) const;
|
||||||
|
|
||||||
bool DecodeJpeg(const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder);
|
bool DecodeJpeg(const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder);
|
||||||
bool EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_override=0) const;
|
bool EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_override=0) const;
|
||||||
|
@ -270,7 +271,7 @@ class Image {
|
||||||
Rgb bg_colour = kRGBBlack);
|
Rgb bg_colour = kRGBBlack);
|
||||||
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 );
|
||||||
void Timestamp(const char *label, const time_t when, const Vector2 &coord, const int size);
|
void Timestamp(const char *label, SystemTimePoint when, const Vector2 &coord, int label_size);
|
||||||
void Colourise(const unsigned int p_reqcolours, const unsigned int p_reqsubpixelorder);
|
void Colourise(const unsigned int p_reqcolours, const unsigned int p_reqsubpixelorder);
|
||||||
void DeColourise();
|
void DeColourise();
|
||||||
|
|
||||||
|
@ -300,8 +301,9 @@ class Edge {
|
||||||
Edge(int32 min_y, int32 max_y, double min_x, double _1_m) : min_y(min_y), max_y(max_y), min_x(min_x), _1_m(_1_m) {}
|
Edge(int32 min_y, int32 max_y, double min_x, double _1_m) : min_y(min_y), max_y(max_y), min_x(min_x), _1_m(_1_m) {}
|
||||||
|
|
||||||
static bool CompareYX(const Edge &e1, const Edge &e2) {
|
static bool CompareYX(const Edge &e1, const Edge &e2) {
|
||||||
if (e1.min_y == e2.min_y)
|
if (e1.min_y == e2.min_y) {
|
||||||
return e1.min_x < e2.min_x;
|
return e1.min_x < e2.min_x;
|
||||||
|
}
|
||||||
return e1.min_y < e2.min_y;
|
return e1.min_y < e2.min_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,16 +180,6 @@ std::string Base64Encode(const std::string &str) {
|
||||||
return outString;
|
return outString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimespecDiff(struct timespec *start, struct timespec *end, struct timespec *diff) {
|
|
||||||
if (((end->tv_nsec) - (start->tv_nsec)) < 0) {
|
|
||||||
diff->tv_sec = end->tv_sec - start->tv_sec - 1;
|
|
||||||
diff->tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec;
|
|
||||||
} else {
|
|
||||||
diff->tv_sec = end->tv_sec - start->tv_sec;
|
|
||||||
diff->tv_nsec = end->tv_nsec - start->tv_nsec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TimevalToString(timeval tv) {
|
std::string TimevalToString(timeval tv) {
|
||||||
tm now = {};
|
tm now = {};
|
||||||
std::array<char, 26> tm_buf = {};
|
std::array<char, 26> tm_buf = {};
|
||||||
|
|
|
@ -76,7 +76,6 @@ std::string ByteArrayToHexString(nonstd::span<const uint8> bytes);
|
||||||
|
|
||||||
std::string Base64Encode(const std::string &str);
|
std::string Base64Encode(const std::string &str);
|
||||||
|
|
||||||
void TimespecDiff(timespec *start, timespec *end, timespec *diff);
|
|
||||||
std::string TimevalToString(timeval tv);
|
std::string TimevalToString(timeval tv);
|
||||||
|
|
||||||
extern unsigned int sse_version;
|
extern unsigned int sse_version;
|
||||||
|
|
Loading…
Reference in New Issue