Use ctzll + new font format for improving drawing speed
This commit is contained in:
parent
6542072334
commit
528699f942
Binary file not shown.
|
@ -4,7 +4,7 @@
|
||||||
configure_file(zm_config_data.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config_data.h" @ONLY)
|
configure_file(zm_config_data.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config_data.h" @ONLY)
|
||||||
|
|
||||||
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
|
||||||
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_font.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
|
||||||
|
|
||||||
|
|
||||||
# A fix for cmake recompiling the source files for every target.
|
# A fix for cmake recompiling the source files for every target.
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "zm.h"
|
||||||
|
#include "zm_font.h"
|
||||||
|
#include "zm_utils.h"
|
||||||
|
|
||||||
|
int ZmFont::ReadFontFile( const std::string &loc ) {
|
||||||
|
|
||||||
|
FILE *f = fopen(loc.c_str(), "rb");
|
||||||
|
if( !f ) return -1; // FILE NOT FOUND
|
||||||
|
|
||||||
|
font = (ZMFONT*)malloc(sizeof(ZMFONT));
|
||||||
|
if(!font)
|
||||||
|
return -1;
|
||||||
|
fread(&font[0], 1, 8 + (sizeof(ZMFONT_BH) * 4), f);
|
||||||
|
// Todo Check magic
|
||||||
|
datasize = (font->header[3].idx * sizeof(uint64_t))+ (font->header[3].charHeight * font->header[3].numberofCodePoints * sizeof(uint64_t));
|
||||||
|
font->data = (uint64_t*)malloc(datasize);
|
||||||
|
fread(&font->data[0], 1, datasize, f);
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *ZmFont::GetBitmapDataForSize( const unsigned int size, uint16_t &charWidth, uint16_t &charHeight ) {
|
||||||
|
charWidth = font->header[size - 1].charWidth;
|
||||||
|
charHeight = font->header[size - 1].charHeight;
|
||||||
|
return &font->data[font->header[size - 1].idx];
|
||||||
|
}
|
3368
src/zm_font.h
3368
src/zm_font.h
File diff suppressed because it is too large
Load Diff
134
src/zm_image.cpp
134
src/zm_image.cpp
|
@ -78,6 +78,9 @@ static deinterlace_4field_fptr_t fptr_deinterlace_4field_gray8;
|
||||||
/* Pointer to image buffer memory copy function */
|
/* Pointer to image buffer memory copy function */
|
||||||
imgbufcpy_fptr_t fptr_imgbufcpy;
|
imgbufcpy_fptr_t fptr_imgbufcpy;
|
||||||
|
|
||||||
|
/* Font */
|
||||||
|
static ZmFont font;
|
||||||
|
|
||||||
void Image::update_function_pointers() {
|
void Image::update_function_pointers() {
|
||||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||||
if ( pixels % 16 || pixels % 12 ) {
|
if ( pixels % 16 || pixels % 12 ) {
|
||||||
|
@ -485,6 +488,11 @@ void Image::Initialise() {
|
||||||
g_u_table = g_u_table_global;
|
g_u_table = g_u_table_global;
|
||||||
b_u_table = b_u_table_global;
|
b_u_table = b_u_table_global;
|
||||||
|
|
||||||
|
Warning("Going to read font file");
|
||||||
|
if ( font.ReadFontFile("/ZoneMinder/fonts/default.zmfnt") < 0)
|
||||||
|
Panic("Invalid font location.");
|
||||||
|
Warning("Font file read");
|
||||||
|
|
||||||
initialised = true;
|
initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1869,8 +1877,11 @@ const Coord Image::centreCoord( const char *text, int size=1 ) const {
|
||||||
line = text+index;
|
line = text+index;
|
||||||
line_no++;
|
line_no++;
|
||||||
}
|
}
|
||||||
int x = (width - (max_line_len * ZM_CHAR_WIDTH * size) ) / 2;
|
|
||||||
int y = (height - (line_no * LINE_HEIGHT * size) ) / 2;
|
uint16_t char_width, char_height;
|
||||||
|
font.GetBitmapDataForSize(size, char_width, char_height);
|
||||||
|
int x = (width - (max_line_len * char_width )) / 2;
|
||||||
|
int y = (height - (line_no * char_height) ) / 2;
|
||||||
return Coord(x, y);
|
return Coord(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1916,7 +1927,10 @@ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
/* RGB32 compatible: complete */
|
||||||
void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour )
|
/* Bitmap decoding trick has been adopted from here:
|
||||||
|
https://lemire.me/blog/2018/02/21/iterating-over-set-bits-quickly/
|
||||||
|
*/
|
||||||
|
__attribute__ ((optimize(3))) void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour )
|
||||||
{
|
{
|
||||||
strncpy(text, p_text, sizeof(text)-1);
|
strncpy(text, p_text, sizeof(text)-1);
|
||||||
|
|
||||||
|
@ -1931,7 +1945,6 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour);
|
const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour);
|
||||||
const uint8_t fg_bw_col = fg_colour & 0xff;
|
const uint8_t fg_bw_col = fg_colour & 0xff;
|
||||||
const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder);
|
const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder);
|
||||||
const bool fg_trans = (fg_colour == RGB_TRANSPARENT);
|
|
||||||
|
|
||||||
const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour);
|
const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour);
|
||||||
const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour);
|
const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour);
|
||||||
|
@ -1939,22 +1952,20 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
const uint8_t bg_bw_col = bg_colour & 0xff;
|
const uint8_t bg_bw_col = bg_colour & 0xff;
|
||||||
const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder);
|
const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder);
|
||||||
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
const bool bg_trans = (bg_colour == RGB_TRANSPARENT);
|
||||||
|
uint16_t char_width = 0, char_height = 0;
|
||||||
int zm_text_bitmask = 0x80;
|
uint64_t *fontbitmap = font.GetBitmapDataForSize(size, char_width, char_height);
|
||||||
if ( size == 2 )
|
|
||||||
zm_text_bitmask = 0x8000;
|
|
||||||
|
|
||||||
while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) {
|
while ( (index < text_len) && (line_len = strcspn(line, "\n")) ) {
|
||||||
|
|
||||||
unsigned int line_width = line_len * ZM_CHAR_WIDTH * size;
|
unsigned int line_width = line_len * char_width;
|
||||||
|
|
||||||
unsigned int lo_line_x = coord.X();
|
unsigned int lo_line_x = coord.X();
|
||||||
unsigned int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT * size);
|
unsigned int lo_line_y = coord.Y() + (line_no * char_height);
|
||||||
|
|
||||||
unsigned int min_line_x = 0;
|
unsigned int min_line_x = 0;
|
||||||
unsigned int max_line_x = width - line_width;
|
unsigned int max_line_x = width - line_width;
|
||||||
unsigned int min_line_y = 0;
|
unsigned int min_line_y = 0;
|
||||||
unsigned int max_line_y = height - (LINE_HEIGHT * size);
|
unsigned int max_line_y = height - char_height;
|
||||||
|
|
||||||
if ( lo_line_x > max_line_x )
|
if ( lo_line_x > max_line_x )
|
||||||
lo_line_x = max_line_x;
|
lo_line_x = max_line_x;
|
||||||
|
@ -1966,7 +1977,7 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
lo_line_y = min_line_y;
|
lo_line_y = min_line_y;
|
||||||
|
|
||||||
unsigned int hi_line_x = lo_line_x + line_width;
|
unsigned int hi_line_x = lo_line_x + line_width;
|
||||||
unsigned int hi_line_y = lo_line_y + (LINE_HEIGHT * size);
|
unsigned int hi_line_y = lo_line_y + char_height;
|
||||||
|
|
||||||
// Clip anything that runs off the right of the screen
|
// Clip anything that runs off the right of the screen
|
||||||
if ( hi_line_x > width )
|
if ( hi_line_x > width )
|
||||||
|
@ -1976,99 +1987,70 @@ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int
|
||||||
|
|
||||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||||
unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x];
|
unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += width ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += width ) {
|
||||||
unsigned char *temp_ptr = ptr;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
uint64_t f = fontbitmap[(line[c] * char_height) + r];
|
||||||
} else {
|
if( !bg_trans ) memset(temp_ptr, bg_bw_col, char_width);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
while(f != 0)
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
{
|
||||||
continue;
|
unsigned long long t = f & -f;
|
||||||
}
|
int idx = char_width - __builtin_ctzll(f>>2);
|
||||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
*(temp_ptr + idx) = fg_bw_col;
|
||||||
}
|
f ^= t;
|
||||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
|
||||||
if ( !fg_trans )
|
|
||||||
*temp_ptr = fg_bw_col;
|
|
||||||
} else if ( !bg_trans ) {
|
|
||||||
*temp_ptr = bg_bw_col;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
temp_ptr += char_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||||
unsigned int wc = width * colours;
|
unsigned int wc = width * colours;
|
||||||
|
|
||||||
unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours];
|
unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||||
unsigned char *temp_ptr = ptr;
|
unsigned char *temp_ptr = ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
uint64_t f = fontbitmap[(line[c] * char_height) + r];
|
||||||
} else {
|
if( !bg_trans ) memset(temp_ptr, 0x0, char_width * colours);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
while( f != 0 )
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
{
|
||||||
continue;
|
uint64_t t = f & -f;
|
||||||
}
|
int idx = char_width - __builtin_ctzll(f >> 2);
|
||||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
RED_PTR_RGBA((temp_ptr + (idx*3))) = fg_r_col;
|
||||||
}
|
GREEN_PTR_RGBA((temp_ptr + (idx*3))) = fg_g_col;
|
||||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) {
|
BLUE_PTR_RGBA((temp_ptr + (idx*3))) = fg_b_col;
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
f ^= t;
|
||||||
if ( !fg_trans ) {
|
|
||||||
RED_PTR_RGBA(temp_ptr) = fg_r_col;
|
|
||||||
GREEN_PTR_RGBA(temp_ptr) = fg_g_col;
|
|
||||||
BLUE_PTR_RGBA(temp_ptr) = fg_b_col;
|
|
||||||
}
|
|
||||||
} else if ( !bg_trans ) {
|
|
||||||
RED_PTR_RGBA(temp_ptr) = bg_r_col;
|
|
||||||
GREEN_PTR_RGBA(temp_ptr) = bg_g_col;
|
|
||||||
BLUE_PTR_RGBA(temp_ptr) = bg_b_col;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
temp_ptr += char_width * colours;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
} else if ( colours == ZM_COLOUR_RGB32 ) {
|
||||||
unsigned int wc = width * colours;
|
unsigned int wc = width * colours;
|
||||||
|
|
||||||
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x) << 2];
|
uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x) << 2];
|
||||||
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (ZM_CHAR_HEIGHT * size); y++, r++, ptr += wc ) {
|
for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < char_height; y++, r++, ptr += wc ) {
|
||||||
Rgb* temp_ptr = (Rgb*)ptr;
|
Rgb* temp_ptr = (Rgb*)ptr;
|
||||||
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) {
|
||||||
int f;
|
if ( line[c] > 0xFF ) {
|
||||||
if ( size == 2 ) {
|
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT * size) + r > sizeof(bigfontdata) ) {
|
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
Warning("Unsupported character %c in %s", line[c], line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f = bigfontdata[(line[c] * ZM_CHAR_HEIGHT * size) + r];
|
uint64_t f = fontbitmap[(line[c] * char_height) + r];
|
||||||
} else {
|
if( !bg_trans ) memset((uint8_t *)temp_ptr, bg_rgb_col, char_width * colours);
|
||||||
if ( (line[c] * ZM_CHAR_HEIGHT) + r > sizeof(fontdata) ) {
|
while( f != 0 )
|
||||||
Warning("Unsupported character %c in %s", line[c], line);
|
{
|
||||||
continue;
|
uint64_t t = f & -f;
|
||||||
}
|
int idx = char_width - __builtin_ctzll(f >> 2);
|
||||||
f = fontdata[(line[c] * ZM_CHAR_HEIGHT) + r];
|
*(temp_ptr + idx) = fg_rgb_col;
|
||||||
}
|
f ^= t;
|
||||||
for ( unsigned int i = 0; i < (ZM_CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) {
|
|
||||||
if ( f & (zm_text_bitmask >> i) ) {
|
|
||||||
if ( !fg_trans ) {
|
|
||||||
*temp_ptr = fg_rgb_col;
|
|
||||||
}
|
|
||||||
} else if ( !bg_trans ) {
|
|
||||||
*temp_ptr = bg_rgb_col;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
temp_ptr += char_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,8 +369,10 @@ $fastblendopts_alarm = array(
|
||||||
);
|
);
|
||||||
|
|
||||||
$label_size = array(
|
$label_size = array(
|
||||||
1 => translate('Default'),
|
1 => translate('Small'),
|
||||||
2 => translate('Large'),
|
2 => translate('Default'),
|
||||||
|
3 => translate('Large'),
|
||||||
|
4 => translate('Extra Large'),
|
||||||
);
|
);
|
||||||
|
|
||||||
$codecs = array(
|
$codecs = array(
|
||||||
|
|
Loading…
Reference in New Issue