From 945b535fca5fbe5c241248bb817ac474ec527c7d Mon Sep 17 00:00:00 2001 From: stan Date: Mon, 16 Sep 2002 09:19:24 +0000 Subject: [PATCH] Initial revision git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2 e3e1d417-86f3-4887-817a-d78f3d33393f --- Makefile | 39 + src/font_6x11.h | 3337 +++++++++++++++++++++++++++++++++++++++++++++++ src/jinclude.h | 91 ++ src/jmemdst.c | 133 ++ src/zm.cpp | 1891 +++++++++++++++++++++++++++ src/zm.h | 623 +++++++++ src/zma.cpp | 69 + src/zmc.cpp | 71 + src/zmcfg.h.z | 5 + src/zmdbg.c | 568 ++++++++ src/zmdbg.h | 128 ++ src/zms.cpp | 73 ++ src/zmu.cpp | 138 ++ web/zm.php | 873 +++++++++++++ 14 files changed, 8039 insertions(+) create mode 100644 Makefile create mode 100644 src/font_6x11.h create mode 100644 src/jinclude.h create mode 100644 src/jmemdst.c create mode 100644 src/zm.cpp create mode 100644 src/zm.h create mode 100644 src/zma.cpp create mode 100644 src/zmc.cpp create mode 100644 src/zmcfg.h.z create mode 100644 src/zmdbg.c create mode 100644 src/zmdbg.h create mode 100644 src/zms.cpp create mode 100644 src/zmu.cpp create mode 100644 web/zm.php diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..f72b67524 --- /dev/null +++ b/Makefile @@ -0,0 +1,39 @@ +all: zmc zma zms zmu + +FLAGS=-g -I/usr/local/include +FLAGS=-O3 -I/usr/local/include +XLIBS= -L. -lmpatrol -lbfd -liberty +XLIBS= + +zmdbg.o: zmdbg.c zmdbg.h + gcc -c $(FLAGS) $< + +jmemdst.o: jmemdst.c + gcc -c $(FLAGS) $< + +zm.o: zm.cpp zm.h zmcfg.h zmdbg.h + g++ -c $(FLAGS) $< + +zmc.o: zmc.cpp zm.h zmcfg.h zmdbg.h + g++ -c $(FLAGS) $< + +zma.o: zma.cpp zm.h zmcfg.h zmdbg.h + g++ -c $(FLAGS) $< + +zms.o: zms.cpp zm.h zmcfg.h zmdbg.h + g++ -c $(FLAGS) $< + +zmu.o: zmu.cpp zm.h zmcfg.h zmdbg.h + g++ -c $(FLAGS) $< + +zmc: zmc.o zm.o zmdbg.o jmemdst.o + g++ $(FLAGS) -Wall -o zmc zmc.o zm.o zmdbg.o jmemdst.o -L/usr/lib/mysql -lmysqlclient -lpthread -ljpeg -ldl -lz -Wl,-E $(XLIBS) + +zma: zma.o zm.o zmdbg.o jmemdst.o + g++ $(FLAGS) -Wall -o zma zma.o zm.o zmdbg.o jmemdst.o -L/usr/lib/mysql -lmysqlclient -lpthread -ljpeg -ldl -lz -Wl,-E $(XLIBS) + +zms: zms.o zm.o zmdbg.o jmemdst.o + g++ $(FLAGS) -Wall -o zms zms.o zm.o zmdbg.o jmemdst.o -L/usr/lib/mysql -lmysqlclient -lpthread -ljpeg -ldl -lz -Wl,-E $(XLIBS) + +zmu: zmu.o zm.o zmdbg.o jmemdst.o + g++ $(FLAGS) -Wall -o zmu zmu.o zm.o zmdbg.o jmemdst.o -L/usr/lib/mysql -lmysqlclient -lpthread -ljpeg -ldl -lz -Wl,-E $(XLIBS) diff --git a/src/font_6x11.h b/src/font_6x11.h new file mode 100644 index 000000000..844ff4f1e --- /dev/null +++ b/src/font_6x11.h @@ -0,0 +1,3337 @@ +/**********************************************/ +/* */ +/* Font file generated by rthelen */ +/* */ +/**********************************************/ + +static unsigned char fontdata[] = { + + /* 0 0x00 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^G' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^H' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 9 0x09 '^J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^K' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 11 0x0b '^L' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^M' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^O' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^P' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^Q' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^S' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^U' */ + 0x18, /* 000 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x78, /* 0 000 */ + 0x78, /* 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^V' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^W' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^X' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^Y' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Z' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^[' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^\' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^]' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^^' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^_' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^`' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x38, /* 00 000 */ + 0x14, /* 000 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x58, /* 0 0 000 */ + 0x28, /* 00 0 000 */ + 0x34, /* 00 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x18, /* 000 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x28, /* 00 0 000 */ + 0x48, /* 0 00 000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x74, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x60, /* 0 00000 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x02, /* 000000 0 */ + 0x02, /* 000000 0 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x70, /* 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '^?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '\200' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '\201' */ + 0x28, /* 00 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '\202' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '\203' */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '\204' */ + 0x58, /* 0 0 000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '\205' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '\206' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '\207' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 '\210' */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '\211' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '\212' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '\213' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '\214' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '\215' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '\216' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '\217' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '\220' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '\221' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '\222' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '\223' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '\224' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '\225' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '\226' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '\227' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '\230' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '\231' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '\232' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '\233' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '\234' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '\235' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '\236' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f '\237' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '\240' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '\241' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '\242' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '\243' */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x40, /* 0 000000 */ + 0x70, /* 0 0000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '\244' */ + 0x44, /* 0 000 00 */ + 0x24, /* 00 00 00 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x14, /* 000 0 00 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '\245' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '\246' */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x3c, /* 00 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '\247' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x58, /* 0 0 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '\250' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '\251' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x34, /* 00 0 00 */ + 0x44, /* 0 000 00 */ + 0x34, /* 00 0 00 */ + 0x08, /* 0000 000 */ + 0x70, /* 0 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '\252' */ + 0x00, /* 00000000 */ + 0x7a, /* 0 0 0 */ + 0x2e, /* 00 0 0 */ + 0x2e, /* 00 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '\253' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '\254' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '\255' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '\256' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x78, /* 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x5c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '\257' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '\260' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 177 0xb1 '\261' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 178 0xb2 '\262' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 179 0xb3 '\263' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 180 0xb4 '\264' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 181 0xb5 '\265' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x74, /* 0 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 182 0xb6 '\266' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x14, /* 000 0 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 183 0xb7 '\267' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x24, /* 00 00 00 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x24, /* 00 00 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 184 0xb8 '\270' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 185 0xb9 '\271' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 186 0xba '\272' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 187 0xbb '\273' */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 188 0xbc '\274' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '\275' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '\276' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '\277' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 192 0xc0 '\300' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '\301' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '\302' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 195 0xc3 '\303' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 196 0xc4 '\304' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '\305' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 198 0xc6 '\306' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 199 0xc7 '\307' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 200 0xc8 '\310' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '\311' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 202 0xca '\312' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '\313' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 204 0xcc '\314' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 205 0xcd '\315' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '\316' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x58, /* 0 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 207 0xcf '\317' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x2c, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '\320' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '\321' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 210 0xd2 '\322' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 211 0xd3 '\323' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '\324' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '\325' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 214 0xd6 '\326' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 215 0xd7 '\327' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 216 0xd8 '\330' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 217 0xd9 '\331' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '\332' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 219 0xdb '\333' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 220 0xdc '\334' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 221 0xdd '\335' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 222 0xde '\336' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 223 0xdf '\337' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '\340' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '\341' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '\342' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '\343' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '\344' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '\345' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '\346' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 '\347' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '\350' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 '\351' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '\352' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '\353' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec '\354' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '\355' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee '\356' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef '\357' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '\360' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '\361' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '\362' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '\363' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '\364' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 245 0xf5 '\365' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 '\366' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '\367' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '\370' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '\371' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '\372' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '\373' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc '\374' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '\375' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '\376' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '\377' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/src/jinclude.h b/src/jinclude.h new file mode 100644 index 000000000..0a4f15146 --- /dev/null +++ b/src/jinclude.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/src/jmemdst.c b/src/jmemdst.c new file mode 100644 index 000000000..2481913e2 --- /dev/null +++ b/src/jmemdst.c @@ -0,0 +1,133 @@ +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data destination object for memory */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + JOCTET *outbuffer; /* target buffer */ + int *outbuffer_size; + JOCTET *buffer; /* start of buffer */ +} mem_destination_mgr; + +typedef mem_destination_mgr * mem_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +static void +init_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + *(dest->outbuffer_size) = 0; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +static boolean +empty_output_buffer (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, OUTPUT_BUF_SIZE ); + *(dest->outbuffer_size) += OUTPUT_BUF_SIZE; + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +static void +term_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + if (datacount > 0) { + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, datacount ); + *(dest->outbuffer_size) += datacount; + } +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +void +jpeg_mem_dest (j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size ) +{ + mem_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(mem_destination_mgr)); + } + + dest = (mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outbuffer = outbuffer; + dest->outbuffer_size = outbuffer_size; +} diff --git a/src/zm.cpp b/src/zm.cpp new file mode 100644 index 000000000..023122f79 --- /dev/null +++ b/src/zm.cpp @@ -0,0 +1,1891 @@ +#include "zm.h" + +MYSQL dbconn; + +void Zone::Setup( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs ) +{ + id = p_id; + label = new char[strlen(p_label)+1]; + strcpy( label, p_label ); + type = p_type; + limits = p_limits; + alarm_rgb = p_alarm_rgb; + alarm_threshold = p_alarm_threshold; + min_alarm_pixels = p_min_alarm_pixels; + max_alarm_pixels = p_max_alarm_pixels; + filter_box = p_filter_box; + min_filter_pixels = p_min_filter_pixels; + max_filter_pixels = p_max_filter_pixels; + min_blob_pixels = p_min_blob_pixels; + max_blob_pixels = p_max_blob_pixels; + min_blobs = p_min_blobs; + max_blobs = p_max_blobs; + + Info(( "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, AT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d\n", id, label, type, limits.Width(), limits.Height(), alarm_rgb, alarm_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs )); + + alarmed = false; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blobs = 0; + image = 0; + score = 0; +} + +Zone::~Zone() +{ + delete[] label; + delete image; +} + +int Zone::Load( int monitor_id, int width, int height, Zone **&zones ) +{ + static char sql[256]; + sprintf( sql, "select Id,Name,Type+0,Units,LoX,LoY,HiX,HiY,AlarmRGB,AlarmThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs from Zones where MonitorId = %d order by Type, Id", monitor_id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't run query: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error(( "Can't use query result: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + int n_zones = mysql_num_rows( result ); + Info(( "Got %d zones for monitor %d\n", n_zones, monitor_id )); + delete[] zones; + zones = new Zone *[n_zones]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int Id = atoi(dbrow[0]); + const char *Name = dbrow[1]; + int Type = atoi(dbrow[2]); + const char *Units = dbrow[3]; + int LoX = atoi(dbrow[4]); + int LoY = atoi(dbrow[5]); + int HiX = atoi(dbrow[6]); + int HiY = atoi(dbrow[7]); + int AlarmRGB = dbrow[8]?atoi(dbrow[8]):0; + int AlarmThreshold = dbrow[9]?atoi(dbrow[9]):0; + int MinAlarmPixels = dbrow[10]?atoi(dbrow[10]):0; + int MaxAlarmPixels = dbrow[11]?atoi(dbrow[11]):0; + int FilterX = dbrow[12]?atoi(dbrow[12]):0; + int FilterY = dbrow[13]?atoi(dbrow[13]):0; + int MinFilterPixels = dbrow[14]?atoi(dbrow[14]):0; + int MaxFilterPixels = dbrow[15]?atoi(dbrow[15]):0; + int MinBlobPixels = dbrow[16]?atoi(dbrow[16]):0; + int MaxBlobPixels = dbrow[17]?atoi(dbrow[17]):0; + int MinBlobs = dbrow[18]?atoi(dbrow[18]):0; + int MaxBlobs = dbrow[19]?atoi(dbrow[19]):0; + + if ( !strcmp( Units, "Percent" ) ) + { + LoX = (LoX*(width-1))/100; + LoY = (LoY*(height-1))/100; + HiX = (HiX*(width-1))/100; + HiY = (HiY*(height-1))/100; + MinAlarmPixels = (MinAlarmPixels*width*height)/100; + MaxAlarmPixels = (MaxAlarmPixels*width*height)/100; + MinFilterPixels = (MinFilterPixels*width*height)/100; + MaxFilterPixels = (MaxFilterPixels*width*height)/100; + MinBlobPixels = (MinBlobPixels*width*height)/100; + MaxBlobPixels = (MaxBlobPixels*width*height)/100; + } + + if ( atoi(dbrow[2]) == Zone::INACTIVE ) + { + zones[i] = new Zone( Id, Name, Box( LoX, LoY, HiX, HiY ) ); + } + else + { + zones[i] = new Zone( Id, Name, (Zone::ZoneType)Type, Box( LoX, LoY, HiX, HiY ), AlarmRGB, AlarmThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs ); + } + } + if ( mysql_errno( &dbconn ) ) + { + Error(( "Can't fetch row: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + return( n_zones ); +} + +void Image::ReadJpeg( const char *filename ) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + FILE * infile; + if ((infile = fopen(filename, "rb" )) == NULL) + { + Error(( "Can't open %s: %s\n", filename, strerror(errno))); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + + jpeg_read_header(&cinfo, TRUE); + + width = cinfo.image_width; + height = cinfo.image_height; + colours = cinfo.num_components; + size = width*height*colours; + + assert( colours == 1 || colours == 3 ); + buffer = new JSAMPLE[size]; + + jpeg_start_decompress(&cinfo); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = width * colours; /* physical row width in buffer */ + while (cinfo.output_scanline < cinfo.output_height) + { + row_pointer = &buffer[cinfo.output_scanline * row_stride]; + jpeg_read_scanlines(&cinfo, &row_pointer, 1); + } + + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + + fclose( infile ); +} + +void Image::WriteJpeg( const char *filename ) const +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + FILE *outfile; + if ((outfile = fopen(filename, "wb" )) == NULL) + { + Error(( "Can't open %s: %s\n", filename, strerror(errno))); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + cinfo.image_width = width; /* image width and height, in pixels */ + cinfo.image_height = height; + cinfo.input_components = colours; /* # of color components per pixel */ + if ( colours == 1 ) + { + cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ + } + else + { + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + } + jpeg_set_defaults(&cinfo); + cinfo.dct_method = JDCT_FASTEST; + //jpeg_set_quality(&cinfo, 100, false); + jpeg_start_compress(&cinfo, TRUE); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo.image_width * cinfo.input_components; /* physical row width in buffer */ + while (cinfo.next_scanline < cinfo.image_height) + { + row_pointer = &buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + + jpeg_finish_compress(&cinfo); + + jpeg_destroy_compress(&cinfo); + + fclose( outfile ); +} + +void Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + jpeg_mem_dest(&cinfo, outbuffer, outbuffer_size ); + + cinfo.image_width = width; /* image width and height, in pixels */ + cinfo.image_height = height; + cinfo.input_components = colours; /* # of color components per pixel */ + if ( colours == 1 ) + { + cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ + } + else + { + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + } + jpeg_set_defaults(&cinfo); + cinfo.dct_method = JDCT_FASTEST; + //jpeg_set_quality(&cinfo, 100, false); + jpeg_start_compress(&cinfo, TRUE); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo.image_width * cinfo.input_components; /* physical row width in buffer */ + while (cinfo.next_scanline < cinfo.image_height) + { + row_pointer = &buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + + jpeg_finish_compress(&cinfo); + + jpeg_destroy_compress(&cinfo); +} + +void Image::Overlay( const Image &image ) +{ + //assert( width == image.width && height == image.height && colours == image.colours ); + assert( width == image.width && height == image.height ); + + unsigned char *pdest = buffer; + unsigned char *psrc = image.buffer; + + if ( colours == 1 ) + { + if ( image.colours == 1 ) + { + while( pdest < (buffer+size) ) + { + if ( *psrc ) + { + *pdest = *psrc; + } + pdest++; + psrc++; + } + } + else + { + Colourise(); + pdest = buffer; + while( pdest < (buffer+size) ) + { + if ( RED(psrc) || GREEN(psrc) || BLUE(psrc) ) + { + RED(pdest) = RED(psrc); + GREEN(pdest) = GREEN(psrc); + BLUE(pdest) = BLUE(psrc); + } + psrc += 3; + pdest += 3; + } + } + } + else + { + if ( image.colours == 1 ) + { + while( pdest < (buffer+size) ) + { + if ( *psrc ) + { + RED(pdest) = GREEN(pdest) = BLUE(pdest) = *psrc++; + } + pdest += 3; + } + } + else + { + while( pdest < (buffer+size) ) + { + if ( RED(psrc) || GREEN(psrc) || BLUE(psrc) ) + { + RED(pdest) = RED(psrc); + GREEN(pdest) = GREEN(psrc); + BLUE(pdest) = BLUE(psrc); + } + psrc += 3; + pdest += 3; + } + } + } +} + +void Image::Blend( const Image &image, double transparency ) const +{ + assert( width == image.width && height == image.height && colours == image.colours ); + + JSAMPLE *psrc = image.buffer; + JSAMPLE *pdest = buffer; + + while( pdest < (buffer+size) ) + { + *pdest++ = (JSAMPLE)round((*pdest * (1.0-transparency))+(*psrc++ * transparency)); + } +} + +void Image::Blend( const Image &image, int transparency ) const +{ + assert( width == image.width && height == image.height && colours == image.colours ); + + JSAMPLE *psrc = image.buffer; + JSAMPLE *pdest = buffer; + + while( pdest < (buffer+size) ) + { + *pdest++ = (JSAMPLE)(((*pdest * (100-transparency))+(*psrc++ * transparency))/100); + } +} + +Image *Image::Merge( int n_images, Image *images[] ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + assert( width == images[i]->width && height == images[i]->height && colours == images[i]->colours ); + } + + Image *result = new Image( width, height, images[0]->colours ); + int size = result->size; + for ( int i = 0; i < size; i++ ) + { + int total = 0; + JSAMPLE *pdest = result->buffer; + for ( int j = 0; j < n_images; j++ ) + { + JSAMPLE *psrc = images[j]->buffer; + total += *psrc; + psrc++; + } + *pdest = total/n_images; + pdest++; + } + return( result ); +} + +Image *Image::Merge( int n_images, Image *images[], double weight ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + assert( width == images[i]->width && height == images[i]->height && colours == images[i]->colours ); + } + + Image *result = new Image( *images[0] ); + int size = result->size; + double factor = 1.0*weight; + for ( int i = 1; i < n_images; i++ ) + { + JSAMPLE *pdest = result->buffer; + JSAMPLE *psrc = images[i]->buffer; + for ( int j = 0; j < size; j++ ) + { + *pdest = (JSAMPLE)(((*pdest)*(1.0-factor))+((*psrc)*factor)); + pdest++; + psrc++; + } + factor *= weight; + } + return( result ); +} + +Image *Image::Highlight( int n_images, Image *images[], const Rgb threshold, const Rgb ref_colour ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + assert( width == images[i]->width && height == images[i]->height && colours == images[i]->colours ); + } + + const Image *reference = Merge( n_images, images ); + + Image *result = new Image( width, height, images[0]->colours ); + int size = result->size; + for ( int c = 0; c < 3; c++ ) + { + for ( int i = 0; i < size; i++ ) + { + int count = 0; + JSAMPLE *pdest = result->buffer+c; + for ( int j = 0; j < n_images; j++ ) + { + JSAMPLE *psrc = images[j]->buffer+c; + + if ( abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) + { + count++; + } + psrc += 3; + } + *pdest = (count*255)/n_images; + pdest += 3; + } + } + return( result ); +} + +Image *Image::Delta( const Image &image, bool absolute ) const +{ + assert( width == image.width && height == image.height && colours == image.colours ); + + Image *result = new Image( width, height, 1 ); + + typedef JSAMPLE IMAGE[width][height][colours]; + IMAGE &data = reinterpret_cast(*buffer); + IMAGE &image_data = reinterpret_cast(*image.buffer); + IMAGE &diff_data = reinterpret_cast(*result->buffer); + + unsigned char *psrc = buffer; + unsigned char *pref = image.buffer; + unsigned char *pdiff = result->buffer; + + if ( colours == 1 ) + { + if ( absolute ) + { + while( psrc < (buffer+size) ) + { + *pdiff++ = abs( *psrc++ - *pref++ ); + } + } + else + { + while( psrc < (buffer+size) ) + { + *pdiff++ = *psrc++ - *pref++; + } + } + } + else + { + if ( absolute ) + { + while( psrc < (buffer+size) ) + { + int red = abs(*psrc++ - *pref++); + int green = abs(*psrc++ - *pref++); + int blue = abs(*psrc++ - *pref++); + //*pdiff++ = (JSAMPLE)sqrt((red*red + green*green + blue*blue)/3); + *pdiff++ = (JSAMPLE)((red + green + blue)/3); + } + } + else + { + while( psrc < (buffer+size) ) + { + int red = *psrc++ - *pref++; + int green = *psrc++ - *pref++; + int blue = *psrc++ - *pref++; + *pdiff++ = 127+((int(red+green+blue))/(3*2)); + } + } + } + return( result ); +} + +unsigned int Image::CheckAlarms( Zone *zone, const Image *delta_image ) const +{ + bool alarm = false; + unsigned int score = 0; + + delete zone->image; + Image *diff_image = zone->image = new Image( *delta_image ); + + int alarm_pixels = 0; + + int lo_x = zone->limits.Lo().X(); + int lo_y = zone->limits.Lo().Y(); + int hi_x = zone->limits.Hi().X(); + int hi_y = zone->limits.Hi().Y(); + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *pdiff = &diff_image->buffer[(y*diff_image->width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff > zone->alarm_threshold ) + { + *pdiff = WHITE; + alarm_pixels++; + continue; + } + *pdiff = BLACK; + } + } + + //diff_image->WriteJpeg( "diff1.jpg" ); + + if ( !alarm_pixels ) return( false ); + if ( zone->min_alarm_pixels && alarm_pixels < zone->min_alarm_pixels ) return( false ); + if ( zone->max_alarm_pixels && alarm_pixels > zone->max_alarm_pixels ) return( false ); + + int filter_pixels = 0; + + int bx = zone->filter_box.X(); + int by = zone->filter_box.Y(); + int bx1 = bx-1; + int by1 = by-1; + + // Now eliminate all pixels that don't participate in a blob + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *pdiff = &diff_image->buffer[(y*diff_image->width)+lo_x]; + + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + if ( 0 ) + { + int count; + int dx; + // Check participation in an X blob + int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; + int hdx = (x<=(hi_x-bx1))?bx1:hi_x-x; + for ( count = 0, dx = ldx; count < bx && dx <= hdx; dx++ ) + { + count = (*(pdiff+dx) == WHITE)?count+1:0; + } + if ( count < bx ) + { + *pdiff = BLACK; + continue; + } + int dy; + // Check participation in a Y blob + int ldy = (y>=(lo_y+by1))?-by1:lo_y-y; + int hdy = (y<=(hi_y-by1))?by1:hi_y-y; + for ( count = 0, dy = ldy; count < by && dy <= hdy; dy++ ) + { + count = (*(pdiff+(diff_image->width*dy)) == WHITE)?count+1:0; + } + if ( count < by ) + { + *pdiff = BLACK; + continue; + } + filter_pixels++; + } + else + { + // Check participation in an X blob + int ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; + int hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); + int ldy = (y>=(lo_y+by1))?-by1:lo_y-y; + int hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); + bool blob = false; + for ( int dy = ldy; !blob && dy <= hdy; dy++ ) + { + for ( int dx = ldx; !blob && dx <= hdx; dx++ ) + { + blob = true; + for ( int dy2 = 0; blob && dy2 < by; dy2++ ) + { + for ( int dx2 = 0; blob && dx2 < bx; dx2++ ) + { + unsigned char *cpdiff = &diff_image->buffer[((y+dy+dy2)*diff_image->width)+x+dx+dx2]; + + if ( !*cpdiff ) + { + blob = false; + } + + } + } + } + } + if ( !blob ) + { + *pdiff = BLACK; + continue; + } + filter_pixels++; + } + } + } + } + + //diff_image->WriteJpeg( "diff2.jpg" ); + + if ( !filter_pixels ) return( false ); + if ( zone->min_filter_pixels && filter_pixels < zone->min_filter_pixels ) return( false ); + if ( zone->max_filter_pixels && filter_pixels > zone->max_filter_pixels ) return( false ); + + int blobs = 0; + + typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; + BlobStats blob_stats[256]; + memset( blob_stats, 0, sizeof(BlobStats)*256 ); + //printf( "%x\n", diff_image->buffer ); + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *pdiff = &diff_image->buffer[(y*diff_image->width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + //printf( "Got white pixel at %d,%d (%x)\n", x, y, pdiff ); + int lx = x>lo_x?*(pdiff-1):0; + int ly = y>lo_y?*(pdiff-diff_image->width):0; + + if ( lx ) + { + //printf( "Left neighbour is %d\n", lx ); + BlobStats *bsx = &blob_stats[lx]; + + if ( ly ) + { + //printf( "Top neighbour is %d\n", ly ); + BlobStats *bsy = &blob_stats[ly]; + + if ( lx == ly ) + { + //printf( "Matching neighbours, setting to %d\n", lx ); + // Add to the blob from the x side (either side really) + *pdiff = lx; + bsx->count++; + //if ( x < bsx->lo_x ) bsx->lo_x = x; + //if ( y < bsx->lo_y ) bsx->lo_y = y; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( y > bsx->hi_y ) bsx->hi_y = y; + } + else + { + // Amortise blobs + BlobStats *bsm = bsx->count>=bsy->count?bsx:bsy; + BlobStats *bss = bsm==bsx?bsy:bsx; + + //printf( "Different neighbours, setting pixels of %d to %d\n", bss->tag, bsm->tag ); + // Now change all those pixels to the other setting + for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++ ) + { + unsigned char *spdiff = &diff_image->buffer[(sy*diff_image->width)+bss->lo_x]; + for ( int sx = bss->lo_x; sx <= bss->hi_x; sx++, spdiff++ ) + { + //printf( "Pixel at %d,%d (%x) is %d", sx, sy, spdiff, *spdiff ); + if ( *spdiff == bss->tag ) + { + //printf( ", setting" ); + *spdiff = bsm->tag; + } + //printf( "\n" ); + } + } + *pdiff = bsm->tag; + + // Merge the slave blob into the master + bsm->count += bss->count+1; + if ( x > bsm->hi_x ) bsm->hi_x = x; + if ( y > bsm->hi_y ) bsm->hi_y = y; + if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x; + if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y; + if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x; + if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y; + + // Clear out the old blob + bss->tag = 0; + bss->count = 0; + bss->lo_x = 0; + bss->lo_y = 0; + bss->hi_x = 0; + bss->hi_y = 0; + + blobs--; + } + } + else + { + //printf( "Setting to left neighbour %d\n", lx ); + // Add to the blob from the x side + *pdiff = lx; + bsx->count++; + //if ( x < bsx->lo_x ) bsx->lo_x = x; + //if ( y < bsx->lo_y ) bsx->lo_y = y; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( y > bsx->hi_y ) bsx->hi_y = y; + } + } + else + { + if ( ly ) + { + //printf( "Setting to top neighbour %d\n", ly ); + + // Add to the blob from the y side + BlobStats *bsy = &blob_stats[ly]; + + *pdiff = ly; + bsy->count++; + //if ( x < bsy->lo_x ) bsy->lo_x = x; + //if ( y < bsy->lo_y ) bsy->lo_y = y; + if ( x > bsy->hi_x ) bsy->hi_x = x; + if ( y > bsy->hi_y ) bsy->hi_y = y; + } + else + { + // Create a new blob + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( !bs->count ) + { + //printf( "Creating new blob %d\n", i ); + *pdiff = i; + bs->tag = i; + bs->count++; + bs->lo_x = bs->hi_x = x; + bs->lo_y = bs->hi_y = y; + blobs++; + break; + } + } + } + } + + } + } + } + + //diff_image->WriteJpeg( "diff3.jpg" ); + + if ( !blobs ) return( false ); + int blob_pixels = filter_pixels; + + // Now eliminate blobs under the alarm_threshold + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count && ((zone->min_blob_pixels && bs->count < zone->min_blob_pixels) || (zone->max_blob_pixels && bs->count > zone->max_blob_pixels)) ) + { + //Info(( "Eliminating blob %d, %d pixels (%d,%d - %d,%d)\n", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y )); + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + unsigned char *spdiff = &diff_image->buffer[(sy*diff_image->width)+bs->lo_x]; + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + blobs--; + blob_pixels -= bs->count; + + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + } + + if ( !blobs ) return( false ); + if ( zone->min_blobs && blobs < zone->min_blobs ) return( false ); + if ( zone->max_blobs && blobs > zone->max_blobs ) return( false ); + + int alarm_lo_x = hi_x+1; + int alarm_hi_x = lo_x-1; + int alarm_lo_y = hi_y+1; + int alarm_hi_y = lo_y-1; + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x; + if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; + if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; + if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; + } + } + + zone->alarm_blobs = blobs; + zone->alarm_pixels = alarm_pixels; + zone->alarm_filter_pixels = filter_pixels; + zone->alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); + score = zone->score = ((100*blob_pixels)/blobs)/(zone->limits.Size().X()*zone->limits.Size().Y()); + if ( zone->Type() == Zone::INCLUSIVE ) + { + zone->score /= 2; + } + else if ( zone->Type() == Zone::EXCLUSIVE ) + { + zone->score *= 2; + } + //Info(( "%d - %d - %d - %.2f\n", zone->alarm_blobs, zone->alarm_pixels, zone->alarm_filter_pixels, zone->result )); + + // Now outline the changed region + if ( zone->alarm_blobs ) + { + Image *high_image = zone->image = new Image( *diff_image ); + + high_image->Colourise(); + alarm = true; + memset( high_image->buffer, 0, high_image->size ); + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *pdiff = &diff_image->buffer[(y*diff_image->width)+lo_x]; + unsigned char *phigh = &high_image->buffer[3*((y*high_image->width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++, pdiff++, phigh += 3 ) + { + bool edge = false; + if ( *pdiff ) + { + if ( !edge && x > 0 && !*(pdiff-1) ) edge = true; + if ( !edge && x < (diff_image->width-1) && !*(pdiff+1) ) edge = true; + if ( !edge && y > 0 && !*(pdiff-diff_image->width) ) edge = true; + if ( !edge && y < (diff_image->height-1) && !*(pdiff+diff_image->width) ) edge = true; + } + if ( edge ) + { + RED(phigh) = RGB_RED_VAL(zone->alarm_rgb); + GREEN(phigh) = RGB_GREEN_VAL(zone->alarm_rgb); + BLUE(phigh) = RGB_BLUE_VAL(zone->alarm_rgb); + } + } + } + delete diff_image; + //high_image->WriteJpeg( "diff4.jpg" ); + + Info(( "%s: Alarm Pixels: %d, Filter Pixels: %d, Blobs: %d, Score: %d\n", zone->Label(), alarm_pixels, filter_pixels, blobs, score )); + } + return( score ); +} + +unsigned int Image::Compare( const Image &image, int n_zones, Zone *zones[] ) const +{ + bool alarm = false; + unsigned int score = 0; + + if ( n_zones <= 0 ) return( alarm ); + + const Image *delta_image = Delta( image ); + + // Blank out all exclusion zones + unsigned char *psrc = buffer; + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + zone->alarmed = false; + if ( zone->Type() != Zone::INACTIVE ) + { + continue; + } + + int lo_x = zone->limits.Lo().X(); + int lo_y = zone->limits.Lo().Y(); + int hi_x = zone->limits.Hi().X(); + int hi_y = zone->limits.Hi().Y(); + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *pdelta = &delta_image->buffer[(y*delta_image->width)]; + for ( int x = lo_x; x <= hi_x; x++ ) + { + *pdelta++ = BLACK; + } + } + } + + unsigned int zone_score = 0; + + // Find all alarm pixels in active zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( zone->Type() != Zone::ACTIVE ) + { + continue; + } + if ( zone_score = CheckAlarms( zone, delta_image ) ) + { + alarm = true; + score += zone_score; + zone->alarmed = true; + } + } + + if ( alarm ) + { + // Find all alarm pixels in inclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( zone->Type() != Zone::INCLUSIVE ) + { + continue; + } + if ( zone_score = CheckAlarms( zone, delta_image ) ) + { + alarm = true; + score += zone_score; + zone->alarmed = true; + } + } + } + else + { + // Find all alarm pixels in exclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( zone->Type() != Zone::EXCLUSIVE ) + { + continue; + } + if ( zone_score = CheckAlarms( zone, delta_image ) ) + { + alarm = true; + score += zone_score; + zone->alarmed = true; + } + } + } + + delete delta_image; + return( score ); +} + +void Image::Annotate( const char *text, const Coord &coord, const Rgb colour ) +{ + int len = strlen( text ); + int text_x = coord.X(); + int text_y = coord.Y(); + + if ( text_x > width-(len*CHAR_WIDTH) ) + { + text_x = width-(len*CHAR_WIDTH); + } + if ( text_y > height-CHAR_HEIGHT ) + { + text_y = height-CHAR_HEIGHT; + } + for ( int y = text_y; y < (text_y+CHAR_HEIGHT); y++) + { + JSAMPLE *ptr = &buffer[((y*width)+text_x)*3]; + for ( int x = 0; x < len; x++) + { + int f = fontdata[text[x] * CHAR_HEIGHT + (y-text_y)]; + for ( int i = CHAR_WIDTH-1; i >= 0; i--) + { + if (f & (CHAR_START << i)) + { + RED(ptr) = RGB_VAL(colour,0); + GREEN(ptr) = RGB_VAL(colour,1); + BLUE(ptr) = RGB_VAL(colour,2); + } + ptr += colours; + } + } + } +} + +void Image::Annotate( const char *text, const Coord &coord ) +{ + int len = strlen( text ); + int text_x = coord.X(); + int text_y = coord.Y(); + + if ( text_x > width-(len*CHAR_WIDTH) ) + { + text_x = width-(len*CHAR_WIDTH); + } + if ( text_y > height-CHAR_HEIGHT ) + { + text_y = height-CHAR_HEIGHT; + } + for ( int y = text_y; y < (text_y+CHAR_HEIGHT); y++) + { + JSAMPLE *ptr = &buffer[((y*width)+text_x)*colours]; + for ( int x = 0; x < len; x++) + { + int f = fontdata[text[x] * CHAR_HEIGHT + (y-text_y)]; + for ( int i = CHAR_WIDTH-1; i >= 0; i--) + { + if (f & (CHAR_START << i)) + { + if ( colours == 1 ) + { + *ptr++ = WHITE; + continue; + } + else + { + RED(ptr) = GREEN(ptr) = BLUE(ptr) = WHITE; + ptr += 3; + continue; + } + } + else + { + if ( colours == 1 ) + { + *ptr++ = BLACK; + continue; + } + else + { + RED(ptr) = GREEN(ptr) = BLUE(ptr) = BLACK; + ptr += 3; + continue; + } + } + //ptr += colours; + } + } + } +} + +void Image::Timestamp( const char *label, time_t when, const Coord &coord ) +{ + char time_text[64]; + strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) ); + char text[64]; + if ( label ) + { + sprintf( text, "%s - %s", label, time_text ); + Annotate( text, coord ); + } + else + { + Annotate( time_text, coord ); + } +} + +void Image::Colourise() +{ + if ( colours == 1 ) + { + colours = 3; + size = width * height * 3; + JSAMPLE *new_buffer = new JSAMPLE[size]; + + JSAMPLE *psrc = buffer; + JSAMPLE *pdest = new_buffer; + while( pdest < (new_buffer+size) ) + { + RED(pdest) = GREEN(pdest) = BLUE(pdest) = *psrc++; + pdest += 3; + } + delete[] buffer; + buffer = new_buffer; + } +} + +void Image::DeColourise() +{ + if ( colours == 3 ) + { + colours = 1; + size = width * height; + + JSAMPLE *psrc = buffer; + JSAMPLE *pdest = buffer; + while( pdest < (buffer+size) ) + { + *pdest++ = (JSAMPLE)sqrt((RED(psrc) + GREEN(psrc) + BLUE(psrc))/3); + psrc += 3; + } + } +} + +Camera::Camera( int p_id, char *p_name, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture=true ) : id( p_id ), device( p_device ), channel( p_channel ), format( p_format ), width( p_width), height( p_height ), colours( p_colours ), capture( p_capture ) +{ + name = new char[strlen(p_name)+1]; + strcpy( name, p_name ); + if ( !camera_count++ && capture ) + { + Initialise( device, channel, format, width, height, colours ); + + } +} + +Camera::~Camera() +{ + if ( !--camera_count && capture ) + { + Terminate(); + } +} + +void Camera::Initialise( int device, int channel, int format, int width, int height, int colours ) +{ + int m_ret; + char device_path[64]; + + sprintf( device_path, "/dev/video%d", device ); + if( (m_videohandle=open(device_path, O_RDONLY)) <=0 ) + { + Error(( "Failed to open video device %s: %s\n", device_path, strerror(errno) )); + exit(-1); + } + + struct video_window vid_win; + if( !ioctl( m_videohandle, VIDIOCGWIN, &vid_win)) + { + Info(( "X:%d\n", vid_win.x )); + Info(( "Y:%d\n", vid_win.y )); + Info(( "W:%d\n", vid_win.width )); + Info(( "H:%d\n", vid_win.height )); + } + else + { + Error(( "Failed to get window attributes: %s\n", strerror(errno) )); + exit(-1); + } + vid_win.x = 0; + vid_win.y = 0; + vid_win.width = width; + vid_win.height = height; + + if( ioctl( m_videohandle, VIDIOCSWIN, &vid_win ) ) + { + Error(( "Failed to set window attributes: %s\n", strerror(errno) )); + exit(-1); + } + + struct video_picture vid_pic; + if( !ioctl( m_videohandle, VIDIOCGPICT, &vid_pic)) + { + Info(( "P:%d\n", vid_pic.palette )); + Info(( "D:%d\n", vid_pic.depth )); + Info(( "B:%d\n", vid_pic.brightness )); + Info(( "h:%d\n", vid_pic.hue )); + Info(( "Cl:%d\n", vid_pic.colour )); + Info(( "Cn:%d\n", vid_pic.contrast )); + } + else + { + Error(( "Failed to get picture attributes: %s\n", strerror(errno) )); + exit(-1); + } + + if ( colours == 1 ) + { + vid_pic.palette = VIDEO_PALETTE_GREY; + vid_pic.depth = 8; + } + else + { + vid_pic.palette = VIDEO_PALETTE_RGB24; + vid_pic.depth = 24; + } + + if( ioctl( m_videohandle, VIDIOCSPICT, &vid_pic ) ) + { + Error(( "Failed to set picture attributes: %s\n", strerror(errno) )); + exit(-1); + } + if(!ioctl(m_videohandle, VIDIOCGMBUF, &m_vmb)) + { + m_vmm = new video_mmap[m_vmb.frames]; + Info(( "vmb.frames = %d\n", m_vmb.frames )); + Info(( "vmb.size = %d\n", m_vmb.size )); + } + else + { + Error(( "Failed to setup memory: %s\n", strerror(errno) )); + exit(-1); + } + + for(int loop=0; loop < m_vmb.frames; loop++) + { + m_vmm[loop].frame = loop; + m_vmm[loop].width = width; + m_vmm[loop].height = height; + m_vmm[loop].format = (colours==1?VIDEO_PALETTE_GREY:VIDEO_PALETTE_RGB24); + } + + m_buffer = (unsigned char *)mmap(0, m_vmb.size, PROT_READ, MAP_SHARED, m_videohandle,0); + if( !((long)m_buffer > 0) ) + { + Error(( "Could not mmap video: %s", strerror(errno) )); + exit(-1); + } + + struct video_channel vs; + + vs.channel = channel; + //vs.norm = VIDEO_MODE_AUTO; + vs.norm = format; + vs.flags = 0; + vs.type = VIDEO_TYPE_CAMERA; + if(ioctl(m_videohandle, VIDIOCSCHAN, &vs)) + { + Error(( "Failed to set camera source %d: %s\n", channel, strerror(errno) )); + exit(-1); + } + + if( !ioctl( m_videohandle, VIDIOCGWIN, &vid_win)) + { + Info(( "X:%d\n", vid_win.x )); + Info(( "Y:%d\n", vid_win.y )); + Info(( "W:%d\n", vid_win.width )); + Info(( "H:%d\n", vid_win.height )); + } + else + { + Error(( "Failed to get window data: %s\n", strerror(errno) )); + exit(-1); + } + + if( !ioctl( m_videohandle, VIDIOCGPICT, &vid_pic)) + { + Info(( "P:%d\n", vid_pic.palette )); + Info(( "D:%d\n", vid_pic.depth )); + Info(( "B:%d\n", vid_pic.brightness )); + Info(( "h:%d\n", vid_pic.hue )); + Info(( "Cl:%d\n", vid_pic.colour )); + Info(( "Cn:%d\n", vid_pic.contrast )); + } + else + { + Error(( "Failed to get window data: %s\n", strerror(errno) )); + exit(-1); + } +} + +void Camera::Terminate() +{ + munmap((char*)m_buffer, m_vmb.size); + + delete[] m_vmm; + + close(m_videohandle); +} + +int Camera::m_cap_frame = 0; +int Camera::m_sync_frame = 0; +video_mbuf Camera::m_vmb; +video_mmap *Camera::m_vmm; +int Camera::m_videohandle; +unsigned char *Camera::m_buffer=0; +int Camera::camera_count = 0; + +Event::Event( Monitor *p_monitor, time_t p_start_time ) : monitor( p_monitor ), start_time( p_start_time ) +{ + static char sql[256]; + sprintf( sql, "insert into Events set MonitorId=%d, Name='Event', StartTime=from_unixtime(%d)", monitor->Id(), start_time ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't insert event: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + id = mysql_insert_id( &dbconn ); + start_frame_id = 0; + end_frame_id = 0; + end_time = 0; + frames = 0; + alarm_frames = 0; + sprintf( path, "%s/%04d", monitor->GetTimestampPath( 0 ), id ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0777 ) ) + { + Error(( "Can't make %s: %s\n", path, strerror(errno))); + } + } +} + +Event::~Event() +{ + static char sql[256]; + sprintf( sql, "update Events set Name='Event-%d', EndTime = now(), Length = %d, Frames = %d, AlarmFrames = %d where Id=%d", id, (end_time-start_time), frames, alarm_frames, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't update event: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } +} + +void Event::AddFrame( time_t timestamp, const Image *image, const Image *alarm_image, unsigned int score ) +{ + frames++; + + static char event_file[256]; + sprintf( event_file, "%s/capture-%03d.jpg", path, frames ); + image->WriteJpeg( event_file ); + + static char sql[256]; + sprintf( sql, "insert into Frames set EventId=%d, FrameId=%d, AlarmFrame=%d, ImagePath='%s', TimeStamp=from_unixtime(%d), Score=%d", id, frames, alarm_image!=0, event_file, timestamp, score ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't insert frame: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + end_frame_id = mysql_insert_id( &dbconn ); + if ( !start_frame_id ) start_frame_id = end_frame_id; + end_time = timestamp; + if ( !start_time ) start_time = end_time; + + if ( alarm_image ) + { + alarm_frames++; + sprintf( event_file, "%s/analyse-%03d.jpg", path, frames ); + alarm_image->WriteJpeg( event_file ); + } +} + +void Event::StreamEvent( const char *path, int event_id, unsigned long refresh=100, FILE *fd=stdout ) +{ + static char sql[256]; + sprintf( sql, "select Id, EventId, ImagePath, TimeStamp from Frames where EventId = %d order by Id", event_id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't run query: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error(( "Can't use query result: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + fprintf( fd, "Server: ZoneMinder Stream Server\r\n" ); + fprintf( fd, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n" ); + fprintf( fd, "\r\n" ); + fprintf( fd, "--ZoneMinderFrame\n" ); + + int n_frames = mysql_num_rows( result ); + Info(( "Got %d frames\n", n_frames )); + FILE *fdj = NULL; + int n_bytes = 0; + static unsigned char buffer[0x10000]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + char filepath[256]; + sprintf( filepath, "%s/%s", path, dbrow[2] ); + if ( fdj = fopen( filepath, "r" ) ) + { + fprintf( fd, "Content-type: image/jpg\n\n" ); + while ( n_bytes = fread( buffer, 1, sizeof(buffer), fdj ) ) + { + fwrite( buffer, 1, n_bytes, fd ); + } + fprintf( fd, "\n--ZoneMinderFrame\n" ); + fflush( fd ); + fclose( fdj ); + } + else + { + Error(( "Can't open %s: %s", filepath, strerror(errno) )); + } + usleep( refresh*1000 ); + } + if ( mysql_errno( &dbconn ) ) + { + Error(( "Can't fetch row: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); +} + +Monitor::Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture, int p_n_zones, Zone *p_zones[] ) : Camera( p_id, p_name, p_device, p_channel, p_format, p_width, p_height, p_colours, p_capture ), function( (Function)p_function ), image( p_width, p_height, p_colours ), ref_image( p_width, p_height, p_colours ), n_zones( p_n_zones ), zones( p_zones ) +{ + fps = 0.0; + event_count = 0; + image_count = 0; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; + + int shared_images_size = sizeof(SharedImages)+(IMAGE_BUFFER_COUNT*sizeof(time_t))+(IMAGE_BUFFER_COUNT*colours*width*height); + int shmid = shmget( 0xcf00cf00|id, shared_images_size, IPC_CREAT|0777 ); + if ( shmid < 0 ) + { + Error(( "Can't shmget: %s\n", strerror(errno))); + exit( -1 ); + } + unsigned char *shm_ptr = (unsigned char *)shmat( shmid, 0, 0 ); + shared_images = (SharedImages *)shm_ptr; + if ( shared_images < 0 ) + { + Error(( "Can't shmat: %s\n", strerror(errno))); + exit( -1 ); + } + + //if ( shmctl( shmid, IPC_RMID, 0 ) ) + //{ + //Error(( "Can't shmctl: %s\n", strerror(errno))); + //exit( -1 ); + //} + + if ( capture ) + { + memset( shared_images, 0, shared_images_size ); + shared_images->state = IDLE; + shared_images->last_write_index = IMAGE_BUFFER_COUNT; + shared_images->last_read_index = IMAGE_BUFFER_COUNT; + } + shared_images->timestamps = (time_t *)(shm_ptr+sizeof(SharedImages)); + shared_images->images = (unsigned char *)(shm_ptr+sizeof(SharedImages)+(IMAGE_BUFFER_COUNT*sizeof(time_t))); + + image_buffer = new Snapshot[IMAGE_BUFFER_COUNT]; + for ( int i = 0; i < IMAGE_BUFFER_COUNT; i++ ) + { + image_buffer[i].timestamp = &(shared_images->timestamps[i]); + image_buffer[i].image = new Image( width, height, colours, &(shared_images->images[i*colours*width*height]) ); + //Info(( "%d: %x - %x", i, image_buffer[i].image, image_buffer[i].image->buffer )); + //*(image_buffer[i].timestamp) = time( 0 ); + //image_buffer[i].image = new Image( width, height, colours ); + //delete[] image_buffer[i].image->buffer; + //image_buffer[i].image->buffer = &(shared_images->images[i*colours*width*height]); + } + if ( !n_zones ) + { + n_zones = 1; + zones = new Zone *[1]; + zones[0] = new Zone( 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED ); + } + start_time = last_fps_time = time( 0 ); + + event = 0; + + Info(( "Monitor %s has function %d\n", name, function )); + + if ( !capture ) + { + ref_image.Assign( width, height, colours, image_buffer[shared_images->last_write_index].image->buffer ); + } + + //if ( capture ) + //{ + //Camera::Capture( ref_image ); + //} +} + +Monitor::~Monitor() +{ + delete[] image_buffer; +} + +Monitor::State Monitor::GetState() const +{ + return( shared_images->state ); +} + +int Monitor::GetImage( int index ) const +{ + if ( index < 0 || index > IMAGE_BUFFER_COUNT ) + { + index = shared_images->last_write_index; + } + Snapshot *snap = &image_buffer[index]; + Image *image = snap->image; + image->WriteJpeg( "zmu.jpg" ); + return( 0 ); +} + +time_t Monitor::GetTimestamp( int index ) const +{ + if ( index < 0 || index > IMAGE_BUFFER_COUNT ) + { + index = shared_images->last_write_index; + } + Snapshot *snap = &image_buffer[index]; + return( *(snap->timestamp) ); +} + +unsigned int Monitor::GetLastReadIndex() const +{ + return( shared_images->last_read_index ); +} + +unsigned int Monitor::GetLastWriteIndex() const +{ + return( shared_images->last_write_index ); +} + +double Monitor::GetFPS() const +{ + int index1 = shared_images->last_write_index; + int index2 = (index1+1)%IMAGE_BUFFER_COUNT;; + + Snapshot *snap1 = &image_buffer[index1]; + time_t time1 = *(snap1->timestamp); + + Snapshot *snap2 = &image_buffer[index2]; + time_t time2 = *(snap2->timestamp); + + double fps = double(IMAGE_BUFFER_COUNT)/(time1-time2); + + return( fps ); +} + +void Monitor::CheckFunction() +{ + static char sql[256]; + sprintf( sql, "select Function+0 where Id = %d", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't run query: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error(( "Can't use query result: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + function = (Function)atoi(dbrow[0]); + } + if ( mysql_errno( &dbconn ) ) + { + Error(( "Can't fetch row: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + if ( function != ACTIVE ) + { + shared_images->state = state = IDLE; + } +} + +void Monitor::DumpZoneImage() +{ + int index = shared_images->last_write_index; + Snapshot *snap = &image_buffer[index]; + Image *image = snap->image; + + Image zone_image( *image ); + zone_image.Colourise(); + for( int i = 0; i < n_zones; i++ ) + { + unsigned char *psrc = zone_image.buffer; + int lo_x = zones[i]->Limits().Lo().X(); + int lo_y = zones[i]->Limits().Lo().Y(); + int hi_x = zones[i]->Limits().Hi().X(); + int hi_y = zones[i]->Limits().Hi().Y(); + for ( int y = 0; y < zone_image.height; y++ ) + { + for ( int x = 0; x < zone_image.width; x++, psrc += 3 ) + { + if ( ( (x == lo_x || x == hi_x) && (y >= lo_y && y <= hi_y) ) + || ( (y == lo_y || y == hi_y) && (x >= lo_x && x <= hi_x) ) + || ( (x > lo_x && x < hi_x && y > lo_y && y < hi_y) && !(x%2) && !(y%2) ) ) + { + if ( zones[i]->Type() == Zone::ACTIVE ) + { + RED(psrc) = RGB_RED_VAL(RGB_RED); + GREEN(psrc) = RGB_GREEN_VAL(RGB_RED); + BLUE(psrc) = RGB_BLUE_VAL(RGB_RED); + } + else if ( zones[i]->Type() == Zone::INCLUSIVE ) + { + RED(psrc) = RGB_RED_VAL(RGB_GREEN); + GREEN(psrc) = RGB_GREEN_VAL(RGB_GREEN); + BLUE(psrc) = RGB_BLUE_VAL(RGB_GREEN); + } + else if ( zones[i]->Type() == Zone::EXCLUSIVE ) + { + RED(psrc) = RGB_RED_VAL(RGB_BLUE); + GREEN(psrc) = RGB_GREEN_VAL(RGB_BLUE); + BLUE(psrc) = RGB_BLUE_VAL(RGB_BLUE); + } + else + { + RED(psrc) = RGB_RED_VAL(RGB_WHITE); + GREEN(psrc) = RGB_GREEN_VAL(RGB_WHITE); + BLUE(psrc) = RGB_BLUE_VAL(RGB_WHITE); + } + } + } + } + } + char filename[64]; + sprintf( filename, "%s-Zones.jpg", name ); + zone_image.WriteJpeg( filename ); +} + +char *Monitor::GetTimestampPath( time_t now ) +{ + static char path[256]; + sprintf( path, "events/%s", name ); + return( path ); + + static char timestamp[64]; + static char event_path[256]; + + strftime( timestamp, sizeof(timestamp), "%Y%m%d", localtime( &now ) ); + sprintf( event_path, "events/%s/%s", name, timestamp ); + struct stat statbuf; + errno = 0; + stat( event_path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( event_path, 0777 ) ) + { + Error(( "Can't make %s: %s\n", event_path, strerror(errno))); + } + } + strftime( timestamp, sizeof(timestamp), "%H%M%S", localtime( &now ) ); + strcat( event_path, "/" ); + strcat( event_path, timestamp ); + errno = 0; + stat( event_path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( event_path, 0777 ) ) + { + Error(( "Can't make %s: %s\n", event_path, strerror(errno))); + } + } + return( event_path ); +} + +void Monitor::DumpImage( Image *image ) const +{ + if ( image_count && !(image_count%10) ) + { + static char new_filename[64]; + static char filename[64]; + //sprintf( filename, "%s%04d.jpg", name, image_count ); + sprintf( filename, "%s.jpg", name ); + sprintf( new_filename, "%s-new.jpg", name ); + image->WriteJpeg( new_filename ); + rename( new_filename, filename ); + } +} + +void Monitor::Analyse() +{ + if ( shared_images->last_read_index == shared_images->last_write_index ) + { + usleep( 10000 ); + return; + } + + time_t now = time( 0 ); + + if ( image_count && !(image_count%FPS_REPORT_INTERVAL) ) + { + fps = double(FPS_REPORT_INTERVAL)/(now-last_fps_time); + Info(( "%s: %d - Processing at %.2f fps\n", name, image_count, fps )); + last_fps_time = now; + } + + int index = shared_images->last_write_index%IMAGE_BUFFER_COUNT; + Snapshot *snap = &image_buffer[index]; + time_t timestamp = *(snap->timestamp); + Image *image = snap->image; + + unsigned int score = 0; + if ( Ready() ) + { + if ( score = ref_image.Compare( *image, n_zones, zones ) ) + { + if ( state == IDLE ) + { + event = new Event( this, timestamp ); + + Info(( "%s: %03d - Gone into alarm state\n", name, image_count )); + int pre_index = ((index+IMAGE_BUFFER_COUNT)-PRE_EVENT_COUNT)%IMAGE_BUFFER_COUNT; + for ( int i = 0; i < PRE_EVENT_COUNT; i++ ) + { + event->AddFrame( *(image_buffer[pre_index].timestamp), image_buffer[pre_index].image ); + pre_index = (pre_index+1)%IMAGE_BUFFER_COUNT; + } + //event->AddFrame( now, &image ); + } + shared_images->state = state = ALARM; + last_alarm_count = image_count; + } + else + { + if ( state == ALARM ) + { + shared_images->state = state = ALERT; + } + else if ( state == ALERT ) + { + if ( image_count-last_alarm_count > POST_EVENT_COUNT ) + { + Info(( "%s: %03d - Left alarm state (%d) - %d(%d) images\n", name, image_count, event->id, event->frames, event->alarm_frames )); + delete event; + shared_images->state = state = IDLE; + } + } + } + if ( state != IDLE ) + { + if ( state == ALARM ) + { + Image alarm_image( *image ); + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + alarm_image.Overlay( zones[i]->AlarmImage() ); + } + } + event->AddFrame( now, image, &alarm_image, score ); + } + else + { + event->AddFrame( now, image ); + } + } + } + ref_image.Blend( *image, 10 ); + DumpImage( image ); + + shared_images->last_read_index = index%IMAGE_BUFFER_COUNT; + image_count++; +} + +void Monitor::ReloadZones() +{ + Info(( "Reloading zones for monitor %s\n", name )); + for( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + //delete[] zones; + n_zones = Zone::Load( id, width, height, zones ); + DumpZoneImage(); +} + +int Monitor::Load( int device, Monitor **&monitors, bool capture ) +{ + static char sql[256]; + if ( device == -1 ) + { + sprintf( sql, "select Id, Name, Function+0, Device, Channel, Format, Width, Height, Colours, LabelFormat, LabelX, LabelY, WarmUpCount, PreEventCount, PostEventCount from Monitors where Function != 'Disabled'" ); + } + else + { + sprintf( sql, "select Id, Name, Function+0, Device, Channel, Format, Width, Height, Colours, LabelFormat, LabelX, LabelY, WarmUpCount, PreEventCount, PostEventCount from Monitors where Function != 'Disabled' and Device = %d", device ); + } + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't run query: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error(( "Can't use query result: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Info(( "Got %d monitors\n", n_monitors )); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + Zone **zones = 0; + int n_zones = Zone::Load( atoi(dbrow[0]), atoi(dbrow[6]), atoi(dbrow[7]), zones ); + monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), capture, n_zones, zones ); + Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones )); + } + if ( mysql_errno( &dbconn ) ) + { + Error(( "Can't fetch row: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +Monitor *Monitor::Load( int id, bool load_zones ) +{ + static char sql[256]; + sprintf( sql, "select Id, Name, Function+0, Device, Channel, Format, Width, Height, Colours, LabelFormat, LabelX, LabelY, WarmUpCount, PreEventCount, PostEventCount from Monitors where Id = %d", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error(( "Can't run query: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error(( "Can't use query result: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Info(( "Got %d monitors\n", n_monitors )); + Monitor *monitor = 0; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + Zone **zones = 0; + int n_zones = 0; + if ( load_zones ) + { + int n_zones = Zone::Load( atoi(dbrow[0]), atoi(dbrow[6]), atoi(dbrow[7]), zones ); + } + monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), false, n_zones, zones ); + Info(( "Loaded monitor %d(%s), %d zones\n", atoi(dbrow[0]), dbrow[1], n_zones )); + } + if ( mysql_errno( &dbconn ) ) + { + Error(( "Can't fetch row: %s\n", mysql_error( &dbconn ) )); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( monitor ); +} + +void Monitor::StreamImages( unsigned long idle, unsigned long refresh, FILE *fd ) +{ + fprintf( fd, "Server: ZoneMinder Stream Server\r\n" ); + fprintf( fd, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n" ); + fprintf( fd, "\r\n" ); + fprintf( fd, "--ZoneMinderFrame\n" ); + int last_read_index = IMAGE_BUFFER_COUNT; + JOCTET img_buffer[width*height*colours]; + int img_buffer_size = 0; + int loop_count = (idle/refresh)-1; + while ( true ) + { + if ( last_read_index != shared_images->last_write_index ) + { + // Send the next frame + last_read_index = shared_images->last_write_index; + int index = shared_images->last_write_index%IMAGE_BUFFER_COUNT; + //Info(( "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer )); + Snapshot *snap = &image_buffer[index]; + Image *image = snap->image; + image->EncodeJpeg( img_buffer, &img_buffer_size ); + + fprintf( fd, "Content-type: image/jpg\n\n" ); + fwrite( img_buffer, 1, img_buffer_size, fd ); + fprintf( fd, "\n--ZoneMinderFrame\n" ); + fflush( fd ); + } + usleep( refresh*1000 ); + for ( int i = 0; shared_images->state == IDLE && i < loop_count; i++ ) + { + usleep( refresh*1000 ); + } + } +} diff --git a/src/zm.h b/src/zm.h new file mode 100644 index 000000000..416fc23ac --- /dev/null +++ b/src/zm.h @@ -0,0 +1,623 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "font_6x11.h" + +extern "C" +{ +#include + +double round(double); + +void jpeg_mem_dest(j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size ); +} + +extern "C" +{ +#include "zmcfg.h" +#include "zmdbg.h" +} + +typedef unsigned int Rgb; + +#define RED(byte) (*(byte)) +#define GREEN(byte) (*(byte+1)) +#define BLUE(byte) (*(byte+2)) + +#define WHITE 0xff +#define WHITE_R 0xff +#define WHITE_G 0xff +#define WHITE_B 0xff + +#define BLACK 0x00 +#define BLACK_R 0x00 +#define BLACK_G 0x00 +#define BLACK_B 0x00 + +#define RGB_WHITE (0x00ffffff) +#define RGB_BLACK (0x00000000) +#define RGB_RED (0x00ff0000) +#define RGB_GREEN (0x0000ff00) +#define RGB_BLUE (0x000000ff) + +#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff) +#define RGB_RED_VAL(v) (((v)>>16)&0xff) +#define RGB_GREEN_VAL(v) (((v)>>8)&0xff) +#define RGB_BLUE_VAL(v) ((v)&0xff) + +extern MYSQL dbconn; + +class Coord +{ +private: + int x, y; + +public: + inline Coord() : x(0), y(0) + { + } + inline Coord( int p_x, int p_y ) : x(p_x), y(p_y) + { + } + inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y) + { + } + inline int &X() { return( x ); } + inline const int &X() const { return( x ); } + inline int &Y() { return( y ); } + inline const int &Y() const { return( y ); } + + inline static Coord Range( const Coord &coord1, const Coord &coord2 ) + { + Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); + return( result ); + } + + inline bool operator==( const Coord &coord ) + { + return( x == coord.x && y == coord.y ); + } + inline bool operator!=( const Coord &coord ) + { + return( x != coord.x || y != coord.y ); + } + inline bool operator>( const Coord &coord ) + { + return( x > coord.x && y > coord.y ); + } + inline bool operator>=( const Coord &coord ) + { + return( !(operator<(coord)) ); + } + inline bool operator<( const Coord &coord ) + { + return( x < coord.x && y < coord.y ); + } + inline bool operator<=( const Coord &coord ) + { + return( !(operator>(coord)) ); + } + inline Coord &operator+=( const Coord &coord ) + { + x += coord.x; + y += coord.y; + return( *this ); + } + inline Coord &operator-=( const Coord &coord ) + { + x -= coord.x; + y -= coord.y; + return( *this ); + } + + inline friend Coord operator+( const Coord &coord1, const Coord &coord2 ) + { + Coord result( coord1 ); + result += coord2; + return( result ); + } + inline friend Coord operator-( const Coord &coord1, const Coord &coord2 ) + { + Coord result( coord1 ); + result -= coord2; + return( result ); + } +}; + +class Box +{ +private: + Coord lo, hi; + Coord size; + +public: + inline Box() + { + } + inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) + { + } + inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) + { + } + inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) + { + } + inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) + { + } + inline const Coord &Lo() const { return( lo ); } + inline const Coord &Hi() const { return( hi ); } + inline const Coord &Size() const { return( size ); } + inline int Width() const + { + return( size.X() ); + } + inline int Height() const + { + return( size.Y() ); + } + + inline bool Inside( const Coord &coord ) const + { + return( coord.X() >= lo.X() && coord.X() <= hi.X() && coord.Y() >= lo.Y() && coord.Y() <= hi.Y() ); + } +}; + +class Zone +{ +friend class Image; + +public: + typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, INACTIVE } ZoneType; + +protected: + // Inputs + int id; + char *label; + ZoneType type; + Box limits; + Rgb alarm_rgb; + + int alarm_threshold; + int min_alarm_pixels; + int max_alarm_pixels; + + Coord filter_box; + int min_filter_pixels; + int max_filter_pixels; + + int min_blob_pixels; + int max_blob_pixels; + int min_blobs; + int max_blobs; + + // Outputs + bool alarmed; + int alarm_pixels; + int alarm_filter_pixels; + int alarm_blobs; + Box alarm_box; + unsigned int score; + Image *image; + +protected: + void Setup( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs ); + +public: + Zone( int p_id, const char *p_label, ZoneType p_type, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 ) + { + Setup( p_id, p_label, p_type, p_limits, p_alarm_rgb, p_alarm_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs ); + } + Zone( int p_id, const char *p_label, const Box &p_limits, const Rgb p_alarm_rgb, int p_alarm_threshold=15, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0 ) + { + Setup( p_id, p_label, Zone::ACTIVE, p_limits, p_alarm_rgb, p_alarm_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs ); + } + Zone( int p_id, const char *p_label, const Box &p_limits ) + { + Setup( p_id, p_label, Zone::INACTIVE, p_limits, RGB_BLACK, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0 ); + } + +public: + ~Zone(); + inline const char *Label() const + { + return( label ); + } + inline ZoneType Type() const + { + return( type ); + } + inline Image &AlarmImage() const + { + return( *image ); + } + inline const Box &Limits() const { return( limits ); } + inline bool Alarmed() const + { + return( alarmed ); + } + static int Load( int monitor_id, int width, int height, Zone **&zones ); +}; + +class Camera; +class Monitor; + +class Image +{ +friend class Camera; +friend class Monitor; + +protected: + enum { CHAR_HEIGHT=11, CHAR_WIDTH=6, CHAR_START=4 }; + +protected: + int width; + int height; + int colours; + int size; + JSAMPLE *buffer; + bool our_buffer; + +public: + Image( const char *filename ) + { + ReadJpeg( filename ); + our_buffer = true; + } + Image( int p_width, int p_height, int p_colours, JSAMPLE *p_buffer=0 ) + { + width = p_width; + height = p_height; + colours = p_colours; + size = width*height*colours; + if ( !p_buffer ) + { + our_buffer = true; + buffer = new JSAMPLE[size]; + memset( buffer, 0, size ); + } + else + { + our_buffer = false; + buffer = p_buffer; + } + } + Image( const Image &p_image ) + { + width = p_image.width; + height = p_image.height; + colours = p_image.colours; + size = p_image.size; + buffer = new JSAMPLE[size]; + memcpy( buffer, p_image.buffer, size ); + our_buffer = true; + } + ~Image() + { + if ( our_buffer ) + { + delete[] buffer; + } + } + + inline void Assign( int p_width, int p_height, int p_colours, unsigned char *new_buffer ) + { + if ( p_width != width || p_height != height || p_colours != colours ) + { + width = p_width; + height = p_height; + colours = p_colours; + size = width*height*colours; + delete[] buffer; + buffer = new JSAMPLE[size]; + memset( buffer, 0, size ); + } + if ( colours == 1 ) + { + memcpy( buffer, new_buffer, size ); + } + else + { + for ( int i = 0; i < size; i += 3 ) + { + buffer[i] = new_buffer[i+2]; + buffer[i+1] = new_buffer[i+1]; + buffer[i+2] = new_buffer[i]; + } + } + + } + inline Image &operator=( const unsigned char *new_buffer ) + { + memcpy( buffer, new_buffer, size ); + return( *this ); + } + + inline int Width() { return( width ); } + inline int Height() { return( height ); } + + void ReadJpeg( const char *filename ); + void WriteJpeg( const char *filename ) const; + void EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const; + void Overlay( const Image &image ); + void Blend( const Image &image, double transparency=0.1 ) const; + void Blend( const Image &image, int transparency=10 ) const; + static Image *Merge( int n_images, Image *images[] ); + static Image *Merge( int n_images, Image *images[], double weight ); + static Image *Highlight( int n_images, Image *images[], const Rgb threshold=RGB_BLACK, const Rgb ref_colour=RGB_RED ); + Image *Delta( const Image &image, bool absolute=true ) const; + unsigned int CheckAlarms( Zone *zone, const Image *delta_image ) const; + unsigned int Compare( const Image &image, int n_zones, Zone *zones[] ) const; + void Annotate( const char *text, const Coord &coord, const Rgb colour ); + void Annotate( const char *text, const Coord &coord ); + void Timestamp( const char *label, time_t when, const Coord &coord ); + void Colourise(); + void DeColourise(); +}; + +class Camera +{ +friend class Image; + +protected: + int id; + char *name; + int device; + int channel; + int format; + int width; + int height; + int colours; + bool capture; + +protected: + static int m_cap_frame; + static int m_sync_frame; + static video_mbuf m_vmb; + static video_mmap *m_vmm; + static int m_videohandle; + static unsigned char *m_buffer; + static int camera_count; + +public: + Camera( int p_id, char *p_name, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture=true ); + ~Camera(); + inline int Id() const + { + return( id ); + } + inline char *Name() const + { + return( name ); + } + static void Initialise( int device, int channel, int format, int width, int height, int colours ); + void Terminate(); + + inline void PreCapture() + { + //Info(( "%s: Capturing image\n", id )); + + if ( camera_count > 1 ) + { + //Info(( "Switching\n" )); + struct video_channel vs; + + vs.channel = channel; + //vs.norm = VIDEO_MODE_AUTO; + vs.norm = format; + vs.flags = 0; + vs.type = VIDEO_TYPE_CAMERA; + if(ioctl(m_videohandle, VIDIOCSCHAN, &vs)) + { + Error(( "Failed to set camera source %d: %s\n", channel, strerror(errno) )); + } + } + //Info(( "MC:%d\n", m_videohandle )); + if ( ioctl(m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame]) ) + { + Error(( "Capture failure for frame %d: %s\n", m_cap_frame, strerror(errno))); + } + m_cap_frame = (m_cap_frame+1)%m_vmb.frames; + } + inline unsigned char *PostCapture() + { + //Info(( "%s: Capturing image\n", id )); + + if ( ioctl(m_videohandle, VIDIOCSYNC, &m_sync_frame) ) + { + Error(( "Sync failure for frame %d: %s\n", m_sync_frame, strerror(errno))); + } + + unsigned char *buffer = m_buffer+(m_sync_frame*m_vmb.size/m_vmb.frames); + m_sync_frame = (m_sync_frame+1)%m_vmb.frames; + + return( buffer ); + } + inline void PostCapture( Image &image ) + { + //Info(( "%s: Capturing image\n", id )); + + if ( ioctl(m_videohandle, VIDIOCSYNC, &m_sync_frame) ) + { + Error(( "Sync failure for frame %d: %s\n", m_sync_frame, strerror(errno))); + } + + unsigned char *buffer = m_buffer+(m_sync_frame*m_vmb.size/m_vmb.frames); + m_sync_frame = (m_sync_frame+1)%m_vmb.frames; + + image.Assign( width, height, colours, buffer ); + } + inline unsigned char *Capture() + { + PreCapture(); + return( PostCapture() ); + } + inline void Capture( Image &image ) + { + PreCapture(); + return( PostCapture( image ) ); + } +}; + +class Event +{ +friend class Monitor; + +protected: + int id; + Monitor *monitor; + time_t start_time; + time_t end_time; + int start_frame_id; + int end_frame_id; + int frames; + int alarm_frames; + char path[256]; + +public: + Event( Monitor *p_monitor, time_t p_start_time ); + ~Event(); + void AddFrame( time_t timestamp, const Image *image, const Image *alarm_frame=NULL, unsigned int score=0 ); + + static void StreamEvent( const char *path, int event_id, unsigned long refresh=100, FILE *fd=stdout ); +}; + +class Monitor : public Camera +{ +protected: + typedef enum + { + WARMUP_COUNT=25, + PRE_EVENT_COUNT=10, + POST_EVENT_COUNT=10, + IMAGE_BUFFER_COUNT=100, + FPS_REPORT_INTERVAL=200, + }; + typedef enum + { + NONE=1, + PASSIVE, + ACTIVE + } Function; + Function function; + double fps; + Image image; + Image ref_image; + int event_count; + int image_count; + int first_alarm_count; + int last_alarm_count; + int buffer_count; + typedef enum { IDLE, ALARM, ALERT } State; + State state; + int n_zones; + Zone **zones; + Event *event; + time_t start_time; + time_t last_fps_time; + + typedef struct Snapshot + { + time_t *timestamp; + Image *image; + }; + + Snapshot *image_buffer; + + typedef struct + { + State state; + int last_write_index; + int last_read_index; + time_t *timestamps; + unsigned char *images; + } SharedImages; + + SharedImages *shared_images; + +public: + Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_colours, bool p_capture=true, int p_n_zones=0, Zone *p_zones[]=0 ); + ~Monitor(); + + State GetState() const; + int GetImage( int index=-1 ) const; + time_t GetTimestamp( int index=-1 ) const; + unsigned int GetLastReadIndex() const; + unsigned int GetLastWriteIndex() const; + double GetFPS() const; + + void CheckFunction(); + void DumpZoneImage(); + + inline void Capture() + { + PreCapture(); + PostCapture(); + } + inline void PostCapture() + { + Camera::PostCapture( image ); + + time_t now = time( 0 ); + + image.Timestamp( name, now, Coord( 0, 280 ) ); + + int index = image_count%IMAGE_BUFFER_COUNT; + + if ( index == shared_images->last_read_index ) + { + Error(( "Error, buffer overrun at index %d\n", index )); + } + *(image_buffer[index].timestamp) = now; + memcpy( image_buffer[index].image->buffer, image.buffer, image.size ); + //Info(( "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer )); + + shared_images->last_write_index = index; + + image_count++; + + if ( image_count && !(image_count%FPS_REPORT_INTERVAL) ) + { + fps = double(FPS_REPORT_INTERVAL)/(now-last_fps_time); + Info(( "%s: %d - Capturing at %.2f fps\n", name, image_count, fps )); + last_fps_time = now; + } + } + + inline bool Ready() + { + return( function == ACTIVE && image_count > WARMUP_COUNT ); + } + + char *GetTimestampPath( time_t now ); + void DumpImage( Image *image ) const; + void Analyse(); + + void Adjust( double ratio ) + { + ref_image.Blend( image, 0.1 ); + } + + void ReloadZones(); + static int Load( int device, Monitor **&monitors, bool capture=true ); + static Monitor *Load( int id, bool load_zones=false ); + void StreamImages( unsigned long idle=5000, unsigned long refresh=50, FILE *fd=stdout ); +}; diff --git a/src/zma.cpp b/src/zma.cpp new file mode 100644 index 000000000..03d8208c7 --- /dev/null +++ b/src/zma.cpp @@ -0,0 +1,69 @@ +#include "zm.h" + +bool reload = false; + +void hup_handler( int signal ) +{ + reload = true; +} + +void main( int argc, const char *argv[] ) +{ + int device = argv[1]?atoi( argv[1] ):0; + + char dbg_name_string[16]; + sprintf( dbg_name_string, "zma-%d", device ); + dbg_name = dbg_name_string; + + DbgInit(); + + //umask( 0 ); + + if ( !mysql_init( &dbconn ) ) + { + fprintf( stderr, "Can't initialise structure: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( !mysql_connect( &dbconn, "", ZM_DB_USERA, ZM_DB_PASSA ) ) + { + fprintf( stderr, "Can't connect to server: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( mysql_select_db( &dbconn, ZM_DATABASE ) ) + { + fprintf( stderr, "Can't select database: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + Monitor **monitors = 0; + int n_monitors = Monitor::Load( device, monitors, false ); + + Info(( "Warming up" )); + sigset_t block_set; + sigemptyset( &block_set ); + struct sigaction action, old_action; + action.sa_handler = hup_handler; + action.sa_mask = block_set; + action.sa_flags = 0; + sigaction( SIGHUP, &action, &old_action ); + sigaddset( &block_set, SIGHUP ); + while( 1 ) + { + // Process the next image + sigprocmask( SIG_BLOCK, &block_set, 0 ); + for ( int i = 0; i < n_monitors; i++ ) + { + monitors[i]->Analyse(); + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + if ( reload ) + { + for ( int i = 0; i < n_monitors; i++ ) + { + monitors[i]->ReloadZones(); + monitors[i]->CheckFunction(); + } + reload = false; + } + } +} diff --git a/src/zmc.cpp b/src/zmc.cpp new file mode 100644 index 000000000..6a3132590 --- /dev/null +++ b/src/zmc.cpp @@ -0,0 +1,71 @@ +#include "zm.h" + +bool reload = false; + +void hup_handler( int signal ) +{ + reload = true; +} + +void main( int argc, const char *argv[] ) +{ + int device = argv[1]?atoi( argv[1] ):0; + + char dbg_name_string[16]; + sprintf( dbg_name_string, "zmc-%d", device ); + dbg_name = dbg_name_string; + + DbgInit(); + + if ( !mysql_init( &dbconn ) ) + { + fprintf( stderr, "Can't initialise structure: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( !mysql_connect( &dbconn, "", ZM_DB_USERA, ZM_DB_PASSA ) ) + { + fprintf( stderr, "Can't connect to server: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( mysql_select_db( &dbconn, ZM_DATABASE ) ) + { + fprintf( stderr, "Can't select database: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + Monitor **monitors = 0; + int n_monitors = Monitor::Load( device, monitors ); + + Info(( "Starting Capture" )); + sigset_t block_set; + sigemptyset( &block_set ); + struct sigaction action, old_action; + action.sa_handler = hup_handler; + action.sa_mask = block_set; + action.sa_flags = 0; + sigaction( SIGHUP, &action, &old_action ); + sigaddset( &block_set, SIGHUP ); + if ( n_monitors == 1 ) + { + monitors[0]->PreCapture(); + } + while( 1 ) + { + /* grab a new one */ + sigprocmask( SIG_BLOCK, &block_set, 0 ); + for ( int i = 0; i < n_monitors; i++ ) + { + monitors[i]->PreCapture(); + monitors[i]->PostCapture(); + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + if ( reload ) + { + for ( int i = 0; i < n_monitors; i++ ) + { + monitors[i]->CheckFunction(); + } + reload = false; + } + } +} diff --git a/src/zmcfg.h.z b/src/zmcfg.h.z new file mode 100644 index 000000000..79f9dae39 --- /dev/null +++ b/src/zmcfg.h.z @@ -0,0 +1,5 @@ +#define ZM_DATABASE "polycam" +#define ZM_DB_USERA "zmadmin" +#define ZM_DB_PASSA "zmadminzm" +#define ZM_DB_USERB "zmuser" +#define ZM_DB_PASSB "zmuserzm" diff --git a/src/zmdbg.c b/src/zmdbg.c new file mode 100644 index 000000000..67440d3e0 --- /dev/null +++ b/src/zmdbg.c @@ -0,0 +1,568 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zmdbg.h" + +#define PRESERVE_ATTEMPTS 3 + +static unsigned int DbgArchive_ext = 1; +static unsigned int DbgArchive_time = 0; +static unsigned int DbgArchive_size = 0; + +static unsigned long DbgArchive_sec = 0; +static unsigned long DbgArchive_cnt = 0; + +static char string[4096]; +static char dbg_string[4096+512]; +static const char *dbg_file; +static int dbg_line; +static int dbg_code; +static char dbg_class[4]; +const char *dbg_name = ""; +int dbg_pid = -1; +static int dbg_switched_on = FALSE; + +int dbg_level = 0; +char dbg_log[128] = ""; +FILE *dbg_log_fd = (FILE *)NULL; +int dbg_print = FALSE; +int dbg_flush = FALSE; +int dbg_runtime = FALSE; +int dbg_add_log_id = FALSE; +struct timeval dbg_start; + +/* support for automatic reopening of debug files on failure to open */ +static int dbg_running = FALSE; +static int dbg_reopen_cnt = 10; +static time_t dbg_log_closed = 0; +static int dbg_trig_arc = FALSE; + +void UsrHandler( int sig ) +{ + if( sig == SIGUSR1) + { + dbg_switched_on = TRUE; + if ( dbg_level < 9 ) + { + dbg_level++; + } +#if 0 + if ( SIGNAL( SIGUSR1,UsrHandler ) < 0 ) + { + Error(( "%s(), error = %s", dbg_policy_nm[dbg_sig_policy], strerror(errno) )); + } +#endif + } + else if ( sig == SIGUSR2 ) + { + if( dbg_level > -3 ) + { + dbg_level--; + } +#if 0 + if ( SIGNAL( SIGUSR2,UsrHandler ) < 0 ) + { + Error(( "%s(), error = %s", dbg_policy_nm[dbg_sig_policy], strerror(errno) )); + } +#endif + } + Info(( "Debug Level Changed to %d", dbg_level )); +} + +int GetDebugEnv( const char * const command ) +{ + char buffer[128]; + char *env_ptr; + + /* dbg_level = 0; */ + /* dbg_log[0] = '\0'; */ + + env_ptr = getenv( "DB_PRINT" ); + if ( env_ptr == (char *)NULL ) + { + dbg_print = FALSE; + } + else + { + dbg_print = atoi( env_ptr ); + } + + env_ptr = getenv( "DB_FLUSH" ); + if ( env_ptr == (char *)NULL ) + { + dbg_flush = FALSE; + } + else + { + dbg_flush = atoi( env_ptr ); + } + + env_ptr = getenv( "DB_RUNTIME" ); + if ( env_ptr == (char *)NULL ) + { + dbg_runtime = FALSE; + } + else + { + dbg_runtime = atoi( env_ptr ); + } + + sprintf(buffer,"DLVL_%s",command); + env_ptr = getenv(buffer); + if( env_ptr != (char *)NULL ) + { + dbg_level = atoi(env_ptr); + } + sprintf( buffer, "DLOG_%s", command ); + env_ptr = getenv( buffer ); + if ( env_ptr != (char *)NULL ) + { + /* If we do not want to add a pid to the debug logs + * which is the default, and original method + */ + if ( env_ptr[strlen(env_ptr)-1] == '+' ) + { + /* remove the + character from the string */ + env_ptr[strlen(env_ptr)-1] = '\0'; + dbg_add_log_id = TRUE; + } + if ( dbg_add_log_id == FALSE ) + { + strcpy( dbg_log, env_ptr ); + } + else + { + sprintf( dbg_log, "%s.%05d", env_ptr, getpid() ); + } + } + env_ptr = getenv( "DB_REOPEN_TRY" ); + if ( env_ptr != (char *) NULL ) + { + /* This counts the number of times the DbgOutput function + * has been called when the debug logs have been closed + * before a reopen is attempted + */ + dbg_reopen_cnt = atoi(env_ptr); + if (dbg_reopen_cnt < 1) + { + dbg_reopen_cnt = 1; + } + } + + return(0); +} + + +char *move_debug_file ( void ) +{ + int i; + static char new_dbg_log[200]; + + for ( i=0; itv_sec -= tp2->tv_sec; + if ( tp1->tv_usec <= tp2->tv_usec ) + { + tp1->tv_sec--; + tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec); + } + else + { + tp1->tv_usec = tp1->tv_usec - tp2->tv_usec; + } +} + +static int DbgArchiveNowLocal( const unsigned long secs ) +{ + DbgArchive_sec = secs; + DbgArchive_cnt = 0; + + fflush ( dbg_log_fd ); + if ( dbg_log_fd != NULL && ( fclose ( dbg_log_fd ) ) == -1 ) + { + Error ( ( "Failed to archive: fclose(), error = %s", strerror ( errno ) ) ); + /* clearing dbg_log_fd to make sure that we don't confused about + * this debug file */ + if (dbg_log_closed == 0) + { + dbg_log_closed = time(NULL); + } + dbg_log_fd = NULL; + } + else + { + char *prev_file; + + dbg_log_fd = (FILE *)NULL; + + prev_file = move_debug_file ( ); + + if ( prev_file == (char*)NULL ) + { + if ( ( dbg_log_fd = fopen ( dbg_log, "a" ) ) == (FILE *)NULL ) + { + if (dbg_log_closed == 0) + { + dbg_log_closed = time(NULL); + } + return ( DBG_ERROR ); + } + Error ( ( "Debug Log archive failed" ) ); + } + else + { + if ( ( dbg_log_fd = fopen ( dbg_log, "w" ) ) == (FILE *)NULL ) + { + if (dbg_log_closed == 0) + { + dbg_log_closed = time(NULL); + } + return ( DBG_ERROR ); + } + } + + Info(("Debug Level = %d, Debug Log = %s",dbg_level,dbg_log)); + } + + return ( DBG_OK ); +} + +int DbgArchiveNow ( void ) +{ + struct timeval tp; + struct timezone tzp; + int rtn; + + gettimeofday( &tp, &tzp ); + + rtn = DbgArchiveNowLocal ( tp.tv_sec ); + Info(("Reopening of debug logs under applications control")); + + return ( rtn ); +} + +int DbgPrepare( const char * const file, const int line, const int code ) +{ + dbg_file = file; + dbg_line = line; + dbg_code = code; + switch(code) + { + case DBG_INF: + strcpy(dbg_class,"INF"); + break; + case DBG_WAR: + strcpy(dbg_class,"WAR"); + break; + case DBG_ERR: + strcpy(dbg_class,"ERR"); + break; + case DBG_FAT: + strcpy(dbg_class,"FAT"); + break; + default: + if(code > 0 && code <= 9) + { + sprintf(dbg_class,"DB%d",code); + } + else + { + Error(("Unknown Error Code %d",code)); + } + break; + } + return(code); +} + +int DbgOutput( const char *fstring, ... ) +{ + char time_string[64]; + va_list arg_ptr; + int log_code; + struct timeval tp; + struct timezone tzp; + static int count = 0; + + string[0] = '\0'; + va_start(arg_ptr,fstring); + vsprintf(string,fstring,arg_ptr); + + gettimeofday( &tp, &tzp ); + + /* Archive processing */ +#if 0 + if ( ( DbgArchive_time && ( ( tp.tv_sec - DbgArchive_sec ) > DbgArchive_time ) ) || + ( DbgArchive_size && ( DbgArchive_cnt > DbgArchive_size ) ) ) + { + int rtn; + + if ( ( rtn = DbgArchiveNowLocal ( tp.tv_sec ) ) != DBG_OK ) + { + return ( rtn ); + } + Info(("Reopening of debug triggered by debug library (MaxOpenTime=%d,MaxSize=%d", DbgArchive_time, DbgArchive_size)); + + } +#endif + + if ( dbg_runtime ) + { + DbgSubtractTime( &tp, &dbg_start ); + + sprintf( time_string, "%d.%03ld", tp.tv_sec, tp.tv_usec/1000 ); + } + else + { + time_t the_time; + + the_time = tp.tv_sec; + + strftime(time_string,63,"%x %H:%M:%S",localtime(&the_time)); + sprintf(&(time_string[strlen(time_string)]), ".%06ld", tp.tv_usec); + + } + sprintf(dbg_string,"%s %s[%d].%s-%s/%d [%s]\n", + time_string,dbg_name,dbg_pid, + dbg_class,dbg_file,dbg_line,string); + if ( dbg_print ) + { + printf("%s", dbg_string); + fflush(stdout); + } + if ( dbg_log_fd != (FILE *)NULL ) + { + int cnt; + + /* + * Attempt to seek to the end of the file. + * This will add about 2 micro seconds to every + * debug call. This is not considerd significant. + * Note that if it fails it fails and we don't care + * it's only to be nice to fstidy. + */ + lseek(fileno(dbg_log_fd), 0, 2); + + if ( ( cnt = fprintf ( dbg_log_fd, "%s", dbg_string ) ) > 0 ) + { + DbgArchive_cnt += cnt; + } + + if ( dbg_flush ) + { + fflush(dbg_log_fd); + } + } + else if (dbg_log_fd == NULL && dbg_running == TRUE) + { + /* in this section, debug is on because dbg_running (i.e. + * InitialiseDebug has been called and TerminateDebug has not), + * dbg_log_fd is NULL, probably from a failed close, so + * what we do is increment the count of times into DbgOutput + * function. Once this is greater than the dbg_reopen_cnt + * we try to archive (this should hopefully tidy things up a + * little, but even if it doesn't it should try reopening + * the debug log. Once it is reopened we spit out an + * extra message for information indicating the time the + * debug log got lost. Note that if we can't archive (say + * filesystem is still full) we just return as we would have + * done earlier. Also note that in the case where we've + * entered this function greater than dbg_reopen_cnt we + * reset the counter. + */ +#if 0 + count++; + if (count > dbg_reopen_cnt) + { + int rtn; + + count = 0; + if ( ( rtn = DbgArchiveNowLocal ( tp.tv_sec ) ) != DBG_OK ) + { + return ( rtn ); + } + Info(("Warning debug log closed since UTC=%d", dbg_log_closed)); + dbg_log_closed = 0; + } +#endif + } + /* For Info, Warning, Errors etc we want to log them */ + if ( dbg_code <= DBG_INF ) + { + if ( !dbg_flush ) + { + fflush(dbg_log_fd); + } + switch(dbg_code) + { + case DBG_INF: + log_code = LOG_INFO; + break; + case DBG_WAR: + log_code = LOG_WARNING; + break; + case DBG_ERR: + log_code = LOG_ERR; + break; + case DBG_FAT: + log_code = LOG_CRIT; + break; + default: + log_code = LOG_CRIT; + break; + } + log_code |= LOG_LOCAL1; + syslog( log_code, "%s [%s]", dbg_class, string ); + } + va_end(arg_ptr); + if ( dbg_code == DBG_FAT ) + { + exit(-1); + } + return( strlen( string ) ); +} + +void DbgArchive ( const unsigned int ArchiveTime, const unsigned int ArchiveSize ) +{ + DbgArchive_time = ArchiveTime; + DbgArchive_size = ArchiveSize; +} diff --git a/src/zmdbg.h b/src/zmdbg.h new file mode 100644 index 000000000..7800bb10a --- /dev/null +++ b/src/zmdbg.h @@ -0,0 +1,128 @@ +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* Leve 0 and below */ +#define DBG_OK 0 +#define DBG_SUCCESS 0 +#define DBG_INFO 1 +#define DBG_WARNING -1 +#define DBG_ERROR -2 +#define DBG_FATAL -3 + +#define DBG_INF 0 +#define DBG_WAR -1 +#define DBG_ERR -2 +#define DBG_FAT -3 + +#ifndef DEBUG_OFF + +#define DbgPrintf(code,params) {\ + if (code <= dbg_level)\ + {\ + (void) DbgPrepare(__FILE__,__LINE__,code);\ + (void) DbgOutput params;\ + }\ + } + +#define Null(params) +#define Debug(level,params) DbgPrintf(level,params) +#define Info(params) DbgPrintf(0, params) +#define Warning(params) DbgPrintf(DBG_WAR,params) +#define Error(params) DbgPrintf(DBG_ERR,params) +#define Fatal(params) DbgPrintf(DBG_FAT,params) +#define Entrypoint(params) DbgPrintf(9,params); +#define Exitpoint(params) DbgPrintf(9,params); +#define Mark() Info(("Mark")) +#define Log() Info(("Log")) +#ifdef __GNUC__ +#define Enter(level) DbgPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) +#define Exit(level) DbgPrintf(level,("Exiting %s",__PRETTY_FUNCTION__)) +#else +#if 0 +#define Enter(level) DbgPrintf(level,("Entering ")) +#define Exit(level) DbgPrintf(level,("Exiting ")) +#endif +#define Enter(level) +#define Exit(level) +#endif + +#define HexDump(t,n) {if(dbg_level == 9) \ + { \ + int _i; \ + int _len; \ + char *_s; \ + _s = (t); \ + _len = (n); \ + for(_i = 0; _i < _len; _i++,_s++) \ + { \ + if(!(_i % 16)) \ + { \ + fprintf(dbg_log_fd,"\n"); \ + } \ + fprintf(dbg_log_fd,"0x%02x ", \ + ((int)*_s)&0xff); \ + } \ + fprintf(dbg_log_fd,"\n"); \ + }} +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__STDC__) || defined(__cplusplus) +int DbgInit(void); +int DbgTerm(void); +int DbgPrepare(const char * const file,const int line, const int code); +int DbgArchiveNow ( void ); +void DbgArchive ( const unsigned int ArchiveTime, const unsigned int ArchiveSize ); +int DbgOutput(const char *fstring, ... ) __attribute__ ((format(printf, 1, 2))); +#else +int DbgInit(); +int DbgTerm(); +int DbgPrepare(); +DbgArchiveNow(); +DbgArchive(); +int DbgOutput(); +#endif + +extern int dbg_level; +extern int dbg_pid; +extern char dbg_log[]; +#ifndef _STDIO_INCLUDED +#include +#endif +extern FILE *dbg_log_fd; +extern const char *dbg_name; +extern int dbg_print; +extern int dbg_flush; +extern int dbg_add_log_id; + +#ifdef __cplusplus +} //extern "C" +#endif + +#else + +#define InitialiseDebug(params) DBG_OK +#define TerminateDebug(params) DBG_OK + +#define Debug(lvl,params) +#define Info(params) +#define Warning(params) +#define Error(params) +#define Fatal(params) +#define Mark() +#define Log() +#define Enter() +#define Exit() + +#define DbgInit() +#define DbgTerm() + +#endif /* DEBUG_ON */ diff --git a/src/zms.cpp b/src/zms.cpp new file mode 100644 index 000000000..8878ad072 --- /dev/null +++ b/src/zms.cpp @@ -0,0 +1,73 @@ +#include "zm.h" + +void main( int argc, const char *argv[] ) +{ + int id = 1; + unsigned long idle = 5000; + unsigned long refresh = 50; + int event = 0; + char *path = "."; + + const char *query = getenv( "QUERY_STRING" ); + if ( query ) + { + char temp_query[256]; + strcpy( temp_query, query ); + char *q_ptr = temp_query; + char *parms[8]; // Shouldn't be more than this + int parm_no = 0; + while( parms[parm_no] = strtok( q_ptr, "&" ) ) + { + parm_no++; + q_ptr = NULL; + } + + for ( int p = 0; p < parm_no; p++ ) + { + char *name = strtok( parms[p], "=" ); + char *value = strtok( NULL, "=" ); + if ( !strcmp( name, "refresh" ) ) + refresh = atol( value ); + else if ( !strcmp( name, "idle" ) ) + idle = atol( value ); + else if ( !strcmp( name, "monitor" ) ) + id = atoi( value ); + else if ( !strcmp( name, "event" ) ) + event = atoi( value ); + else if ( !strcmp( name, "path" ) ) + path = value; + } + } + + dbg_name = "zms"; + + DbgInit(); + + if ( !mysql_init( &dbconn ) ) + { + fprintf( stderr, "Can't initialise structure: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( !mysql_connect( &dbconn, "", "zmuser", "zmuserzm" ) ) + { + fprintf( stderr, "Can't connect to server: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( mysql_select_db( &dbconn, "polycam" ) ) + { + fprintf( stderr, "Can't select database: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + if ( !event ) + { + Monitor *monitor = Monitor::Load( id ); + + if ( monitor ) + monitor->StreamImages( idle, refresh, stdout ); + } + else + { + Event::StreamEvent( path, event, refresh, stdout ); + } +} diff --git a/src/zmu.cpp b/src/zmu.cpp new file mode 100644 index 000000000..9e95c88c8 --- /dev/null +++ b/src/zmu.cpp @@ -0,0 +1,138 @@ +#include +#include "zm.h" + +void main( int argc, char *argv[] ) +{ + static struct option long_options[] = { + {"monitor", 1, 0, 'm'}, + {"image", 2, 0, 'i'}, + {"timestamp", 2, 0, 't'}, + {"state", 0, 0, 's'}, + {"read_index", 0, 0, 'r'}, + {"write_index", 0, 0, 'w'}, + {"fps", 0, 0, 'f'}, + {"zones", 0, 0, 'z'}, + {0, 0, 0, 0} + }; + + int id = 1; + enum { STATE, IMAGE, TIME, READ_IDX, WRITE_IDX, FPS, ZONES } function = STATE; + int image_idx = -1; + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + + int c = getopt_long (argc, argv, "m:srwi::t::fz", long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 'm': + id = atoi(optarg); + break; + case 's': + function = STATE; + break; + case 'i': + function = IMAGE; + if ( optarg ) + { + image_idx = atoi( optarg ); + } + break; + case 't': + function = TIME; + if ( optarg ) + { + image_idx = atoi( optarg ); + } + break; + case 'r': + function = READ_IDX; + break; + case 'w': + function = WRITE_IDX; + break; + case 'f': + function = FPS; + break; + case 'z': + function = ZONES; + break; + case '?': + //fprintf( stderr, "What?\n" ); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } + +#if 0 + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + +#endif + //printf( "Monitor %d, Function %d, ImageIdx %d\n", id, function, image_idx ); + + dbg_name = "zmu"; + + DbgInit(); + + if ( !mysql_init( &dbconn ) ) + { + fprintf( stderr, "Can't initialise structure: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( !mysql_connect( &dbconn, "", "zmuser", "zmuserzm" ) ) + { + fprintf( stderr, "Can't connect to server: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + if ( mysql_select_db( &dbconn, "polycam" ) ) + { + fprintf( stderr, "Can't select database: %s\n", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + Monitor *monitor = Monitor::Load( id ); + + if ( monitor ) + { + if ( function == STATE ) + { + printf( "%d\n", monitor->GetState() ); + } + else if ( function == IMAGE ) + { + monitor->GetImage( image_idx ); + } + else if ( function == TIME ) + { + printf( "%d\n", monitor->GetTimestamp( image_idx ) ); + } + else if ( function == READ_IDX ) + { + printf( "%d\n", monitor->GetLastReadIndex() ); + } + else if ( function == WRITE_IDX ) + { + printf( "%d\n", monitor->GetLastWriteIndex() ); + } + else if ( function == FPS ) + { + printf( "%.2f\n", monitor->GetFPS() ); + } + else if ( function == ZONES ) + { + monitor->ReloadZones(); + } + } +} diff --git a/web/zm.php b/web/zm.php new file mode 100644 index 000000000..914938c9a --- /dev/null +++ b/web/zm.php @@ -0,0 +1,873 @@ +NOW() - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) as HourEventCount, count(if(E.StartTime>NOW() - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) as DayEventCount, count(if(E.StartTime>NOW() - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) as WeekEventCount, count(if(E.StartTime>NOW() - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) as MonthEventCount, count(Z.MonitorId) as ZoneCount from Monitors as M inner join Zones as Z on Z.MonitorId = M.Id left join Events as E on E.MonitorId = M.Id group by E.MonitorId,Z.MonitorId order by Id" ); + $sql = "select M.*, count(E.Id) as EventCount, count(if(E.Archived,1,NULL)) as ArchEventCount, count(if(E.StartTime>NOW() - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) as HourEventCount, count(if(E.StartTime>NOW() - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) as DayEventCount, count(if(E.StartTime>NOW() - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) as WeekEventCount, count(if(E.StartTime>NOW() - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) as MonthEventCount from Monitors as M left join Events as E on E.MonitorId = M.Id group by E.MonitorId order by Id"; + $result = mysql_query( $sql ); + if ( !$result ) + echo mysql_error(); + $monitors = array(); + $max_width = 0; + $max_height = 0; + while( $row = mysql_fetch_assoc( $result ) ) + { + if ( $max_width < $row[Width] ) $max_width = $row[Width]; + if ( $max_height < $row[Height] ) $max_height = $row[Height]; + $sql = "select count(Id) as ZoneCount, count(if(Type='Active',1,NULL)) as ActZoneCount, count(if(Type='Inclusive',1,NULL)) as IncZoneCount, count(if(Type='Exclusive',1,NULL)) as ExcZoneCount, count(if(Type='Inactive',1,NULL)) as InactZoneCount from Zones where MonitorId = '$row[Id]'"; + $result2 = mysql_query( $sql ); + if ( !$result2 ) + echo mysql_error(); + $row2 = mysql_fetch_assoc( $result2 ); + $monitors[] = array_merge( $row, $row2 ); + } + + //echo phpinfo(); +?> + + +ZM - Console + + + + +

