diff --git a/draw.c b/draw.c index 69a3171d..4369f672 100644 --- a/draw.c +++ b/draw.c @@ -1069,10 +1069,10 @@ struct draw_char draw_table[]= { /** * draw_textn */ -static int draw_textn(unsigned char *image, unsigned int startx, unsigned int starty, unsigned int width, const char *text, int len, unsigned int factor) +static int draw_textn(unsigned char *image, int startx, int starty, int width, const char *text, int len, int factor) { - unsigned int x, y; + int x, y; int pos, line_offset, next_char_offs; unsigned char *image_ptr, *char_ptr; @@ -1082,10 +1082,10 @@ static int draw_textn(unsigned char *image, unsigned int startx, unsigned int st if (startx + len * 6 * factor >= width) len = (width-startx-1)/(6*factor); - line_offset = width - 7 * factor; - next_char_offs = width * 8 * factor - 6 * factor; + line_offset = width - (7 * factor); + next_char_offs = (width * 8 * factor) - (6 * factor); - image_ptr = image + startx + starty * width; + image_ptr = image + startx + (starty * width); for (pos = 0; pos < len; pos++) { int pos_check = (int)text[pos]; @@ -1126,19 +1126,36 @@ static int draw_textn(unsigned char *image, unsigned int startx, unsigned int st /** * draw_text */ -int draw_text(unsigned char *image, unsigned int width, unsigned int height, unsigned int startx, unsigned int starty, const char *text, unsigned int factor) +int draw_text(unsigned char *image, int width, int height, int startx, int starty, const char *text, int factor) { int num_nl = 0; const char *end, *begin; - const int line_space = factor * 9; + int line_space, txtlen; /* Count the number of newlines in "text" so we scroll it up the image. */ - end = text; - + begin = end = text; + txtlen = 0; while ((end = strstr(end, NEWLINE))) { + if ((end - begin)>txtlen) txtlen = (end - begin); num_nl++; end += sizeof(NEWLINE)-1; } + if (txtlen == 0) txtlen = strlen(text); + + /* Adjust the factor if it is out of bounds + * txtlen at this point is the approx length of longest line + */ + if ((txtlen * 7 * factor) > width){ + factor = (width / (txtlen * 7)); + if (factor <= 0) factor = 1; + } + + if (((num_nl+1) * 8 * factor) > height){ + factor = (height / ((num_nl+1) * 8)); + if (factor <= 0) factor = 1; + } + + line_space = factor * 9; starty -= line_space * num_nl; @@ -1147,12 +1164,6 @@ int draw_text(unsigned char *image, unsigned int width, unsigned int height, uns while ((end = strstr(end, NEWLINE))) { int len = end-begin; - // Check that we won't be writing outside of the image. - if (startx < len*8*factor || starty + 7*factor > height) { - MOTION_LOG(ERR, TYPE_CORE, NO_ERRNO, "Text was too large for image in draw_text"); - return 1; - } - draw_textn(image, startx, starty, width, begin, len, factor); end += sizeof(NEWLINE)-1; begin = end; diff --git a/motion.c b/motion.c index 5f6b0efb..fcbabbe3 100644 --- a/motion.c +++ b/motion.c @@ -623,9 +623,9 @@ static void process_image_ring(struct context *cnt, unsigned int max_images) mystrftime(cnt, tmp, sizeof(tmp), "%H%M%S-%q", &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tv, NULL, 0); draw_text(cnt->imgs.image_ring[cnt->imgs.image_ring_out].image_norm, - cnt->imgs.width, cnt->imgs.height, 10, 20, tmp, cnt->conf.text_scale); + cnt->imgs.width, cnt->imgs.height, 10, 20, tmp, cnt->text_scale); draw_text(cnt->imgs.image_ring[cnt->imgs.image_ring_out].image_norm, - cnt->imgs.width, cnt->imgs.height, 10, 30, t, cnt->conf.text_scale); + cnt->imgs.width, cnt->imgs.height, 10, 30, t, cnt->text_scale); } /* Output the picture to jpegs and ffmpeg */ @@ -658,7 +658,7 @@ static void process_image_ring(struct context *cnt, unsigned int max_images) frames); sprintf(tmp, "Fillerframes %d", frames); draw_text(cnt->imgs.image_ring[cnt->imgs.image_ring_out].image_norm, - cnt->imgs.width, cnt->imgs.height, 10, 40, tmp, cnt->conf.text_scale); + cnt->imgs.width, cnt->imgs.height, 10, 40, tmp, cnt->text_scale); } } /* Check how many frames it was last sec */ @@ -868,6 +868,34 @@ static void init_mask_privacy(struct context *cnt){ } +static void init_text_scale(struct context *cnt){ + + /* Consider that web interface may change conf values at any moment. + * The below can put two sections in the image so make sure that after + * scaling does not occupy more than 1/4 of image (10 pixels * 2 lines) + */ + + cnt->text_scale = cnt->conf.text_scale; + if (cnt->text_scale <= 0) cnt->text_scale = 1; + + if ((cnt->text_scale * 10 * 2) > (cnt->imgs.width / 4)) { + cnt->text_scale = (cnt->imgs.width / (4 * 10 * 2)); + if (cnt->text_scale <= 0) cnt->text_scale = 1; + MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "Invalid text scale. Adjusted to %d", cnt->text_scale); + } + + if ((cnt->text_scale * 10 * 2) > (cnt->imgs.height / 4)) { + cnt->text_scale = (cnt->imgs.height / (4 * 10 * 2)); + if (cnt->text_scale <= 0) cnt->text_scale = 1; + MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO, "Invalid text scale. Adjusted to %d", cnt->text_scale); + } + + /* If we had to modify the scale, change conf so we don't get another message */ + cnt->conf.text_scale = cnt->text_scale; + +} + + /** * motion_init * @@ -1014,6 +1042,8 @@ static int motion_init(struct context *cnt) */ rotate_init(cnt); /* rotate_deinit is called in main */ + init_text_scale(cnt); /*Initialize and validate the text_scale */ + /* Capture first image, or we will get an alarm on start */ if (cnt->video_dev >= 0) { int i; @@ -1027,7 +1057,7 @@ static int motion_init(struct context *cnt) if (i >= 5) { memset(cnt->imgs.image_virgin.image_norm, 0x80, cnt->imgs.size_norm); /* initialize to grey */ draw_text(cnt->imgs.image_virgin.image_norm, cnt->imgs.width, cnt->imgs.height, - 10, 20, "Error capturing first image", cnt->conf.text_scale); + 10, 20, "Error capturing first image", cnt->text_scale); MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error capturing first image"); } } @@ -1844,8 +1874,7 @@ static int mlp_capture(struct context *cnt){ memset(cnt->current_image->image_norm, 0x80, cnt->imgs.size_norm); mystrftime(cnt, tmpout, sizeof(tmpout), tmpin, &tv1, NULL, 0); draw_text(cnt->current_image->image_norm, cnt->imgs.width, cnt->imgs.height, - 10, 20 * cnt->conf.text_scale, - tmpout, cnt->conf.text_scale); + 10, 20 * cnt->text_scale, tmpout, cnt->text_scale); /* Write error message only once */ if (cnt->missing_frame_counter == MISSING_FRAMES_TIMEOUT * cnt->conf.frame_limit) { @@ -2055,6 +2084,7 @@ static void mlp_tuning(struct context *cnt){ static void mlp_overlay(struct context *cnt){ char tmp[PATH_MAX]; + /***** MOTION LOOP - TEXT AND GRAPHICS OVERLAY SECTION *****/ /* * Some overlays on top of the motion image @@ -2086,8 +2116,7 @@ static void mlp_overlay(struct context *cnt){ sprintf(tmp, "-"); draw_text(cnt->current_image->image_norm, cnt->imgs.width, cnt->imgs.height, - cnt->imgs.width - 10, 10, - tmp, cnt->conf.text_scale); + cnt->imgs.width - 10, 10, tmp, cnt->text_scale); } /* @@ -2098,12 +2127,12 @@ static void mlp_overlay(struct context *cnt){ sprintf(tmp, "D:%5d L:%3d N:%3d", cnt->current_image->diffs, cnt->current_image->total_labels, cnt->noise); draw_text(cnt->imgs.img_motion.image_norm, cnt->imgs.width, cnt->imgs.height, - cnt->imgs.width - 10, cnt->imgs.height - 30 * cnt->conf.text_scale, - tmp, cnt->conf.text_scale); + cnt->imgs.width - 10, cnt->imgs.height - (30 * cnt->text_scale), + tmp, cnt->text_scale); sprintf(tmp, "THREAD %d SETUP", cnt->threadnr); draw_text(cnt->imgs.img_motion.image_norm, cnt->imgs.width, cnt->imgs.height, - cnt->imgs.width - 10, cnt->imgs.height - 10 * cnt->conf.text_scale, - tmp, cnt->conf.text_scale); + cnt->imgs.width - 10, cnt->imgs.height - (10 * cnt->text_scale), + tmp, cnt->text_scale); } /* Add text in lower left corner of the pictures */ @@ -2111,8 +2140,7 @@ static void mlp_overlay(struct context *cnt){ mystrftime(cnt, tmp, sizeof(tmp), cnt->conf.text_left, &cnt->current_image->timestamp_tv, NULL, 0); draw_text(cnt->current_image->image_norm, cnt->imgs.width, cnt->imgs.height, - 10, cnt->imgs.height - 10 * cnt->conf.text_scale, - tmp, cnt->conf.text_scale); + 10, cnt->imgs.height - (10 * cnt->text_scale), tmp, cnt->text_scale); } /* Add text in lower right corner of the pictures */ @@ -2120,8 +2148,8 @@ static void mlp_overlay(struct context *cnt){ mystrftime(cnt, tmp, sizeof(tmp), cnt->conf.text_right, &cnt->current_image->timestamp_tv, NULL, 0); draw_text(cnt->current_image->image_norm, cnt->imgs.width, cnt->imgs.height, - cnt->imgs.width - 10, cnt->imgs.height - 10 * cnt->conf.text_scale, - tmp, cnt->conf.text_scale); + cnt->imgs.width - 10, cnt->imgs.height - (10 * cnt->text_scale), + tmp, cnt->text_scale); } } @@ -2449,11 +2477,15 @@ static void mlp_loopback(struct context *cnt){ } + static void mlp_parmsupdate(struct context *cnt){ /***** MOTION LOOP - ONCE PER SECOND PARAMETER UPDATE SECTION *****/ /* Check for some config parameter changes but only every second */ if (cnt->shots == 0) { + + init_text_scale(cnt); /* Initialize and validate text_scale */ + if (strcasecmp(cnt->conf.output_pictures, "on") == 0) cnt->new_img = NEWIMG_ON; else if (strcasecmp(cnt->conf.output_pictures, "first") == 0) @@ -2517,6 +2549,9 @@ static void mlp_parmsupdate(struct context *cnt){ cnt->conf.sql_log_timelapse * FTYPE_MPEG_TIMELAPSE; #endif /* defined(HAVE_MYSQL) || defined(HAVE_PGSQL) || defined(HAVE_SQLITE3) */ + + + } } diff --git a/motion.h b/motion.h index ad83355f..34b15364 100644 --- a/motion.h +++ b/motion.h @@ -305,9 +305,9 @@ struct image_data { /* date/time drawing, draw.c */ int draw_text(unsigned char *image, - unsigned int width, unsigned int height, - unsigned int startx, unsigned int starty, - const char *text, unsigned int factor); + int width, int height, + int startx, int starty, + const char *text, int factor); int initialize_chars(void); struct images { @@ -418,6 +418,7 @@ struct context { int diffs_last[THRESHOLD_TUNE_LENGTH]; int smartmask_speed; + /* Commands to the motion thread */ volatile unsigned int snapshot; /* Make a snapshot */ volatile unsigned int makemovie; /* End a movie */ @@ -436,10 +437,10 @@ struct context { int prev_event; unsigned long long database_event_id; unsigned int lightswitch_framecounter; - char text_event_string[PATH_MAX]; /* The text for conv. spec. %C - - we assume PATH_MAX normally 4096 characters is fine */ - int postcap; /* downcounter, frames left to to send post event */ + char text_event_string[PATH_MAX]; /* The text for conv. spec. %C - */ + int text_scale; + int postcap; /* downcounter, frames left to to send post event */ int shots; unsigned int detecting_motion; struct tm *currenttime_tm;