Zone Monitor Console

+ + + + + + +
MonitorsCurrently configured for bandwidth (change to + high + medium + low )Monitor All
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDevice/ChannelFunctionDimensionsEventsHourDayWeekMonthArchiveZonesDelete
./dev/video ()xx
  
+ + + + + +ZM - Cycle Watch + + + + +

+ + + + + + +ZM - <?php echo $monitor[Name] ?> - Monitor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StreamStillsStreamClose
+ + + + + + + + + +
Status:
+ + + + + +ZM - <?php echo $monitor ?> - Events <?php if ( $archived ) { ?>Archive<?php } ?> + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Last eventsRecentAllArchiveCheck All
 
+ + + + + + + + + + + +
IdNameTimeLengthFramesDelete
()
+
+ + + + + +ZM - Images - <?php echo $event[Name] ?> - Images + + + + + + + +
+ + $thumb_image"; + else + $command = "jpegtopnm -dct fast $image | pnmscalefixed $fraction | ppmtojpeg --dct=fast > $thumb_image"; + #exec( escapeshellcmd( $command ) ); + exec( $command ); + } + } +?> + + + + + + +
<?php echo $frame_id ?>/<?php echo $row[Score] ?>
+ + + + + +ZM - Image <?php echo $eid."-".$fid ?> + + + + + + + + + + + + 1 ) { ?> + + + + 1 ) { ?> + + + + + + + + + + + + + +
Image DeleteClose
First Prev Next Last 
+ + + + + +ZM - Event - <?php echo $event[Name] ?> + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
RefreshDeleteArchiveImagesVideoClose
+ + + + + +ZM - <?php echo $monitor[Name] ?> - Zones + + + + + +" href="index.php?view=zone&zid="> + + + +

Zones

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameTypeUnitsDimensionsDelete
.,-,
 
+ + +$event_dir/mpeg.log" ) ); + } + + //chdir( $event_dir ); + //header("Content-type: video/mpeg"); + //header("Content-Disposition: inline; filename=$video_name"); + header("Location: $video_file" ); +}